From bea6a4c59ec4a9c1da43e8889da9f2c10815c765 Mon Sep 17 00:00:00 2001 From: matthewpeterkort Date: Wed, 24 Jun 2026 11:43:04 -0700 Subject: [PATCH 01/15] cleanup server to be human readable and semantically cleaner. need to test --- .codexignore | 7 + .gitignore | 7 +- Makefile | 50 + README.md | 18 +- cmd/arango-fhir-proto/main.go | 167 +- cmd/arango-fhir-server/main.go | 57 +- cmd/generate/main.go | 73 +- docs/DATAFRAME_BUILDER_PORTABILITY.md | 20 +- docs/DEVELOPER_ARCHITECTURE.md | 110 +- docs/QUICKSTART.md | 16 +- experimental/README.md | 13 + experimental/docker-compose.yml | 10 + go.mod | 22 +- go.sum | 44 +- internal/api/doc.go | 2 + internal/{writeapi => api}/http_test.go | 30 +- internal/api/import_route.go | 130 + internal/api/middleware.go | 61 + internal/api/routes.go | 36 + internal/api/server.go | 107 + internal/api/service.go | 104 + internal/api/service_test.go | 76 + internal/authscope/doc.go | 3 + internal/authscope/principal.go | 54 + internal/{writeapi => authscope}/scope.go | 17 +- .../{writeapi => authscope}/scope_test.go | 15 +- internal/catalog/auth_resource_paths.go | 98 - .../{catalogcache => catalog/cache}/cache.go | 40 +- .../cache}/cache_test.go | 16 +- internal/catalog/discovery.go | 204 - internal/catalog/field_catalog.go | 918 - internal/catalog/helpers.go | 277 + internal/catalog/progress.go | 25 - internal/catalog/read_auth_paths.go | 54 + internal/catalog/read_fields.go | 104 + internal/catalog/read_references.go | 108 + internal/catalog/types.go | 146 + internal/catalog/write_persist.go | 41 + internal/catalog/write_profiler.go | 399 + ...catalog_test.go => write_profiler_test.go} | 6 +- internal/dataframe/auth.go | 51 + internal/dataframe/builder_types.go | 80 + internal/dataframe/compile.go | 70 + internal/dataframe/compile_fields.go | 202 + internal/dataframe/dataframe.go | 993 - internal/dataframe/dataframe_test.go | 117 +- .../dataframe/document_reference_semantics.go | 87 + internal/dataframe/execution.go | 87 + ...advanced_compile.go => lowered_compile.go} | 16 +- .../{advanced_types.go => lowered_types.go} | 44 +- internal/dataframe/pivots.go | 77 + internal/dataframe/planner.go | 70 +- internal/dataframe/query_runtime.go | 26 + internal/dataframe/selectors.go | 46 + internal/dataframe/service.go | 102 + internal/dataframe/traversal_rules.go | 102 + internal/dataframe/validation.go | 286 + .../fieldrefs.go | 98 +- internal/dataframebuilder/fieldrefs_test.go | 60 + internal/dataframebuilder/helpers.go | 17 + internal/dataframebuilder/input_mapping.go | 197 + .../input_mapping_test.go} | 6 +- internal/dataframebuilder/input_resolution.go | 249 + internal/dataframebuilder/introspection.go | 133 + .../introspection_test.go} | 40 +- internal/dataframebuilder/service.go | 72 + internal/dataframebuilder/types.go | 34 + internal/dbio/dbio.go | 49 - internal/experimental/benchmark.go | 200 - .../experimental/store/postgres/client.go | 818 - internal/experimental/store/surreal/client.go | 379 - internal/fhirschema/generated.go | 61010 +++++++++++++++- internal/fhirschema/schema.go | 137 +- internal/fhirschema/schema_test.go | 44 +- internal/fhirsemantics/registry.go | 233 - internal/fhirsemantics/registry_test.go | 43 - internal/graphqlapi/generated.go | 2 +- internal/graphqlapi/handler.go | 9 - internal/graphqlapi/http_integration_test.go | 153 +- internal/graphqlapi/mappers.go | 355 - internal/graphqlapi/output_mapping.go | 166 + internal/graphqlapi/resolver.go | 11 +- internal/graphqlapi/schema.resolvers.go | 21 +- internal/graphqlapi/service.go | 456 - internal/{proto => ingest}/backend.go | 58 +- internal/{proto => ingest}/bench_test.go | 6 +- internal/ingest/doc.go | 3 + internal/{proto => ingest}/files.go | 2 +- internal/{proto => ingest}/files_test.go | 2 +- internal/{proto => ingest}/generated_load.go | 4 +- .../{proto => ingest}/integration_test.go | 65 +- internal/{proto => ingest}/load.go | 37 +- internal/{proto => ingest}/parity_test.go | 4 +- internal/{proto => ingest}/progress.go | 6 +- internal/{proto => ingest}/row_builder.go | 2 +- internal/proto/catalog.go | 32 - internal/proto/querysvc.go | 42 - internal/proto/value_decode.go | 32 - internal/querysvc/build_scalar_index.go | 177 - internal/querysvc/prepare_case_assay.go | 389 - internal/querysvc/query.go | 175 - internal/querysvc/support.go | 65 - internal/store/arango/client.go | 8 +- internal/store/arango/options.go | 6 + internal/store/{store.go => arango/types.go} | 2 +- internal/writeapi/http.go | 351 - internal/writeapi/service.go | 315 - internal/writeapi/service_test.go | 198 - scripts/delete-ds-store.sh | 11 - 109 files changed, 62691 insertions(+), 10434 deletions(-) create mode 100644 .codexignore create mode 100644 Makefile create mode 100644 experimental/README.md create mode 100644 experimental/docker-compose.yml create mode 100644 internal/api/doc.go rename internal/{writeapi => api}/http_test.go (83%) create mode 100644 internal/api/import_route.go create mode 100644 internal/api/middleware.go create mode 100644 internal/api/routes.go create mode 100644 internal/api/server.go create mode 100644 internal/api/service.go create mode 100644 internal/api/service_test.go create mode 100644 internal/authscope/doc.go create mode 100644 internal/authscope/principal.go rename internal/{writeapi => authscope}/scope.go (95%) rename internal/{writeapi => authscope}/scope_test.go (85%) delete mode 100644 internal/catalog/auth_resource_paths.go rename internal/{catalogcache => catalog/cache}/cache.go (61%) rename internal/{catalogcache => catalog/cache}/cache_test.go (70%) delete mode 100644 internal/catalog/discovery.go delete mode 100644 internal/catalog/field_catalog.go create mode 100644 internal/catalog/helpers.go delete mode 100644 internal/catalog/progress.go create mode 100644 internal/catalog/read_auth_paths.go create mode 100644 internal/catalog/read_fields.go create mode 100644 internal/catalog/read_references.go create mode 100644 internal/catalog/types.go create mode 100644 internal/catalog/write_persist.go create mode 100644 internal/catalog/write_profiler.go rename internal/catalog/{field_catalog_test.go => write_profiler_test.go} (97%) create mode 100644 internal/dataframe/auth.go create mode 100644 internal/dataframe/builder_types.go create mode 100644 internal/dataframe/compile.go create mode 100644 internal/dataframe/compile_fields.go delete mode 100644 internal/dataframe/dataframe.go create mode 100644 internal/dataframe/document_reference_semantics.go create mode 100644 internal/dataframe/execution.go rename internal/dataframe/{advanced_compile.go => lowered_compile.go} (99%) rename internal/dataframe/{advanced_types.go => lowered_types.go} (91%) create mode 100644 internal/dataframe/pivots.go create mode 100644 internal/dataframe/query_runtime.go create mode 100644 internal/dataframe/selectors.go create mode 100644 internal/dataframe/service.go create mode 100644 internal/dataframe/traversal_rules.go create mode 100644 internal/dataframe/validation.go rename internal/{graphqlapi => dataframebuilder}/fieldrefs.go (61%) create mode 100644 internal/dataframebuilder/fieldrefs_test.go create mode 100644 internal/dataframebuilder/helpers.go create mode 100644 internal/dataframebuilder/input_mapping.go rename internal/{graphqlapi/mappers_test.go => dataframebuilder/input_mapping_test.go} (95%) create mode 100644 internal/dataframebuilder/input_resolution.go create mode 100644 internal/dataframebuilder/introspection.go rename internal/{graphqlapi/service_test.go => dataframebuilder/introspection_test.go} (60%) create mode 100644 internal/dataframebuilder/service.go create mode 100644 internal/dataframebuilder/types.go delete mode 100644 internal/dbio/dbio.go delete mode 100644 internal/experimental/benchmark.go delete mode 100644 internal/experimental/store/postgres/client.go delete mode 100644 internal/experimental/store/surreal/client.go delete mode 100644 internal/fhirsemantics/registry.go delete mode 100644 internal/fhirsemantics/registry_test.go delete mode 100644 internal/graphqlapi/mappers.go create mode 100644 internal/graphqlapi/output_mapping.go delete mode 100644 internal/graphqlapi/service.go rename internal/{proto => ingest}/backend.go (50%) rename internal/{proto => ingest}/bench_test.go (98%) create mode 100644 internal/ingest/doc.go rename internal/{proto => ingest}/files.go (98%) rename internal/{proto => ingest}/files_test.go (96%) rename internal/{proto => ingest}/generated_load.go (99%) rename internal/{proto => ingest}/integration_test.go (72%) rename internal/{proto => ingest}/load.go (93%) rename internal/{proto => ingest}/parity_test.go (99%) rename internal/{proto => ingest}/progress.go (83%) rename internal/{proto => ingest}/row_builder.go (99%) delete mode 100644 internal/proto/catalog.go delete mode 100644 internal/proto/querysvc.go delete mode 100644 internal/proto/value_decode.go delete mode 100644 internal/querysvc/build_scalar_index.go delete mode 100644 internal/querysvc/prepare_case_assay.go delete mode 100644 internal/querysvc/query.go delete mode 100644 internal/querysvc/support.go create mode 100644 internal/store/arango/options.go rename internal/store/{store.go => arango/types.go} (97%) delete mode 100644 internal/writeapi/http.go delete mode 100644 internal/writeapi/service.go delete mode 100644 internal/writeapi/service_test.go delete mode 100755 scripts/delete-ds-store.sh diff --git a/.codexignore b/.codexignore new file mode 100644 index 0000000..d0595a7 --- /dev/null +++ b/.codexignore @@ -0,0 +1,7 @@ +.gocache/ +bin/ +data/ +META/ +arango-fhir-proto +arango-fhir-server +.DS_Store diff --git a/.gitignore b/.gitignore index 5ca0973..f02ae2a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,7 @@ .DS_Store - +.gocache/ +bin/ +data/ +META/ +arango-fhir-proto +arango-fhir-server diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ebff3e3 --- /dev/null +++ b/Makefile @@ -0,0 +1,50 @@ +.PHONY: build build-cli build-server clean generate-fhir generate-graphql graphql-check gqlgen-check test docker-build docker-run + +GO ?= go +GOCACHE_DIR ?= $(CURDIR)/.gocache +GOFLAGS ?= +SCHEMA_PATH ?= schemas/graph-fhir.json +IMAGE ?= arango-fhir-proto:local + +build: build-cli build-server + +build-cli: + mkdir -p bin $(GOCACHE_DIR) + GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) build $(GOFLAGS) -o bin/arango-fhir-proto ./cmd/arango-fhir-proto + +build-server: + mkdir -p bin $(GOCACHE_DIR) + GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) build $(GOFLAGS) -o bin/arango-fhir-server ./cmd/arango-fhir-server + +generate-graphql: + rm -f internal/graphqlapi/generated.go internal/graphqlapi/model/models.go internal/graphqlapi/schema.resolvers.go + mkdir -p $(GOCACHE_DIR) + @status=0; \ + GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) run github.com/99designs/gqlgen generate || status=$$?; \ + if [ -f internal/graphqlapi/generated.go ]; then \ + perl -0pi -e 's/return &res, graphql::ErrorOnPath\\(ctx, err\\)/return res, graphql::ErrorOnPath(ctx, err)/g; s/return &res, graphql\\.ErrorOnPath\\(ctx, err\\)/return res, graphql.ErrorOnPath(ctx, err)/g' internal/graphqlapi/generated.go; \ + fi; \ + test $$status -eq 0 -o -f internal/graphqlapi/generated.go + +generate-fhir: + mkdir -p $(GOCACHE_DIR) + GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) run ./cmd/generate -schema $(SCHEMA_PATH) -out-dir internal/fhir + +graphql-check: + mkdir -p $(GOCACHE_DIR) + GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) test $(GOFLAGS) ./internal/graphqlapi ./internal/dataframe -count=1 + +gqlgen-check: graphql-check + +test: + mkdir -p $(GOCACHE_DIR) + GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) test $(GOFLAGS) ./... -count=1 + +docker-build: + docker build -t $(IMAGE) . + +docker-run: + docker run --rm -p 8080:8080 $(IMAGE) + +clean: + rm -rf bin diff --git a/README.md b/README.md index 544364f..6be90ff 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ backend. This repo now has two main runtime surfaces: - `arango-fhir-proto`: CLI for load, discovery, query, prepare, and benchmark work -- `arango-fhir-server`: Fiber + GraphQL/REST server for dataframe reads and bulk ingest +- `arango-fhir-server`: Fiber server for GraphQL reads plus a direct REST import endpoint The current product direction is: @@ -14,8 +14,6 @@ The current product direction is: - store graph edges in `fhir_edge` - profile populated fields into `fhir_field_catalog` - expose builder introspection and dataframe execution through GraphQL -- keep bulk ingest as REST, not GraphQL - ArangoDB is the first-class backend for dataframe execution. SurrealDB and Postgres code remains under [`experimental/`](experimental/) for research and benchmarking only. @@ -31,14 +29,15 @@ benchmarking only. - [`cmd/arango-fhir-proto/main.go`](cmd/arango-fhir-proto/main.go): CLI entrypoint - [`cmd/arango-fhir-server/main.go`](cmd/arango-fhir-server/main.go): HTTP server entrypoint -- [`internal/proto`](internal/proto): load pipeline and backend bootstrap helpers +- [`internal/ingest`](internal/ingest): load pipeline and Arango ingest bootstrap/runtime - [`internal/catalog`](internal/catalog): populated-field and populated-reference discovery -- [`internal/catalogcache`](internal/catalogcache): per-project discovery cache +- [`internal/catalog/cache`](internal/catalog/cache): per-project discovery cache - [`internal/graphqlapi`](internal/graphqlapi): GraphQL schema, request mapping, introspection service - [`internal/dataframe`](internal/dataframe): dataframe validation, lowering, and AQL compilation - [`internal/fhirschema`](internal/fhirschema): generated schema metadata used by planner/validation - [`internal/fhirsemantics`](internal/fhirsemantics): friendly `fieldRef`s and semantic lowering hints -- [`internal/writeapi`](internal/writeapi): REST import API and in-process operation manager +- [`internal/api`](internal/api): HTTP API surface and ingest import wiring +- [`internal/authscope`](internal/authscope): shared request principal context and auth-resource-path scope resolution - [`queries/`](queries/): Arango AQL query artifacts - [`experimental/`](experimental/): non-primary backend work and benchmark artifacts @@ -119,10 +118,8 @@ The server mounts: - `GET /graphql` - `POST /graphql` - `POST /api/v1/imports` -- `GET /api/v1/imports/:id` -- `GET /api/v1/imports/:id/events` -Write/import behavior lives in [`internal/writeapi/http.go`](internal/writeapi/http.go). +HTTP wiring lives in [`internal/api/routes.go`](internal/api/routes.go) and [`internal/api/server.go`](internal/api/server.go). ## Primary Collections @@ -133,7 +130,7 @@ The loader bootstraps: - `fhir_field_catalog` - `patient_file_rollup` -See [`internal/proto/backend.go`](internal/proto/backend.go). +See [`internal/ingest/backend.go`](internal/ingest/backend.go). ## Status @@ -141,7 +138,6 @@ What is current and real: - GraphQL introspection for populated traversals/fields/pivots - GraphQL dataframe execution on Arango -- REST bulk ingest with in-process operation tracking - generated schema metadata in `internal/fhirschema` - semantic alias/lowering hints in `internal/fhirsemantics` diff --git a/cmd/arango-fhir-proto/main.go b/cmd/arango-fhir-proto/main.go index 586d7ec..11fba4d 100644 --- a/cmd/arango-fhir-proto/main.go +++ b/cmd/arango-fhir-proto/main.go @@ -10,14 +10,12 @@ import ( "runtime/pprof" "runtime/trace" - "arangodb-proto/internal/experimental" - "arangodb-proto/internal/proto" + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/ingest" ) const ( - defaultBackend = "arango" defaultURL = "http://127.0.0.1:8529" - defaultNS = "fhir_proto" defaultDatabase = "fhir_proto" defaultProject = "ARANGODB_PROTO" defaultSchema = "schemas/graph-fhir.json" @@ -42,12 +40,6 @@ func main() { err = runDiscoverPopulatedReferences(ctx, os.Args[2:]) case "discover-populated-fields": err = runDiscoverPopulatedFields(ctx, os.Args[2:]) - case "prepare-gdc-case-assay-matrix": - err = runPrepareCaseAssayMatrix(ctx, os.Args[2:]) - case "build-scalar-index": - err = runBuildScalarIndex(ctx, os.Args[2:]) - case "benchmark": - err = runBenchmark(ctx, os.Args[2:]) default: usage() os.Exit(2) @@ -60,18 +52,13 @@ func main() { func runLoad(ctx context.Context, args []string) error { fs := flag.NewFlagSet("load", flag.ExitOnError) - opts := proto.LoadOptions{} + opts := ingest.LoadOptions{} cpuProfile := fs.String("cpu-profile", "", "Write CPU profile to file") memProfile := fs.String("mem-profile", "", "Write heap profile to file at end of run") traceProfile := fs.String("trace-profile", "", "Write runtime trace to file") blockProfile := fs.String("block-profile", "", "Write block profile to file at end of run") - fs.StringVar(&opts.Backend, "backend", defaultBackend, "Backend: arango, surreal, or postgres") fs.StringVar(&opts.URL, "url", defaultURL, "Backend base URL") - fs.StringVar(&opts.Namespace, "namespace", defaultNS, "SurrealDB namespace") fs.StringVar(&opts.Database, "database", defaultDatabase, "Backend database") - fs.StringVar(&opts.Username, "username", "root", "Backend username") - fs.StringVar(&opts.Password, "password", "root", "Backend password") - fs.StringVar(&opts.AuthToken, "auth-token", "", "SurrealDB auth token; overrides username/password when set") fs.StringVar(&opts.Schema, "schema", defaultSchema, "graph-fhir JSON schema") fs.StringVar(&opts.MetaDir, "meta-dir", defaultMetaDir, "Directory containing META/*.ndjson") fs.StringVar(&opts.Project, "project", defaultProject, "Project label") @@ -96,7 +83,7 @@ func runLoad(ctx context.Context, args []string) error { deferredErr = stopErr } }() - summary, err := proto.Load(ctx, opts) + summary, err := ingest.Load(ctx, opts) if err != nil { return err } @@ -106,148 +93,18 @@ func runLoad(ctx context.Context, args []string) error { return printJSON(summary) } -func runQuery(ctx context.Context, args []string, bulk bool) error { - name := "query-gdc-case-assay-matrix" - if bulk { - name = "export-gdc-case-assay-matrix" - } - fs := flag.NewFlagSet(name, flag.ExitOnError) - opts := proto.QueryOptions{Bulk: bulk} - fs.StringVar(&opts.Backend, "backend", defaultBackend, "Backend: arango, surreal, or postgres") - fs.StringVar(&opts.URL, "url", defaultURL, "Backend base URL") - fs.StringVar(&opts.Namespace, "namespace", defaultNS, "SurrealDB namespace") - fs.StringVar(&opts.Database, "database", defaultDatabase, "Backend database") - fs.StringVar(&opts.Username, "username", "root", "Backend username") - fs.StringVar(&opts.Password, "password", "root", "Backend password") - fs.StringVar(&opts.AuthToken, "auth-token", "", "SurrealDB auth token; overrides username/password when set") - fs.StringVar(&opts.Project, "project", defaultProject, "Project label") - fs.StringVar(&opts.AuthResourcePath, "auth-resource-path", "", "Optional auth resource path used to scope dataframe/export queries, for example EllrottLab-GDC_Data") - fs.StringVar(&opts.PatientKey, "patient-key", "", "Optional patient _key bind var for backend-specific probe queries") - fs.StringVar(&opts.QueryFile, "query", "", "Backend-specific query file; defaults to the case/assay query for the selected backend") - fs.StringVar(&opts.Output, "output", "", "Output path; defaults to stdout") - fs.StringVar(&opts.Index, "index", proto.DefaultBulkIndex(), "Elasticsearch bulk target index") - fs.IntVar(&opts.BatchSize, "cursor-batch-size", 1000, "Query cursor batch size") - fs.IntVar(&opts.ProgressEvery, "progress-every", 50000, "Emit progress every N rows") - fs.IntVar(&opts.MaxRows, "max-rows", 0, "Stop after N output rows") - if err := fs.Parse(args); err != nil { - return err - } - if opts.QueryFile == "" { - opts.QueryFile = proto.DefaultCaseAssayQueryPathForBackend(opts.Backend) - } - if bulk && opts.Output == "" { - return fmt.Errorf("--output is required for %s", name) - } - rows, err := proto.Query(ctx, opts) - if err != nil { - return err - } - return printJSON(map[string]any{"step": name, "rows": rows, "output": opts.Output}) -} - -func runBenchmark(ctx context.Context, args []string) error { - fs := flag.NewFlagSet("benchmark", flag.ExitOnError) - opts := experimental.BenchmarkOptions{} - fs.StringVar(&opts.Backend, "backend", defaultBackend, "Backend: arango, surreal, or postgres") - fs.StringVar(&opts.URL, "url", defaultURL, "Backend base URL") - fs.StringVar(&opts.Namespace, "namespace", defaultNS, "SurrealDB namespace") - fs.StringVar(&opts.Database, "database", defaultDatabase, "Backend database") - fs.StringVar(&opts.Username, "username", "root", "Backend username") - fs.StringVar(&opts.Password, "password", "root", "Backend password") - fs.StringVar(&opts.AuthToken, "auth-token", "", "SurrealDB auth token; overrides username/password when set") - fs.StringVar(&opts.Schema, "schema", defaultSchema, "graph-fhir JSON schema") - fs.StringVar(&opts.MetaDir, "meta-dir", defaultMetaDir, "Directory containing META/*.ndjson") - fs.StringVar(&opts.Project, "project", defaultProject, "Project label") - fs.StringVar(&opts.AuthResourcePath, "auth-resource-path", "", "Optional auth resource path copied onto loaded records and used in dataframe queries") - fs.StringVar(&opts.QueryFile, "query", "", "Backend-specific dataframe query file") - fs.StringVar(&opts.DatasetName, "dataset-name", "", "Optional benchmark dataset label") - fs.StringVar(&opts.Output, "output", "", "Optional path to keep the benchmark dataframe output; defaults to a temporary file") - fs.IntVar(&opts.BatchSize, "batch-size", 5000, "Bulk insert batch size") - fs.IntVar(&opts.CursorBatchSize, "cursor-batch-size", 1000, "Query cursor batch size") - fs.IntVar(&opts.ProgressEvery, "progress-every", 50000, "Emit progress every N rows") - fs.IntVar(&opts.WriterCount, "writers", 8, "Concurrent writer goroutines") - fs.BoolVar(&opts.Truncate, "truncate", true, "Truncate prototype collections before benchmarking") - fs.StringVar(&opts.WriteAPI, "write-api", "import", "Bulk write API: import or document") - if err := fs.Parse(args); err != nil { - return err - } - if opts.QueryFile == "" { - opts.QueryFile = proto.DefaultCaseAssayQueryPathForBackend(opts.Backend) - } - summary, err := experimental.Benchmark(ctx, opts) - if err != nil { - return err - } - return printJSON(summary) -} - -func runPrepareCaseAssayMatrix(ctx context.Context, args []string) error { - fs := flag.NewFlagSet("prepare-gdc-case-assay-matrix", flag.ExitOnError) - opts := proto.PrepareCaseAssayOptions{} - fs.StringVar(&opts.Backend, "backend", defaultBackend, "Backend: arango, surreal, or postgres") - fs.StringVar(&opts.URL, "url", defaultURL, "Backend base URL") - fs.StringVar(&opts.Namespace, "namespace", defaultNS, "SurrealDB namespace") - fs.StringVar(&opts.Database, "database", defaultDatabase, "Backend database") - fs.StringVar(&opts.Username, "username", "root", "Backend username") - fs.StringVar(&opts.Password, "password", "root", "Backend password") - fs.StringVar(&opts.AuthToken, "auth-token", "", "SurrealDB auth token; overrides username/password when set") - fs.StringVar(&opts.Project, "project", defaultProject, "Project label") - fs.StringVar(&opts.AuthResourcePath, "auth-resource-path", "", "Optional auth resource path used to scope prepare work") - fs.IntVar(&opts.BatchSize, "batch-size", 1000, "Bulk insert batch size for helper rows") - fs.IntVar(&opts.ProgressEvery, "progress-every", 5000, "Emit progress every N prepared rows") - fs.BoolVar(&opts.Truncate, "truncate", true, "Truncate helper collections before preparing") - if err := fs.Parse(args); err != nil { - return err - } - summary, err := proto.PrepareGDCCaseAssayMatrix(ctx, opts) - if err != nil { - return err - } - return printJSON(summary) -} - -func runBuildScalarIndex(ctx context.Context, args []string) error { - fs := flag.NewFlagSet("build-scalar-index", flag.ExitOnError) - opts := proto.BuildScalarIndexOptions{} - fs.StringVar(&opts.Backend, "backend", defaultBackend, "Backend: arango, surreal, or postgres") - fs.StringVar(&opts.URL, "url", defaultURL, "Backend base URL") - fs.StringVar(&opts.Namespace, "namespace", defaultNS, "SurrealDB namespace") - fs.StringVar(&opts.Database, "database", defaultDatabase, "Backend database") - fs.StringVar(&opts.Username, "username", "root", "Backend username") - fs.StringVar(&opts.Password, "password", "root", "Backend password") - fs.StringVar(&opts.AuthToken, "auth-token", "", "SurrealDB auth token; overrides username/password when set") - fs.StringVar(&opts.Project, "project", "", "Optional project filter") - fs.StringVar(&opts.ResourceType, "resource-type", "", "Optional resource type filter") - fs.IntVar(&opts.BatchSize, "batch-size", 5000, "Bulk insert batch size for scalar rows") - fs.IntVar(&opts.ProgressEvery, "progress-every", 5000, "Emit progress every N scanned resources") - fs.BoolVar(&opts.Truncate, "truncate", true, "Delete existing matching scalar rows before rebuilding") - if err := fs.Parse(args); err != nil { - return err - } - summary, err := proto.BuildScalarIndex(ctx, opts) - if err != nil { - return err - } - return printJSON(summary) -} - func runDiscoverPopulatedReferences(ctx context.Context, args []string) error { fs := flag.NewFlagSet("discover-populated-references", flag.ExitOnError) - opts := proto.PopulatedReferenceOptions{} - fs.StringVar(&opts.Backend, "backend", defaultBackend, "Backend: arango, surreal, or postgres") + opts := catalog.PopulatedReferenceOptions{} fs.StringVar(&opts.URL, "url", defaultURL, "Backend base URL") - fs.StringVar(&opts.Namespace, "namespace", defaultNS, "SurrealDB namespace") fs.StringVar(&opts.Database, "database", defaultDatabase, "Backend database") - fs.StringVar(&opts.Username, "username", "root", "Backend username") - fs.StringVar(&opts.Password, "password", "root", "Backend password") - fs.StringVar(&opts.AuthToken, "auth-token", "", "SurrealDB auth token; overrides username/password when set") fs.StringVar(&opts.Project, "project", defaultProject, "Project label") fs.StringVar(&opts.FromType, "from-type", "", "Optional source collection/resource type filter, for example Patient") fs.IntVar(&opts.CursorBatch, "cursor-batch-size", 1000, "Query cursor batch size") if err := fs.Parse(args); err != nil { return err } - results, err := proto.DiscoverPopulatedReferences(ctx, opts) + results, err := catalog.DiscoverPopulatedReferences(ctx, opts) if err != nil { return err } @@ -256,14 +113,9 @@ func runDiscoverPopulatedReferences(ctx context.Context, args []string) error { func runDiscoverPopulatedFields(ctx context.Context, args []string) error { fs := flag.NewFlagSet("discover-populated-fields", flag.ExitOnError) - opts := proto.PopulatedFieldOptions{} - fs.StringVar(&opts.Backend, "backend", defaultBackend, "Backend: arango, surreal, or postgres") + opts := catalog.PopulatedFieldOptions{} fs.StringVar(&opts.URL, "url", defaultURL, "Backend base URL") - fs.StringVar(&opts.Namespace, "namespace", defaultNS, "SurrealDB namespace") fs.StringVar(&opts.Database, "database", defaultDatabase, "Backend database") - fs.StringVar(&opts.Username, "username", "root", "Backend username") - fs.StringVar(&opts.Password, "password", "root", "Backend password") - fs.StringVar(&opts.AuthToken, "auth-token", "", "SurrealDB auth token; overrides username/password when set") fs.StringVar(&opts.Project, "project", defaultProject, "Project label") fs.StringVar(&opts.ResourceType, "resource-type", "", "Optional resource type filter, for example Patient") fs.BoolVar(&opts.PivotOnly, "pivot-only", false, "Return only pivot-candidate fields") @@ -271,7 +123,7 @@ func runDiscoverPopulatedFields(ctx context.Context, args []string) error { if err := fs.Parse(args); err != nil { return err } - results, err := proto.DiscoverPopulatedFields(ctx, opts) + results, err := catalog.DiscoverPopulatedFields(ctx, opts) if err != nil { return err } @@ -294,9 +146,6 @@ func usage() { arango-fhir-proto export-gdc-case-assay-matrix --output FILE [flags] arango-fhir-proto discover-populated-references [flags] arango-fhir-proto discover-populated-fields [flags] - arango-fhir-proto prepare-gdc-case-assay-matrix [flags] - arango-fhir-proto build-scalar-index [flags] - arango-fhir-proto benchmark [flags] `) } diff --git a/cmd/arango-fhir-server/main.go b/cmd/arango-fhir-server/main.go index 820e5e3..da86818 100644 --- a/cmd/arango-fhir-server/main.go +++ b/cmd/arango-fhir-server/main.go @@ -6,16 +6,16 @@ import ( "log/slog" "os" - "arangodb-proto/internal/catalogcache" - "arangodb-proto/internal/graphqlapi" - "arangodb-proto/internal/proto" - "arangodb-proto/internal/writeapi" + "github.com/calypr/loom/internal/api" + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/catalog/cache" + "github.com/calypr/loom/internal/graphqlapi" + "github.com/calypr/loom/internal/ingest" ) const ( - defaultBackend = "arango" defaultURL = "http://127.0.0.1:8529" - defaultNS = "fhir_proto" defaultDatabase = "fhir_proto" defaultSchema = "schemas/graph-fhir.json" ) @@ -23,19 +23,13 @@ const ( func main() { fs := flag.NewFlagSet("arango-fhir-server", flag.ExitOnError) listenAddr := fs.String("listen", ":8080", "HTTP listen address") - maxConcurrent := fs.Int("max-concurrent-imports", 1, "Maximum concurrent in-process imports") bodyLimit := fs.Int("body-limit", 1024*1024*1024, "Maximum request body size in bytes") readBufferSize := fs.Int("read-buffer-size", 1024*1024, "Fiber request read buffer size in bytes; also limits max header size") noAuth := fs.Bool("no-auth", false, "Disable scope-based auth for local demo use") - loadOpts := proto.LoadOptions{} - fs.StringVar(&loadOpts.Backend, "backend", defaultBackend, "Backend: arango, surreal, or postgres") + loadOpts := ingest.LoadOptions{} fs.StringVar(&loadOpts.URL, "url", defaultURL, "Backend base URL") - fs.StringVar(&loadOpts.Namespace, "namespace", defaultNS, "SurrealDB namespace") fs.StringVar(&loadOpts.Database, "database", defaultDatabase, "Backend database") - fs.StringVar(&loadOpts.Username, "username", "root", "Backend username") - fs.StringVar(&loadOpts.Password, "password", "root", "Backend password") - fs.StringVar(&loadOpts.AuthToken, "auth-token", "", "SurrealDB auth token; overrides username/password when set") fs.StringVar(&loadOpts.Schema, "schema", defaultSchema, "graph-fhir JSON schema") fs.IntVar(&loadOpts.BatchSize, "batch-size", 5000, "Bulk insert batch size") fs.IntVar(&loadOpts.ProgressEvery, "progress-every", 50000, "Emit progress every N input rows") @@ -49,25 +43,24 @@ func main() { } logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) - discoveryCache := catalogcache.New() - var scopeResolver *writeapi.ScopeResolver - authenticator := writeapi.Authenticator(writeapi.BearerTokenAuthenticator{}) - authorizer := writeapi.Authorizer(writeapi.ScopeAuthorizer{}) + discoveryCache := cache.New() + var scopeResolver *authscope.ScopeResolver + authenticator := authscope.Authenticator(authscope.BearerTokenAuthenticator{}) + authorizer := authscope.Authorizer(authscope.ScopeAuthorizer{}) if *noAuth { - authenticator = writeapi.StaticAuthenticator{ - Principal: writeapi.Principal{Subject: "local-demo"}, + authenticator = authscope.StaticAuthenticator{ + Principal: authscope.Principal{Subject: "local-demo"}, } - authorizer = writeapi.AllowAllAuthorizer{} + authorizer = authscope.AllowAllAuthorizer{} } else { - scopeResolver = writeapi.NewScopeResolver(writeapi.ScopeResolverConfig{ + scopeResolver = authscope.NewScopeResolver(authscope.ScopeResolverConfig{ ConnectionOptions: loadOpts.ConnectionOptions, }) - authorizer = writeapi.ScopeAuthorizer{Resolver: scopeResolver} + authorizer = authscope.ScopeAuthorizer{Resolver: scopeResolver} } - service, err := writeapi.NewService(writeapi.ServiceConfig{ - Runner: writeapi.ProtoRunner{BaseOptions: loadOpts}, - Logger: logger, - MaxConcurrent: *maxConcurrent, + service, err := api.NewService(api.ServiceConfig{ + Runner: api.IngestRunner{BaseOptions: loadOpts}, + Logger: logger, OnSuccess: func(project string) { discoveryCache.InvalidateProject(project) if scopeResolver != nil { @@ -79,14 +72,14 @@ func main() { fmt.Fprintln(os.Stderr, err) os.Exit(1) } - graphService := graphqlapi.NewService(graphqlapi.ServiceConfig{ + graphResolver := graphqlapi.NewResolver(graphqlapi.ResolverConfig{ ConnectionOptions: loadOpts.ConnectionOptions, - DiscoverReferences: discoveryCache.DiscoverReferences(proto.DiscoverPopulatedReferences), - DiscoverFields: discoveryCache.DiscoverFields(proto.DiscoverPopulatedFields), + DiscoverReferences: discoveryCache.DiscoverReferences(catalog.DiscoverPopulatedReferences), + DiscoverFields: discoveryCache.DiscoverFields(catalog.DiscoverPopulatedFields), ScopeResolver: scopeResolver, }) - graphHandler := graphqlapi.NewHandler(graphqlapi.NewResolver(graphService)) - server, err := writeapi.NewHTTPServer(writeapi.HTTPConfig{ + graphHandler := graphqlapi.NewHandler(graphResolver) + server, err := api.NewHTTPServer(api.HTTPConfig{ Service: service, Authenticator: authenticator, Authorizer: authorizer, @@ -102,7 +95,7 @@ func main() { os.Exit(1) } - logger.Info("starting write api server", "listen", *listenAddr, "backend", loadOpts.Backend, "database", loadOpts.Database, "no_auth", *noAuth) + logger.Info("starting server", "listen", *listenAddr, "backend", "arango", "database", loadOpts.Database, "no_auth", *noAuth) if err := server.App().Listen(*listenAddr); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) diff --git a/cmd/generate/main.go b/cmd/generate/main.go index 9e69082..d5d826f 100644 --- a/cmd/generate/main.go +++ b/cmd/generate/main.go @@ -43,13 +43,19 @@ type Property struct { type Link struct { Rel string `json:"rel"` TargetHints TargetHints `json:"targetHints"` + TargetSchema TargetSchema `json:"targetSchema"` TemplatePointers TemplatePointers `json:"templatePointers"` } type TargetHints struct { - Backref []string `json:"backref"` - Direction []string `json:"direction"` - RegexMatch []string `json:"regex_match"` + Backref []string `json:"backref"` + Direction []string `json:"direction"` + Multiplicity []string `json:"multiplicity"` + RegexMatch []string `json:"regex_match"` +} + +type TargetSchema struct { + Ref string `json:"$ref"` } type TemplatePointers struct { @@ -1011,6 +1017,34 @@ func generateFHIRSchema(schema *Schema, path string) error { sb.WriteString("\t\t},\n") sb.WriteString("\t},\n") } + sb.WriteString("}\n\n") + sb.WriteString("var generatedTraversals = map[string]TraversalSpec{\n") + seenTraversalKeys := map[string]struct{}{} + for _, k := range keys { + def := schema.Defs[k] + if def == nil || len(def.Links) == 0 { + continue + } + for _, link := range def.Links { + toType := refName(link.TargetSchema.Ref) + if strings.TrimSpace(toType) == "" { + toType = targetTypeFromLabel(link.Rel) + } + if strings.TrimSpace(link.Rel) == "" || strings.TrimSpace(toType) == "" { + continue + } + forwardKey := traversalKey(k, link.Rel, toType) + if _, ok := seenTraversalKeys[forwardKey]; !ok { + writeGeneratedTraversal(&sb, k, link.Rel, toType, link, forwardKey) + seenTraversalKeys[forwardKey] = struct{}{} + } + reverseKey := traversalKey(toType, link.Rel, k) + if _, ok := seenTraversalKeys[reverseKey]; !ok { + writeGeneratedTraversal(&sb, toType, link.Rel, k, link, reverseKey) + seenTraversalKeys[reverseKey] = struct{}{} + } + } + } sb.WriteString("}\n") return os.WriteFile(path, []byte(sb.String()), 0644) } @@ -1113,6 +1147,39 @@ func writeGeneratedProperties(sb *strings.Builder, props map[string]*Property, i } } +func writeGeneratedStringSlice(sb *strings.Builder, fieldName string, values []string, indent int) { + writeIndent(sb, indent) + sb.WriteString(fieldName) + sb.WriteString(": []string{") + if len(values) == 0 { + sb.WriteString("},\n") + return + } + sb.WriteString("\n") + for _, value := range values { + writeIndent(sb, indent+1) + sb.WriteString(fmt.Sprintf("%q,\n", value)) + } + writeIndent(sb, indent) + sb.WriteString("},\n") +} + +func traversalKey(fromType, edgeLabel, toType string) string { + return fromType + "|" + edgeLabel + "|" + toType +} + +func writeGeneratedTraversal(sb *strings.Builder, fromType, edgeLabel, toType string, link Link, key string) { + sb.WriteString(fmt.Sprintf("\t%q: {\n", key)) + sb.WriteString(fmt.Sprintf("\t\tFromType: %q,\n", fromType)) + sb.WriteString(fmt.Sprintf("\t\tEdgeLabel: %q,\n", edgeLabel)) + sb.WriteString(fmt.Sprintf("\t\tToType: %q,\n", toType)) + writeGeneratedStringSlice(sb, "Direction", link.TargetHints.Direction, 2) + writeGeneratedStringSlice(sb, "Multiplicity", link.TargetHints.Multiplicity, 2) + writeGeneratedStringSlice(sb, "Backref", link.TargetHints.Backref, 2) + writeGeneratedStringSlice(sb, "RegexMatch", link.TargetHints.RegexMatch, 2) + sb.WriteString("\t},\n") +} + func writeIndent(sb *strings.Builder, n int) { for i := 0; i < n; i++ { sb.WriteString("\t") diff --git a/docs/DATAFRAME_BUILDER_PORTABILITY.md b/docs/DATAFRAME_BUILDER_PORTABILITY.md index a880ac4..24ff8b1 100644 --- a/docs/DATAFRAME_BUILDER_PORTABILITY.md +++ b/docs/DATAFRAME_BUILDER_PORTABILITY.md @@ -29,9 +29,9 @@ This is not a generic graph-builder schema. It is a builder contract for the specific graph and field surfaces already present in this repo: - populated references discovered from `fhir_edge`, as implemented in - [internal/proto/discovery.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/proto/discovery.go:9) + [internal/catalog/read_references.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/catalog/read_references.go) - populated canonical field paths and pivot metadata discovered at load time in - [internal/proto/field_catalog.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/proto/field_catalog.go:17) + [internal/catalog/write_profiler.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/catalog/write_profiler.go) - traversal and field-plucking behavior demonstrated by the live `gdc_case_assay_matrix` AQL in [queries/gdc_case_assay_matrix_arango_rows.aql](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/queries/gdc_case_assay_matrix_arango_rows.aql:1) @@ -51,7 +51,7 @@ The traversal surface is already represented in `fhir_edge` as: - `edge_count` That is the exact shape returned by -[internal/proto/discovery.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/proto/discovery.go:42), +[internal/catalog/read_references.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/catalog/read_references.go), which currently groups edges by `from_type`, `label`, and `to_type`. Example logical edges already used by the case-assay query: @@ -86,7 +86,7 @@ The field catalog already records observed canonical FHIR paths per This is the stored shape of `FieldCatalogDocument` in -[internal/proto/field_catalog.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/proto/field_catalog.go:29). +[internal/catalog/types.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/catalog/types.go). The path walker canonicalizes arrays with bracket wildcards such as: @@ -97,9 +97,9 @@ The path walker canonicalizes arrays with bracket wildcards such as: That behavior is implemented by `walkShapeValue`, `appendPath`, and `extractAccessorValues` in -[internal/proto/field_catalog.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/proto/field_catalog.go:362), +[internal/catalog/write_profiler.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/catalog/write_profiler.go), and tested in -[internal/proto/field_catalog_test.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/proto/field_catalog_test.go:7). +[internal/catalog/write_profiler_test.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/catalog/write_profiler_test.go). ### Pivot Semantics @@ -111,11 +111,11 @@ V1 pivot semantics already exist in the load-time field profiler: The current implementation marks a field as a pivot candidate when `classifyObjectShape` detects a `CodeableConcept`, via -[internal/proto/field_catalog.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/proto/field_catalog.go:439). +[internal/catalog/write_profiler.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/catalog/write_profiler.go). Observed pivot columns are accumulated by `addPivotColumn` in -[internal/proto/field_catalog.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/proto/field_catalog.go:249). +[internal/catalog/write_profiler.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/catalog/write_profiler.go). The expected behavior is tested in -[internal/proto/field_catalog_test.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/proto/field_catalog_test.go:92). +[internal/catalog/write_profiler_test.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/catalog/write_profiler_test.go). This contract draft keeps those semantics intact. It does not invent generalized pivoting beyond what the prototype already observes. @@ -586,7 +586,7 @@ as: - `pivot_columns` containing observed coding displays That exact behavior is tested in -[internal/proto/field_catalog_test.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/proto/field_catalog_test.go:92). +[internal/catalog/write_profiler_test.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/catalog/write_profiler_test.go). Example GraphQL mutation: diff --git a/docs/DEVELOPER_ARCHITECTURE.md b/docs/DEVELOPER_ARCHITECTURE.md index 34344f0..afa7bb4 100644 --- a/docs/DEVELOPER_ARCHITECTURE.md +++ b/docs/DEVELOPER_ARCHITECTURE.md @@ -46,14 +46,12 @@ The server entrypoint is: It wires together: - Fiber HTTP server -- REST bulk ingest service - GraphQL dataframe service -- discovery cache invalidation after successful writes - optional scope-aware auth for reads/writes Mounted routes are registered in: -- [`internal/writeapi/http.go`](../internal/writeapi/http.go) +- [`internal/api/routes.go`](../internal/api/routes.go) Current routes: @@ -61,15 +59,12 @@ Current routes: - `GET /graphql` - `POST /graphql` - `GET /apollo` -- `POST /api/v1/imports` -- `GET /api/v1/imports/:id` -- `GET /api/v1/imports/:id/events` ## 2. Storage Model The repo’s logical collections are defined in: -- [`internal/proto/backend.go`](../internal/proto/backend.go) +- [`internal/ingest/backend.go`](../internal/ingest/backend.go) Current primary collections: @@ -88,18 +83,17 @@ Important details: The common backend interface is: -- [`internal/store/store.go`](../internal/store/store.go) +- `internal/store/arango` -Arango is the main execution backend for reads. Backend selection is abstracted -through: +Arango is the only runtime backend. Connection setup lives in: -- [`internal/dbio/dbio.go`](../internal/dbio/dbio.go) +- [`internal/store/arango/`](../internal/store/arango/) ## 3. Load Pipeline The primary load implementation is: -- [`internal/proto/load.go`](../internal/proto/load.go) +- [`internal/ingest/load.go`](../internal/ingest/load.go) High-level flow: @@ -116,10 +110,11 @@ High-level flow: Key load-related pieces: -- [`internal/proto/files.go`](../internal/proto/files.go): NDJSON discovery and scanners -- [`internal/proto/row_builder.go`](../internal/proto/row_builder.go): generated vs generic row-builder surface -- [`internal/proto/generated_load.go`](../internal/proto/generated_load.go): generated fast-path extraction -- [`internal/catalog/field_catalog.go`](../internal/catalog/field_catalog.go): load-time field profiling +- [`internal/ingest/files.go`](../internal/ingest/files.go): NDJSON discovery and scanners +- [`internal/ingest/row_builder.go`](../internal/ingest/row_builder.go): generated vs generic row-builder surface +- [`internal/ingest/generated_load.go`](../internal/ingest/generated_load.go): generated fast-path extraction +- [`internal/catalog/write_profiler.go`](../internal/catalog/write_profiler.go): load-time field profiling +- [`internal/catalog/write_persist.go`](../internal/catalog/write_persist.go): field catalog persistence The loader can still run in a slower generic mode, but the intended fast path is the generated FHIR-specific path. @@ -133,9 +128,9 @@ Builder introspection depends on two discovery surfaces: These live in: -- [`internal/catalog/discovery.go`](../internal/catalog/discovery.go) -- [`internal/catalog/field_catalog.go`](../internal/catalog/field_catalog.go) -- [`internal/catalog/auth_resource_paths.go`](../internal/catalog/auth_resource_paths.go) +- [`internal/catalog/read_references.go`](../internal/catalog/read_references.go) +- [`internal/catalog/read_fields.go`](../internal/catalog/read_fields.go) +- [`internal/catalog/read_auth_paths.go`](../internal/catalog/read_auth_paths.go) Important behavior: @@ -147,7 +142,7 @@ Important behavior: The server wraps discovery in a cache: -- [`internal/catalogcache/cache.go`](../internal/catalogcache/cache.go) +- [`internal/catalog/cache/cache.go`](../internal/catalog/cache/cache.go) That cache is invalidated after successful writes by the server bootstrap code in: @@ -181,7 +176,7 @@ The GraphQL split is intentional: - dataframe execution mutation: - `runFhirDataframe` -GraphQL is the read/builder contract. It is not used for bulk ingest. +GraphQL is the read/builder contract. ## 6. FHIR Schema Metadata vs. FHIR Semantics @@ -236,10 +231,13 @@ The dataframe subsystem is: Current important files: -- [`internal/dataframe/dataframe.go`](../internal/dataframe/dataframe.go): service entrypoint, validation, auth-scope prep, compile/run orchestration +- [`internal/dataframe/service.go`](../internal/dataframe/service.go): service entrypoint and run orchestration +- [`internal/dataframe/validation.go`](../internal/dataframe/validation.go): builder and traversal validation against catalog discovery +- [`internal/dataframe/auth.go`](../internal/dataframe/auth.go): auth-scope and project authorization handling +- [`internal/dataframe/compile.go`](../internal/dataframe/compile.go): compiled query contract and compile entrypoint - [`internal/dataframe/planner.go`](../internal/dataframe/planner.go): request lowering and optimization planning -- [`internal/dataframe/advanced_types.go`](../internal/dataframe/advanced_types.go): advanced internal builder structures -- [`internal/dataframe/advanced_compile.go`](../internal/dataframe/advanced_compile.go): advanced lowered builder -> optimized AQL +- [`internal/dataframe/lowered_types.go`](../internal/dataframe/lowered_types.go): lowered internal builder structures +- [`internal/dataframe/lowered_compile.go`](../internal/dataframe/lowered_compile.go): lowered builder -> optimized AQL Current execution model: @@ -255,52 +253,38 @@ Important current truth: - optimizer complexity lives under the covers - Arango is the only supported runtime for `runFhirDataframe` -## 8. Query Execution Service +## 8. Query Execution -Direct query helpers and older query-oriented flows now live under: +Row-oriented AQL execution now lives with the dataframe runtime: -- [`internal/querysvc`](../internal/querysvc) +- [`internal/dataframe/query_runtime.go`](../internal/dataframe/query_runtime.go) -Key files: - -- [`internal/querysvc/query.go`](../internal/querysvc/query.go): direct query execution and bulk export helpers -- [`internal/querysvc/prepare_case_assay.go`](../internal/querysvc/prepare_case_assay.go): helper-table preparation -- [`internal/querysvc/build_scalar_index.go`](../internal/querysvc/build_scalar_index.go): scalar index build path - -This package is mostly for: - -- CLI-oriented query/export flows -- prepared helper surfaces -- benchmark support - -It is distinct from the GraphQL dataframe path, which compiles from the GraphQL -builder contract instead of simply reading a canned query file. +CLI-oriented canned query/export behavior lives with the CLI command surface: -## 9. REST Write API +- [`cmd/arango-fhir-proto/query.go`](../cmd/arango-fhir-proto/query.go) -Bulk ingest is intentionally REST-only. +This keeps the split honest: -Core files: +- `internal/dataframe` owns the callback-based row execution hook used by GraphQL/dataframe reads +- `cmd/arango-fhir-proto` owns file-based query/export command behavior and stdout/file shaping -- [`internal/writeapi/http.go`](../internal/writeapi/http.go) -- [`internal/writeapi/service.go`](../internal/writeapi/service.go) +## 9. HTTP/Auth Layer -Design choices: +The import HTTP server lives in: -- one uploaded NDJSON file per import request -- explicit `project` and `resource_type` -- async HTTP contract via operation polling -- in-process execution, not a distributed job system +- [`internal/api/routes.go`](../internal/api/routes.go) +- [`internal/api/service.go`](../internal/api/service.go) +- [`internal/authscope/principal.go`](../internal/authscope/principal.go) +- [`internal/authscope/scope.go`](../internal/authscope/scope.go) -The server persists minimal operation state in memory: +The API package now owns: -- operation metadata -- status -- event stream -- load summary +- Fiber app construction +- request ID / recovery / logging / auth middleware +- principal extraction and request context propagation +- scope resolution for GraphQL auth-aware reads -This is enough for workflow-runner orchestration without turning this service -into a scheduler. +It no longer exposes import job endpoints. ## 10. Experimental Code @@ -350,12 +334,12 @@ If you want to: - then run `make generate-graphql` - change dataframe lowering or optimization: - [`internal/dataframe/planner.go`](../internal/dataframe/planner.go) - - [`internal/dataframe/advanced_compile.go`](../internal/dataframe/advanced_compile.go) -- change bulk ingest HTTP behavior: - - [`internal/writeapi/http.go`](../internal/writeapi/http.go) - - [`internal/writeapi/service.go`](../internal/writeapi/service.go) + - [`internal/dataframe/lowered_compile.go`](../internal/dataframe/lowered_compile.go) +- change HTTP middleware or auth wiring: + - [`internal/api/routes.go`](../internal/api/routes.go) + - [`internal/authscope/scope.go`](../internal/authscope/scope.go) - change backend bootstrap/index strategy: - - [`internal/proto/backend.go`](../internal/proto/backend.go) + - [`internal/ingest/backend.go`](../internal/ingest/backend.go) ## 13. Current Reality Check diff --git a/docs/QUICKSTART.md b/docs/QUICKSTART.md index 894a232..d0c99bb 100644 --- a/docs/QUICKSTART.md +++ b/docs/QUICKSTART.md @@ -66,7 +66,7 @@ What this does: - profiles populated fields for builder introspection The bootstrap and collection definitions live in -[`internal/proto/backend.go`](../internal/proto/backend.go). +[`internal/ingest/backend.go`](../internal/ingest/backend.go). ## 4. Start the HTTP server @@ -348,19 +348,7 @@ Notes: - the server validates selectors/traversals against populated-field and populated-reference discovery - `fieldRef` is the preferred frontend-friendly path when available -## 7. Optional: test the REST write API - -The server also exposes a write/import API: - -- `POST /api/v1/imports` -- `GET /api/v1/imports/:id` -- `GET /api/v1/imports/:id/events` - -The REST surface is for bulk NDJSON ingest. GraphQL is for reads/dataframing. - -The HTTP registration lives in [`internal/writeapi/http.go`](../internal/writeapi/http.go). - -## 8. Shut down local Arango +## 7. Shut down local Arango ```bash rtk docker compose -f experimental/docker-compose.yml down diff --git a/experimental/README.md b/experimental/README.md new file mode 100644 index 0000000..3463830 --- /dev/null +++ b/experimental/README.md @@ -0,0 +1,13 @@ +# Experimental Benchmarks + +This directory is now Arango-only. + +Use it for benchmark helper scripts, benchmark notes, and other non-runtime +artifacts that support the main Arango path. + +The primary runtime lives at: + +- root [`docker-compose.yml`](../docker-compose.yml) +- [`queries/`](../queries/) +- [`internal/store/arango/`](../internal/store/arango/) +- [`internal/ingest/`](../internal/ingest/) diff --git a/experimental/docker-compose.yml b/experimental/docker-compose.yml new file mode 100644 index 0000000..975e888 --- /dev/null +++ b/experimental/docker-compose.yml @@ -0,0 +1,10 @@ +services: + arangodb: + image: arangodb:3.12 + container_name: github.com/calypr/loom + environment: + ARANGO_NO_AUTH: "1" + ports: + - "8529:8529" + volumes: + - ./data:/var/lib/arangodb3 diff --git a/go.mod b/go.mod index 5551a1d..40d8f97 100644 --- a/go.mod +++ b/go.mod @@ -1,20 +1,19 @@ -module arangodb-proto +module github.com/calypr/loom go 1.25.0 require ( + github.com/99designs/gqlgen v0.17.66 github.com/arangodb/go-driver/v2 v2.3.1 github.com/bmeg/jsonschema/v6 v6.0.4 github.com/bmeg/jsonschemagraph v0.0.4-0.20250828230703-257ca9afd85a github.com/bytedance/sonic v1.15.2 github.com/gofiber/fiber/v3 v3.3.0 github.com/google/uuid v1.6.0 - github.com/jackc/pgx/v5 v5.7.2 - github.com/surrealdb/surrealdb.go v1.4.0 + github.com/vektah/gqlparser/v2 v2.5.22 ) require ( - github.com/99designs/gqlgen v0.17.66 // indirect github.com/agnivade/levenshtein v1.2.0 // indirect github.com/andybalholm/brotli v1.2.1 // indirect github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e // indirect @@ -22,22 +21,16 @@ require ( github.com/bytedance/gopkg v0.1.3 // indirect github.com/bytedance/sonic/loader v0.5.1 // indirect github.com/cloudwego/base64x v0.1.6 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/dchest/siphash v1.2.3 // indirect - github.com/fxamacker/cbor/v2 v2.9.2 // indirect github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/gofiber/schema v1.7.1 // indirect github.com/gofiber/utils/v2 v2.0.6 // indirect - github.com/gofrs/uuid v4.4.0+incompatible // indirect github.com/gorilla/websocket v1.5.3 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect - github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect - github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/kkdai/maglev v0.2.0 // indirect github.com/klauspost/compress v1.18.6 // indirect github.com/klauspost/cpuid/v2 v2.2.9 // indirect @@ -50,30 +43,21 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rs/zerolog v1.34.0 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sosodev/duration v1.3.1 // indirect github.com/tinylib/msgp v1.6.4 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/urfave/cli/v2 v2.27.5 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.71.0 // indirect - github.com/vektah/gqlparser/v2 v2.5.22 // indirect - github.com/x448/float16 v0.8.4 // indirect - github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect golang.org/x/crypto v0.51.0 // indirect - golang.org/x/mod v0.35.0 // indirect golang.org/x/net v0.54.0 // indirect - golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.44.0 // indirect golang.org/x/term v0.43.0 // indirect golang.org/x/text v0.37.0 // indirect - golang.org/x/tools v0.44.0 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect google.golang.org/grpc v1.71.0 // indirect google.golang.org/protobuf v1.36.7 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/bmeg/jsonschemagraph => /Users/peterkor/Desktop/BMEG/jsonschemagraph diff --git a/go.sum b/go.sum index 0a51ff5..87a35d7 100644 --- a/go.sum +++ b/go.sum @@ -2,14 +2,22 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT github.com/99designs/gqlgen v0.17.66 h1:2/SRc+h3115fCOZeTtsqrB5R5gTGm+8qCAwcrZa+CXA= github.com/99designs/gqlgen v0.17.66/go.mod h1:gucrb5jK5pgCKzAGuOMMVU9C8PnReecHEHd2UxLQwCg= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/PuerkitoBio/goquery v1.9.3 h1:mpJr/ikUA9/GNJB/DBZcGeFDXUtosHRyRrwh7KGdTG0= +github.com/PuerkitoBio/goquery v1.9.3/go.mod h1:1ndLHPdTz+DyQPICCWYlYQMPl0oXZj0G6D4LCYA6u4U= github.com/agnivade/levenshtein v1.2.0 h1:U9L4IOT0Y3i0TIlUIDJ7rVUziKi/zPbrJGaFrtYH3SY= github.com/agnivade/levenshtein v1.2.0/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.2.1 h1:R+f5xP285VArJDRgowrfb9DqL18yVK0gKAW/F+eTWro= github.com/andybalholm/brotli v1.2.1/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY= +github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss= +github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU= github.com/arangodb/go-driver/v2 v2.3.1 h1:km44FjBl6Uh+rD+0mPLLCkOv7QNOTl460Eid7jwQFMQ= github.com/arangodb/go-driver/v2 v2.3.1/go.mod h1:Mi++s/SLvrrXKmLpAy84ivZ3fuyUBPu7ydmyJo3PMlk= github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e h1:Xg+hGrY2LcQBbxd0ZFdbGSyRKTYMZCfBbw/pMJFOk1g= github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e/go.mod h1:mq7Shfa/CaixoDxiyAAc5jZ6CVBAyPaNQCGS7mkj4Ho= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/bmeg/grip v0.0.0-20250915204302-93cb1e8117c8 h1:UhgcpVbQuvqg8KJ0ioB4i/KaQw1Zel34oHKjSENPEIA= github.com/bmeg/grip v0.0.0-20250915204302-93cb1e8117c8/go.mod h1:mIN98ALRqqjqRHqopIuZ9iDJ97w4gAzXqdKE6Enuu7Y= @@ -25,8 +33,6 @@ github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= -github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -34,10 +40,10 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/dchest/siphash v1.2.2/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4= github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA= github.com/dchest/siphash v1.2.3/go.mod h1:0NvQU092bT0ipiFN++/rXm69QG9tVxLAlQHIXMPAkHc= +github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54 h1:SG7nF6SRlWhcT7cNTs5R6Hk4V2lcmLz2NsG2VnInyNo= +github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= github.com/dlclark/regexp2 v1.11.2 h1:/u628IuisSTwri5/UKloiIsH8+qF2Pu7xEQX+yIKg68= github.com/dlclark/regexp2 v1.11.2/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/dolthub/maphash v0.1.0 h1:bsQ7JsF4FkkWyrP3oCnFJgrCUAFbFf3kOl4L/QxPDyQ= -github.com/dolthub/maphash v0.1.0/go.mod h1:gkg4Ch4CdCDu5h6PMriVLawB7koZ+5ijb9puGMV50a4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -60,11 +66,7 @@ github.com/gofiber/schema v1.7.1 h1:oSJBKdgP8JeIME4TQSAqlNKTU2iBB+2RNmKi8Nsc+TI= github.com/gofiber/schema v1.7.1/go.mod h1:A/X5Ffyru4p9eBdp99qu+nzviHzQiZ7odLT+TwxWhbk= github.com/gofiber/utils/v2 v2.0.6 h1:7fXYy7nSsyqbH0GQUMtK4Kwjy4J7R5742VM7JsZxzOs= github.com/gofiber/utils/v2 v2.0.6/go.mod h1:p7mAHAk3+oUK10ZX2xTw9fZQixb4hCg8SKd4IH2xroU= -github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= -github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= -github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -90,14 +92,6 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= -github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= -github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= -github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.7.2 h1:mLoDLV6sonKlvjIEsV56SkWNCnuNv531l94GaIzO+XI= -github.com/jackc/pgx/v5 v5.7.2/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ= -github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= -github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/maglev v0.2.0 h1:w6DCW0kAA6fstZqXkrBrlgIC3jeIRXkjOYea/m6EK/Y= @@ -116,8 +110,6 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= -github.com/lxzan/gws v1.8.9 h1:VU3SGUeWlQrEwfUSfokcZep8mdg/BrUF+y73YYshdBM= -github.com/lxzan/gws v1.8.9/go.mod h1:d9yHaR1eDTBHagQC6KY7ycUOaz5KWeqQtP3xu7aMK8Y= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= @@ -141,8 +133,8 @@ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99 github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/shamaton/msgpack/v3 v3.1.2 h1:d5gWAIyMU4M0WgDjz6IFSCuXJUA2dFwRHBpDclE8CLw= github.com/shamaton/msgpack/v3 v3.1.2/go.mod h1:DcQG8jrdrQCIxr3HlMYkiXdMhK+KfN2CitkyzsQV4uc= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -166,14 +158,10 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/surrealdb/surrealdb.go v1.4.0 h1:c3Tump5z+b1j27M6Puj0By59axd13ME2NFYptHiIdRw= -github.com/surrealdb/surrealdb.go v1.4.0/go.mod h1:ju3vn9OHXde9Ulvc7/fP9I8ylkiapOdBSdrEs2PmTtA= github.com/tinylib/msgp v1.6.4 h1:mOwYbyYDLPj35mkA2BjjYejgJk9BuHxDdvRnb6v2ZcQ= github.com/tinylib/msgp v1.6.4/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= -github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.71.0 h1:tepR7H+Guh9VUqxxcPggYi8R3lGUu2Rsdh+z7/FCY3k= @@ -182,8 +170,6 @@ github.com/vektah/gqlparser/v2 v2.5.22 h1:yaaeJ0fu+nv1vUMW0Hl+aS1eiv1vMfapBNjpff github.com/vektah/gqlparser/v2 v2.5.22/go.mod h1:xMl+ta8a5M1Yo1A1Iwt/k7gSpscwSnHZdw7tfhEGfTM= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= -github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -218,8 +204,6 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= -golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -236,8 +220,6 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= -golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -265,8 +247,6 @@ golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= -golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/api/doc.go b/internal/api/doc.go new file mode 100644 index 0000000..7d61328 --- /dev/null +++ b/internal/api/doc.go @@ -0,0 +1,2 @@ +// Package api owns the HTTP API surface and import ingest orchestration. +package api diff --git a/internal/writeapi/http_test.go b/internal/api/http_test.go similarity index 83% rename from internal/writeapi/http_test.go rename to internal/api/http_test.go index 64c6b83..2ff797f 100644 --- a/internal/writeapi/http_test.go +++ b/internal/api/http_test.go @@ -1,4 +1,4 @@ -package writeapi +package api import ( "bytes" @@ -12,18 +12,19 @@ import ( "strings" "testing" - "arangodb-proto/internal/proto" + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/ingest" ) type denyAuthorizer struct{} -func (denyAuthorizer) AuthorizeWrite(ctx context.Context, principal *Principal, project, authResourcePath string) error { +func (denyAuthorizer) AuthorizeWrite(ctx context.Context, principal *authscope.Principal, project, authResourcePath string) error { return errors.New("nope") } func TestCreateImportAccepted(t *testing.T) { svc, err := NewService(ServiceConfig{ - Runner: fakeRunner{summary: proto.LoadSummary{Files: 1, VerticesInserted: 2, EdgesInserted: 1}}, + Runner: fakeRunner{summary: ingest.LoadSummary{Files: 1, VerticesInserted: 2, EdgesInserted: 1}}, }) if err != nil { t.Fatal(err) @@ -44,7 +45,7 @@ func TestCreateImportAccepted(t *testing.T) { } defer resp.Body.Close() - if resp.StatusCode != http.StatusAccepted { + if resp.StatusCode != http.StatusOK { body, _ := io.ReadAll(resp.Body) t.Fatalf("status = %d, body = %s", resp.StatusCode, string(body)) } @@ -52,14 +53,21 @@ func TestCreateImportAccepted(t *testing.T) { if err := json.NewDecoder(resp.Body).Decode(&payload); err != nil { t.Fatal(err) } - if payload["import_id"] == "" { - t.Fatalf("missing import_id: %#v", payload) + if payload["resource_type"] != "Patient" { + t.Fatalf("unexpected payload: %#v", payload) + } + summary, ok := payload["summary"].(map[string]any) + if !ok { + t.Fatalf("missing summary: %#v", payload) + } + if summary["vertices_inserted"] != float64(2) { + t.Fatalf("unexpected summary: %#v", summary) } } func TestCreateImportRejectsMissingProject(t *testing.T) { svc, err := NewService(ServiceConfig{ - Runner: fakeRunner{summary: proto.LoadSummary{Files: 1}}, + Runner: fakeRunner{summary: ingest.LoadSummary{Files: 1}}, }) if err != nil { t.Fatal(err) @@ -85,7 +93,7 @@ func TestCreateImportRejectsMissingProject(t *testing.T) { func TestCreateImportRejectsUnauthorized(t *testing.T) { svc, err := NewService(ServiceConfig{ - Runner: fakeRunner{summary: proto.LoadSummary{Files: 1}}, + Runner: fakeRunner{summary: ingest.LoadSummary{Files: 1}}, }) if err != nil { t.Fatal(err) @@ -116,7 +124,7 @@ func TestCreateImportRejectsUnauthorized(t *testing.T) { func TestCreateImportRejectsUnsupportedMediaType(t *testing.T) { svc, err := NewService(ServiceConfig{ - Runner: fakeRunner{summary: proto.LoadSummary{Files: 1}}, + Runner: fakeRunner{summary: ingest.LoadSummary{Files: 1}}, }) if err != nil { t.Fatal(err) @@ -141,7 +149,7 @@ func TestCreateImportRejectsUnsupportedMediaType(t *testing.T) { func TestApolloSandboxRouteServed(t *testing.T) { svc, err := NewService(ServiceConfig{ - Runner: fakeRunner{summary: proto.LoadSummary{Files: 1}}, + Runner: fakeRunner{summary: ingest.LoadSummary{Files: 1}}, }) if err != nil { t.Fatal(err) diff --git a/internal/api/import_route.go b/internal/api/import_route.go new file mode 100644 index 0000000..258147a --- /dev/null +++ b/internal/api/import_route.go @@ -0,0 +1,130 @@ +package api + +import ( + "fmt" + "io" + "mime/multipart" + "os" + "path/filepath" + "strconv" + "strings" + + "github.com/calypr/loom/internal/authscope" + + "github.com/gofiber/fiber/v3" +) + +func (s *HTTPServer) createImport(c fiber.Ctx) error { + if !c.IsMultipart() { + return &apiError{Status: fiber.StatusUnsupportedMediaType, Code: "unsupported_media_type", Message: "expected multipart/form-data"} + } + form, err := c.Req().MultipartForm() + if err != nil { + return &apiError{Status: fiber.StatusBadRequest, Code: "invalid_multipart_form", Message: err.Error()} + } + fileCount := 0 + for _, files := range form.File { + fileCount += len(files) + } + if fileCount != 1 { + return &apiError{Status: fiber.StatusBadRequest, Code: "invalid_file_count", Message: "exactly one uploaded file is required"} + } + + project := strings.TrimSpace(c.Req().FormValue("project")) + if project == "" { + return &apiError{Status: fiber.StatusBadRequest, Code: "missing_project", Message: "project is required"} + } + resourceType := strings.TrimSpace(c.Req().FormValue("resource_type")) + if resourceType == "" { + return &apiError{Status: fiber.StatusBadRequest, Code: "missing_resource_type", Message: "resource_type is required"} + } + authResourcePath := strings.TrimSpace(c.Req().FormValue("auth_resource_path")) + truncate, err := parseOptionalBool(c.Req().FormValue("truncate")) + if err != nil { + return &apiError{Status: fiber.StatusBadRequest, Code: "invalid_truncate", Message: err.Error()} + } + useGeneric, err := parseOptionalBool(c.Req().FormValue("use_generic")) + if err != nil { + return &apiError{Status: fiber.StatusBadRequest, Code: "invalid_use_generic", Message: err.Error()} + } + + principal, _ := c.Locals("principal").(*authscope.Principal) + if err := s.authz.AuthorizeWrite(c.Context(), principal, project, authResourcePath); err != nil { + return &apiError{Status: fiber.StatusForbidden, Code: "forbidden", Message: err.Error()} + } + + fileHeader, err := c.Req().FormFile("file") + if err != nil { + return &apiError{Status: fiber.StatusBadRequest, Code: "missing_file", Message: "file upload is required"} + } + stagedPath, err := stageUploadedFile(fileHeader) + if err != nil { + return &apiError{Status: fiber.StatusInternalServerError, Code: "stage_failed", Message: err.Error()} + } + defer os.Remove(stagedPath) + + req := ImportRequest{ + Project: project, + ResourceType: resourceType, + AuthResourcePath: authResourcePath, + Truncate: truncate, + UseGeneric: useGeneric, + StagedFilePath: stagedPath, + OriginalFilename: fileHeader.Filename, + } + if principal != nil { + req.SubmittedBy = principal.Subject + } + result, err := s.service.Run(c.Context(), req) + if err != nil { + return &apiError{Status: fiber.StatusBadRequest, Code: "invalid_import_request", Message: err.Error()} + } + + return c.Status(fiber.StatusOK).JSON(fiber.Map{ + "project": result.Project, + "resource_type": result.ResourceType, + "auth_resource_path": result.AuthResourcePath, + "original_filename": result.OriginalFilename, + "submitted_by": result.SubmittedBy, + "summary": result.Summary, + }) +} + +func parseOptionalBool(raw string) (bool, error) { + raw = strings.TrimSpace(raw) + if raw == "" { + return false, nil + } + value, err := strconv.ParseBool(raw) + if err != nil { + return false, fmt.Errorf("invalid boolean value %q", raw) + } + return value, nil +} + +func stageUploadedFile(fileHeader *multipart.FileHeader) (string, error) { + src, err := fileHeader.Open() + if err != nil { + return "", err + } + defer src.Close() + + ext := filepath.Ext(fileHeader.Filename) + if ext == "" { + ext = ".ndjson" + } + dst, err := os.CreateTemp("", "arango-fhir-upload-*"+ext) + if err != nil { + return "", err + } + if _, err := io.Copy(dst, src); err != nil { + dst.Close() + os.Remove(dst.Name()) + return "", err + } + if err := dst.Close(); err != nil { + os.Remove(dst.Name()) + return "", err + } + return dst.Name(), nil +} diff --git a/internal/api/middleware.go b/internal/api/middleware.go new file mode 100644 index 0000000..f3c0588 --- /dev/null +++ b/internal/api/middleware.go @@ -0,0 +1,61 @@ +package api + +import ( + "errors" + "time" + + "github.com/calypr/loom/internal/authscope" + + "github.com/gofiber/fiber/v3" + "github.com/google/uuid" +) + +func (s *HTTPServer) requestIDMiddleware(c fiber.Ctx) error { + requestID := c.Get("X-Request-ID") + if requestID == "" { + requestID = uuid.NewString() + } + c.Locals("request_id", requestID) + c.Set("X-Request-ID", requestID) + return c.Next() +} + +func (s *HTTPServer) recoveryMiddleware(c fiber.Ctx) (err error) { + defer func() { + if recovered := recover(); recovered != nil { + s.logger.Error("panic recovered", "request_id", requestIDFromCtx(c), "path", c.Path(), "panic", recovered) + err = &apiError{Status: fiber.StatusInternalServerError, Code: "internal_error", Message: "internal server error"} + } + }() + return c.Next() +} + +func (s *HTTPServer) loggingMiddleware(c fiber.Ctx) error { + start := time.Now() + err := c.Next() + if err != nil { + var apiErr *apiError + if errors.As(err, &apiErr) && c.Response().StatusCode() < 400 { + c.Status(apiErr.Status) + } + } + s.logger.Info("http request", "request_id", requestIDFromCtx(c), "method", c.Method(), "path", c.Path(), "status", c.Response().StatusCode(), "duration_ms", time.Since(start).Milliseconds()) + return err +} + +func (s *HTTPServer) authenticationMiddleware(c fiber.Ctx) error { + principal, err := s.authn.Authenticate(c.Context(), c.GetReqHeaders()) + if err != nil { + return &apiError{Status: fiber.StatusUnauthorized, Code: "unauthorized", Message: err.Error()} + } + c.Locals("principal", principal) + c.SetContext(authscope.ContextWithPrincipal(c.Context(), principal)) + return c.Next() +} + +func requestIDFromCtx(c fiber.Ctx) string { + if requestID, ok := c.Locals("request_id").(string); ok && requestID != "" { + return requestID + } + return "" +} diff --git a/internal/api/routes.go b/internal/api/routes.go new file mode 100644 index 0000000..b27de1b --- /dev/null +++ b/internal/api/routes.go @@ -0,0 +1,36 @@ +package api + +import ( + "github.com/gofiber/fiber/v3" + "github.com/gofiber/fiber/v3/middleware/adaptor" +) + +func (s *HTTPServer) register() { + s.app.Use(s.requestIDMiddleware, s.recoveryMiddleware, s.loggingMiddleware, s.authenticationMiddleware) + s.registerHealthRoutes() + s.registerGraphQLRoutes() + s.registerImportRoutes() +} + +func (s *HTTPServer) registerHealthRoutes() { + s.app.Get("/healthz", func(c fiber.Ctx) error { + return c.Status(fiber.StatusOK).JSON(fiber.Map{"status": "ok"}) + }) +} + +func (s *HTTPServer) registerGraphQLRoutes() { + if s.cfgGraphQLPlaygroundHandler != nil { + s.app.Get("/graphql", adaptor.HTTPHandlerWithContext(s.cfgGraphQLPlaygroundHandler)) + } + if s.cfgApolloSandboxHandler != nil { + s.app.Get("/apollo", adaptor.HTTPHandlerWithContext(s.cfgApolloSandboxHandler)) + } + if s.cfgGraphQLHandler != nil { + s.app.Post("/graphql", adaptor.HTTPHandlerWithContext(s.cfgGraphQLHandler)) + } +} + +func (s *HTTPServer) registerImportRoutes() { + api := s.app.Group("/api/v1") + api.Post("/imports", s.createImport) +} diff --git a/internal/api/server.go b/internal/api/server.go new file mode 100644 index 0000000..d346f91 --- /dev/null +++ b/internal/api/server.go @@ -0,0 +1,107 @@ +package api + +import ( + "errors" + "log/slog" + "net/http" + + "github.com/calypr/loom/internal/authscope" + + "github.com/gofiber/fiber/v3" +) + +type HTTPConfig struct { + Service *Service + Authenticator authscope.Authenticator + Authorizer authscope.Authorizer + GraphQLHandler http.Handler + GraphQLPlaygroundHandler http.Handler + ApolloSandboxHandler http.Handler + Logger *slog.Logger + BodyLimit int + ReadBufferSize int +} + +type HTTPServer struct { + app *fiber.App + service *Service + authn authscope.Authenticator + authz authscope.Authorizer + logger *slog.Logger + cfgGraphQLHandler http.Handler + cfgGraphQLPlaygroundHandler http.Handler + cfgApolloSandboxHandler http.Handler +} + +type apiError struct { + Status int + Code string + Message string +} + +func (e *apiError) Error() string { return e.Message } + +type errorEnvelope struct { + Error errorBody `json:"error"` +} + +type errorBody struct { + Code string `json:"code"` + Message string `json:"message"` + RequestID string `json:"request_id,omitempty"` +} + +func NewHTTPServer(cfg HTTPConfig) (*HTTPServer, error) { + if cfg.Service == nil { + return nil, errors.New("service is required") + } + if cfg.Authenticator == nil { + cfg.Authenticator = authscope.BearerTokenAuthenticator{} + } + if cfg.Authorizer == nil { + cfg.Authorizer = authscope.AllowAllAuthorizer{} + } + if cfg.Logger == nil { + cfg.Logger = slog.Default() + } + if cfg.BodyLimit <= 0 { + cfg.BodyLimit = 1024 * 1024 * 1024 + } + if cfg.ReadBufferSize <= 0 { + cfg.ReadBufferSize = 1024 * 1024 + } + + server := &HTTPServer{ + service: cfg.Service, + authn: cfg.Authenticator, + authz: cfg.Authorizer, + logger: cfg.Logger, + cfgGraphQLHandler: cfg.GraphQLHandler, + cfgGraphQLPlaygroundHandler: cfg.GraphQLPlaygroundHandler, + cfgApolloSandboxHandler: cfg.ApolloSandboxHandler, + } + app := fiber.New(fiber.Config{ + BodyLimit: cfg.BodyLimit, + ReadBufferSize: cfg.ReadBufferSize, + ErrorHandler: func(c fiber.Ctx, err error) error { + requestID := requestIDFromCtx(c) + var apiErr *apiError + if errors.As(err, &apiErr) { + return c.Status(apiErr.Status).JSON(errorEnvelope{ + Error: errorBody{Code: apiErr.Code, Message: apiErr.Message, RequestID: requestID}, + }) + } + server.logger.Error("unhandled request error", "request_id", requestID, "path", c.Path(), "error", err.Error()) + return c.Status(fiber.StatusInternalServerError).JSON(errorEnvelope{ + Error: errorBody{Code: "internal_error", Message: "internal server error", RequestID: requestID}, + }) + }, + }) + server.app = app + server.register() + return server, nil +} + +func (s *HTTPServer) App() *fiber.App { + return s.app +} diff --git a/internal/api/service.go b/internal/api/service.go new file mode 100644 index 0000000..db59a71 --- /dev/null +++ b/internal/api/service.go @@ -0,0 +1,104 @@ +package api + +import ( + "context" + "errors" + "log/slog" + + "github.com/calypr/loom/internal/ingest" +) + +type ImportRequest struct { + Project string `json:"project"` + ResourceType string `json:"resource_type"` + AuthResourcePath string `json:"auth_resource_path,omitempty"` + Truncate bool `json:"truncate"` + UseGeneric bool `json:"use_generic"` + StagedFilePath string `json:"-"` + OriginalFilename string `json:"original_filename"` + SubmittedBy string `json:"submitted_by,omitempty"` +} + +type ImportResult struct { + Project string `json:"project"` + ResourceType string `json:"resource_type"` + AuthResourcePath string `json:"auth_resource_path,omitempty"` + OriginalFilename string `json:"original_filename"` + SubmittedBy string `json:"submitted_by,omitempty"` + Summary *ingest.LoadSummary `json:"summary,omitempty"` +} + +type Runner interface { + Run(ctx context.Context, req ImportRequest, sink ingest.EventSink) (ingest.LoadSummary, error) +} + +type IngestRunner struct { + BaseOptions ingest.LoadOptions +} + +func (r IngestRunner) Run(ctx context.Context, req ImportRequest, sink ingest.EventSink) (ingest.LoadSummary, error) { + opts := r.BaseOptions + opts.Project = req.Project + opts.AuthResourcePath = req.AuthResourcePath + opts.Truncate = req.Truncate + opts.UseGeneric = req.UseGeneric + opts.EventSink = sink + return ingest.LoadSingleResourceFile(ctx, opts, req.ResourceType, req.StagedFilePath) +} + +type ServiceConfig struct { + Runner Runner + Logger *slog.Logger + OnSuccess func(project string) +} + +type Service struct { + runner Runner + logger *slog.Logger + onSuccess func(project string) +} + +func NewService(cfg ServiceConfig) (*Service, error) { + if cfg.Runner == nil { + return nil, errors.New("runner is required") + } + if cfg.Logger == nil { + cfg.Logger = slog.Default() + } + return &Service{ + runner: cfg.Runner, + logger: cfg.Logger, + onSuccess: cfg.OnSuccess, + }, nil +} + +func (s *Service) Run(ctx context.Context, req ImportRequest) (*ImportResult, error) { + if req.Project == "" { + return nil, errors.New("project is required") + } + if req.ResourceType == "" { + return nil, errors.New("resource_type is required") + } + if req.StagedFilePath == "" { + return nil, errors.New("staged file path is required") + } + + summary, err := s.runner.Run(ctx, req, nil) + if err != nil { + s.logger.Error("import failed", "project", req.Project, "resource_type", req.ResourceType, "error", err.Error()) + return nil, err + } + if s.onSuccess != nil { + s.onSuccess(req.Project) + } + s.logger.Info("import succeeded", "project", req.Project, "resource_type", req.ResourceType, "vertices", summary.VerticesInserted, "edges", summary.EdgesInserted) + summaryCopy := summary + return &ImportResult{ + Project: req.Project, + ResourceType: req.ResourceType, + AuthResourcePath: req.AuthResourcePath, + OriginalFilename: req.OriginalFilename, + SubmittedBy: req.SubmittedBy, + Summary: &summaryCopy, + }, nil +} diff --git a/internal/api/service_test.go b/internal/api/service_test.go new file mode 100644 index 0000000..f8a0b19 --- /dev/null +++ b/internal/api/service_test.go @@ -0,0 +1,76 @@ +package api + +import ( + "context" + "errors" + "testing" + + "github.com/calypr/loom/internal/ingest" +) + +type fakeRunner struct { + summary ingest.LoadSummary + err error +} + +func (r fakeRunner) Run(ctx context.Context, req ImportRequest, sink ingest.EventSink) (ingest.LoadSummary, error) { + if r.err != nil { + return ingest.LoadSummary{}, r.err + } + return r.summary, nil +} + +func TestServiceRunSuccess(t *testing.T) { + var invalidated []string + svc, err := NewService(ServiceConfig{ + Runner: fakeRunner{summary: ingest.LoadSummary{Files: 1, VerticesInserted: 3, EdgesInserted: 5}}, + OnSuccess: func(project string) { + invalidated = append(invalidated, project) + }, + }) + if err != nil { + t.Fatal(err) + } + + result, err := svc.Run(context.Background(), ImportRequest{ + Project: "P1", + ResourceType: "Patient", + StagedFilePath: "/tmp/patient.ndjson", + OriginalFilename: "Patient.ndjson", + SubmittedBy: "tester", + }) + if err != nil { + t.Fatal(err) + } + if result.Summary == nil || result.Summary.VerticesInserted != 3 || result.Summary.EdgesInserted != 5 { + t.Fatalf("unexpected summary: %#v", result.Summary) + } + if len(invalidated) != 1 || invalidated[0] != "P1" { + t.Fatalf("invalidated = %#v", invalidated) + } +} + +func TestServiceRunFailure(t *testing.T) { + called := false + svc, err := NewService(ServiceConfig{ + Runner: fakeRunner{err: errors.New("boom")}, + OnSuccess: func(project string) { + called = true + }, + }) + if err != nil { + t.Fatal(err) + } + + _, err = svc.Run(context.Background(), ImportRequest{ + Project: "P1", + ResourceType: "Patient", + StagedFilePath: "/tmp/patient.ndjson", + }) + if err == nil { + t.Fatal("expected error") + } + if called { + t.Fatal("expected no invalidation on failure") + } +} diff --git a/internal/authscope/doc.go b/internal/authscope/doc.go new file mode 100644 index 0000000..7b0545a --- /dev/null +++ b/internal/authscope/doc.go @@ -0,0 +1,3 @@ +// Package authscope owns shared request principal context, bearer auth, +// and auth-resource-path scope resolution used by read and write surfaces. +package authscope diff --git a/internal/authscope/principal.go b/internal/authscope/principal.go new file mode 100644 index 0000000..56db2e2 --- /dev/null +++ b/internal/authscope/principal.go @@ -0,0 +1,54 @@ +package authscope + +import "context" + +type Principal struct { + Subject string `json:"subject"` + Claims map[string]string `json:"claims,omitempty"` + Projects []string `json:"projects,omitempty"` + AuthResourcePaths []string `json:"auth_resource_paths,omitempty"` + AuthorizationHeader string `json:"-"` +} + +type principalContextKey struct{} + +func ContextWithPrincipal(ctx context.Context, principal *Principal) context.Context { + if principal == nil { + return ctx + } + return context.WithValue(ctx, principalContextKey{}, principal) +} + +func PrincipalFromContext(ctx context.Context) (*Principal, bool) { + if ctx == nil { + return nil, false + } + principal, ok := ctx.Value(principalContextKey{}).(*Principal) + return principal, ok +} + +type Authenticator interface { + Authenticate(ctx context.Context, headers map[string][]string) (*Principal, error) +} + +type Authorizer interface { + AuthorizeWrite(ctx context.Context, principal *Principal, project, authResourcePath string) error +} + +type StaticAuthenticator struct { + Principal Principal +} + +func (a StaticAuthenticator) Authenticate(ctx context.Context, headers map[string][]string) (*Principal, error) { + principal := a.Principal + if principal.Subject == "" { + principal.Subject = "anonymous" + } + return &principal, nil +} + +type AllowAllAuthorizer struct{} + +func (AllowAllAuthorizer) AuthorizeWrite(ctx context.Context, principal *Principal, project, authResourcePath string) error { + return nil +} diff --git a/internal/writeapi/scope.go b/internal/authscope/scope.go similarity index 95% rename from internal/writeapi/scope.go rename to internal/authscope/scope.go index 10948d5..65242db 100644 --- a/internal/writeapi/scope.go +++ b/internal/authscope/scope.go @@ -1,4 +1,4 @@ -package writeapi +package authscope import ( "context" @@ -12,7 +12,8 @@ import ( "sync" "time" - "arangodb-proto/internal/proto" + "github.com/calypr/loom/internal/catalog" + arangostore "github.com/calypr/loom/internal/store/arango" ) type ResourceAccessClient interface { @@ -20,16 +21,16 @@ type ResourceAccessClient interface { } type ScopeResolverConfig struct { - ConnectionOptions proto.ConnectionOptions + ConnectionOptions arangostore.ConnectionOptions ResourceAccess ResourceAccessClient - ListExistingAuthResourcePaths func(context.Context, proto.AuthResourcePathOptions) ([]string, error) + ListExistingAuthResourcePaths func(context.Context, catalog.AuthResourcePathOptions) ([]string, error) CacheTTL time.Duration } type ScopeResolver struct { - connOpts proto.ConnectionOptions + connOpts arangostore.ConnectionOptions resourceAccess ResourceAccessClient - listExisting func(context.Context, proto.AuthResourcePathOptions) ([]string, error) + listExisting func(context.Context, catalog.AuthResourcePathOptions) ([]string, error) cacheTTL time.Duration mu sync.RWMutex @@ -62,7 +63,7 @@ func (a BearerTokenAuthenticator) Authenticate(ctx context.Context, headers map[ func NewScopeResolver(cfg ScopeResolverConfig) *ScopeResolver { if cfg.ListExistingAuthResourcePaths == nil { - cfg.ListExistingAuthResourcePaths = proto.DiscoverExistingAuthResourcePaths + cfg.ListExistingAuthResourcePaths = catalog.DiscoverExistingAuthResourcePaths } if cfg.CacheTTL <= 0 { cfg.CacheTTL = 30 * time.Second @@ -182,7 +183,7 @@ func (r *ScopeResolver) listExistingPaths(ctx context.Context, project string) ( if ok && now.Before(entry.expiresAt) { return cloneStrings(entry.paths), nil } - paths, err := r.listExisting(ctx, proto.AuthResourcePathOptions{ + paths, err := r.listExisting(ctx, catalog.AuthResourcePathOptions{ ConnectionOptions: r.connOpts, Project: project, }) diff --git a/internal/writeapi/scope_test.go b/internal/authscope/scope_test.go similarity index 85% rename from internal/writeapi/scope_test.go rename to internal/authscope/scope_test.go index 06b2679..da60c04 100644 --- a/internal/writeapi/scope_test.go +++ b/internal/authscope/scope_test.go @@ -1,10 +1,11 @@ -package writeapi +package authscope import ( "context" "testing" - "arangodb-proto/internal/proto" + "github.com/calypr/loom/internal/catalog" + arangostore "github.com/calypr/loom/internal/store/arango" ) type fakeResourceAccessClient struct { @@ -17,14 +18,14 @@ func (f fakeResourceAccessClient) GetAllowedResources(ctx context.Context, autho func TestScopeResolverResolveReadAuthResourcePathsIntersectsDBPaths(t *testing.T) { resolver := NewScopeResolver(ScopeResolverConfig{ - ConnectionOptions: proto.ConnectionOptions{Backend: "arango"}, + ConnectionOptions: arangostore.ConnectionOptions{}, ResourceAccess: fakeResourceAccessClient{ resources: []string{ "/programs/EllrottLab/projects/GDC_Data", "/programs/EllrottLab/projects/Other", }, }, - ListExistingAuthResourcePaths: func(ctx context.Context, opts proto.AuthResourcePathOptions) ([]string, error) { + ListExistingAuthResourcePaths: func(ctx context.Context, opts catalog.AuthResourcePathOptions) ([]string, error) { return []string{"EllrottLab-GDC_Data", "Another-Missing"}, nil }, }) @@ -42,11 +43,11 @@ func TestScopeResolverResolveReadAuthResourcePathsIntersectsDBPaths(t *testing.T func TestScopeResolverRejectsRequestedPathOutsideIntersection(t *testing.T) { resolver := NewScopeResolver(ScopeResolverConfig{ - ConnectionOptions: proto.ConnectionOptions{Backend: "arango"}, + ConnectionOptions: arangostore.ConnectionOptions{}, ResourceAccess: fakeResourceAccessClient{ resources: []string{"/programs/EllrottLab/projects/GDC_Data"}, }, - ListExistingAuthResourcePaths: func(ctx context.Context, opts proto.AuthResourcePathOptions) ([]string, error) { + ListExistingAuthResourcePaths: func(ctx context.Context, opts catalog.AuthResourcePathOptions) ([]string, error) { return []string{"EllrottLab-GDC_Data"}, nil }, }) @@ -62,7 +63,7 @@ func TestScopeResolverRejectsRequestedPathOutsideIntersection(t *testing.T) { func TestScopeAuthorizerRequiresScopedWritePath(t *testing.T) { authz := ScopeAuthorizer{ Resolver: NewScopeResolver(ScopeResolverConfig{ - ConnectionOptions: proto.ConnectionOptions{Backend: "arango"}, + ConnectionOptions: arangostore.ConnectionOptions{}, ResourceAccess: fakeResourceAccessClient{ resources: []string{"/programs/EllrottLab/projects/GDC_Data"}, }, diff --git a/internal/catalog/auth_resource_paths.go b/internal/catalog/auth_resource_paths.go deleted file mode 100644 index 1a6eb30..0000000 --- a/internal/catalog/auth_resource_paths.go +++ /dev/null @@ -1,98 +0,0 @@ -package catalog - -import ( - "context" - "time" - - "arangodb-proto/internal/dbio" -) - -type AuthResourcePathOptions struct { - dbio.ConnectionOptions - Project string - CursorBatch int -} - -const existingAuthResourcePathsAQL = ` -FOR d IN fhir_field_catalog - FILTER d.project == @project - FILTER d.auth_resource_path != null AND d.auth_resource_path != "" - COLLECT auth_resource_path = d.auth_resource_path - SORT auth_resource_path - RETURN auth_resource_path -` - -const existingAuthResourcePathsSurrealQL = ` -SELECT VALUE auth_resource_path -FROM fhir_field_catalog -WHERE project = $project - AND auth_resource_path != NONE - AND auth_resource_path != "" -GROUP ALL BY auth_resource_path -ORDER BY auth_resource_path ASC; -` - -const existingAuthResourcePathsPostgresSQL = ` -SELECT DISTINCT auth_resource_path -FROM fhir_field_catalog -WHERE project = @project - AND auth_resource_path IS NOT NULL - AND auth_resource_path <> '' -ORDER BY auth_resource_path ASC; -` - -func DiscoverExistingAuthResourcePaths(ctx context.Context, opts AuthResourcePathOptions) ([]string, error) { - if opts.CursorBatch <= 0 { - opts.CursorBatch = 1000 - } - client, err := dbio.OpenBackend(ctx, opts.ConnectionOptions) - if err != nil { - return nil, err - } - start := time.Now() - emit("go_discovery_start", map[string]any{ - "database": opts.Database, - "project": opts.Project, - "cursor_batch_size": opts.CursorBatch, - "query": "existing_auth_resource_paths", - }) - - query := existingAuthResourcePathsAQL - switch dbio.BackendName(opts.Backend) { - case dbio.BackendSurreal: - query = existingAuthResourcePathsSurrealQL - case dbio.BackendPostgres: - query = existingAuthResourcePathsPostgresSQL - } - results := make([]string, 0, 16) - err = client.QueryRows(ctx, query, opts.CursorBatch, map[string]any{"project": opts.Project}, func(row map[string]any) error { - if path := stringValue(row["auth_resource_path"]); path != "" { - results = append(results, path) - return nil - } - if value := stringValue(row["value"]); value != "" { - results = append(results, value) - } - return nil - }) - if err != nil { - return nil, err - } - emit("go_discovery_complete", map[string]any{ - "database": opts.Database, - "project": opts.Project, - "rows": len(results), - "seconds": secondsSince(start), - "query": "existing_auth_resource_paths", - }) - return results, nil -} - -func cloneStrings(in []string) []string { - if in == nil { - return nil - } - out := make([]string, len(in)) - copy(out, in) - return out -} diff --git a/internal/catalogcache/cache.go b/internal/catalog/cache/cache.go similarity index 61% rename from internal/catalogcache/cache.go rename to internal/catalog/cache/cache.go index ce83aee..085101f 100644 --- a/internal/catalogcache/cache.go +++ b/internal/catalog/cache/cache.go @@ -1,4 +1,4 @@ -package catalogcache +package cache import ( "context" @@ -8,24 +8,24 @@ import ( "strings" "sync" - "arangodb-proto/internal/proto" + "github.com/calypr/loom/internal/catalog" ) type Cache struct { mu sync.RWMutex - fields map[string][]proto.PopulatedField - references map[string][]proto.PopulatedReference + fields map[string][]catalog.PopulatedField + references map[string][]catalog.PopulatedReference } func New() *Cache { return &Cache{ - fields: make(map[string][]proto.PopulatedField), - references: make(map[string][]proto.PopulatedReference), + fields: make(map[string][]catalog.PopulatedField), + references: make(map[string][]catalog.PopulatedReference), } } -func (c *Cache) DiscoverFields(fn func(context.Context, proto.PopulatedFieldOptions) ([]proto.PopulatedField, error)) func(context.Context, proto.PopulatedFieldOptions) ([]proto.PopulatedField, error) { - return func(ctx context.Context, opts proto.PopulatedFieldOptions) ([]proto.PopulatedField, error) { +func (c *Cache) DiscoverFields(fn func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error)) func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + return func(ctx context.Context, opts catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { key, err := fieldKey(opts) if err != nil { return nil, err @@ -47,8 +47,8 @@ func (c *Cache) DiscoverFields(fn func(context.Context, proto.PopulatedFieldOpti } } -func (c *Cache) DiscoverReferences(fn func(context.Context, proto.PopulatedReferenceOptions) ([]proto.PopulatedReference, error)) func(context.Context, proto.PopulatedReferenceOptions) ([]proto.PopulatedReference, error) { - return func(ctx context.Context, opts proto.PopulatedReferenceOptions) ([]proto.PopulatedReference, error) { +func (c *Cache) DiscoverReferences(fn func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error)) func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + return func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { key, err := referenceKey(opts) if err != nil { return nil, err @@ -93,11 +93,11 @@ func (c *Cache) InvalidateProject(project string) { func (c *Cache) InvalidateAll() { c.mu.Lock() defer c.mu.Unlock() - c.fields = make(map[string][]proto.PopulatedField) - c.references = make(map[string][]proto.PopulatedReference) + c.fields = make(map[string][]catalog.PopulatedField) + c.references = make(map[string][]catalog.PopulatedReference) } -func fieldKey(opts proto.PopulatedFieldOptions) (string, error) { +func fieldKey(opts catalog.PopulatedFieldOptions) (string, error) { scope, err := authScopeKey(opts.AuthResourcePaths) if err != nil { return "", err @@ -105,7 +105,7 @@ func fieldKey(opts proto.PopulatedFieldOptions) (string, error) { return fmt.Sprintf("%s|%s|%t|%s", strings.TrimSpace(opts.Project), strings.TrimSpace(opts.ResourceType), opts.PivotOnly, scope), nil } -func referenceKey(opts proto.PopulatedReferenceOptions) (string, error) { +func referenceKey(opts catalog.PopulatedReferenceOptions) (string, error) { scope, err := authScopeKey(opts.AuthResourcePaths) if err != nil { return "", err @@ -126,11 +126,11 @@ func authScopeKey(paths []string) (string, error) { return string(encoded), nil } -func cloneFields(in []proto.PopulatedField) []proto.PopulatedField { +func cloneFields(in []catalog.PopulatedField) []catalog.PopulatedField { if len(in) == 0 { - return []proto.PopulatedField{} + return []catalog.PopulatedField{} } - out := make([]proto.PopulatedField, len(in)) + out := make([]catalog.PopulatedField, len(in)) for i := range in { out[i] = in[i] if in[i].DistinctValues != nil { @@ -143,11 +143,11 @@ func cloneFields(in []proto.PopulatedField) []proto.PopulatedField { return out } -func cloneReferences(in []proto.PopulatedReference) []proto.PopulatedReference { +func cloneReferences(in []catalog.PopulatedReference) []catalog.PopulatedReference { if len(in) == 0 { - return []proto.PopulatedReference{} + return []catalog.PopulatedReference{} } - out := make([]proto.PopulatedReference, len(in)) + out := make([]catalog.PopulatedReference, len(in)) copy(out, in) return out } diff --git a/internal/catalogcache/cache_test.go b/internal/catalog/cache/cache_test.go similarity index 70% rename from internal/catalogcache/cache_test.go rename to internal/catalog/cache/cache_test.go index 5dc8822..763177a 100644 --- a/internal/catalogcache/cache_test.go +++ b/internal/catalog/cache/cache_test.go @@ -1,21 +1,21 @@ -package catalogcache +package cache import ( "context" "testing" - "arangodb-proto/internal/proto" + "github.com/calypr/loom/internal/catalog" ) func TestCacheDiscoverFieldsCachesAndInvalidatesByProject(t *testing.T) { cache := New() calls := 0 - discover := cache.DiscoverFields(func(ctx context.Context, opts proto.PopulatedFieldOptions) ([]proto.PopulatedField, error) { + discover := cache.DiscoverFields(func(ctx context.Context, opts catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { calls++ - return []proto.PopulatedField{{ResourceType: opts.ResourceType, Path: "gender"}}, nil + return []catalog.PopulatedField{{ResourceType: opts.ResourceType, Path: "gender"}}, nil }) - opts := proto.PopulatedFieldOptions{Project: "P1", ResourceType: "Patient"} + opts := catalog.PopulatedFieldOptions{Project: "P1", ResourceType: "Patient"} if _, err := discover(context.Background(), opts); err != nil { t.Fatal(err) } @@ -46,12 +46,12 @@ func TestCacheDiscoverFieldsCachesAndInvalidatesByProject(t *testing.T) { func TestCacheDiscoverReferencesSeparatesAuthScopes(t *testing.T) { cache := New() calls := 0 - discover := cache.DiscoverReferences(func(ctx context.Context, opts proto.PopulatedReferenceOptions) ([]proto.PopulatedReference, error) { + discover := cache.DiscoverReferences(func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { calls++ - return []proto.PopulatedReference{{FromType: opts.NodeType, Label: "subject_Patient", ToType: "Specimen"}}, nil + return []catalog.PopulatedReference{{FromType: opts.NodeType, Label: "subject_Patient", ToType: "Specimen"}}, nil }) - base := proto.PopulatedReferenceOptions{Project: "P1", NodeType: "Patient", Mode: proto.TraversalModeBuilder} + base := catalog.PopulatedReferenceOptions{Project: "P1", NodeType: "Patient", Mode: catalog.TraversalModeBuilder} withA := base withA.AuthResourcePaths = []string{"a"} withB := base diff --git a/internal/catalog/discovery.go b/internal/catalog/discovery.go deleted file mode 100644 index 2b8f8fd..0000000 --- a/internal/catalog/discovery.go +++ /dev/null @@ -1,204 +0,0 @@ -package catalog - -import ( - "context" - "fmt" - "time" - - "arangodb-proto/internal/dbio" -) - -const populatedReferencesAQL = ` -FOR e IN fhir_edge - FILTER e.project == @project - FILTER @auth_resource_paths_unrestricted == true OR e.auth_resource_path IN @auth_resource_paths - FILTER ( - @mode == "builder" && (@node_type == null || e.to_type == @node_type) - ) || ( - @mode != "builder" && (@from_type == null || e.from_type == @from_type) - ) - COLLECT - from_type = (@mode == "builder" ? @node_type : e.from_type), - label = e.label, - to_type = (@mode == "builder" ? e.from_type : e.to_type) - WITH COUNT INTO edge_count - SORT from_type, edge_count DESC, label, to_type - RETURN { - from_type, - label, - to_type, - edge_count - } -` - -const populatedReferencesSurrealQL = ` -SELECT - IF $mode = "builder" THEN $node_type ELSE from_type END AS from_type, - label, - IF $mode = "builder" THEN from_type ELSE to_type END AS to_type, - count() AS edge_count -FROM fhir_edge -WHERE project = $project - AND ($auth_resource_paths_unrestricted = true OR auth_resource_path INSIDE $auth_resource_paths) - AND ( - ($mode = "builder" AND ($node_type = "" OR to_type = $node_type)) - OR - ($mode != "builder" AND ($from_type = "" OR from_type = $from_type)) - ) -GROUP BY from_type, label, to_type -ORDER BY from_type ASC, edge_count DESC, label ASC, to_type ASC; -` - -const populatedReferencesPostgresSQL = ` -SELECT - CASE WHEN @mode = 'builder' THEN @node_type ELSE src_type END AS from_type, - edge_type AS label, - CASE WHEN @mode = 'builder' THEN src_type ELSE dst_type END AS to_type, - COUNT(*)::bigint AS edge_count -FROM fhir_edge -WHERE project = @project - AND (@auth_resource_paths_unrestricted = true OR auth_resource_path = ANY(@auth_resource_paths)) - AND ( - (@mode = 'builder' AND (NULLIF(@node_type, '') IS NULL OR dst_type = @node_type)) - OR - (@mode <> 'builder' AND (NULLIF(@from_type, '') IS NULL OR src_type = @from_type)) - ) -GROUP BY - CASE WHEN @mode = 'builder' THEN @node_type ELSE src_type END, - edge_type, - CASE WHEN @mode = 'builder' THEN src_type ELSE dst_type END -ORDER BY from_type ASC, edge_count DESC, label ASC, to_type ASC; -` - -const ( - TraversalModeStorage = "storage" - TraversalModeBuilder = "builder" -) - -type PopulatedReferenceOptions struct { - dbio.ConnectionOptions - Project string - AuthResourcePaths []string - FromType string - NodeType string - Mode string - CursorBatch int -} - -type PopulatedReference struct { - FromType string `json:"from_type"` - Label string `json:"label"` - ToType string `json:"to_type"` - EdgeCount int64 `json:"edge_count"` -} - -func DiscoverPopulatedReferences(ctx context.Context, opts PopulatedReferenceOptions) ([]PopulatedReference, error) { - if opts.CursorBatch <= 0 { - opts.CursorBatch = 1000 - } - client, err := dbio.OpenBackend(ctx, opts.ConnectionOptions) - if err != nil { - return nil, err - } - - start := time.Now() - emit("go_discovery_start", map[string]any{ - "database": opts.Database, - "project": opts.Project, - "from_type": opts.FromType, - "node_type": opts.NodeType, - "mode": opts.Mode, - "auth_resource_paths": opts.AuthResourcePaths, - "cursor_batch_size": opts.CursorBatch, - "query": "populated_references", - }) - - mode := opts.Mode - if mode == "" { - mode = TraversalModeStorage - } - - query := populatedReferencesAQL - bindVars := map[string]any{ - "project": opts.Project, - "auth_resource_paths": cloneStrings(opts.AuthResourcePaths), - "auth_resource_paths_unrestricted": len(opts.AuthResourcePaths) == 0, - "mode": mode, - } - switch dbio.BackendName(opts.Backend) { - case dbio.BackendSurreal: - query = populatedReferencesSurrealQL - bindVars["from_type"] = opts.FromType - bindVars["node_type"] = opts.NodeType - case dbio.BackendPostgres: - query = populatedReferencesPostgresSQL - bindVars["from_type"] = opts.FromType - bindVars["node_type"] = opts.NodeType - default: - if opts.FromType != "" { - bindVars["from_type"] = opts.FromType - } else { - bindVars["from_type"] = nil - } - if opts.NodeType != "" { - bindVars["node_type"] = opts.NodeType - } else { - bindVars["node_type"] = nil - } - } - - results := make([]PopulatedReference, 0, 64) - err = client.QueryRows(ctx, query, opts.CursorBatch, bindVars, func(row map[string]any) error { - ref := PopulatedReference{ - FromType: stringValue(row["from_type"]), - Label: stringValue(row["label"]), - ToType: stringValue(row["to_type"]), - } - count, err := int64Value(row["edge_count"]) - if err != nil { - return fmt.Errorf("decode edge_count for %s/%s/%s: %w", ref.FromType, ref.Label, ref.ToType, err) - } - ref.EdgeCount = count - results = append(results, ref) - return nil - }) - if err != nil { - return nil, err - } - - emit("go_discovery_complete", map[string]any{ - "database": opts.Database, - "project": opts.Project, - "from_type": opts.FromType, - "node_type": opts.NodeType, - "mode": mode, - "auth_resource_paths": opts.AuthResourcePaths, - "rows": len(results), - "seconds": secondsSince(start), - }) - return results, nil -} - -func stringValue(value any) string { - if s, ok := value.(string); ok { - return s - } - return "" -} - -func int64Value(value any) (int64, error) { - switch v := value.(type) { - case int64: - return v, nil - case int32: - return int64(v), nil - case int: - return int64(v), nil - case float64: - return int64(v), nil - case float32: - return int64(v), nil - default: - return 0, fmt.Errorf("unsupported numeric type %T", value) - } -} diff --git a/internal/catalog/field_catalog.go b/internal/catalog/field_catalog.go deleted file mode 100644 index acd3fff..0000000 --- a/internal/catalog/field_catalog.go +++ /dev/null @@ -1,918 +0,0 @@ -package catalog - -import ( - "context" - "encoding/json" - "fmt" - "slices" - "sort" - "strings" - "sync" - "time" - - "arangodb-proto/internal/dbio" - "arangodb-proto/internal/fhirschema" - "arangodb-proto/internal/store" - - "github.com/bytedance/sonic" -) - -const ( - FieldCatalogCollection = "fhir_field_catalog" - fieldCatalogDistinctCap = 50 - fieldCatalogPivotCap = 50 - fieldKindScalar = "scalar" - fieldKindObject = "object" - fieldKindArray = "array" - fieldKindCodeableConcept = "codeable_concept" - fieldKindCoding = "coding" - pivotKindCodeableConcept = "codeable_concept_display_value" - pivotKindObservation = "observation_code_value" -) - -type FieldCatalogDocument struct { - Key string `json:"_key"` - Project string `json:"project"` - AuthResourcePath string `json:"auth_resource_path,omitempty"` - ResourceType string `json:"resource_type"` - Path string `json:"path"` - Kind string `json:"kind"` - DocCount int64 `json:"doc_count"` - SampleCount int `json:"sample_count"` - DistinctValues []string `json:"distinct_values,omitempty"` - DistinctTruncated bool `json:"distinct_truncated"` - PivotCandidate bool `json:"pivot_candidate"` - PivotKind string `json:"pivot_kind,omitempty"` - PivotColumns []string `json:"pivot_columns,omitempty"` - PivotFamily string `json:"pivot_family,omitempty"` - PivotColumnSelect string `json:"pivot_column_selector,omitempty"` - PivotValueSelect string `json:"pivot_value_selector,omitempty"` -} - -type PopulatedFieldOptions struct { - dbio.ConnectionOptions - Project string - AuthResourcePaths []string - ResourceType string - PivotOnly bool - CursorBatch int -} - -type PopulatedField struct { - Project string `json:"project"` - AuthResourcePath string `json:"auth_resource_path,omitempty"` - ResourceType string `json:"resource_type"` - Path string `json:"path"` - Kind string `json:"kind"` - DocCount int64 `json:"doc_count"` - SampleCount int `json:"sample_count"` - DistinctValues []string `json:"distinct_values,omitempty"` - DistinctTruncated bool `json:"distinct_truncated"` - PivotCandidate bool `json:"pivot_candidate"` - PivotKind string `json:"pivot_kind,omitempty"` - PivotColumns []string `json:"pivot_columns,omitempty"` - PivotFamily string `json:"pivot_family,omitempty"` - PivotColumnSelect string `json:"pivot_column_selector,omitempty"` - PivotValueSelect string `json:"pivot_value_selector,omitempty"` -} - -const populatedFieldsAQL = ` -FOR d IN fhir_field_catalog - FILTER d.project == @project - FILTER @auth_resource_paths_unrestricted == true OR d.auth_resource_path IN @auth_resource_paths - FILTER @resource_type == null OR d.resource_type == @resource_type - FILTER @pivot_only == false OR d.pivot_candidate == true - SORT d.resource_type, d.doc_count DESC, d.path - RETURN { - project: d.project, - auth_resource_path: d.auth_resource_path, - resource_type: d.resource_type, - path: d.path, - kind: d.kind, - doc_count: d.doc_count, - sample_count: d.sample_count, - distinct_values: d.distinct_values, - distinct_truncated: d.distinct_truncated, - pivot_candidate: d.pivot_candidate, - pivot_kind: d.pivot_kind, - pivot_columns: d.pivot_columns, - pivot_family: d.pivot_family, - pivot_column_selector: d.pivot_column_selector, - pivot_value_selector: d.pivot_value_selector - } -` - -const populatedFieldsSurrealQL = ` -SELECT - project, - resource_type, - path, - kind, - doc_count, - sample_count, - distinct_values, - distinct_truncated, - pivot_candidate, - pivot_kind, - pivot_columns, - pivot_family, - pivot_column_selector, - pivot_value_selector -FROM fhir_field_catalog -WHERE project = $project - AND ($auth_resource_paths_unrestricted = true OR auth_resource_path INSIDE $auth_resource_paths) - AND ($resource_type = "" OR resource_type = $resource_type) - AND ($pivot_only = false OR pivot_candidate = true) -ORDER BY resource_type ASC, doc_count DESC, path ASC; -` - -const populatedFieldsPostgresSQL = ` -SELECT - project, - auth_resource_path, - resource_type, - path, - kind, - doc_count, - sample_count, - COALESCE(distinct_values, ARRAY[]::text[]) AS distinct_values, - distinct_truncated, - pivot_candidate, - pivot_kind, - COALESCE(pivot_columns, ARRAY[]::text[]) AS pivot_columns, - pivot_family, - pivot_column_selector, - pivot_value_selector -FROM fhir_field_catalog -WHERE project = @project - AND (@auth_resource_paths_unrestricted = true OR auth_resource_path = ANY(@auth_resource_paths)) - AND (NULLIF(@resource_type, '') IS NULL OR resource_type = @resource_type) - AND (@pivot_only = false OR pivot_candidate = true) -ORDER BY resource_type ASC, doc_count DESC, path ASC; -` - -type Profiler struct { - project string - authResourcePath string - resourceType string - shapeCache *ShapePlanCache - stats map[string]*fieldCatalogStats -} - -type fieldCatalogStats struct { - path string - kind string - docCount int64 - distinctValues []string - distinctSet map[string]struct{} - distinctTruncated bool - pivotCandidate bool - pivotKind string - pivotColumns []string - pivotColumnSet map[string]struct{} - pivotFamily string - pivotColumnSelect string - pivotValueSelect string -} - -type ShapePlanCache struct { - mu sync.RWMutex - plans map[string]*shapePlan -} - -type shapePlan struct { - fields []*fieldPlan -} - -type fieldPlan struct { - Path string - Kind string - Accessor []pathStep - PivotCandidate bool - PivotKind string -} - -type pathStep struct { - field string - iterateArray bool -} - -func NewShapePlanCache() *ShapePlanCache { - return &ShapePlanCache{plans: make(map[string]*shapePlan)} -} - -func NewProfiler(project, authResourcePath, resourceType string, cache *ShapePlanCache) *Profiler { - return &Profiler{ - project: project, - authResourcePath: authResourcePath, - resourceType: resourceType, - shapeCache: cache, - stats: make(map[string]*fieldCatalogStats), - } -} - -func (p *Profiler) ObservePayload(payload map[string]any, timings map[string]float64) { - if payload == nil { - return - } - fingerprintStart := time.Now() - fingerprint := shapeFingerprintForValue(payload) - timings["field_shape_fingerprint"] += time.Since(fingerprintStart).Seconds() - - planStart := time.Now() - plan := p.shapeCache.getOrBuild(fingerprint, payload) - timings["field_shape_plan"] += time.Since(planStart).Seconds() - - observeStart := time.Now() - for _, field := range plan.fields { - values, ok := extractAccessorValues(payload, field.Accessor) - if !ok { - continue - } - stat := p.ensureStat(field) - stat.docCount++ - switch field.Kind { - case fieldKindScalar: - for _, value := range values { - if text, ok := scalarStringValue(value); ok { - stat.addDistinct(text) - } - } - case fieldKindCodeableConcept: - for _, value := range values { - if cc, ok := value.(map[string]any); ok { - for _, col := range codeableConceptColumns(cc) { - stat.addPivotColumn(col) - stat.addDistinct(col) - } - } - } - } - } - p.observeObservationCodePivot(payload) - timings["field_profile"] += time.Since(observeStart).Seconds() -} - -func (p *Profiler) ensureStat(field *fieldPlan) *fieldCatalogStats { - if stat, ok := p.stats[field.Path]; ok { - return stat - } - stat := &fieldCatalogStats{ - path: field.Path, - kind: field.Kind, - pivotCandidate: field.PivotCandidate, - pivotKind: field.PivotKind, - distinctSet: make(map[string]struct{}), - pivotColumnSet: make(map[string]struct{}), - } - if field.PivotCandidate { - if spec, ok := fhirschema.DefaultPivotSpec(p.resourceType, field.Path, ""); ok { - stat.pivotFamily = spec.Family - stat.pivotColumnSelect = fhirschema.SelectorExpression(spec.ColumnSelector) - stat.pivotValueSelect = fhirschema.SelectorExpression(spec.ValueSelector) - } - } - p.stats[field.Path] = stat - return stat -} - -func (s *fieldCatalogStats) addDistinct(value string) { - value = strings.TrimSpace(value) - if value == "" { - return - } - if _, ok := s.distinctSet[value]; ok { - return - } - if len(s.distinctValues) >= fieldCatalogDistinctCap { - s.distinctTruncated = true - return - } - s.distinctSet[value] = struct{}{} - s.distinctValues = append(s.distinctValues, value) -} - -func (s *fieldCatalogStats) addPivotColumn(value string) { - value = strings.TrimSpace(value) - if value == "" { - return - } - if _, ok := s.pivotColumnSet[value]; ok { - return - } - if len(s.pivotColumns) >= fieldCatalogPivotCap { - s.distinctTruncated = true - return - } - s.pivotColumnSet[value] = struct{}{} - s.pivotColumns = append(s.pivotColumns, value) -} - -func (s *fieldCatalogStats) setPivotDefaults(family string, columnSelector string, valueSelector string) { - if strings.TrimSpace(family) != "" { - s.pivotFamily = family - } - if strings.TrimSpace(columnSelector) != "" { - s.pivotColumnSelect = columnSelector - } - if strings.TrimSpace(valueSelector) != "" { - s.pivotValueSelect = valueSelector - } -} - -func (p *Profiler) Merge(other *Profiler) { - for path, otherStat := range other.stats { - stat, ok := p.stats[path] - if !ok { - stat = &fieldCatalogStats{ - path: otherStat.path, - kind: otherStat.kind, - pivotCandidate: otherStat.pivotCandidate, - pivotKind: otherStat.pivotKind, - pivotFamily: otherStat.pivotFamily, - pivotColumnSelect: otherStat.pivotColumnSelect, - pivotValueSelect: otherStat.pivotValueSelect, - distinctSet: make(map[string]struct{}), - pivotColumnSet: make(map[string]struct{}), - } - p.stats[path] = stat - } - stat.docCount += otherStat.docCount - stat.distinctTruncated = stat.distinctTruncated || otherStat.distinctTruncated - stat.setPivotDefaults(otherStat.pivotFamily, otherStat.pivotColumnSelect, otherStat.pivotValueSelect) - for _, value := range otherStat.distinctValues { - stat.addDistinct(value) - } - for _, value := range otherStat.pivotColumns { - stat.addPivotColumn(value) - } - } -} - -func (p *Profiler) Documents() []FieldCatalogDocument { - out := make([]FieldCatalogDocument, 0, len(p.stats)) - paths := make([]string, 0, len(p.stats)) - for path := range p.stats { - paths = append(paths, path) - } - sort.Strings(paths) - for _, path := range paths { - stat := p.stats[path] - distinctValues := append([]string(nil), stat.distinctValues...) - pivotColumns := append([]string(nil), stat.pivotColumns...) - slices.Sort(distinctValues) - slices.Sort(pivotColumns) - out = append(out, FieldCatalogDocument{ - Key: fieldCatalogKey(p.project, p.authResourcePath, p.resourceType, stat.path), - Project: p.project, - AuthResourcePath: p.authResourcePath, - ResourceType: p.resourceType, - Path: stat.path, - Kind: stat.kind, - DocCount: stat.docCount, - SampleCount: len(distinctValues), - DistinctValues: distinctValues, - DistinctTruncated: stat.distinctTruncated, - PivotCandidate: stat.pivotCandidate, - PivotKind: stat.pivotKind, - PivotColumns: pivotColumns, - PivotFamily: stat.pivotFamily, - PivotColumnSelect: stat.pivotColumnSelect, - PivotValueSelect: stat.pivotValueSelect, - }) - } - return out -} - -func fieldCatalogKey(project, authResourcePath, resourceType, path string) string { - return sanitizeCollectionKey(project + "::" + authResourcePath + "::" + resourceType + "::" + path) -} - -func (c *ShapePlanCache) getOrBuild(fingerprint string, payload map[string]any) *shapePlan { - c.mu.RLock() - plan, ok := c.plans[fingerprint] - c.mu.RUnlock() - if ok { - return plan - } - c.mu.Lock() - defer c.mu.Unlock() - if plan, ok = c.plans[fingerprint]; ok { - return plan - } - plan = buildShapePlan(payload) - c.plans[fingerprint] = plan - return plan -} - -func (c *ShapePlanCache) planCount() int { - c.mu.RLock() - defer c.mu.RUnlock() - return len(c.plans) -} - -func buildShapePlan(payload map[string]any) *shapePlan { - fieldMap := make(map[string]*fieldPlan) - walkShapeValue(payload, nil, "", fieldMap) - paths := make([]string, 0, len(fieldMap)) - for path := range fieldMap { - paths = append(paths, path) - } - sort.Strings(paths) - fields := make([]*fieldPlan, 0, len(paths)) - for _, path := range paths { - fields = append(fields, fieldMap[path]) - } - return &shapePlan{fields: fields} -} - -func walkShapeValue(value any, accessor []pathStep, path string, fieldMap map[string]*fieldPlan) { - switch typed := value.(type) { - case map[string]any: - if path != "" { - kind, pivotCandidate, pivotKind := classifyObjectShape(typed) - addFieldPlan(fieldMap, path, accessor, kind, pivotCandidate, pivotKind) - } - keys := sortedKeys(typed) - for _, key := range keys { - child := typed[key] - if child == nil { - continue - } - switch childTyped := child.(type) { - case []any: - arrayPath := appendPath(path, key, true) - arrayAccessor := appendAccessor(accessor, pathStep{field: key, iterateArray: true}) - addFieldPlan(fieldMap, arrayPath, arrayAccessor, fieldKindArray, false, "") - for _, item := range childTyped { - if item == nil { - continue - } - walkShapeValue(item, arrayAccessor, arrayPath, fieldMap) - } - default: - childPath := appendPath(path, key, false) - childAccessor := appendAccessor(accessor, pathStep{field: key}) - walkShapeValue(child, childAccessor, childPath, fieldMap) - } - } - case []any: - if path != "" { - addFieldPlan(fieldMap, path, accessor, fieldKindArray, false, "") - } - for _, item := range typed { - if item == nil { - continue - } - walkShapeValue(item, accessor, path, fieldMap) - } - default: - if path != "" { - addFieldPlan(fieldMap, path, accessor, fieldKindScalar, false, "") - } - } -} - -func addFieldPlan(fieldMap map[string]*fieldPlan, path string, accessor []pathStep, kind string, pivotCandidate bool, pivotKind string) { - if existing, ok := fieldMap[path]; ok { - if existing.Kind == fieldKindObject && (kind == fieldKindCodeableConcept || kind == fieldKindCoding) { - existing.Kind = kind - } - if existing.Kind == fieldKindArray && kind != fieldKindArray { - // preserve array kind for the array path itself - } - if pivotCandidate { - existing.PivotCandidate = true - existing.PivotKind = pivotKind - } - return - } - copiedAccessor := append([]pathStep(nil), accessor...) - fieldMap[path] = &fieldPlan{ - Path: path, - Kind: kind, - Accessor: copiedAccessor, - PivotCandidate: pivotCandidate, - PivotKind: pivotKind, - } -} - -func classifyObjectShape(value map[string]any) (string, bool, string) { - if isCodeableConceptShape(value) { - return fieldKindCodeableConcept, true, pivotKindCodeableConcept - } - if isCodingShape(value) { - return fieldKindCoding, false, "" - } - return fieldKindObject, false, "" -} - -func isCodeableConceptShape(value map[string]any) bool { - _, hasCoding := value["coding"] - _, hasText := value["text"] - return hasCoding || hasText -} - -func isCodingShape(value map[string]any) bool { - _, hasSystem := value["system"] - _, hasCode := value["code"] - _, hasDisplay := value["display"] - return hasSystem || hasCode || hasDisplay -} - -func (p *Profiler) observeObservationCodePivot(payload map[string]any) { - if p.resourceType != "Observation" { - return - } - codeValue, ok := payload["code"].(map[string]any) - if !ok { - return - } - valueSelector := observationValueSelectorFromPayload(payload) - if valueSelector == "" { - return - } - stat, ok := p.stats["code"] - if !ok { - stat = &fieldCatalogStats{ - path: "code", - kind: fieldKindCodeableConcept, - pivotCandidate: true, - pivotKind: pivotKindObservation, - distinctSet: make(map[string]struct{}), - pivotColumnSet: make(map[string]struct{}), - } - p.stats["code"] = stat - } - stat.pivotCandidate = true - stat.pivotKind = pivotKindObservation - stat.setPivotDefaults(fhirschema.PivotFamilyObservationCodeValue, "code.coding[].display", valueSelector) - for _, col := range codeableConceptColumns(codeValue) { - stat.addPivotColumn(col) - } -} - -func observationValueSelectorFromPayload(payload map[string]any) string { - if value, ok := payload["valueQuantity"].(map[string]any); ok && value["value"] != nil { - return "valueQuantity.value" - } - if value, ok := payload["valueCodeableConcept"].(map[string]any); ok { - if strings.TrimSpace(stringValue(value["text"])) != "" { - return "valueCodeableConcept.text" - } - if len(codeableConceptColumns(value)) > 0 { - return "valueCodeableConcept.coding[].display" - } - } - for _, name := range []string{"valueString", "valueInteger", "valueBoolean", "valueDecimal", "valueDateTime", "valueTime"} { - if payload[name] != nil { - return name - } - } - if value, ok := payload["valuePeriod"].(map[string]any); ok { - if value["start"] != nil { - return "valuePeriod.start" - } - if value["end"] != nil { - return "valuePeriod.end" - } - } - if value, ok := payload["valueRange"].(map[string]any); ok { - if low, ok := value["low"].(map[string]any); ok && low["value"] != nil { - return "valueRange.low.value" - } - if high, ok := value["high"].(map[string]any); ok && high["value"] != nil { - return "valueRange.high.value" - } - } - if value, ok := payload["valueRatio"].(map[string]any); ok { - if num, ok := value["numerator"].(map[string]any); ok && num["value"] != nil { - return "valueRatio.numerator.value" - } - if den, ok := value["denominator"].(map[string]any); ok && den["value"] != nil { - return "valueRatio.denominator.value" - } - } - return "" -} - -func appendPath(prefix, key string, array bool) string { - if prefix == "" { - if array { - return key + "[]" - } - return key - } - if array { - return prefix + "." + key + "[]" - } - return prefix + "." + key -} - -func appendAccessor(accessor []pathStep, step pathStep) []pathStep { - out := append([]pathStep(nil), accessor...) - out = append(out, step) - return out -} - -func extractAccessorValues(root any, accessor []pathStep) ([]any, bool) { - nodes := []any{root} - for _, step := range accessor { - next := make([]any, 0, len(nodes)) - for _, node := range nodes { - obj, ok := node.(map[string]any) - if !ok { - continue - } - value, ok := obj[step.field] - if !ok || value == nil { - continue - } - if step.iterateArray { - items, ok := value.([]any) - if !ok { - continue - } - next = append(next, items...) - continue - } - next = append(next, value) - } - if len(next) == 0 { - return nil, false - } - nodes = next - } - if len(nodes) == 0 { - return nil, false - } - return nodes, true -} - -func scalarStringValue(value any) (string, bool) { - switch typed := value.(type) { - case string: - return typed, true - case bool: - if typed { - return "true", true - } - return "false", true - case float64: - return fmt.Sprintf("%v", typed), true - case float32: - return fmt.Sprintf("%v", typed), true - case int: - return fmt.Sprintf("%d", typed), true - case int64: - return fmt.Sprintf("%d", typed), true - case int32: - return fmt.Sprintf("%d", typed), true - default: - return "", false - } -} - -func codeableConceptColumns(value map[string]any) []string { - seen := make(map[string]struct{}) - out := make([]string, 0, 4) - appendValue := func(text string) { - text = strings.TrimSpace(text) - if text == "" { - return - } - if _, ok := seen[text]; ok { - return - } - seen[text] = struct{}{} - out = append(out, text) - } - if text, ok := value["text"].(string); ok { - appendValue(text) - } - if codingValues, ok := value["coding"].([]any); ok { - for _, raw := range codingValues { - coding, ok := raw.(map[string]any) - if !ok { - continue - } - if display, ok := coding["display"].(string); ok { - appendValue(display) - continue - } - if code, ok := coding["code"].(string); ok { - appendValue(code) - } - } - } - return out -} - -func sortedKeys(value map[string]any) []string { - keys := make([]string, 0, len(value)) - for key := range value { - keys = append(keys, key) - } - sort.Strings(keys) - return keys -} - -func shapeFingerprintForValue(value any) string { - switch typed := value.(type) { - case map[string]any: - keys := sortedKeys(typed) - parts := make([]string, 0, len(keys)) - for _, key := range keys { - parts = append(parts, key+":"+shapeFingerprintForValue(typed[key])) - } - return "{" + strings.Join(parts, ",") + "}" - case []any: - childPrints := make([]string, 0, len(typed)) - seen := make(map[string]struct{}) - for _, item := range typed { - fingerprint := shapeFingerprintForValue(item) - if _, ok := seen[fingerprint]; ok { - continue - } - seen[fingerprint] = struct{}{} - childPrints = append(childPrints, fingerprint) - } - sort.Strings(childPrints) - return "[" + strings.Join(childPrints, "|") + "]" - case string: - return "s" - case bool: - return "b" - case float64, float32, int, int32, int64: - return "n" - case nil: - return "0" - default: - return fmt.Sprintf("%T", value) - } -} - -func WriteFieldCatalog(ctx context.Context, client store.Backend, collection string, docs []FieldCatalogDocument, batchSize int, overwrite bool, writeAPI string, timings map[string]float64) error { - if len(docs) == 0 { - return nil - } - start := time.Now() - rawDocs := make([]json.RawMessage, 0, len(docs)) - for _, doc := range docs { - data, err := sonic.ConfigFastest.Marshal(&doc) - if err != nil { - return err - } - rawDocs = append(rawDocs, json.RawMessage(data)) - } - timings["field_catalog_marshal"] += time.Since(start).Seconds() - - for i := 0; i < len(rawDocs); i += batchSize { - end := i + batchSize - if end > len(rawDocs) { - end = len(rawDocs) - } - insertStart := time.Now() - if err := client.InsertBatchRaw(ctx, collection, rawDocs[i:end], overwrite, writeAPI); err != nil { - return err - } - timings["field_catalog_insert"] += time.Since(insertStart).Seconds() - } - return nil -} - -func sanitizeCollectionKey(value string) string { - value = strings.TrimSpace(value) - if value == "" { - return "_" - } - var b strings.Builder - b.Grow(len(value)) - for _, r := range value { - switch { - case r >= 'A' && r <= 'Z', - r >= 'a' && r <= 'z', - r >= '0' && r <= '9', - strings.ContainsRune("_-:.@()+,=;$!*'", r): - b.WriteRune(r) - default: - b.WriteRune('_') - } - } - return b.String() -} - -func DiscoverPopulatedFields(ctx context.Context, opts PopulatedFieldOptions) ([]PopulatedField, error) { - if opts.CursorBatch <= 0 { - opts.CursorBatch = 1000 - } - client, err := dbio.OpenBackend(ctx, opts.ConnectionOptions) - if err != nil { - return nil, err - } - - start := time.Now() - emit("go_discovery_start", map[string]any{ - "database": opts.Database, - "project": opts.Project, - "resource_type": opts.ResourceType, - "pivot_only": opts.PivotOnly, - "auth_resource_paths": opts.AuthResourcePaths, - "cursor_batch_size": opts.CursorBatch, - "query": "populated_fields", - }) - - query := populatedFieldsAQL - bindVars := map[string]any{ - "project": opts.Project, - "pivot_only": opts.PivotOnly, - "auth_resource_paths": cloneStrings(opts.AuthResourcePaths), - "auth_resource_paths_unrestricted": len(opts.AuthResourcePaths) == 0, - } - switch dbio.BackendName(opts.Backend) { - case dbio.BackendSurreal: - query = populatedFieldsSurrealQL - bindVars["resource_type"] = opts.ResourceType - case dbio.BackendPostgres: - query = populatedFieldsPostgresSQL - bindVars["resource_type"] = opts.ResourceType - default: - if opts.ResourceType != "" { - bindVars["resource_type"] = opts.ResourceType - } else { - bindVars["resource_type"] = nil - } - } - - results := make([]PopulatedField, 0, 64) - err = client.QueryRows(ctx, query, opts.CursorBatch, bindVars, func(row map[string]any) error { - results = append(results, PopulatedField{ - Project: stringValue(row["project"]), - AuthResourcePath: stringValue(row["auth_resource_path"]), - ResourceType: stringValue(row["resource_type"]), - Path: stringValue(row["path"]), - Kind: stringValue(row["kind"]), - DocCount: int64Must(row["doc_count"]), - SampleCount: int(int64Must(row["sample_count"])), - DistinctValues: stringSliceValue(row["distinct_values"]), - DistinctTruncated: boolValue(row["distinct_truncated"]), - PivotCandidate: boolValue(row["pivot_candidate"]), - PivotKind: stringValue(row["pivot_kind"]), - PivotColumns: stringSliceValue(row["pivot_columns"]), - PivotFamily: stringValue(row["pivot_family"]), - PivotColumnSelect: stringValue(row["pivot_column_selector"]), - PivotValueSelect: stringValue(row["pivot_value_selector"]), - }) - return nil - }) - if err != nil { - return nil, err - } - - emit("go_discovery_complete", map[string]any{ - "database": opts.Database, - "project": opts.Project, - "resource_type": opts.ResourceType, - "pivot_only": opts.PivotOnly, - "auth_resource_paths": opts.AuthResourcePaths, - "rows": len(results), - "seconds": secondsSince(start), - }) - return results, nil -} - -func stringSliceValue(value any) []string { - items, ok := value.([]any) - if !ok { - return nil - } - out := make([]string, 0, len(items)) - for _, item := range items { - if text, ok := item.(string); ok { - out = append(out, text) - } - } - return out -} - -func boolValue(value any) bool { - v, _ := value.(bool) - return v -} - -func int64Must(value any) int64 { - switch typed := value.(type) { - case int64: - return typed - case int32: - return int64(typed) - case int: - return int64(typed) - case float64: - return int64(typed) - case float32: - return int64(typed) - default: - return 0 - } -} diff --git a/internal/catalog/helpers.go b/internal/catalog/helpers.go new file mode 100644 index 0000000..938eb07 --- /dev/null +++ b/internal/catalog/helpers.go @@ -0,0 +1,277 @@ +package catalog + +import ( + "encoding/json" + "fmt" + "os" + "sort" + "strings" + "time" +) + +func emit(event string, fields map[string]any) { + payload := map[string]any{"event": event} + for key, value := range fields { + payload[key] = value + } + data, err := json.Marshal(payload) + if err != nil { + fmt.Fprintln(os.Stderr, err) + return + } + fmt.Fprintln(os.Stdout, string(data)) +} + +func secondsSince(start time.Time) float64 { + return time.Since(start).Seconds() +} + +func cloneStrings(in []string) []string { + if in == nil { + return nil + } + out := make([]string, len(in)) + copy(out, in) + return out +} + +func stringValue(value any) string { + if s, ok := value.(string); ok { + return s + } + return "" +} + +func int64Value(value any) (int64, error) { + switch v := value.(type) { + case int64: + return v, nil + case int32: + return int64(v), nil + case int: + return int64(v), nil + case float64: + return int64(v), nil + case float32: + return int64(v), nil + default: + return 0, fmt.Errorf("unsupported numeric type %T", value) + } +} + +func int64Must(value any) int64 { + switch typed := value.(type) { + case int64: + return typed + case int32: + return int64(typed) + case int: + return int64(typed) + case float64: + return int64(typed) + case float32: + return int64(typed) + default: + return 0 + } +} + +func boolValue(value any) bool { + v, _ := value.(bool) + return v +} + +func stringSliceValue(value any) []string { + items, ok := value.([]any) + if !ok { + return nil + } + out := make([]string, 0, len(items)) + for _, item := range items { + if text, ok := item.(string); ok { + out = append(out, text) + } + } + return out +} + +func fieldCatalogKey(project, authResourcePath, resourceType, path string) string { + return sanitizeCollectionKey(project + "::" + authResourcePath + "::" + resourceType + "::" + path) +} + +func sanitizeCollectionKey(value string) string { + value = strings.TrimSpace(value) + if value == "" { + return "_" + } + var b strings.Builder + b.Grow(len(value)) + for _, r := range value { + switch { + case r >= 'A' && r <= 'Z', + r >= 'a' && r <= 'z', + r >= '0' && r <= '9', + strings.ContainsRune("_-:.@()+,=;$!*'", r): + b.WriteRune(r) + default: + b.WriteRune('_') + } + } + return b.String() +} + +func appendPath(prefix, key string, array bool) string { + if prefix == "" { + if array { + return key + "[]" + } + return key + } + if array { + return prefix + "." + key + "[]" + } + return prefix + "." + key +} + +func appendAccessor(accessor []pathStep, step pathStep) []pathStep { + out := append([]pathStep(nil), accessor...) + out = append(out, step) + return out +} + +func extractAccessorValues(root any, accessor []pathStep) ([]any, bool) { + nodes := []any{root} + for _, step := range accessor { + next := make([]any, 0, len(nodes)) + for _, node := range nodes { + obj, ok := node.(map[string]any) + if !ok { + continue + } + value, ok := obj[step.field] + if !ok || value == nil { + continue + } + if step.iterateArray { + items, ok := value.([]any) + if !ok { + continue + } + next = append(next, items...) + continue + } + next = append(next, value) + } + if len(next) == 0 { + return nil, false + } + nodes = next + } + if len(nodes) == 0 { + return nil, false + } + return nodes, true +} + +func scalarStringValue(value any) (string, bool) { + switch typed := value.(type) { + case string: + return typed, true + case bool: + if typed { + return "true", true + } + return "false", true + case float64: + return fmt.Sprintf("%v", typed), true + case float32: + return fmt.Sprintf("%v", typed), true + case int: + return fmt.Sprintf("%d", typed), true + case int64: + return fmt.Sprintf("%d", typed), true + case int32: + return fmt.Sprintf("%d", typed), true + default: + return "", false + } +} + +func codeableConceptColumns(value map[string]any) []string { + seen := make(map[string]struct{}) + out := make([]string, 0, 4) + appendValue := func(text string) { + text = strings.TrimSpace(text) + if text == "" { + return + } + if _, ok := seen[text]; ok { + return + } + seen[text] = struct{}{} + out = append(out, text) + } + if text, ok := value["text"].(string); ok { + appendValue(text) + } + if codingValues, ok := value["coding"].([]any); ok { + for _, raw := range codingValues { + coding, ok := raw.(map[string]any) + if !ok { + continue + } + if display, ok := coding["display"].(string); ok { + appendValue(display) + continue + } + if code, ok := coding["code"].(string); ok { + appendValue(code) + } + } + } + return out +} + +func sortedKeys(value map[string]any) []string { + keys := make([]string, 0, len(value)) + for key := range value { + keys = append(keys, key) + } + sort.Strings(keys) + return keys +} + +func shapeFingerprintForValue(value any) string { + switch typed := value.(type) { + case map[string]any: + keys := sortedKeys(typed) + parts := make([]string, 0, len(keys)) + for _, key := range keys { + parts = append(parts, key+":"+shapeFingerprintForValue(typed[key])) + } + return "{" + strings.Join(parts, ",") + "}" + case []any: + childPrints := make([]string, 0, len(typed)) + seen := make(map[string]struct{}) + for _, item := range typed { + fingerprint := shapeFingerprintForValue(item) + if _, ok := seen[fingerprint]; ok { + continue + } + seen[fingerprint] = struct{}{} + childPrints = append(childPrints, fingerprint) + } + sort.Strings(childPrints) + return "[" + strings.Join(childPrints, "|") + "]" + case string: + return "s" + case bool: + return "b" + case float64, float32, int, int32, int64: + return "n" + case nil: + return "0" + default: + return fmt.Sprintf("%T", value) + } +} diff --git a/internal/catalog/progress.go b/internal/catalog/progress.go deleted file mode 100644 index c49668e..0000000 --- a/internal/catalog/progress.go +++ /dev/null @@ -1,25 +0,0 @@ -package catalog - -import ( - "encoding/json" - "fmt" - "os" - "time" -) - -func emit(event string, fields map[string]any) { - payload := map[string]any{"event": event} - for key, value := range fields { - payload[key] = value - } - data, err := json.Marshal(payload) - if err != nil { - fmt.Fprintln(os.Stderr, err) - return - } - fmt.Fprintln(os.Stdout, string(data)) -} - -func secondsSince(start time.Time) float64 { - return time.Since(start).Seconds() -} diff --git a/internal/catalog/read_auth_paths.go b/internal/catalog/read_auth_paths.go new file mode 100644 index 0000000..b5b26cc --- /dev/null +++ b/internal/catalog/read_auth_paths.go @@ -0,0 +1,54 @@ +package catalog + +import ( + "context" + "time" + + arangostore "github.com/calypr/loom/internal/store/arango" +) + +const existingAuthResourcePathsAQL = ` +FOR d IN fhir_field_catalog + FILTER d.project == @project + FILTER d.auth_resource_path != null AND d.auth_resource_path != "" + COLLECT auth_resource_path = d.auth_resource_path + SORT auth_resource_path + RETURN auth_resource_path +` + +func DiscoverExistingAuthResourcePaths(ctx context.Context, opts AuthResourcePathOptions) ([]string, error) { + if opts.CursorBatch <= 0 { + opts.CursorBatch = 1000 + } + client, err := arangostore.Open(ctx, opts.URL, opts.Database) + if err != nil { + return nil, err + } + defer client.Close(ctx) + start := time.Now() + emit("go_discovery_start", map[string]any{ + "database": opts.Database, + "project": opts.Project, + "cursor_batch_size": opts.CursorBatch, + "query": "existing_auth_resource_paths", + }) + + results := make([]string, 0, 16) + err = client.QueryRows(ctx, existingAuthResourcePathsAQL, opts.CursorBatch, map[string]any{"project": opts.Project}, func(row map[string]any) error { + if path := stringValue(row["auth_resource_path"]); path != "" { + results = append(results, path) + } + return nil + }) + if err != nil { + return nil, err + } + emit("go_discovery_complete", map[string]any{ + "database": opts.Database, + "project": opts.Project, + "rows": len(results), + "seconds": secondsSince(start), + "query": "existing_auth_resource_paths", + }) + return results, nil +} diff --git a/internal/catalog/read_fields.go b/internal/catalog/read_fields.go new file mode 100644 index 0000000..67f2e2e --- /dev/null +++ b/internal/catalog/read_fields.go @@ -0,0 +1,104 @@ +package catalog + +import ( + "context" + "time" + + arangostore "github.com/calypr/loom/internal/store/arango" +) + +const populatedFieldsAQL = ` +FOR d IN fhir_field_catalog + FILTER d.project == @project + FILTER @auth_resource_paths_unrestricted == true OR d.auth_resource_path IN @auth_resource_paths + FILTER @resource_type == null OR d.resource_type == @resource_type + FILTER @pivot_only == false OR d.pivot_candidate == true + SORT d.resource_type, d.doc_count DESC, d.path + RETURN { + project: d.project, + auth_resource_path: d.auth_resource_path, + resource_type: d.resource_type, + path: d.path, + kind: d.kind, + doc_count: d.doc_count, + sample_count: d.sample_count, + distinct_values: d.distinct_values, + distinct_truncated: d.distinct_truncated, + pivot_candidate: d.pivot_candidate, + pivot_kind: d.pivot_kind, + pivot_columns: d.pivot_columns, + pivot_family: d.pivot_family, + pivot_column_selector: d.pivot_column_selector, + pivot_value_selector: d.pivot_value_selector + } +` + +func DiscoverPopulatedFields(ctx context.Context, opts PopulatedFieldOptions) ([]PopulatedField, error) { + if opts.CursorBatch <= 0 { + opts.CursorBatch = 1000 + } + client, err := arangostore.Open(ctx, opts.URL, opts.Database) + if err != nil { + return nil, err + } + defer client.Close(ctx) + + start := time.Now() + emit("go_discovery_start", map[string]any{ + "database": opts.Database, + "project": opts.Project, + "resource_type": opts.ResourceType, + "pivot_only": opts.PivotOnly, + "auth_resource_paths": opts.AuthResourcePaths, + "cursor_batch_size": opts.CursorBatch, + "query": "populated_fields", + }) + + bindVars := map[string]any{ + "project": opts.Project, + "pivot_only": opts.PivotOnly, + "auth_resource_paths": cloneStrings(opts.AuthResourcePaths), + "auth_resource_paths_unrestricted": len(opts.AuthResourcePaths) == 0, + } + if opts.ResourceType != "" { + bindVars["resource_type"] = opts.ResourceType + } else { + bindVars["resource_type"] = nil + } + + results := make([]PopulatedField, 0, 64) + err = client.QueryRows(ctx, populatedFieldsAQL, opts.CursorBatch, bindVars, func(row map[string]any) error { + results = append(results, PopulatedField{ + Project: stringValue(row["project"]), + AuthResourcePath: stringValue(row["auth_resource_path"]), + ResourceType: stringValue(row["resource_type"]), + Path: stringValue(row["path"]), + Kind: stringValue(row["kind"]), + DocCount: int64Must(row["doc_count"]), + SampleCount: int(int64Must(row["sample_count"])), + DistinctValues: stringSliceValue(row["distinct_values"]), + DistinctTruncated: boolValue(row["distinct_truncated"]), + PivotCandidate: boolValue(row["pivot_candidate"]), + PivotKind: stringValue(row["pivot_kind"]), + PivotColumns: stringSliceValue(row["pivot_columns"]), + PivotFamily: stringValue(row["pivot_family"]), + PivotColumnSelect: stringValue(row["pivot_column_selector"]), + PivotValueSelect: stringValue(row["pivot_value_selector"]), + }) + return nil + }) + if err != nil { + return nil, err + } + + emit("go_discovery_complete", map[string]any{ + "database": opts.Database, + "project": opts.Project, + "resource_type": opts.ResourceType, + "pivot_only": opts.PivotOnly, + "auth_resource_paths": opts.AuthResourcePaths, + "rows": len(results), + "seconds": secondsSince(start), + }) + return results, nil +} diff --git a/internal/catalog/read_references.go b/internal/catalog/read_references.go new file mode 100644 index 0000000..a9d21f3 --- /dev/null +++ b/internal/catalog/read_references.go @@ -0,0 +1,108 @@ +package catalog + +import ( + "context" + "fmt" + "time" + + arangostore "github.com/calypr/loom/internal/store/arango" +) + +const populatedReferencesAQL = ` +FOR e IN fhir_edge + FILTER e.project == @project + FILTER @auth_resource_paths_unrestricted == true OR e.auth_resource_path IN @auth_resource_paths + FILTER ( + @mode == "builder" && (@node_type == null || e.to_type == @node_type) + ) || ( + @mode != "builder" && (@from_type == null || e.from_type == @from_type) + ) + COLLECT + from_type = (@mode == "builder" ? @node_type : e.from_type), + label = e.label, + to_type = (@mode == "builder" ? e.from_type : e.to_type) + WITH COUNT INTO edge_count + SORT from_type, edge_count DESC, label, to_type + RETURN { + from_type, + label, + to_type, + edge_count + } +` + +func DiscoverPopulatedReferences(ctx context.Context, opts PopulatedReferenceOptions) ([]PopulatedReference, error) { + if opts.CursorBatch <= 0 { + opts.CursorBatch = 1000 + } + client, err := arangostore.Open(ctx, opts.URL, opts.Database) + if err != nil { + return nil, err + } + defer client.Close(ctx) + + start := time.Now() + emit("go_discovery_start", map[string]any{ + "database": opts.Database, + "project": opts.Project, + "from_type": opts.FromType, + "node_type": opts.NodeType, + "mode": opts.Mode, + "auth_resource_paths": opts.AuthResourcePaths, + "cursor_batch_size": opts.CursorBatch, + "query": "populated_references", + }) + + mode := opts.Mode + if mode == "" { + mode = TraversalModeStorage + } + + bindVars := map[string]any{ + "project": opts.Project, + "auth_resource_paths": cloneStrings(opts.AuthResourcePaths), + "auth_resource_paths_unrestricted": len(opts.AuthResourcePaths) == 0, + "mode": mode, + } + if opts.FromType != "" { + bindVars["from_type"] = opts.FromType + } else { + bindVars["from_type"] = nil + } + if opts.NodeType != "" { + bindVars["node_type"] = opts.NodeType + } else { + bindVars["node_type"] = nil + } + + results := make([]PopulatedReference, 0, 64) + err = client.QueryRows(ctx, populatedReferencesAQL, opts.CursorBatch, bindVars, func(row map[string]any) error { + ref := PopulatedReference{ + FromType: stringValue(row["from_type"]), + Label: stringValue(row["label"]), + ToType: stringValue(row["to_type"]), + } + count, err := int64Value(row["edge_count"]) + if err != nil { + return fmt.Errorf("decode edge_count for %s/%s/%s: %w", ref.FromType, ref.Label, ref.ToType, err) + } + ref.EdgeCount = count + results = append(results, ref) + return nil + }) + if err != nil { + return nil, err + } + + emit("go_discovery_complete", map[string]any{ + "database": opts.Database, + "project": opts.Project, + "from_type": opts.FromType, + "node_type": opts.NodeType, + "mode": mode, + "auth_resource_paths": opts.AuthResourcePaths, + "rows": len(results), + "seconds": secondsSince(start), + }) + return results, nil +} diff --git a/internal/catalog/types.go b/internal/catalog/types.go new file mode 100644 index 0000000..4878263 --- /dev/null +++ b/internal/catalog/types.go @@ -0,0 +1,146 @@ +package catalog + +import ( + "sync" + + arangostore "github.com/calypr/loom/internal/store/arango" +) + +const ( + FieldCatalogCollection = "fhir_field_catalog" + fieldCatalogDistinctCap = 50 + fieldCatalogPivotCap = 50 + fieldKindScalar = "scalar" + fieldKindObject = "object" + fieldKindArray = "array" + fieldKindCodeableConcept = "codeable_concept" + fieldKindCoding = "coding" + pivotKindCodeableConcept = "codeable_concept_display_value" + pivotKindObservation = "observation_code_value" +) + +const ( + TraversalModeStorage = "storage" + TraversalModeBuilder = "builder" +) + +// Write-side catalog records persisted during load. +type FieldCatalogDocument struct { + Key string `json:"_key"` + Project string `json:"project"` + AuthResourcePath string `json:"auth_resource_path,omitempty"` + ResourceType string `json:"resource_type"` + Path string `json:"path"` + Kind string `json:"kind"` + DocCount int64 `json:"doc_count"` + SampleCount int `json:"sample_count"` + DistinctValues []string `json:"distinct_values,omitempty"` + DistinctTruncated bool `json:"distinct_truncated"` + PivotCandidate bool `json:"pivot_candidate"` + PivotKind string `json:"pivot_kind,omitempty"` + PivotColumns []string `json:"pivot_columns,omitempty"` + PivotFamily string `json:"pivot_family,omitempty"` + PivotColumnSelect string `json:"pivot_column_selector,omitempty"` + PivotValueSelect string `json:"pivot_value_selector,omitempty"` +} + +// Read-side field discovery request and response types. +type PopulatedFieldOptions struct { + arangostore.ConnectionOptions + Project string + AuthResourcePaths []string + ResourceType string + PivotOnly bool + CursorBatch int +} + +type PopulatedField struct { + Project string `json:"project"` + AuthResourcePath string `json:"auth_resource_path,omitempty"` + ResourceType string `json:"resource_type"` + Path string `json:"path"` + Kind string `json:"kind"` + DocCount int64 `json:"doc_count"` + SampleCount int `json:"sample_count"` + DistinctValues []string `json:"distinct_values,omitempty"` + DistinctTruncated bool `json:"distinct_truncated"` + PivotCandidate bool `json:"pivot_candidate"` + PivotKind string `json:"pivot_kind,omitempty"` + PivotColumns []string `json:"pivot_columns,omitempty"` + PivotFamily string `json:"pivot_family,omitempty"` + PivotColumnSelect string `json:"pivot_column_selector,omitempty"` + PivotValueSelect string `json:"pivot_value_selector,omitempty"` +} + +// Read-side auth path discovery request type. +type AuthResourcePathOptions struct { + arangostore.ConnectionOptions + Project string + CursorBatch int +} + +// Read-side reference discovery request and response types. +type PopulatedReferenceOptions struct { + arangostore.ConnectionOptions + Project string + AuthResourcePaths []string + FromType string + NodeType string + Mode string + CursorBatch int +} + +type PopulatedReference struct { + FromType string `json:"from_type"` + Label string `json:"label"` + ToType string `json:"to_type"` + EdgeCount int64 `json:"edge_count"` +} + +// Write-side field profiling state. +type Profiler struct { + project string + authResourcePath string + resourceType string + shapeCache *ShapePlanCache + stats map[string]*fieldCatalogStats +} + +type fieldCatalogStats struct { + path string + kind string + docCount int64 + distinctValues []string + distinctSet map[string]struct{} + distinctTruncated bool + pivotCandidate bool + pivotKind string + pivotColumns []string + pivotColumnSet map[string]struct{} + pivotFamily string + pivotColumnSelect string + pivotValueSelect string +} + +// Shared write-side shape planning cache. +type ShapePlanCache struct { + mu sync.RWMutex + plans map[string]*shapePlan +} + +type shapePlan struct { + fields []*fieldPlan +} + +type fieldPlan struct { + Path string + Kind string + Accessor []pathStep + PivotCandidate bool + PivotKind string +} + +type pathStep struct { + field string + iterateArray bool +} diff --git a/internal/catalog/write_persist.go b/internal/catalog/write_persist.go new file mode 100644 index 0000000..71c4652 --- /dev/null +++ b/internal/catalog/write_persist.go @@ -0,0 +1,41 @@ +package catalog + +import ( + "context" + "encoding/json" + "time" + + arangostore "github.com/calypr/loom/internal/store/arango" + + "github.com/bytedance/sonic" +) + +func WriteFieldCatalog(ctx context.Context, client *arangostore.Client, collection string, docs []FieldCatalogDocument, batchSize int, overwrite bool, writeAPI string, timings map[string]float64) error { + if len(docs) == 0 { + return nil + } + + start := time.Now() + rawDocs := make([]json.RawMessage, 0, len(docs)) + for _, doc := range docs { + data, err := sonic.ConfigFastest.Marshal(&doc) + if err != nil { + return err + } + rawDocs = append(rawDocs, json.RawMessage(data)) + } + timings["field_catalog_marshal"] += time.Since(start).Seconds() + + for i := 0; i < len(rawDocs); i += batchSize { + end := i + batchSize + if end > len(rawDocs) { + end = len(rawDocs) + } + insertStart := time.Now() + if err := client.InsertBatchRaw(ctx, collection, rawDocs[i:end], overwrite, writeAPI); err != nil { + return err + } + timings["field_catalog_insert"] += time.Since(insertStart).Seconds() + } + return nil +} diff --git a/internal/catalog/write_profiler.go b/internal/catalog/write_profiler.go new file mode 100644 index 0000000..bc2fbab --- /dev/null +++ b/internal/catalog/write_profiler.go @@ -0,0 +1,399 @@ +package catalog + +import ( + "slices" + "sort" + "strings" + "time" + + "github.com/calypr/loom/internal/fhirschema" +) + +func NewShapePlanCache() *ShapePlanCache { + return &ShapePlanCache{plans: make(map[string]*shapePlan)} +} + +func NewProfiler(project, authResourcePath, resourceType string, cache *ShapePlanCache) *Profiler { + return &Profiler{ + project: project, + authResourcePath: authResourcePath, + resourceType: resourceType, + shapeCache: cache, + stats: make(map[string]*fieldCatalogStats), + } +} + +func (p *Profiler) ObservePayload(payload map[string]any, timings map[string]float64) { + if payload == nil { + return + } + fingerprintStart := time.Now() + fingerprint := shapeFingerprintForValue(payload) + timings["field_shape_fingerprint"] += time.Since(fingerprintStart).Seconds() + + planStart := time.Now() + plan := p.shapeCache.getOrBuild(fingerprint, payload) + timings["field_shape_plan"] += time.Since(planStart).Seconds() + + observeStart := time.Now() + for _, field := range plan.fields { + values, ok := extractAccessorValues(payload, field.Accessor) + if !ok { + continue + } + stat := p.ensureStat(field) + stat.docCount++ + switch field.Kind { + case fieldKindScalar: + for _, value := range values { + if text, ok := scalarStringValue(value); ok { + stat.addDistinct(text) + } + } + case fieldKindCodeableConcept: + for _, value := range values { + if cc, ok := value.(map[string]any); ok { + for _, col := range codeableConceptColumns(cc) { + stat.addPivotColumn(col) + stat.addDistinct(col) + } + } + } + } + } + p.observeObservationCodePivot(payload) + timings["field_profile"] += time.Since(observeStart).Seconds() +} + +func (p *Profiler) Merge(other *Profiler) { + for path, otherStat := range other.stats { + stat, ok := p.stats[path] + if !ok { + stat = &fieldCatalogStats{ + path: otherStat.path, + kind: otherStat.kind, + pivotCandidate: otherStat.pivotCandidate, + pivotKind: otherStat.pivotKind, + pivotFamily: otherStat.pivotFamily, + pivotColumnSelect: otherStat.pivotColumnSelect, + pivotValueSelect: otherStat.pivotValueSelect, + distinctSet: make(map[string]struct{}), + pivotColumnSet: make(map[string]struct{}), + } + p.stats[path] = stat + } + stat.docCount += otherStat.docCount + stat.distinctTruncated = stat.distinctTruncated || otherStat.distinctTruncated + stat.setPivotDefaults(otherStat.pivotFamily, otherStat.pivotColumnSelect, otherStat.pivotValueSelect) + for _, value := range otherStat.distinctValues { + stat.addDistinct(value) + } + for _, value := range otherStat.pivotColumns { + stat.addPivotColumn(value) + } + } +} + +func (p *Profiler) Documents() []FieldCatalogDocument { + out := make([]FieldCatalogDocument, 0, len(p.stats)) + paths := make([]string, 0, len(p.stats)) + for path := range p.stats { + paths = append(paths, path) + } + sort.Strings(paths) + for _, path := range paths { + stat := p.stats[path] + distinctValues := append([]string(nil), stat.distinctValues...) + pivotColumns := append([]string(nil), stat.pivotColumns...) + slices.Sort(distinctValues) + slices.Sort(pivotColumns) + out = append(out, FieldCatalogDocument{ + Key: fieldCatalogKey(p.project, p.authResourcePath, p.resourceType, stat.path), + Project: p.project, + AuthResourcePath: p.authResourcePath, + ResourceType: p.resourceType, + Path: stat.path, + Kind: stat.kind, + DocCount: stat.docCount, + SampleCount: len(distinctValues), + DistinctValues: distinctValues, + DistinctTruncated: stat.distinctTruncated, + PivotCandidate: stat.pivotCandidate, + PivotKind: stat.pivotKind, + PivotColumns: pivotColumns, + PivotFamily: stat.pivotFamily, + PivotColumnSelect: stat.pivotColumnSelect, + PivotValueSelect: stat.pivotValueSelect, + }) + } + return out +} + +func (p *Profiler) ensureStat(field *fieldPlan) *fieldCatalogStats { + if stat, ok := p.stats[field.Path]; ok { + return stat + } + stat := &fieldCatalogStats{ + path: field.Path, + kind: field.Kind, + pivotCandidate: field.PivotCandidate, + pivotKind: field.PivotKind, + distinctSet: make(map[string]struct{}), + pivotColumnSet: make(map[string]struct{}), + } + if field.PivotCandidate { + if spec, ok := fhirschema.DefaultPivotSpec(p.resourceType, field.Path, ""); ok { + stat.pivotFamily = spec.Family + stat.pivotColumnSelect = fhirschema.SelectorExpression(spec.ColumnSelector) + stat.pivotValueSelect = fhirschema.SelectorExpression(spec.ValueSelector) + } + } + p.stats[field.Path] = stat + return stat +} + +func (s *fieldCatalogStats) addDistinct(value string) { + value = strings.TrimSpace(value) + if value == "" { + return + } + if _, ok := s.distinctSet[value]; ok { + return + } + if len(s.distinctValues) >= fieldCatalogDistinctCap { + s.distinctTruncated = true + return + } + s.distinctSet[value] = struct{}{} + s.distinctValues = append(s.distinctValues, value) +} + +func (s *fieldCatalogStats) addPivotColumn(value string) { + value = strings.TrimSpace(value) + if value == "" { + return + } + if _, ok := s.pivotColumnSet[value]; ok { + return + } + if len(s.pivotColumns) >= fieldCatalogPivotCap { + s.distinctTruncated = true + return + } + s.pivotColumnSet[value] = struct{}{} + s.pivotColumns = append(s.pivotColumns, value) +} + +func (s *fieldCatalogStats) setPivotDefaults(family string, columnSelector string, valueSelector string) { + if strings.TrimSpace(family) != "" { + s.pivotFamily = family + } + if strings.TrimSpace(columnSelector) != "" { + s.pivotColumnSelect = columnSelector + } + if strings.TrimSpace(valueSelector) != "" { + s.pivotValueSelect = valueSelector + } +} + +func (c *ShapePlanCache) getOrBuild(fingerprint string, payload map[string]any) *shapePlan { + c.mu.RLock() + plan, ok := c.plans[fingerprint] + c.mu.RUnlock() + if ok { + return plan + } + c.mu.Lock() + defer c.mu.Unlock() + if plan, ok = c.plans[fingerprint]; ok { + return plan + } + plan = buildShapePlan(payload) + c.plans[fingerprint] = plan + return plan +} + +func buildShapePlan(payload map[string]any) *shapePlan { + fieldMap := make(map[string]*fieldPlan) + walkShapeValue(payload, nil, "", fieldMap) + paths := make([]string, 0, len(fieldMap)) + for path := range fieldMap { + paths = append(paths, path) + } + sort.Strings(paths) + fields := make([]*fieldPlan, 0, len(paths)) + for _, path := range paths { + fields = append(fields, fieldMap[path]) + } + return &shapePlan{fields: fields} +} + +func walkShapeValue(value any, accessor []pathStep, path string, fieldMap map[string]*fieldPlan) { + switch typed := value.(type) { + case map[string]any: + if path != "" { + kind, pivotCandidate, pivotKind := classifyObjectShape(typed) + addFieldPlan(fieldMap, path, accessor, kind, pivotCandidate, pivotKind) + } + keys := sortedKeys(typed) + for _, key := range keys { + child := typed[key] + if child == nil { + continue + } + switch childTyped := child.(type) { + case []any: + arrayPath := appendPath(path, key, true) + arrayAccessor := appendAccessor(accessor, pathStep{field: key, iterateArray: true}) + addFieldPlan(fieldMap, arrayPath, arrayAccessor, fieldKindArray, false, "") + for _, item := range childTyped { + if item == nil { + continue + } + walkShapeValue(item, arrayAccessor, arrayPath, fieldMap) + } + default: + childPath := appendPath(path, key, false) + childAccessor := appendAccessor(accessor, pathStep{field: key}) + walkShapeValue(child, childAccessor, childPath, fieldMap) + } + } + case []any: + if path != "" { + addFieldPlan(fieldMap, path, accessor, fieldKindArray, false, "") + } + for _, item := range typed { + if item == nil { + continue + } + walkShapeValue(item, accessor, path, fieldMap) + } + default: + if path != "" { + addFieldPlan(fieldMap, path, accessor, fieldKindScalar, false, "") + } + } +} + +func addFieldPlan(fieldMap map[string]*fieldPlan, path string, accessor []pathStep, kind string, pivotCandidate bool, pivotKind string) { + if existing, ok := fieldMap[path]; ok { + if existing.Kind == fieldKindObject && (kind == fieldKindCodeableConcept || kind == fieldKindCoding) { + existing.Kind = kind + } + if existing.Kind == fieldKindArray && kind != fieldKindArray { + return + } + if pivotCandidate { + existing.PivotCandidate = true + existing.PivotKind = pivotKind + } + return + } + copiedAccessor := append([]pathStep(nil), accessor...) + fieldMap[path] = &fieldPlan{ + Path: path, + Kind: kind, + Accessor: copiedAccessor, + PivotCandidate: pivotCandidate, + PivotKind: pivotKind, + } +} + +func classifyObjectShape(value map[string]any) (string, bool, string) { + if isCodeableConceptShape(value) { + return fieldKindCodeableConcept, true, pivotKindCodeableConcept + } + if isCodingShape(value) { + return fieldKindCoding, false, "" + } + return fieldKindObject, false, "" +} + +func isCodeableConceptShape(value map[string]any) bool { + _, hasCoding := value["coding"] + _, hasText := value["text"] + return hasCoding || hasText +} + +func isCodingShape(value map[string]any) bool { + _, hasSystem := value["system"] + _, hasCode := value["code"] + _, hasDisplay := value["display"] + return hasSystem || hasCode || hasDisplay +} + +func (p *Profiler) observeObservationCodePivot(payload map[string]any) { + if p.resourceType != "Observation" { + return + } + codeValue, ok := payload["code"].(map[string]any) + if !ok { + return + } + valueSelector := observationValueSelectorFromPayload(payload) + if valueSelector == "" { + return + } + stat, ok := p.stats["code"] + if !ok { + stat = &fieldCatalogStats{ + path: "code", + kind: fieldKindCodeableConcept, + pivotCandidate: true, + pivotKind: pivotKindObservation, + distinctSet: make(map[string]struct{}), + pivotColumnSet: make(map[string]struct{}), + } + p.stats["code"] = stat + } + stat.pivotCandidate = true + stat.pivotKind = pivotKindObservation + stat.setPivotDefaults(fhirschema.PivotFamilyObservationCodeValue, "code.coding[].display", valueSelector) + for _, col := range codeableConceptColumns(codeValue) { + stat.addPivotColumn(col) + } +} + +func observationValueSelectorFromPayload(payload map[string]any) string { + if value, ok := payload["valueQuantity"].(map[string]any); ok && value["value"] != nil { + return "valueQuantity.value" + } + if value, ok := payload["valueCodeableConcept"].(map[string]any); ok { + if strings.TrimSpace(stringValue(value["text"])) != "" { + return "valueCodeableConcept.text" + } + if len(codeableConceptColumns(value)) > 0 { + return "valueCodeableConcept.coding[].display" + } + } + for _, name := range []string{"valueString", "valueInteger", "valueBoolean", "valueDecimal", "valueDateTime", "valueTime"} { + if payload[name] != nil { + return name + } + } + if value, ok := payload["valuePeriod"].(map[string]any); ok { + if value["start"] != nil { + return "valuePeriod.start" + } + if value["end"] != nil { + return "valuePeriod.end" + } + } + if value, ok := payload["valueRange"].(map[string]any); ok { + if low, ok := value["low"].(map[string]any); ok && low["value"] != nil { + return "valueRange.low.value" + } + if high, ok := value["high"].(map[string]any); ok && high["value"] != nil { + return "valueRange.high.value" + } + } + if value, ok := payload["valueRatio"].(map[string]any); ok { + if num, ok := value["numerator"].(map[string]any); ok && num["value"] != nil { + return "valueRatio.numerator.value" + } + if den, ok := value["denominator"].(map[string]any); ok && den["value"] != nil { + return "valueRatio.denominator.value" + } + } + return "" +} diff --git a/internal/catalog/field_catalog_test.go b/internal/catalog/write_profiler_test.go similarity index 97% rename from internal/catalog/field_catalog_test.go rename to internal/catalog/write_profiler_test.go index 77b5196..d57ac99 100644 --- a/internal/catalog/field_catalog_test.go +++ b/internal/catalog/write_profiler_test.go @@ -4,7 +4,7 @@ import ( "slices" "testing" - "arangodb-proto/internal/fhirschema" + "github.com/calypr/loom/internal/fhirschema" ) func TestFieldCatalogProfilerCanonicalPaths(t *testing.T) { @@ -80,10 +80,6 @@ func TestFieldCatalogShapeCacheReusesPlans(t *testing.T) { profiler.ObservePayload(first, timings) profiler.ObservePayload(second, timings) - if got := cache.planCount(); got != 1 { - t.Fatalf("shape cache plan count = %d, want 1", got) - } - docs := profiler.Documents() docByPath := make(map[string]FieldCatalogDocument) for _, doc := range docs { diff --git a/internal/dataframe/auth.go b/internal/dataframe/auth.go new file mode 100644 index 0000000..7d8655e --- /dev/null +++ b/internal/dataframe/auth.go @@ -0,0 +1,51 @@ +package dataframe + +import ( + "context" + "fmt" + + "github.com/calypr/loom/internal/authscope" +) + +func (s *Service) resolveAuthResourcePaths(ctx context.Context, principal *authscope.Principal, project string, requested []string) ([]string, error) { + if s.scopeResolver != nil { + return s.scopeResolver.ResolveReadAuthResourcePaths(ctx, principal, project, requested) + } + if len(requested) == 0 { + if principal == nil || len(principal.AuthResourcePaths) == 0 { + return nil, nil + } + return append([]string(nil), principal.AuthResourcePaths...), nil + } + if principal == nil || len(principal.AuthResourcePaths) == 0 { + return append([]string(nil), requested...), nil + } + for _, path := range requested { + found := false + for _, candidate := range principal.AuthResourcePaths { + if candidate == path { + found = true + break + } + } + if !found { + return nil, fmt.Errorf("authResourcePath %q is outside caller scope", path) + } + } + return append([]string(nil), requested...), nil +} + +func authorizeProject(principal *authscope.Principal, project string, ignorePrincipalProjects bool) error { + if ignorePrincipalProjects { + return nil + } + if principal == nil || len(principal.Projects) == 0 { + return nil + } + for _, candidate := range principal.Projects { + if candidate == project { + return nil + } + } + return fmt.Errorf("principal is not authorized for project %q", project) +} diff --git a/internal/dataframe/builder_types.go b/internal/dataframe/builder_types.go new file mode 100644 index 0000000..813060a --- /dev/null +++ b/internal/dataframe/builder_types.go @@ -0,0 +1,80 @@ +package dataframe + +type Builder struct { + Project string + AuthResourcePaths []string + RootResourceType string + PlanHint *PlanHint + Fields []FieldSelect + Pivots []PivotSelect + Aggregates []AggregateSelect + Slices []RepresentativeSlice + Traversals []TraversalStep + Sets []NamedSet + DerivedFields []DerivedField + RepresentativeSlices []RepresentativeSlice +} + +type TraversalStep struct { + Label string + ToResourceType string + Alias string + Fields []FieldSelect + Pivots []PivotSelect + Aggregates []AggregateSelect + Slices []RepresentativeSlice + Traversals []TraversalStep + Sets []NamedSet + DerivedFields []DerivedField + RepresentativeSlices []RepresentativeSlice +} + +type FieldSelect struct { + Name string + FieldRef string + Select string + FallbackFieldRefs []string + FallbackSelects []string + ValueMode string +} + +type PivotSelect struct { + Name string + FieldRef string + ColumnSelect string + ValueSelect string + Columns []string + PivotFamily string +} + +type AggregateSelect struct { + Name string + Operation string + FieldRef string + Select string + PredicateFieldRef string + PredicatePath string + PredicateEquals string + ValueMode string +} + +type RunRequest struct { + Builder Builder + Limit int +} + +type Result struct { + Columns []string + Rows []map[string]any + RowCount int +} + +func cloneStrings(in []string) []string { + if in == nil { + return nil + } + if len(in) == 0 { + return []string{} + } + return append([]string(nil), in...) +} diff --git a/internal/dataframe/compile.go b/internal/dataframe/compile.go new file mode 100644 index 0000000..9166f15 --- /dev/null +++ b/internal/dataframe/compile.go @@ -0,0 +1,70 @@ +package dataframe + +import "fmt" + +type CompiledQuery struct { + Project string + RootResourceType string + AuthResourcePaths []string + PlanMode string + PlanProfile string + NamedSetCount int + FileSummaries bool + StudyLookup bool + Query string + BindVars map[string]any + Columns []string + PivotFields []string + Limit int +} + +func Compile(builder Builder, limit int) (CompiledQuery, error) { + if usesLoweredBuilder(builder) { + return compileLowered(builder, limit) + } + return CompiledQuery{}, fmt.Errorf("unsupported dataframe query shape: request was not lowered into the optimized lowered plan") +} + +func planMode(hint *PlanHint) string { + if hint == nil || hint.Mode == "" { + return "unsupported" + } + return hint.Mode +} + +func planProfile(hint *PlanHint) string { + if hint == nil { + return "" + } + return hint.Profile +} + +func planNamedSetCount(hint *PlanHint) int { + if hint == nil { + return 0 + } + return hint.NamedSetCount +} + +func planFileSummaries(hint *PlanHint) bool { + if hint == nil { + return false + } + return hint.ClassifiedFileSummaries +} + +func planStudyLookup(hint *PlanHint) bool { + if hint == nil { + return false + } + return hint.StudyLookup +} + +type compiler struct { + builder Builder + bindVars map[string]any + columns []string + pivotFields []string + bindCount int + pivotExprs map[string]string +} diff --git a/internal/dataframe/compile_fields.go b/internal/dataframe/compile_fields.go new file mode 100644 index 0000000..dca8fdd --- /dev/null +++ b/internal/dataframe/compile_fields.go @@ -0,0 +1,202 @@ +package dataframe + +import ( + "fmt" + "strings" +) + +func (c *compiler) compileTraversal(parentVar string, parentIsArray bool, step TraversalStep, lets *[]string, objectLines *[]string) error { + labelBind := c.newBind(step.Alias+"_label", step.Label) + toBind := c.newBind(step.Alias+"_to", step.ToResourceType) + nodeVar := sanitizeColumnName(step.Alias) + "_nodes" + var let string + if parentIsArray { + let = fmt.Sprintf(" LET %s = UNIQUE(FLATTEN(FOR __parent IN %s FOR __node, __edge IN 1..1 INBOUND __parent fhir_edge FILTER __edge.project == @project FILTER @auth_resource_paths_unrestricted == true OR (__edge.auth_resource_path IN @auth_resource_paths AND __node.auth_resource_path IN @auth_resource_paths) FILTER __edge.label == @%s FILTER __node.resourceType == @%s RETURN [__node]))", nodeVar, parentVar, labelBind, toBind) + } else { + let = fmt.Sprintf(" LET %s = UNIQUE(FOR __node, __edge IN 1..1 INBOUND %s fhir_edge FILTER __edge.project == @project FILTER @auth_resource_paths_unrestricted == true OR (__edge.auth_resource_path IN @auth_resource_paths AND __node.auth_resource_path IN @auth_resource_paths) FILTER __edge.label == @%s FILTER __node.resourceType == @%s RETURN __node)", nodeVar, parentVar, labelBind, toBind) + } + *lets = append(*lets, let) + for _, field := range step.Fields { + sel, _ := ParseSelector(field.Select) + expr, err := c.compileTraversalFieldSelect(nodeVar, field, sel) + if err != nil { + return err + } + colName := sanitizeColumnName(step.Alias + "__" + field.Name) + *objectLines = append(*objectLines, fmt.Sprintf(" %s: %s", quoteKey(colName), expr)) + c.columns = append(c.columns, colName) + } + for _, pivot := range step.Pivots { + keySel, _ := ParseSelector(pivot.ColumnSelect) + valueSel, _ := ParseSelector(pivot.ValueSelect) + colName := sanitizeColumnName(step.Alias + "__" + pivot.Name) + expr, err := c.compileTraversalPivot(nodeVar, keySel, valueSel, pivot.Columns) + if err != nil { + return err + } + *objectLines = append(*objectLines, fmt.Sprintf(" %s: %s", quoteKey(colName), expr)) + c.columns = append(c.columns, colName) + c.pivotFields = append(c.pivotFields, colName) + } + for _, agg := range step.Aggregates { + expr, err := c.compileSetAggregateExpr(nodeVar, agg) + if err != nil { + return err + } + colName := sanitizeColumnName(step.Alias + "__" + agg.Name) + *objectLines = append(*objectLines, fmt.Sprintf(" %s: %s", quoteKey(colName), expr)) + c.columns = append(c.columns, colName) + } + for _, slice := range step.Slices { + expr, err := c.compileSetSlice(nodeVar, setModeNode, slice) + if err != nil { + return err + } + colName := sanitizeColumnName(step.Alias + "__" + slice.Name) + *objectLines = append(*objectLines, fmt.Sprintf(" %s: %s", quoteKey(colName), expr)) + c.columns = append(c.columns, colName) + } + for _, child := range step.Traversals { + if err := c.compileTraversal(nodeVar, true, child, lets, objectLines); err != nil { + return err + } + } + return nil +} + +func (c *compiler) compileRootFieldSelect(payloadVar string, field FieldSelect, sel Selector) (string, error) { + if len(field.FallbackSelects) > 0 { + return c.compileFirstNonNullExpr(payloadVar, append([]string{field.Select}, field.FallbackSelects...)), nil + } + return c.compileRootField(payloadVar, sel) +} + +func (c *compiler) compileRootField(payloadVar string, sel Selector) (string, error) { + if sel.Filter == nil && selectorHasNoArrays(sel) { + return compileDirectExpr(payloadVar, sel.Steps), nil + } + return "FIRST" + compileSelectorArrayExpr(payloadVar, sel, c), nil +} + +func (c *compiler) compileTraversalFieldSelect(nodeVar string, field FieldSelect, sel Selector) (string, error) { + if len(field.FallbackSelects) > 0 { + tmp := DerivedField{ + Source: nodeVar, + Select: field.Select, + FallbackSelects: field.FallbackSelects, + } + return c.compileUniqueField("", tmp, map[string]setMode{nodeVar: setModeNode}) + } + return c.compileTraversalField(nodeVar, sel) +} + +func (c *compiler) compileTraversalField(nodeVar string, sel Selector) (string, error) { + return fmt.Sprintf("UNIQUE(FLATTEN(FOR __n IN %s RETURN %s))", nodeVar, compileSelectorArrayExpr("__n.payload", sel, c)), nil +} + +func (c *compiler) compileRootPivot(payloadVar string, keySel Selector, valueSel Selector, columns []string) (string, error) { + return c.compilePivotMapExpr("FOR __item IN ["+payloadVar+"]", "__item", keySel, valueSel, columns) +} + +func (c *compiler) compileTraversalPivot(nodeVar string, keySel Selector, valueSel Selector, columns []string) (string, error) { + return c.compilePivotMapExpr("FOR __item IN "+nodeVar, "__item.payload", keySel, valueSel, columns) +} + +func selectorHasNoArrays(sel Selector) bool { + for _, step := range sel.Steps { + if step.Iterate || step.Index != nil { + return false + } + } + return true +} + +func compileDirectExpr(rootVar string, steps []SelectorStep) string { + cur := rootVar + for _, step := range steps { + if step.Index != nil { + cur = fmt.Sprintf("((%s.%s ? %s.%s : [])[%d])", cur, step.Field, cur, step.Field, *step.Index) + continue + } + cur = fmt.Sprintf("%s.%s", cur, step.Field) + } + return cur +} + +func compileSelectorArrayExpr(rootVar string, sel Selector, c *compiler) string { + prefix := sel.Steps + if len(prefix) == 0 { + return "[]" + } + last := prefix[len(prefix)-1] + prefix = prefix[:len(prefix)-1] + lines := []string{fmt.Sprintf("FOR __root IN [%s]", rootVar)} + cur := "__root" + tmpCount := 0 + for _, step := range prefix { + next := fmt.Sprintf("__s%d", tmpCount) + tmpCount++ + switch { + case step.Iterate: + lines = append(lines, fmt.Sprintf(" FOR %s IN (%s.%s ? %s.%s : [])", next, cur, step.Field, cur, step.Field)) + case step.Index != nil: + lines = append(lines, fmt.Sprintf(" LET %s = ((%s.%s ? %s.%s : [])[%d])", next, cur, step.Field, cur, step.Field, *step.Index)) + lines = append(lines, fmt.Sprintf(" FILTER %s != null", next)) + default: + lines = append(lines, fmt.Sprintf(" LET %s = %s.%s", next, cur, step.Field)) + lines = append(lines, fmt.Sprintf(" FILTER %s != null", next)) + } + cur = next + } + if sel.Filter != nil { + filterBind := c.newBind("contains", sel.Filter.Needle) + lines = append(lines, fmt.Sprintf(" FILTER CONTAINS(%s.%s ? %s.%s : \"\", @%s)", cur, sel.Filter.Field, cur, sel.Filter.Field, filterBind)) + } + finalExpr := extractFinalExpr(cur, last) + lines = append(lines, fmt.Sprintf(" LET __value = %s", finalExpr)) + lines = append(lines, " FILTER __value != null") + lines = append(lines, " RETURN __value") + return "(\n " + strings.Join(lines, "\n ") + "\n )" +} + +func (c *compiler) compilePivotMapExpr(itemLoop string, payloadVar string, keySel Selector, valueSel Selector, columns []string) (string, error) { + keyExpr := compileSelectorArrayExpr(payloadVar, keySel, c) + valueExpr := compileSelectorArrayExpr(payloadVar, valueSel, c) + filterLine := "" + if len(columns) > 0 { + colBind := c.newBind("pivot_cols", append([]string(nil), columns...)) + filterLine = fmt.Sprintf("\n FILTER POSITION(@%s, __key, true)", colBind) + } + return fmt.Sprintf(`MERGE( + FOR __pair IN ( + %s + LET __keys = UNIQUE(%s) + LET __values = %s + FILTER LENGTH(__values) > 0 + FOR __key IN __keys%s + RETURN { key: __key, values: __values } + ) + COLLECT __key = __pair.key INTO __group + LET __flat_values = UNIQUE(FLATTEN(__group[*].__pair.values)) + FILTER LENGTH(__flat_values) > 0 + RETURN { [__key]: FIRST(__flat_values) } + )`, itemLoop, keyExpr, valueExpr, filterLine), nil +} + +func extractFinalExpr(cur string, step SelectorStep) string { + switch { + case step.Iterate: + return fmt.Sprintf("(%s.%s ? %s.%s : [])", cur, step.Field, cur, step.Field) + case step.Index != nil: + return fmt.Sprintf("((%s.%s ? %s.%s : [])[%d])", cur, step.Field, cur, step.Field, *step.Index) + default: + return fmt.Sprintf("%s.%s", cur, step.Field) + } +} + +func (c *compiler) newBind(prefix string, value any) string { + name := fmt.Sprintf("__%s_%d", sanitizeColumnName(prefix), c.bindCount) + c.bindCount++ + c.bindVars[name] = value + return name +} diff --git a/internal/dataframe/dataframe.go b/internal/dataframe/dataframe.go deleted file mode 100644 index 743b0da..0000000 --- a/internal/dataframe/dataframe.go +++ /dev/null @@ -1,993 +0,0 @@ -package dataframe - -import ( - "context" - "encoding/json" - "fmt" - "strings" - - "arangodb-proto/internal/fhirschema" - "arangodb-proto/internal/proto" - "arangodb-proto/internal/writeapi" -) - -const defaultRowLimit = 25 - -type Builder struct { - Project string - AuthResourcePaths []string - RootResourceType string - PlanHint *PlanHint - Fields []FieldSelect - Pivots []PivotSelect - Aggregates []AggregateSelect - Slices []RepresentativeSlice - Traversals []TraversalStep - Sets []NamedSet - DerivedFields []DerivedField - RepresentativeSlices []RepresentativeSlice -} - -type TraversalStep struct { - Label string - ToResourceType string - Alias string - Fields []FieldSelect - Pivots []PivotSelect - Aggregates []AggregateSelect - Slices []RepresentativeSlice - Traversals []TraversalStep - Sets []NamedSet - DerivedFields []DerivedField - RepresentativeSlices []RepresentativeSlice -} - -type FieldSelect struct { - Name string - FieldRef string - Select string - FallbackFieldRefs []string - FallbackSelects []string - ValueMode string -} - -type PivotSelect struct { - Name string - FieldRef string - ColumnSelect string - ValueSelect string - Columns []string - PivotFamily string -} - -type AggregateSelect struct { - Name string - Operation string - FieldRef string - Select string - PredicateFieldRef string - PredicatePath string - PredicateEquals string - ValueMode string -} - -type RunRequest struct { - Builder Builder - Limit int -} - -type Result struct { - Columns []string - Rows []map[string]any - RowCount int -} - -type ServiceConfig struct { - ConnectionOptions proto.ConnectionOptions - DiscoverReferences func(context.Context, proto.PopulatedReferenceOptions) ([]proto.PopulatedReference, error) - DiscoverFields func(context.Context, proto.PopulatedFieldOptions) ([]proto.PopulatedField, error) - ExecuteRows func(context.Context, proto.ExecuteQueryOptions, string, map[string]any, func(map[string]any) error) error - ScopeResolver *writeapi.ScopeResolver -} - -type Service struct { - connOpts proto.ConnectionOptions - discoverReferences func(context.Context, proto.PopulatedReferenceOptions) ([]proto.PopulatedReference, error) - discoverFields func(context.Context, proto.PopulatedFieldOptions) ([]proto.PopulatedField, error) - executeRows func(context.Context, proto.ExecuteQueryOptions, string, map[string]any, func(map[string]any) error) error - scopeResolver *writeapi.ScopeResolver -} - -func NewService(cfg ServiceConfig) *Service { - svc := &Service{ - connOpts: cfg.ConnectionOptions, - scopeResolver: cfg.ScopeResolver, - } - if cfg.DiscoverReferences != nil { - svc.discoverReferences = cfg.DiscoverReferences - } else { - svc.discoverReferences = proto.DiscoverPopulatedReferences - } - if cfg.DiscoverFields != nil { - svc.discoverFields = cfg.DiscoverFields - } else { - svc.discoverFields = proto.DiscoverPopulatedFields - } - if cfg.ExecuteRows != nil { - svc.executeRows = cfg.ExecuteRows - } else { - svc.executeRows = proto.ExecuteQueryRows - } - return svc -} - -func (s *Service) Run(ctx context.Context, req RunRequest) (*Result, error) { - if protoBackend := strings.ToLower(strings.TrimSpace(s.connOpts.Backend)); protoBackend != "" && protoBackend != "arango" { - return nil, fmt.Errorf("runFhirDataframe currently supports only backend \"arango\"") - } - - spec, err := s.prepareSpec(ctx, req.Builder) - if err != nil { - return nil, err - } - limit := req.Limit - if limit <= 0 { - limit = defaultRowLimit - } - compiled, err := Compile(spec, limit) - if err != nil { - return nil, err - } - return s.runQuery(ctx, compiled) -} - -func (s *Service) prepareSpec(ctx context.Context, builder Builder) (Builder, error) { - if builder.Project == "" { - return Builder{}, fmt.Errorf("project is required") - } - if builder.RootResourceType == "" { - return Builder{}, fmt.Errorf("rootResourceType is required") - } - principal, _ := writeapi.PrincipalFromContext(ctx) - resolvedPaths, err := s.resolveAuthResourcePaths(ctx, principal, builder.Project, builder.AuthResourcePaths) - if err != nil { - return Builder{}, err - } - if err := authorizeProject(principal, builder.Project, s.scopeResolver != nil); err != nil { - return Builder{}, err - } - builder.AuthResourcePaths = resolvedPaths - if err := s.validateBuilder(ctx, builder); err != nil { - return Builder{}, err - } - expanded, err := s.expandPivotColumns(ctx, builder) - if err != nil { - return Builder{}, err - } - planned, err := lowerGraphQLBuilder(expanded) - if err != nil { - return Builder{}, err - } - if err := validateAdvancedBuilder(planned); err != nil { - return Builder{}, err - } - return planned, nil -} - -func (s *Service) validateBuilder(ctx context.Context, builder Builder) error { - seenAliases := map[string]struct{}{} - rootFields, err := s.discoverFields(ctx, proto.PopulatedFieldOptions{ - ConnectionOptions: s.connOpts, - Project: builder.Project, - AuthResourcePaths: builder.AuthResourcePaths, - ResourceType: builder.RootResourceType, - }) - if err != nil { - return err - } - rootPivots, err := s.discoverFields(ctx, proto.PopulatedFieldOptions{ - ConnectionOptions: s.connOpts, - Project: builder.Project, - AuthResourcePaths: builder.AuthResourcePaths, - ResourceType: builder.RootResourceType, - PivotOnly: true, - }) - if err != nil { - return err - } - if err := validateNodeSelections(builder.Fields, builder.Pivots, builder.Aggregates, builder.Slices, rootFields, rootPivots); err != nil { - return err - } - for _, step := range builder.Traversals { - if err := s.validateTraversal(ctx, builder.Project, builder.AuthResourcePaths, builder.RootResourceType, step, seenAliases); err != nil { - return err - } - } - return nil -} - -func (s *Service) validateTraversal(ctx context.Context, project string, authResourcePaths []string, sourceType string, step TraversalStep, seenAliases map[string]struct{}) error { - if step.Alias == "" { - return fmt.Errorf("traversal alias is required") - } - if _, ok := seenAliases[step.Alias]; ok { - return fmt.Errorf("traversal alias %q is duplicated", step.Alias) - } - seenAliases[step.Alias] = struct{}{} - refs, err := s.discoverReferences(ctx, proto.PopulatedReferenceOptions{ - ConnectionOptions: s.connOpts, - Project: project, - AuthResourcePaths: authResourcePaths, - NodeType: sourceType, - Mode: proto.TraversalModeBuilder, - }) - if err != nil { - return err - } - found := false - for _, ref := range refs { - if ref.Label == step.Label && ref.ToType == step.ToResourceType { - found = true - break - } - } - if !found { - return fmt.Errorf("traversal %s -> %s (%s) is not populated", sourceType, step.ToResourceType, step.Label) - } - fields, err := s.discoverFields(ctx, proto.PopulatedFieldOptions{ - ConnectionOptions: s.connOpts, - Project: project, - AuthResourcePaths: authResourcePaths, - ResourceType: step.ToResourceType, - }) - if err != nil { - return err - } - pivotFields, err := s.discoverFields(ctx, proto.PopulatedFieldOptions{ - ConnectionOptions: s.connOpts, - Project: project, - AuthResourcePaths: authResourcePaths, - ResourceType: step.ToResourceType, - PivotOnly: true, - }) - if err != nil { - return err - } - if err := validateNodeSelections(step.Fields, step.Pivots, step.Aggregates, step.Slices, fields, pivotFields); err != nil { - return fmt.Errorf("alias %s: %w", step.Alias, err) - } - for _, child := range step.Traversals { - if err := s.validateTraversal(ctx, project, authResourcePaths, step.ToResourceType, child, seenAliases); err != nil { - return err - } - } - return nil -} - -func validateNodeSelections(fields []FieldSelect, pivots []PivotSelect, aggregates []AggregateSelect, slices []RepresentativeSlice, discovered []proto.PopulatedField, pivotable []proto.PopulatedField) error { - seenFields := map[string]struct{}{} - for _, field := range fields { - if field.Name == "" || field.Select == "" { - return fmt.Errorf("field selections require name and select") - } - if _, ok := seenFields[field.Name]; ok { - return fmt.Errorf("field name %q is duplicated", field.Name) - } - seenFields[field.Name] = struct{}{} - if _, err := ParseSelector(field.Select); err != nil { - return fmt.Errorf("invalid selector for field %q: %w", field.Name, err) - } - for _, fallback := range field.FallbackSelects { - if _, err := ParseSelector(fallback); err != nil { - return fmt.Errorf("invalid fallback selector for field %q: %w", field.Name, err) - } - } - } - seenPivots := map[string]struct{}{} - for _, pivot := range pivots { - if pivot.Name == "" || pivot.ColumnSelect == "" || pivot.ValueSelect == "" { - return fmt.Errorf("pivot selections require name, column selector, and value selector") - } - if _, ok := seenPivots[pivot.Name]; ok { - return fmt.Errorf("pivot name %q is duplicated", pivot.Name) - } - seenPivots[pivot.Name] = struct{}{} - columnSel, err := ParseSelector(pivot.ColumnSelect) - if err != nil { - return fmt.Errorf("invalid column selector for pivot %q: %w", pivot.Name, err) - } - valueSel, err := ParseSelector(pivot.ValueSelect) - if err != nil { - return fmt.Errorf("invalid value selector for pivot %q: %w", pivot.Name, err) - } - pivotSpec, err := fhirschema.ValidatePivotSelectors(resourceTypeFromDiscovered(discovered), selectorSpecFromSelector(columnSel), selectorSpecFromSelector(valueSel)) - if err != nil { - return fmt.Errorf("pivot %q: %w", pivot.Name, err) - } - match := findFieldByPath(pivotable, pivotRootPath(resourceTypeFromDiscovered(discovered), pivotSpec.Family, columnSel.CanonicalPath())) - if match == nil || !match.PivotCandidate { - return fmt.Errorf("pivot selector %q is not pivotable", pivot.ColumnSelect) - } - if len(pivot.Columns) == 0 && len(match.PivotColumns) == 0 { - return fmt.Errorf("pivot %q has no available pivot columns", pivot.Name) - } - pivot.PivotFamily = pivotSpec.Family - } - seenAggregates := map[string]struct{}{} - for _, agg := range aggregates { - if strings.TrimSpace(agg.Name) == "" { - return fmt.Errorf("aggregate selections require name") - } - if _, ok := seenAggregates[agg.Name]; ok { - return fmt.Errorf("aggregate name %q is duplicated", agg.Name) - } - seenAggregates[agg.Name] = struct{}{} - switch strings.ToUpper(strings.TrimSpace(agg.Operation)) { - case "COUNT", "COUNT_DISTINCT", "EXISTS", "DISTINCT_VALUES": - default: - return fmt.Errorf("aggregate %q uses unsupported operation %q", agg.Name, agg.Operation) - } - if strings.TrimSpace(agg.Select) != "" { - sel, err := ParseSelector(agg.Select) - if err != nil { - return fmt.Errorf("invalid aggregate selector for %q: %w", agg.Name, err) - } - if findFieldByPath(discovered, sel.CanonicalPath()) == nil { - return fmt.Errorf("aggregate selector %q is not present in populated fields", agg.Select) - } - } - if strings.TrimSpace(agg.PredicatePath) != "" { - sel, err := ParseSelector(agg.PredicatePath) - if err != nil { - return fmt.Errorf("invalid aggregate predicate selector for %q: %w", agg.Name, err) - } - if findFieldByPath(discovered, sel.CanonicalPath()) == nil { - return fmt.Errorf("aggregate predicate selector %q is not present in populated fields", agg.PredicatePath) - } - } - } - seenSlices := map[string]struct{}{} - for _, slice := range slices { - if strings.TrimSpace(slice.Name) == "" { - return fmt.Errorf("representative slices require name") - } - if _, ok := seenSlices[slice.Name]; ok { - return fmt.Errorf("representative slice name %q is duplicated", slice.Name) - } - seenSlices[slice.Name] = struct{}{} - if slice.Limit <= 0 { - return fmt.Errorf("representative slice %q requires positive limit", slice.Name) - } - if strings.TrimSpace(slice.PredicatePath) != "" { - sel, err := ParseSelector(slice.PredicatePath) - if err != nil { - return fmt.Errorf("invalid representative slice predicate for %q: %w", slice.Name, err) - } - if findFieldByPath(discovered, sel.CanonicalPath()) == nil { - return fmt.Errorf("representative slice predicate %q is not present in populated fields", slice.PredicatePath) - } - } - for _, field := range slice.Fields { - if strings.TrimSpace(field.Name) == "" || strings.TrimSpace(field.Select) == "" { - return fmt.Errorf("representative slice %q requires fields with name and select", slice.Name) - } - sel, err := ParseSelector(field.Select) - if err != nil { - return fmt.Errorf("invalid representative slice field for %q: %w", slice.Name, err) - } - if findFieldByPath(discovered, sel.CanonicalPath()) == nil { - return fmt.Errorf("representative slice selector %q is not present in populated fields", field.Select) - } - for _, fallback := range field.FallbackSelects { - fallbackSel, err := ParseSelector(fallback) - if err != nil { - return fmt.Errorf("invalid representative slice fallback selector for %q: %w", slice.Name, err) - } - if findFieldByPath(discovered, fallbackSel.CanonicalPath()) == nil { - return fmt.Errorf("representative slice fallback selector %q is not present in populated fields", fallback) - } - } - } - } - for _, field := range fields { - sel, _ := ParseSelector(field.Select) - if findFieldByPath(discovered, sel.CanonicalPath()) == nil { - return fmt.Errorf("selector %q is not present in populated fields", field.Select) - } - for _, fallback := range field.FallbackSelects { - fallbackSel, _ := ParseSelector(fallback) - if findFieldByPath(discovered, fallbackSel.CanonicalPath()) == nil { - return fmt.Errorf("fallback selector %q is not present in populated fields", fallback) - } - } - } - return nil -} - -func (s *Service) expandPivotColumns(ctx context.Context, builder Builder) (Builder, error) { - pivots, err := s.discoverFields(ctx, proto.PopulatedFieldOptions{ - ConnectionOptions: s.connOpts, - Project: builder.Project, - AuthResourcePaths: builder.AuthResourcePaths, - ResourceType: builder.RootResourceType, - PivotOnly: true, - }) - if err != nil { - return Builder{}, err - } - builder.Pivots = fillPivotColumns(builder.Pivots, pivots) - for i := range builder.Traversals { - if err := s.expandTraversalPivotColumns(ctx, builder.Project, builder.AuthResourcePaths, &builder.Traversals[i]); err != nil { - return Builder{}, err - } - } - return builder, nil -} - -func (s *Service) expandTraversalPivotColumns(ctx context.Context, project string, authResourcePaths []string, step *TraversalStep) error { - pivots, err := s.discoverFields(ctx, proto.PopulatedFieldOptions{ - ConnectionOptions: s.connOpts, - Project: project, - AuthResourcePaths: authResourcePaths, - ResourceType: step.ToResourceType, - PivotOnly: true, - }) - if err != nil { - return err - } - step.Pivots = fillPivotColumns(step.Pivots, pivots) - for i := range step.Traversals { - if err := s.expandTraversalPivotColumns(ctx, project, authResourcePaths, &step.Traversals[i]); err != nil { - return err - } - } - return nil -} - -func fillPivotColumns(in []PivotSelect, discovered []proto.PopulatedField) []PivotSelect { - if len(in) == 0 { - return []PivotSelect{} - } - out := make([]PivotSelect, 0, len(in)) - for _, pivot := range in { - if strings.TrimSpace(pivot.PivotFamily) == "" { - if item := findFieldByPath(discovered, pivotRootPath(resourceTypeFromDiscovered(discovered), pivot.PivotFamily, canonicalColumnSelect(pivot.ColumnSelect))); item != nil { - pivot.PivotFamily = item.PivotFamily - } - } - out = append(out, pivot) - } - return out -} - -func canonicalColumnSelect(expr string) string { - sel, err := ParseSelector(expr) - if err != nil { - return "" - } - return sel.CanonicalPath() -} - -func pivotRootPath(resourceType string, family string, columnCanonical string) string { - if family == fhirschema.PivotFamilyObservationCodeValue || (resourceType == "Observation" && strings.HasPrefix(columnCanonical, "code")) { - return "code" - } - parts := strings.Split(columnCanonical, ".") - for i := len(parts); i > 0; i-- { - path := strings.Join(parts[:i], ".") - if fhirschema.ResolvesToCodeableConcept(resourceType, path) { - return path - } - } - return columnCanonical -} - -func resourceTypeFromDiscovered(fields []proto.PopulatedField) string { - if len(fields) == 0 { - return "" - } - return fields[0].ResourceType -} - -func selectorSpecFromSelector(sel Selector) fhirschema.FieldSelectorSpec { - sourcePath := "" - valuePath := "" - if len(sel.Steps) > 0 { - last := len(sel.Steps) - 1 - valuePath = selectorStepText(sel.Steps[last]) - if last > 0 { - parts := make([]string, 0, last) - for _, step := range sel.Steps[:last] { - parts = append(parts, selectorStepText(step)) - } - sourcePath = strings.Join(parts, ".") - } - } - var where *fhirschema.FieldPredicateSpec - if sel.Filter != nil { - where = &fhirschema.FieldPredicateSpec{ - Path: sel.Filter.Field, - Op: fhirschema.PredicateContains, - Value: sel.Filter.Needle, - } - } - return fhirschema.FieldSelectorSpec{ - SourcePath: sourcePath, - Where: where, - ValuePath: valuePath, - } -} - -func findFieldByPath(fields []proto.PopulatedField, path string) *proto.PopulatedField { - for i := range fields { - if fields[i].Path == path { - return &fields[i] - } - } - return nil -} - -func (s *Service) runQuery(ctx context.Context, compiled CompiledQuery) (*Result, error) { - rows := make([]map[string]any, 0, compiled.Limit) - rowCount := 0 - columns := materializedColumns(compiled.Columns, compiled.PivotFields) - seenColumns := make(map[string]struct{}, len(columns)) - for _, col := range columns { - seenColumns[col] = struct{}{} - } - err := s.executeRows(ctx, proto.ExecuteQueryOptions{ - ConnectionOptions: s.connOpts, - BatchSize: 1000, - }, compiled.Query, compiled.BindVars, func(row map[string]any) error { - flatRow := flattenPivotFields(cloneRow(row), compiled.PivotFields) - for key := range flatRow { - if _, ok := seenColumns[key]; ok { - continue - } - seenColumns[key] = struct{}{} - columns = append(columns, key) - } - rows = append(rows, flatRow) - rowCount++ - return nil - }) - if err != nil { - return nil, err - } - return &Result{ - Columns: columns, - Rows: rows, - RowCount: rowCount, - }, nil -} - -func materializedColumns(columns []string, pivotFields []string) []string { - if len(columns) == 0 { - return []string{} - } - skip := make(map[string]struct{}, len(pivotFields)) - for _, field := range pivotFields { - skip[field] = struct{}{} - } - out := make([]string, 0, len(columns)) - for _, col := range columns { - if _, ok := skip[col]; ok { - continue - } - out = append(out, col) - } - return out -} - -func flattenPivotFields(row map[string]any, pivotFields []string) map[string]any { - for _, field := range pivotFields { - value, ok := row[field] - if !ok { - continue - } - obj, ok := value.(map[string]any) - if !ok { - continue - } - delete(row, field) - for key, item := range obj { - row[sanitizeColumnName(field+"__"+key)] = item - } - } - return row -} - -func cloneRow(in map[string]any) map[string]any { - if in == nil { - return map[string]any{} - } - out := make(map[string]any, len(in)) - for k, v := range in { - out[k] = v - } - return out -} - -func (s *Service) resolveAuthResourcePaths(ctx context.Context, principal *writeapi.Principal, project string, requested []string) ([]string, error) { - if s.scopeResolver != nil { - return s.scopeResolver.ResolveReadAuthResourcePaths(ctx, principal, project, requested) - } - if len(requested) == 0 { - if principal == nil || len(principal.AuthResourcePaths) == 0 { - return nil, nil - } - return append([]string(nil), principal.AuthResourcePaths...), nil - } - if principal == nil || len(principal.AuthResourcePaths) == 0 { - return append([]string(nil), requested...), nil - } - for _, path := range requested { - found := false - for _, candidate := range principal.AuthResourcePaths { - if candidate == path { - found = true - break - } - } - if !found { - return nil, fmt.Errorf("authResourcePath %q is outside caller scope", path) - } - } - return append([]string(nil), requested...), nil -} - -func authorizeProject(principal *writeapi.Principal, project string, ignorePrincipalProjects bool) error { - if ignorePrincipalProjects { - return nil - } - if principal == nil || len(principal.Projects) == 0 { - return nil - } - for _, candidate := range principal.Projects { - if candidate == project { - return nil - } - } - return fmt.Errorf("principal is not authorized for project %q", project) -} - -type Selector = fhirschema.Selector -type SelectorStep = fhirschema.SelectorStep -type ContainsFilter = fhirschema.ContainsFilter - -func ParseSelector(input string) (Selector, error) { - return fhirschema.ParseSelector(input) -} - -type CompiledQuery struct { - Project string - RootResourceType string - AuthResourcePaths []string - PlanMode string - PlanProfile string - NamedSetCount int - FileSummaries bool - StudyLookup bool - Query string - BindVars map[string]any - Columns []string - PivotFields []string - Limit int -} - -func Compile(builder Builder, limit int) (CompiledQuery, error) { - if usesAdvancedBuilder(builder) { - return compileAdvanced(builder, limit) - } - return CompiledQuery{}, fmt.Errorf("unsupported dataframe query shape: request was not lowered into the optimized advanced plan") -} - -func planMode(hint *PlanHint) string { - if hint == nil || hint.Mode == "" { - return "unsupported" - } - return hint.Mode -} - -func planProfile(hint *PlanHint) string { - if hint == nil { - return "" - } - return hint.Profile -} - -func planNamedSetCount(hint *PlanHint) int { - if hint == nil { - return 0 - } - return hint.NamedSetCount -} - -func planFileSummaries(hint *PlanHint) bool { - if hint == nil { - return false - } - return hint.ClassifiedFileSummaries -} - -func planStudyLookup(hint *PlanHint) bool { - if hint == nil { - return false - } - return hint.StudyLookup -} - -type compiler struct { - builder Builder - bindVars map[string]any - columns []string - pivotFields []string - bindCount int - pivotExprs map[string]string -} - -func (c *compiler) compileTraversal(parentVar string, parentIsArray bool, step TraversalStep, lets *[]string, objectLines *[]string) error { - labelBind := c.newBind(step.Alias+"_label", step.Label) - toBind := c.newBind(step.Alias+"_to", step.ToResourceType) - nodeVar := sanitizeColumnName(step.Alias) + "_nodes" - var let string - if parentIsArray { - let = fmt.Sprintf(" LET %s = UNIQUE(FLATTEN(FOR __parent IN %s FOR __node, __edge IN 1..1 INBOUND __parent fhir_edge FILTER __edge.project == @project FILTER @auth_resource_paths_unrestricted == true OR (__edge.auth_resource_path IN @auth_resource_paths AND __node.auth_resource_path IN @auth_resource_paths) FILTER __edge.label == @%s FILTER __node.resourceType == @%s RETURN [__node]))", nodeVar, parentVar, labelBind, toBind) - } else { - let = fmt.Sprintf(" LET %s = UNIQUE(FOR __node, __edge IN 1..1 INBOUND %s fhir_edge FILTER __edge.project == @project FILTER @auth_resource_paths_unrestricted == true OR (__edge.auth_resource_path IN @auth_resource_paths AND __node.auth_resource_path IN @auth_resource_paths) FILTER __edge.label == @%s FILTER __node.resourceType == @%s RETURN __node)", nodeVar, parentVar, labelBind, toBind) - } - *lets = append(*lets, let) - for _, field := range step.Fields { - sel, _ := ParseSelector(field.Select) - expr, err := c.compileTraversalFieldSelect(nodeVar, field, sel) - if err != nil { - return err - } - colName := sanitizeColumnName(step.Alias + "__" + field.Name) - *objectLines = append(*objectLines, fmt.Sprintf(" %s: %s", quoteKey(colName), expr)) - c.columns = append(c.columns, colName) - } - for _, pivot := range step.Pivots { - keySel, _ := ParseSelector(pivot.ColumnSelect) - valueSel, _ := ParseSelector(pivot.ValueSelect) - colName := sanitizeColumnName(step.Alias + "__" + pivot.Name) - expr, err := c.compileTraversalPivot(nodeVar, keySel, valueSel, pivot.Columns) - if err != nil { - return err - } - *objectLines = append(*objectLines, fmt.Sprintf(" %s: %s", quoteKey(colName), expr)) - c.columns = append(c.columns, colName) - c.pivotFields = append(c.pivotFields, colName) - } - for _, agg := range step.Aggregates { - expr, err := c.compileSetAggregateExpr(nodeVar, agg) - if err != nil { - return err - } - colName := sanitizeColumnName(step.Alias + "__" + agg.Name) - *objectLines = append(*objectLines, fmt.Sprintf(" %s: %s", quoteKey(colName), expr)) - c.columns = append(c.columns, colName) - } - for _, slice := range step.Slices { - expr, err := c.compileSetSlice(nodeVar, setModeNode, slice) - if err != nil { - return err - } - colName := sanitizeColumnName(step.Alias + "__" + slice.Name) - *objectLines = append(*objectLines, fmt.Sprintf(" %s: %s", quoteKey(colName), expr)) - c.columns = append(c.columns, colName) - } - for _, child := range step.Traversals { - if err := c.compileTraversal(nodeVar, true, child, lets, objectLines); err != nil { - return err - } - } - return nil -} - -func (c *compiler) compileRootFieldSelect(payloadVar string, field FieldSelect, sel Selector) (string, error) { - if len(field.FallbackSelects) > 0 { - return c.compileFirstNonNullExpr(payloadVar, append([]string{field.Select}, field.FallbackSelects...)), nil - } - return c.compileRootField(payloadVar, sel) -} - -func (c *compiler) compileRootField(payloadVar string, sel Selector) (string, error) { - if sel.Filter == nil && selectorHasNoArrays(sel) { - return compileDirectExpr(payloadVar, sel.Steps), nil - } - return "FIRST" + compileSelectorArrayExpr(payloadVar, sel, c), nil -} - -func (c *compiler) compileTraversalFieldSelect(nodeVar string, field FieldSelect, sel Selector) (string, error) { - if len(field.FallbackSelects) > 0 { - tmp := DerivedField{ - Source: nodeVar, - Select: field.Select, - FallbackSelects: field.FallbackSelects, - } - return c.compileUniqueField("", tmp, map[string]setMode{nodeVar: setModeNode}) - } - return c.compileTraversalField(nodeVar, sel) -} - -func (c *compiler) compileTraversalField(nodeVar string, sel Selector) (string, error) { - return fmt.Sprintf("UNIQUE(FLATTEN(FOR __n IN %s RETURN %s))", nodeVar, compileSelectorArrayExpr("__n.payload", sel, c)), nil -} - -func (c *compiler) compileRootPivot(payloadVar string, keySel Selector, valueSel Selector, columns []string) (string, error) { - return c.compilePivotMapExpr("FOR __item IN ["+payloadVar+"]", "__item", keySel, valueSel, columns) -} - -func (c *compiler) compileTraversalPivot(nodeVar string, keySel Selector, valueSel Selector, columns []string) (string, error) { - return c.compilePivotMapExpr("FOR __item IN "+nodeVar, "__item.payload", keySel, valueSel, columns) -} - -func selectorHasNoArrays(sel Selector) bool { - for _, step := range sel.Steps { - if step.Iterate || step.Index != nil { - return false - } - } - return true -} - -func compileDirectExpr(rootVar string, steps []SelectorStep) string { - cur := rootVar - for _, step := range steps { - if step.Index != nil { - cur = fmt.Sprintf("((%s.%s ? %s.%s : [])[%d])", cur, step.Field, cur, step.Field, *step.Index) - continue - } - cur = fmt.Sprintf("%s.%s", cur, step.Field) - } - return cur -} - -func compileSelectorArrayExpr(rootVar string, sel Selector, c *compiler) string { - prefix := sel.Steps - if len(prefix) == 0 { - return "[]" - } - last := prefix[len(prefix)-1] - prefix = prefix[:len(prefix)-1] - lines := []string{fmt.Sprintf("FOR __root IN [%s]", rootVar)} - cur := "__root" - tmpCount := 0 - for _, step := range prefix { - next := fmt.Sprintf("__s%d", tmpCount) - tmpCount++ - switch { - case step.Iterate: - lines = append(lines, fmt.Sprintf(" FOR %s IN (%s.%s ? %s.%s : [])", next, cur, step.Field, cur, step.Field)) - case step.Index != nil: - lines = append(lines, fmt.Sprintf(" LET %s = ((%s.%s ? %s.%s : [])[%d])", next, cur, step.Field, cur, step.Field, *step.Index)) - lines = append(lines, fmt.Sprintf(" FILTER %s != null", next)) - default: - lines = append(lines, fmt.Sprintf(" LET %s = %s.%s", next, cur, step.Field)) - lines = append(lines, fmt.Sprintf(" FILTER %s != null", next)) - } - cur = next - } - if sel.Filter != nil { - filterBind := c.newBind("contains", sel.Filter.Needle) - lines = append(lines, fmt.Sprintf(" FILTER CONTAINS(%s.%s ? %s.%s : \"\", @%s)", cur, sel.Filter.Field, cur, sel.Filter.Field, filterBind)) - } - finalExpr := extractFinalExpr(cur, last) - lines = append(lines, fmt.Sprintf(" LET __value = %s", finalExpr)) - lines = append(lines, " FILTER __value != null") - lines = append(lines, " RETURN __value") - return "(\n " + strings.Join(lines, "\n ") + "\n )" -} - -func compileObjectArrayExpr(rootVar string, sel Selector, c *compiler) string { - lines := []string{fmt.Sprintf("FOR __root IN [%s]", rootVar)} - cur := "__root" - tmpCount := 0 - for _, step := range sel.Steps { - next := fmt.Sprintf("__o%d", tmpCount) - tmpCount++ - switch { - case step.Iterate: - lines = append(lines, fmt.Sprintf(" FOR %s IN (%s.%s ? %s.%s : [])", next, cur, step.Field, cur, step.Field)) - case step.Index != nil: - lines = append(lines, fmt.Sprintf(" LET %s = ((%s.%s ? %s.%s : [])[%d])", next, cur, step.Field, cur, step.Field, *step.Index)) - lines = append(lines, fmt.Sprintf(" FILTER %s != null", next)) - default: - lines = append(lines, fmt.Sprintf(" LET %s = %s.%s", next, cur, step.Field)) - lines = append(lines, fmt.Sprintf(" FILTER %s != null", next)) - } - cur = next - } - lines = append(lines, fmt.Sprintf(" FILTER %s != null", cur)) - lines = append(lines, fmt.Sprintf(" RETURN %s", cur)) - return "(\n " + strings.Join(lines, "\n ") + "\n )" -} - -func (c *compiler) compilePivotMapExpr(itemLoop string, payloadVar string, keySel Selector, valueSel Selector, columns []string) (string, error) { - keyExpr := compileSelectorArrayExpr(payloadVar, keySel, c) - valueExpr := compileSelectorArrayExpr(payloadVar, valueSel, c) - filterLine := "" - if len(columns) > 0 { - colBind := c.newBind("pivot_cols", append([]string(nil), columns...)) - filterLine = fmt.Sprintf("\n FILTER POSITION(@%s, __key, true)", colBind) - } - return fmt.Sprintf(`MERGE( - FOR __pair IN ( - %s - LET __keys = UNIQUE(%s) - LET __values = %s - FILTER LENGTH(__values) > 0 - FOR __key IN __keys%s - RETURN { key: __key, values: __values } - ) - COLLECT __key = __pair.key INTO __group - LET __flat_values = UNIQUE(FLATTEN(__group[*].__pair.values)) - FILTER LENGTH(__flat_values) > 0 - RETURN { [__key]: FIRST(__flat_values) } - )`, itemLoop, keyExpr, valueExpr, filterLine), nil -} - -func extractFinalExpr(cur string, step SelectorStep) string { - switch { - case step.Iterate: - return fmt.Sprintf("(%s.%s ? %s.%s : [])", cur, step.Field, cur, step.Field) - case step.Index != nil: - return fmt.Sprintf("((%s.%s ? %s.%s : [])[%d])", cur, step.Field, cur, step.Field, *step.Index) - default: - return fmt.Sprintf("%s.%s", cur, step.Field) - } -} - -func (c *compiler) newBind(prefix string, value any) string { - name := fmt.Sprintf("__%s_%d", sanitizeColumnName(prefix), c.bindCount) - c.bindCount++ - c.bindVars[name] = value - return name -} - -func sanitizeColumnName(in string) string { - var b strings.Builder - for _, r := range in { - switch { - case r >= 'a' && r <= 'z', r >= 'A' && r <= 'Z', r >= '0' && r <= '9': - b.WriteRune(r) - default: - b.WriteRune('_') - } - } - return b.String() -} - -func quoteKey(key string) string { - data, _ := json.Marshal(key) - return string(data) -} - -func selectorStepText(step SelectorStep) string { - switch { - case step.Iterate: - return step.Field + "[]" - case step.Index != nil: - return fmt.Sprintf("%s[%d]", step.Field, *step.Index) - default: - return step.Field - } -} - -func cloneStrings(in []string) []string { - if in == nil { - return nil - } - if len(in) == 0 { - return []string{} - } - return append([]string(nil), in...) -} - -func max(a, b int) int { - if a > b { - return a - } - return b -} diff --git a/internal/dataframe/dataframe_test.go b/internal/dataframe/dataframe_test.go index 496affe..e356dcd 100644 --- a/internal/dataframe/dataframe_test.go +++ b/internal/dataframe/dataframe_test.go @@ -6,8 +6,9 @@ import ( "strings" "testing" - "arangodb-proto/internal/proto" - "arangodb-proto/internal/writeapi" + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/catalog" + arangostore "github.com/calypr/loom/internal/store/arango" ) func TestParseSelector(t *testing.T) { @@ -23,7 +24,7 @@ func TestParseSelector(t *testing.T) { } } -func TestCompileRejectsNonAdvancedBuilder(t *testing.T) { +func TestCompileRejectsNonLoweredBuilder(t *testing.T) { _, err := Compile(Builder{ Project: "P1", RootResourceType: "Patient", @@ -66,8 +67,8 @@ func TestLowerGraphQLBuilderUsesStructuralLowering(t *testing.T) { if err != nil { t.Fatalf("expected case-assay profile to match, got %v", err) } - if !usesAdvancedBuilder(planned) { - t.Fatal("expected planner to return advanced builder") + if !usesLoweredBuilder(planned) { + t.Fatal("expected planner to return lowered builder") } if planned.PlanHint == nil || planned.PlanHint.Profile != "patient_case_assay_family" { t.Fatalf("unexpected plan hint: %#v", planned.PlanHint) @@ -255,24 +256,24 @@ func TestLowerGraphQLBuilderPreservesUnrestrictedAuthScope(t *testing.T) { func TestServiceRejectsUnsupportedSimpleQuery(t *testing.T) { svc := NewService(ServiceConfig{ - ConnectionOptions: proto.ConnectionOptions{Backend: "arango"}, - DiscoverReferences: func(ctx context.Context, opts proto.PopulatedReferenceOptions) ([]proto.PopulatedReference, error) { - return []proto.PopulatedReference{{FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 1}}, nil + ConnectionOptions: arangostore.ConnectionOptions{}, + DiscoverReferences: func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + return []catalog.PopulatedReference{{FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 1}}, nil }, - DiscoverFields: func(ctx context.Context, opts proto.PopulatedFieldOptions) ([]proto.PopulatedField, error) { + DiscoverFields: func(ctx context.Context, opts catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { if opts.PivotOnly { - return []proto.PopulatedField{}, nil + return []catalog.PopulatedField{}, nil } if opts.ResourceType == "Patient" { - return []proto.PopulatedField{{ResourceType: "Patient", Path: "gender", Kind: "scalar"}}, nil + return []catalog.PopulatedField{{ResourceType: "Patient", Path: "gender", Kind: "scalar"}}, nil } - return []proto.PopulatedField{{ResourceType: "Specimen", Path: "type.coding[].display", Kind: "scalar"}}, nil + return []catalog.PopulatedField{{ResourceType: "Specimen", Path: "type.coding[].display", Kind: "scalar"}}, nil }, - ExecuteRows: func(ctx context.Context, opts proto.ExecuteQueryOptions, query string, bindVars map[string]any, visit func(map[string]any) error) error { + ExecuteRows: func(ctx context.Context, opts ExecuteQueryOptions, query string, bindVars map[string]any, visit func(map[string]any) error) error { return visit(map[string]any{"_key": "p1", "gender": "female", "specimen__specimen_type": []string{"Blood"}}) }, }) - ctx := writeapi.ContextWithPrincipal(context.Background(), &writeapi.Principal{ + ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{ Projects: []string{"P1"}, AuthResourcePaths: []string{"pathA"}, }) @@ -297,37 +298,37 @@ func TestServiceRejectsUnsupportedSimpleQuery(t *testing.T) { func TestServiceRunCaseAssayRecipe(t *testing.T) { svc := NewService(ServiceConfig{ - ConnectionOptions: proto.ConnectionOptions{Backend: "arango"}, - DiscoverReferences: func(ctx context.Context, opts proto.PopulatedReferenceOptions) ([]proto.PopulatedReference, error) { + ConnectionOptions: arangostore.ConnectionOptions{}, + DiscoverReferences: func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { switch opts.NodeType { case "Patient": - return []proto.PopulatedReference{ + return []catalog.PopulatedReference{ {FromType: "Patient", Label: "subject_Patient", ToType: "Condition", EdgeCount: 1}, {FromType: "Patient", Label: "subject_Patient", ToType: "ResearchSubject", EdgeCount: 1}, {FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 1}, {FromType: "Patient", Label: "subject_Patient", ToType: "MedicationAdministration", EdgeCount: 1}, }, nil case "Specimen": - return []proto.PopulatedReference{ + return []catalog.PopulatedReference{ {FromType: "Specimen", Label: "subject_Specimen", ToType: "DocumentReference", EdgeCount: 1}, {FromType: "Specimen", Label: "member_entity_Specimen", ToType: "Group", EdgeCount: 1}, }, nil case "Group": - return []proto.PopulatedReference{ + return []catalog.PopulatedReference{ {FromType: "Group", Label: "subject_Group", ToType: "DocumentReference", EdgeCount: 1}, }, nil default: - return []proto.PopulatedReference{}, nil + return []catalog.PopulatedReference{}, nil } }, - DiscoverFields: func(ctx context.Context, opts proto.PopulatedFieldOptions) ([]proto.PopulatedField, error) { - return []proto.PopulatedField{ + DiscoverFields: func(ctx context.Context, opts catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + return []catalog.PopulatedField{ {ResourceType: opts.ResourceType, Path: "gender", Kind: "scalar"}, {ResourceType: opts.ResourceType, Path: "id", Kind: "scalar"}, {ResourceType: opts.ResourceType, Path: "status", Kind: "scalar"}, }, nil }, - ExecuteRows: func(ctx context.Context, opts proto.ExecuteQueryOptions, query string, bindVars map[string]any, visit func(map[string]any) error) error { + ExecuteRows: func(ctx context.Context, opts ExecuteQueryOptions, query string, bindVars map[string]any, visit func(map[string]any) error) error { if !strings.Contains(query, "LET root_patient_neighbor_set") || !strings.Contains(query, "LET patient_condition_set") || !strings.Contains(query, "LET specimen_group_set") { t.Fatalf("expected advanced planned query, got:\n%s", query) } @@ -337,7 +338,7 @@ func TestServiceRunCaseAssayRecipe(t *testing.T) { return visit(map[string]any{"_key": "p1", "gender": "female"}) }, }) - ctx := writeapi.ContextWithPrincipal(context.Background(), &writeapi.Principal{ + ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{ Projects: []string{"P1"}, AuthResourcePaths: []string{"pathA"}, }) @@ -403,14 +404,14 @@ func containsDerivedFieldWithSelect(fields []DerivedField, wantName, wantSelect func TestServiceRejectsUnsupportedRootOnlyQuery(t *testing.T) { svc := NewService(ServiceConfig{ - ConnectionOptions: proto.ConnectionOptions{Backend: "arango"}, - DiscoverReferences: func(ctx context.Context, opts proto.PopulatedReferenceOptions) ([]proto.PopulatedReference, error) { - return []proto.PopulatedReference{}, nil + ConnectionOptions: arangostore.ConnectionOptions{}, + DiscoverReferences: func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + return []catalog.PopulatedReference{}, nil }, - DiscoverFields: func(ctx context.Context, opts proto.PopulatedFieldOptions) ([]proto.PopulatedField, error) { - return []proto.PopulatedField{{ResourceType: "Patient", Path: "gender", Kind: "scalar"}}, nil + DiscoverFields: func(ctx context.Context, opts catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + return []catalog.PopulatedField{{ResourceType: "Patient", Path: "gender", Kind: "scalar"}}, nil }, - ExecuteRows: func(ctx context.Context, opts proto.ExecuteQueryOptions, query string, bindVars map[string]any, visit func(map[string]any) error) error { + ExecuteRows: func(ctx context.Context, opts ExecuteQueryOptions, query string, bindVars map[string]any, visit func(map[string]any) error) error { return visit(map[string]any{"_key": "p1", "gender": "female"}) }, }) @@ -427,8 +428,8 @@ func TestServiceRejectsUnsupportedRootOnlyQuery(t *testing.T) { } func TestServiceRejectsUnauthorizedAuthPath(t *testing.T) { - svc := NewService(ServiceConfig{ConnectionOptions: proto.ConnectionOptions{Backend: "arango"}}) - ctx := writeapi.ContextWithPrincipal(context.Background(), &writeapi.Principal{ + svc := NewService(ServiceConfig{ConnectionOptions: arangostore.ConnectionOptions{}}) + ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{ Projects: []string{"P1"}, AuthResourcePaths: []string{"pathA"}, }) @@ -444,3 +445,55 @@ func TestServiceRejectsUnauthorizedAuthPath(t *testing.T) { t.Fatal("expected auth path error") } } + +func TestLookupPlannerTraversalUsesSchemaDerivedMetadata(t *testing.T) { + cases := []struct { + fromType string + edgeLabel string + toType string + role traversalRole + }{ + {"Patient", "subject_Patient", "Condition", traversalRolePatientNeighborChild}, + {"Patient", "subject_Patient", "Specimen", traversalRolePatientNeighborChild}, + {"Patient", "focus_Patient", "Observation", traversalRolePatientDirectChild}, + {"Specimen", "subject_Specimen", "DocumentReference", traversalRoleSpecimenDocumentReference}, + {"Group", "subject_Group", "DocumentReference", traversalRoleGroupDocumentReference}, + } + for _, tc := range cases { + spec, ok := lookupPlannerTraversal(tc.fromType, tc.edgeLabel, tc.toType) + if !ok { + t.Fatalf("expected traversal %s %s %s", tc.fromType, tc.edgeLabel, tc.toType) + } + if spec.Role != tc.role { + t.Fatalf("unexpected role for %s %s %s: %q", tc.fromType, tc.edgeLabel, tc.toType, spec.Role) + } + if spec.Schema.FromType != tc.fromType || spec.Schema.EdgeLabel != tc.edgeLabel || spec.Schema.ToType != tc.toType { + t.Fatalf("unexpected schema spec: %#v", spec.Schema) + } + } +} + +func TestLookupPlannerTraversalRejectsUnsupportedTuple(t *testing.T) { + if _, ok := lookupPlannerTraversal("Patient", "subject_Patient", "Medication"); ok { + t.Fatal("expected unsupported tuple to miss") + } +} + +func TestDocumentReferenceSummaryFieldMapping(t *testing.T) { + got, ok := mapDocumentReferenceSelectorToSummaryField(`category[].coding[].display where system contains "workflow_type"`) + if !ok { + t.Fatal("expected workflow_type selector to map") + } + if got != "workflow_type" { + t.Fatalf("unexpected mapped field: %q", got) + } +} + +func TestRequiresResearchStudyHydration(t *testing.T) { + if requiresResearchStudyHydration("study.reference", "ResearchSubject.study_reference") { + t.Fatal("default generated study ref should not require hydration") + } + if !requiresResearchStudyHydration("study.display", "ResearchSubject.study_display") { + t.Fatal("study child selector should require hydration") + } +} diff --git a/internal/dataframe/document_reference_semantics.go b/internal/dataframe/document_reference_semantics.go new file mode 100644 index 0000000..3a1cedb --- /dev/null +++ b/internal/dataframe/document_reference_semantics.go @@ -0,0 +1,87 @@ +package dataframe + +import ( + "strings" + + "github.com/calypr/loom/internal/fhirschema" +) + +type documentReferenceSummarySpec struct { + Selector fhirschema.FieldSelectorSpec + SummaryName string +} + +var documentReferenceSummarySpecs = []documentReferenceSummarySpec{ + {Selector: selector("identifier[]", whereContains("system", "file_id"), "value"), SummaryName: "file_id"}, + {Selector: selector("content[].attachment", nil, "title"), SummaryName: "file_name"}, + {Selector: selector("content[].attachment", nil, "url"), SummaryName: "file_url"}, + {Selector: selector("content[].attachment", nil, "size"), SummaryName: "file_size"}, + {Selector: selector("category[].coding[]", whereContains("system", "data_category"), "display"), SummaryName: "data_category"}, + {Selector: selector("category[].coding[]", whereContains("system", "data_type"), "display"), SummaryName: "data_type"}, + {Selector: selector("category[].coding[]", whereContains("system", "experimental_strategy"), "display"), SummaryName: "experimental_strategy"}, + {Selector: selector("category[].coding[]", whereContains("system", "workflow_type"), "display"), SummaryName: "workflow_type"}, + {Selector: selector("category[].coding[]", whereContains("system", "platform"), "display"), SummaryName: "platform"}, + {Selector: selector("category[].coding[]", whereContains("system", "access"), "display"), SummaryName: "access"}, + {Selector: selector("type.coding[]", nil, "display"), SummaryName: "data_format"}, +} + +func mapDocumentReferenceSelectorToSummaryField(selectorExpr string) (string, bool) { + parsed, err := fhirschema.ParseSelector(selectorExpr) + if err != nil { + return "", false + } + for _, spec := range documentReferenceSummarySpecs { + if fhirschema.CanonicalPath(spec.Selector) != parsed.CanonicalPath() { + continue + } + if !sameContainsPredicate(spec.Selector.Where, parsed.Filter) { + continue + } + return spec.SummaryName, true + } + return "", false +} + +func selectorNeedsDocumentReferenceSummary(selectorExpr string) bool { + _, ok := mapDocumentReferenceSelectorToSummaryField(selectorExpr) + return ok +} + +func requiresResearchStudyHydration(selectorExpr string, fieldRef string) bool { + if strings.TrimSpace(fieldRef) == "ResearchSubject.study_reference" { + return false + } + parsed, err := fhirschema.ParseSelector(selectorExpr) + if err != nil { + return false + } + return strings.HasPrefix(parsed.CanonicalPath(), "study.") +} + +func selector(sourcePath string, predicate *fhirschema.FieldPredicateSpec, valuePath string) fhirschema.FieldSelectorSpec { + return fhirschema.FieldSelectorSpec{ + SourcePath: strings.TrimSpace(sourcePath), + Where: predicate, + ValuePath: strings.TrimSpace(valuePath), + } +} + +func whereContains(path, value string) *fhirschema.FieldPredicateSpec { + return &fhirschema.FieldPredicateSpec{ + Path: path, + Op: fhirschema.PredicateContains, + Value: value, + } +} + +func sameContainsPredicate(expected *fhirschema.FieldPredicateSpec, actual *fhirschema.ContainsFilter) bool { + if expected == nil && actual == nil { + return true + } + if expected == nil || actual == nil { + return false + } + return strings.EqualFold(strings.TrimSpace(expected.Path), strings.TrimSpace(actual.Field)) && + strings.EqualFold(strings.TrimSpace(expected.Op), fhirschema.PredicateContains) && + strings.TrimSpace(expected.Value) == strings.TrimSpace(actual.Needle) +} diff --git a/internal/dataframe/execution.go b/internal/dataframe/execution.go new file mode 100644 index 0000000..720057f --- /dev/null +++ b/internal/dataframe/execution.go @@ -0,0 +1,87 @@ +package dataframe + +import ( + "context" +) + +func (s *Service) runQuery(ctx context.Context, compiled CompiledQuery) (*Result, error) { + rows := make([]map[string]any, 0, compiled.Limit) + rowCount := 0 + columns := materializedColumns(compiled.Columns, compiled.PivotFields) + seenColumns := make(map[string]struct{}, len(columns)) + for _, col := range columns { + seenColumns[col] = struct{}{} + } + + err := s.executeRows(ctx, ExecuteQueryOptions{ + ConnectionOptions: s.connOpts, + BatchSize: 1000, + }, compiled.Query, compiled.BindVars, func(row map[string]any) error { + flatRow := flattenPivotFields(cloneRow(row), compiled.PivotFields) + for key := range flatRow { + if _, ok := seenColumns[key]; ok { + continue + } + seenColumns[key] = struct{}{} + columns = append(columns, key) + } + rows = append(rows, flatRow) + rowCount++ + return nil + }) + if err != nil { + return nil, err + } + return &Result{ + Columns: columns, + Rows: rows, + RowCount: rowCount, + }, nil +} + +func materializedColumns(columns []string, pivotFields []string) []string { + if len(columns) == 0 { + return []string{} + } + skip := make(map[string]struct{}, len(pivotFields)) + for _, field := range pivotFields { + skip[field] = struct{}{} + } + out := make([]string, 0, len(columns)) + for _, col := range columns { + if _, ok := skip[col]; ok { + continue + } + out = append(out, col) + } + return out +} + +func flattenPivotFields(row map[string]any, pivotFields []string) map[string]any { + for _, field := range pivotFields { + value, ok := row[field] + if !ok { + continue + } + obj, ok := value.(map[string]any) + if !ok { + continue + } + delete(row, field) + for key, item := range obj { + row[sanitizeColumnName(field+"__"+key)] = item + } + } + return row +} + +func cloneRow(in map[string]any) map[string]any { + if in == nil { + return map[string]any{} + } + out := make(map[string]any, len(in)) + for k, v := range in { + out[k] = v + } + return out +} diff --git a/internal/dataframe/advanced_compile.go b/internal/dataframe/lowered_compile.go similarity index 99% rename from internal/dataframe/advanced_compile.go rename to internal/dataframe/lowered_compile.go index b3d7591..076f8fa 100644 --- a/internal/dataframe/advanced_compile.go +++ b/internal/dataframe/lowered_compile.go @@ -13,7 +13,7 @@ const ( setModeObject setMode = "object" ) -func compileAdvanced(builder Builder, limit int) (CompiledQuery, error) { +func compileLowered(builder Builder, limit int) (CompiledQuery, error) { c := &compiler{ builder: builder, bindVars: map[string]any{ @@ -205,13 +205,13 @@ func (c *compiler) compileNamedSet(rootVar string, set NamedSet, modes map[strin } type pivotMapGroup struct { - letName string - sourceExpr string - mode setMode - keySelect string - valueSelect string - columns []string - columnSet map[string]struct{} + letName string + sourceExpr string + mode setMode + keySelect string + valueSelect string + columns []string + columnSet map[string]struct{} unrestricted bool } diff --git a/internal/dataframe/advanced_types.go b/internal/dataframe/lowered_types.go similarity index 91% rename from internal/dataframe/advanced_types.go rename to internal/dataframe/lowered_types.go index 285f262..3455a45 100644 --- a/internal/dataframe/advanced_types.go +++ b/internal/dataframe/lowered_types.go @@ -37,34 +37,34 @@ type NamedSet struct { } type DerivedField struct { - Name string - Source string - Operation string - Select string - FallbackSelects []string - Predicate string - PredicatePath string - PredicateEquals string - PivotColumns []string - PivotFamily string - PivotKeySelect string + Name string + Source string + Operation string + Select string + FallbackSelects []string + Predicate string + PredicatePath string + PredicateEquals string + PivotColumns []string + PivotFamily string + PivotKeySelect string PivotValueSelect string - RawExpr string - ConstValue any + RawExpr string + ConstValue any } type RepresentativeSlice struct { - Name string - SourceSet string - Predicate string + Name string + SourceSet string + Predicate string PredicateFieldRef string - PredicatePath string - PredicateEquals string - Limit int - Fields []FieldSelect + PredicatePath string + PredicateEquals string + Limit int + Fields []FieldSelect } -func usesAdvancedBuilder(builder Builder) bool { +func usesLoweredBuilder(builder Builder) bool { if len(builder.Sets) > 0 || len(builder.DerivedFields) > 0 || len(builder.RepresentativeSlices) > 0 { return true } @@ -76,7 +76,7 @@ func usesAdvancedBuilder(builder Builder) bool { return false } -func validateAdvancedBuilder(builder Builder) error { +func validateLoweredBuilder(builder Builder) error { seenSets := map[string]struct{}{} for _, set := range builder.Sets { if strings.TrimSpace(set.Name) == "" { diff --git a/internal/dataframe/pivots.go b/internal/dataframe/pivots.go new file mode 100644 index 0000000..37a845d --- /dev/null +++ b/internal/dataframe/pivots.go @@ -0,0 +1,77 @@ +package dataframe + +import ( + "context" + + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/fhirschema" +) + +func (s *Service) expandPivotColumns(ctx context.Context, builder Builder) (Builder, error) { + pivots, err := s.discoverFields(ctx, catalog.PopulatedFieldOptions{ + ConnectionOptions: s.connOpts, + Project: builder.Project, + AuthResourcePaths: builder.AuthResourcePaths, + ResourceType: builder.RootResourceType, + PivotOnly: true, + }) + if err != nil { + return Builder{}, err + } + builder.Pivots = fillPivotColumns(builder.Pivots, pivots) + for i := range builder.Traversals { + if err := s.expandTraversalPivotColumns(ctx, builder.Project, builder.AuthResourcePaths, &builder.Traversals[i]); err != nil { + return Builder{}, err + } + } + return builder, nil +} + +func (s *Service) expandTraversalPivotColumns(ctx context.Context, project string, authResourcePaths []string, step *TraversalStep) error { + pivots, err := s.discoverFields(ctx, catalog.PopulatedFieldOptions{ + ConnectionOptions: s.connOpts, + Project: project, + AuthResourcePaths: authResourcePaths, + ResourceType: step.ToResourceType, + PivotOnly: true, + }) + if err != nil { + return err + } + step.Pivots = fillPivotColumns(step.Pivots, pivots) + for i := range step.Traversals { + if err := s.expandTraversalPivotColumns(ctx, project, authResourcePaths, &step.Traversals[i]); err != nil { + return err + } + } + return nil +} + +func fillPivotColumns(in []PivotSelect, discovered []catalog.PopulatedField) []PivotSelect { + if len(in) == 0 { + return []PivotSelect{} + } + out := make([]PivotSelect, 0, len(in)) + resourceType := resourceTypeFromDiscovered(discovered) + for _, pivot := range in { + if pivot.PivotFamily == "" { + columnSel, colErr := ParseSelector(pivot.ColumnSelect) + valueSel, valErr := ParseSelector(pivot.ValueSelect) + if colErr == nil && valErr == nil { + spec, err := fhirschema.ValidatePivotSelectors(resourceType, selectorSpecFromSelector(columnSel), selectorSpecFromSelector(valueSel)) + if err == nil { + pivot.PivotFamily = spec.Family + } + } + } + out = append(out, pivot) + } + return out +} + +func resourceTypeFromDiscovered(fields []catalog.PopulatedField) string { + if len(fields) == 0 { + return "" + } + return fields[0].ResourceType +} diff --git a/internal/dataframe/planner.go b/internal/dataframe/planner.go index 187f26f..eac3a72 100644 --- a/internal/dataframe/planner.go +++ b/internal/dataframe/planner.go @@ -3,8 +3,6 @@ package dataframe import ( "fmt" "strings" - - "arangodb-proto/internal/fhirsemantics" ) type PlanHint struct { @@ -121,7 +119,7 @@ func lowerGraphQLBuilder(builder Builder) (Builder, error) { } ctx.builder.PlanHint = &PlanHint{ - Mode: "advanced_lowered", + Mode: "lowered", Profile: "patient_case_assay_family", NamedSetCount: len(ctx.builder.Sets), ClassifiedFileSummaries: ctx.documentReferenceSummarySet != "", @@ -136,7 +134,7 @@ func unsupportedLoweringError(msg string) error { func supportsSemanticLoweringFamily(node logicalNode, sourceType string) bool { for _, child := range node.Children { - if _, ok := fhirsemantics.ResolveTraversal(sourceType, child.Label, child.ResourceType); !ok { + if _, ok := lookupPlannerTraversal(sourceType, child.Label, child.ResourceType); !ok { return false } if !supportsSemanticLoweringFamily(child, child.ResourceType) { @@ -158,12 +156,12 @@ func (ctx *loweringContext) lowerPatientRoot(root logicalNode) bool { } for _, child := range root.Children { - spec, ok := fhirsemantics.ResolveTraversal(root.ResourceType, child.Label, child.ResourceType) + spec, ok := lookupPlannerTraversal(root.ResourceType, child.Label, child.ResourceType) if !ok { return false } switch spec.Role { - case fhirsemantics.TraversalRolePatientNeighborChild: + case traversalRolePatientNeighborChild: sourceSet := ctx.ensurePatientChildSet(spec, useRootNeighbors) if child.ResourceType == "ResearchSubject" && requestNeedsStudyHydration(child) { ctx.ensureStudyLookupSet(sourceSet) @@ -179,10 +177,10 @@ func (ctx *loweringContext) lowerPatientRoot(root logicalNode) bool { } else { ctx.lowerNodeSelections(child, sourceSet, false) } - case fhirsemantics.TraversalRolePatientDocumentReference: + case traversalRolePatientDocumentReference: sourceSet := ctx.ensurePatientDocumentReferenceSet(useRootNeighbors) ctx.lowerDocumentReferenceNode(child, sourceSet) - case fhirsemantics.TraversalRolePatientDirectChild: + case traversalRolePatientDirectChild: sourceSet := ctx.ensureDirectTraversalSet(spec, "") if child.ResourceType == "Group" { if !ctx.lowerGroupNode(child, sourceSet) { @@ -205,17 +203,17 @@ func (ctx *loweringContext) lowerPatientRoot(root logicalNode) bool { func (ctx *loweringContext) lowerSpecimenNode(node logicalNode, specimenSet string) bool { ctx.lowerNodeSelections(node, specimenSet, false) for _, child := range node.Children { - spec, ok := fhirsemantics.ResolveTraversal(node.ResourceType, child.Label, child.ResourceType) + spec, ok := lookupPlannerTraversal(node.ResourceType, child.Label, child.ResourceType) if !ok { return false } switch spec.Role { - case fhirsemantics.TraversalRoleSpecimenGroup: + case traversalRoleSpecimenGroup: groupSet := ctx.ensureSpecimenGroupSet(specimenSet) if !ctx.lowerGroupNode(child, groupSet) { return false } - case fhirsemantics.TraversalRoleSpecimenDocumentReference: + case traversalRoleSpecimenDocumentReference: docSet := ctx.ensureSpecimenDocumentReferenceSet(specimenSet) ctx.lowerDocumentReferenceNode(child, docSet) default: @@ -228,11 +226,11 @@ func (ctx *loweringContext) lowerSpecimenNode(node logicalNode, specimenSet stri func (ctx *loweringContext) lowerGroupNode(node logicalNode, groupSet string) bool { ctx.lowerNodeSelections(node, groupSet, false) for _, child := range node.Children { - spec, ok := fhirsemantics.ResolveTraversal(node.ResourceType, child.Label, child.ResourceType) + spec, ok := lookupPlannerTraversal(node.ResourceType, child.Label, child.ResourceType) if !ok { return false } - if spec.Role != fhirsemantics.TraversalRoleGroupDocumentReference { + if spec.Role != traversalRoleGroupDocumentReference { return false } docSet := ctx.ensureGroupDocumentReferenceSet(groupSet) @@ -365,32 +363,32 @@ func (ctx *loweringContext) ensureSet(set NamedSet, mode string) string { return set.Name } -func (ctx *loweringContext) ensurePatientChildSet(spec fhirsemantics.TraversalSpec, useRootNeighbors bool) string { - if name, ok := ctx.patientTypeSets[spec.ToType]; ok { +func (ctx *loweringContext) ensurePatientChildSet(spec plannerTraversal, useRootNeighbors bool) string { + if name, ok := ctx.patientTypeSets[spec.Schema.ToType]; ok { return name } setName := spec.SetName if strings.TrimSpace(setName) == "" { - setName = "patient_" + sanitizeColumnName(strings.ToLower(spec.ToType)) + "_set" + setName = "patient_" + sanitizeColumnName(strings.ToLower(spec.Schema.ToType)) + "_set" } set := NamedSet{ Name: setName, Kind: SetKindFilter, Source: ctx.rootNeighborSet, - MatchResourceType: spec.ToType, + MatchResourceType: spec.Schema.ToType, SortField: "_key", } if !useRootNeighbors { set = NamedSet{ Name: setName, Kind: SetKindTraverse, - Label: spec.EdgeLabel, - ToResourceType: spec.ToType, + Label: spec.Schema.EdgeLabel, + ToResourceType: spec.Schema.ToType, Unique: true, } } - ctx.patientTypeSets[spec.ToType] = ctx.ensureSet(set, "node") - return ctx.patientTypeSets[spec.ToType] + ctx.patientTypeSets[spec.Schema.ToType] = ctx.ensureSet(set, "node") + return ctx.patientTypeSets[spec.Schema.ToType] } func (ctx *loweringContext) ensureSpecimenGroupSet(specimenSet string) string { @@ -514,13 +512,13 @@ func (ctx *loweringContext) ensureStudyLookupSet(researchSubjectSet string) stri return ctx.studyLookupSet } -func (ctx *loweringContext) ensureDirectTraversalSet(spec fhirsemantics.TraversalSpec, sourceSet string) string { +func (ctx *loweringContext) ensureDirectTraversalSet(spec plannerTraversal, sourceSet string) string { mode := "node" set := NamedSet{ Name: spec.SetName, Kind: SetKindTraverse, - Label: spec.EdgeLabel, - ToResourceType: spec.ToType, + Label: spec.Schema.EdgeLabel, + ToResourceType: spec.Schema.ToType, Unique: true, } if sourceSet != "" { @@ -532,7 +530,7 @@ func (ctx *loweringContext) ensureDirectTraversalSet(spec fhirsemantics.Traversa func shouldUseRootNeighborSet(children []logicalNode, rootType string) bool { count := 0 for _, child := range children { - spec, ok := fhirsemantics.ResolveTraversal(rootType, child.Label, child.ResourceType) + spec, ok := lookupPlannerTraversal(rootType, child.Label, child.ResourceType) if ok && spec.SharedRootNeighborEligible { count++ } @@ -567,33 +565,33 @@ func requestUsesDocumentReferenceSummary(root logicalNode) bool { nodes := collectDocumentReferenceNodes(root) for _, node := range nodes { for _, field := range node.Fields { - if fhirsemantics.SelectorNeedsDocumentReferenceSummary(field.Select) { + if selectorNeedsDocumentReferenceSummary(field.Select) { return true } for _, fallback := range field.FallbackSelects { - if fhirsemantics.SelectorNeedsDocumentReferenceSummary(fallback) { + if selectorNeedsDocumentReferenceSummary(fallback) { return true } } } for _, agg := range node.Aggregates { - if fhirsemantics.SelectorNeedsDocumentReferenceSummary(agg.Select) { + if selectorNeedsDocumentReferenceSummary(agg.Select) { return true } - if fhirsemantics.SelectorNeedsDocumentReferenceSummary(agg.PredicatePath) { + if selectorNeedsDocumentReferenceSummary(agg.PredicatePath) { return true } } for _, slice := range node.Slices { - if fhirsemantics.SelectorNeedsDocumentReferenceSummary(slice.PredicatePath) { + if selectorNeedsDocumentReferenceSummary(slice.PredicatePath) { return true } for _, field := range slice.Fields { - if fhirsemantics.SelectorNeedsDocumentReferenceSummary(field.Select) { + if selectorNeedsDocumentReferenceSummary(field.Select) { return true } for _, fallback := range field.FallbackSelects { - if fhirsemantics.SelectorNeedsDocumentReferenceSummary(fallback) { + if selectorNeedsDocumentReferenceSummary(fallback) { return true } } @@ -626,20 +624,16 @@ func hasSingleDocumentReferenceAlias(root logicalNode) bool { func requestNeedsStudyHydration(node logicalNode) bool { for _, field := range node.Fields { - if fhirsemantics.RequiresResearchStudyHydration(field.Select, field.FieldRef) { + if requiresResearchStudyHydration(field.Select, field.FieldRef) { return true } } for _, slice := range node.Slices { for _, field := range slice.Fields { - if fhirsemantics.RequiresResearchStudyHydration(field.Select, field.FieldRef) { + if requiresResearchStudyHydration(field.Select, field.FieldRef) { return true } } } return false } - -func mapDocumentReferenceSelectorToSummaryField(selectText string) (string, bool) { - return fhirsemantics.DocumentReferenceSummaryField(selectText) -} diff --git a/internal/dataframe/query_runtime.go b/internal/dataframe/query_runtime.go new file mode 100644 index 0000000..eccfe4a --- /dev/null +++ b/internal/dataframe/query_runtime.go @@ -0,0 +1,26 @@ +package dataframe + +import ( + "context" + + arangostore "github.com/calypr/loom/internal/store/arango" +) + +type ExecuteQueryOptions struct { + arangostore.ConnectionOptions + BatchSize int +} + +func ExecuteQueryRows(ctx context.Context, opts ExecuteQueryOptions, query string, bindVars map[string]any, visit func(map[string]any) error) error { + if opts.BatchSize <= 0 { + opts.BatchSize = 1000 + } + client, err := arangostore.Open(ctx, opts.URL, opts.Database) + if err != nil { + return err + } + defer client.Close(ctx) + return client.QueryRows(ctx, query, opts.BatchSize, bindVars, func(row map[string]any) error { + return visit(row) + }) +} diff --git a/internal/dataframe/selectors.go b/internal/dataframe/selectors.go new file mode 100644 index 0000000..ec39f48 --- /dev/null +++ b/internal/dataframe/selectors.go @@ -0,0 +1,46 @@ +package dataframe + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/calypr/loom/internal/fhirschema" +) + +type Selector = fhirschema.Selector +type SelectorStep = fhirschema.SelectorStep +type ContainsFilter = fhirschema.ContainsFilter + +func ParseSelector(input string) (Selector, error) { + return fhirschema.ParseSelector(input) +} + +func selectorStepText(step SelectorStep) string { + switch { + case step.Iterate: + return step.Field + "[]" + case step.Index != nil: + return fmt.Sprintf("%s[%d]", step.Field, *step.Index) + default: + return step.Field + } +} + +func sanitizeColumnName(in string) string { + var b strings.Builder + for _, r := range in { + switch { + case r >= 'a' && r <= 'z', r >= 'A' && r <= 'Z', r >= '0' && r <= '9': + b.WriteRune(r) + default: + b.WriteRune('_') + } + } + return b.String() +} + +func quoteKey(key string) string { + data, _ := json.Marshal(key) + return string(data) +} diff --git a/internal/dataframe/service.go b/internal/dataframe/service.go new file mode 100644 index 0000000..fbed4f4 --- /dev/null +++ b/internal/dataframe/service.go @@ -0,0 +1,102 @@ +package dataframe + +import ( + "context" + "fmt" + + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/catalog" + arangostore "github.com/calypr/loom/internal/store/arango" +) + +const defaultRowLimit = 25 + +type ServiceConfig struct { + ConnectionOptions arangostore.ConnectionOptions + DiscoverReferences func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) + DiscoverFields func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) + ExecuteRows func(context.Context, ExecuteQueryOptions, string, map[string]any, func(map[string]any) error) error + ScopeResolver *authscope.ScopeResolver +} + +type Service struct { + connOpts arangostore.ConnectionOptions + discoverReferences func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) + discoverFields func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) + executeRows func(context.Context, ExecuteQueryOptions, string, map[string]any, func(map[string]any) error) error + scopeResolver *authscope.ScopeResolver +} + +func NewService(cfg ServiceConfig) *Service { + svc := &Service{ + connOpts: cfg.ConnectionOptions, + scopeResolver: cfg.ScopeResolver, + } + if cfg.DiscoverReferences != nil { + svc.discoverReferences = cfg.DiscoverReferences + } else { + svc.discoverReferences = catalog.DiscoverPopulatedReferences + } + if cfg.DiscoverFields != nil { + svc.discoverFields = cfg.DiscoverFields + } else { + svc.discoverFields = catalog.DiscoverPopulatedFields + } + if cfg.ExecuteRows != nil { + svc.executeRows = cfg.ExecuteRows + } else { + svc.executeRows = ExecuteQueryRows + } + return svc +} + +func (s *Service) Run(ctx context.Context, req RunRequest) (*Result, error) { + spec, err := s.prepareSpec(ctx, req.Builder) + if err != nil { + return nil, err + } + limit := req.Limit + if limit <= 0 { + limit = defaultRowLimit + } + compiled, err := Compile(spec, limit) + if err != nil { + return nil, err + } + return s.runQuery(ctx, compiled) +} + +func (s *Service) prepareSpec(ctx context.Context, builder Builder) (Builder, error) { + if builder.Project == "" { + return Builder{}, fmt.Errorf("project is required") + } + if builder.RootResourceType == "" { + return Builder{}, fmt.Errorf("rootResourceType is required") + } + + principal, _ := authscope.PrincipalFromContext(ctx) + resolvedPaths, err := s.resolveAuthResourcePaths(ctx, principal, builder.Project, builder.AuthResourcePaths) + if err != nil { + return Builder{}, err + } + if err := authorizeProject(principal, builder.Project, s.scopeResolver != nil); err != nil { + return Builder{}, err + } + + builder.AuthResourcePaths = resolvedPaths + if err := s.validateBuilder(ctx, builder); err != nil { + return Builder{}, err + } + expanded, err := s.expandPivotColumns(ctx, builder) + if err != nil { + return Builder{}, err + } + planned, err := lowerGraphQLBuilder(expanded) + if err != nil { + return Builder{}, err + } + if err := validateLoweredBuilder(planned); err != nil { + return Builder{}, err + } + return planned, nil +} diff --git a/internal/dataframe/traversal_rules.go b/internal/dataframe/traversal_rules.go new file mode 100644 index 0000000..212b078 --- /dev/null +++ b/internal/dataframe/traversal_rules.go @@ -0,0 +1,102 @@ +package dataframe + +import "github.com/calypr/loom/internal/fhirschema" + +type traversalRole string + +const ( + traversalRolePatientNeighborChild traversalRole = "PATIENT_NEIGHBOR_CHILD" + traversalRolePatientDirectChild traversalRole = "PATIENT_DIRECT_CHILD" + traversalRolePatientDocumentReference traversalRole = "PATIENT_DOCUMENT_REFERENCE" + traversalRoleSpecimenGroup traversalRole = "SPECIMEN_GROUP" + traversalRoleSpecimenDocumentReference traversalRole = "SPECIMEN_DOCUMENT_REFERENCE" + traversalRoleGroupDocumentReference traversalRole = "GROUP_DOCUMENT_REFERENCE" +) + +type plannerTraversal struct { + Schema fhirschema.TraversalSpec + Role traversalRole + SetName string + SharedRootNeighborEligible bool +} + +func lookupPlannerTraversal(fromType, edgeLabel, toType string) (plannerTraversal, bool) { + spec, ok := fhirschema.LookupTraversal(fromType, edgeLabel, toType) + if !ok { + return plannerTraversal{}, false + } + rule, ok := classifyPlannerTraversal(spec) + if !ok { + return plannerTraversal{}, false + } + return rule, true +} + +func classifyPlannerTraversal(spec fhirschema.TraversalSpec) (plannerTraversal, bool) { + switch traversalKey(spec.FromType, spec.EdgeLabel, spec.ToType) { + case traversalKey("Patient", "subject_Patient", "Condition"): + return patientNeighborTraversal(spec, "patient_condition_set"), true + case traversalKey("Patient", "subject_Patient", "ResearchSubject"): + return patientNeighborTraversal(spec, "patient_research_subject_set"), true + case traversalKey("Patient", "subject_Patient", "Specimen"): + return patientNeighborTraversal(spec, "patient_specimen_set"), true + case traversalKey("Patient", "subject_Patient", "MedicationAdministration"): + return patientNeighborTraversal(spec, "patient_medication_administration_set"), true + case traversalKey("Patient", "subject_Patient", "Observation"): + return patientNeighborTraversal(spec, "patient_subject_observation_set"), true + case traversalKey("Patient", "subject_Patient", "ImagingStudy"): + return patientNeighborTraversal(spec, "patient_imaging_study_set"), true + case traversalKey("Patient", "subject_Patient", "DocumentReference"): + return plannerTraversal{ + Schema: spec, + Role: traversalRolePatientDocumentReference, + SetName: "patient_document_reference_set", + SharedRootNeighborEligible: true, + }, true + case traversalKey("Patient", "focus_Patient", "Observation"): + return patientDirectTraversal(spec, "patient_focus_observation_set"), true + case traversalKey("Patient", "member_entity_Patient", "Group"): + return patientDirectTraversal(spec, "patient_group_set"), true + case traversalKey("Specimen", "member_entity_Specimen", "Group"): + return plannerTraversal{ + Schema: spec, + Role: traversalRoleSpecimenGroup, + SetName: "specimen_group_set", + }, true + case traversalKey("Specimen", "subject_Specimen", "DocumentReference"): + return plannerTraversal{ + Schema: spec, + Role: traversalRoleSpecimenDocumentReference, + SetName: "specimen_document_reference_set", + }, true + case traversalKey("Group", "subject_Group", "DocumentReference"): + return plannerTraversal{ + Schema: spec, + Role: traversalRoleGroupDocumentReference, + SetName: "group_document_reference_set", + }, true + default: + return plannerTraversal{}, false + } +} + +func patientNeighborTraversal(spec fhirschema.TraversalSpec, setName string) plannerTraversal { + return plannerTraversal{ + Schema: spec, + Role: traversalRolePatientNeighborChild, + SetName: setName, + SharedRootNeighborEligible: true, + } +} + +func patientDirectTraversal(spec fhirschema.TraversalSpec, setName string) plannerTraversal { + return plannerTraversal{ + Schema: spec, + Role: traversalRolePatientDirectChild, + SetName: setName, + } +} + +func traversalKey(fromType, edgeLabel, toType string) string { + return fromType + "|" + edgeLabel + "|" + toType +} diff --git a/internal/dataframe/validation.go b/internal/dataframe/validation.go new file mode 100644 index 0000000..b1dcd60 --- /dev/null +++ b/internal/dataframe/validation.go @@ -0,0 +1,286 @@ +package dataframe + +import ( + "context" + "fmt" + "strings" + + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/fhirschema" +) + +func (s *Service) validateBuilder(ctx context.Context, builder Builder) error { + seenAliases := map[string]struct{}{} + rootFields, err := s.discoverFields(ctx, catalog.PopulatedFieldOptions{ + ConnectionOptions: s.connOpts, + Project: builder.Project, + AuthResourcePaths: builder.AuthResourcePaths, + ResourceType: builder.RootResourceType, + }) + if err != nil { + return err + } + rootPivots, err := s.discoverFields(ctx, catalog.PopulatedFieldOptions{ + ConnectionOptions: s.connOpts, + Project: builder.Project, + AuthResourcePaths: builder.AuthResourcePaths, + ResourceType: builder.RootResourceType, + PivotOnly: true, + }) + if err != nil { + return err + } + if err := validateNodeSelections(builder.Fields, builder.Pivots, builder.Aggregates, builder.Slices, rootFields, rootPivots); err != nil { + return err + } + for _, step := range builder.Traversals { + if err := s.validateTraversal(ctx, builder.Project, builder.AuthResourcePaths, builder.RootResourceType, step, seenAliases); err != nil { + return err + } + } + return nil +} + +func (s *Service) validateTraversal(ctx context.Context, project string, authResourcePaths []string, sourceType string, step TraversalStep, seenAliases map[string]struct{}) error { + if step.Alias == "" { + return fmt.Errorf("traversal alias is required") + } + if _, ok := seenAliases[step.Alias]; ok { + return fmt.Errorf("traversal alias %q is duplicated", step.Alias) + } + seenAliases[step.Alias] = struct{}{} + + refs, err := s.discoverReferences(ctx, catalog.PopulatedReferenceOptions{ + ConnectionOptions: s.connOpts, + Project: project, + AuthResourcePaths: authResourcePaths, + NodeType: sourceType, + Mode: catalog.TraversalModeBuilder, + }) + if err != nil { + return err + } + found := false + for _, ref := range refs { + if ref.Label == step.Label && ref.ToType == step.ToResourceType { + found = true + break + } + } + if !found { + return fmt.Errorf("traversal %s -> %s (%s) is not populated", sourceType, step.ToResourceType, step.Label) + } + + fields, err := s.discoverFields(ctx, catalog.PopulatedFieldOptions{ + ConnectionOptions: s.connOpts, + Project: project, + AuthResourcePaths: authResourcePaths, + ResourceType: step.ToResourceType, + }) + if err != nil { + return err + } + pivotFields, err := s.discoverFields(ctx, catalog.PopulatedFieldOptions{ + ConnectionOptions: s.connOpts, + Project: project, + AuthResourcePaths: authResourcePaths, + ResourceType: step.ToResourceType, + PivotOnly: true, + }) + if err != nil { + return err + } + if err := validateNodeSelections(step.Fields, step.Pivots, step.Aggregates, step.Slices, fields, pivotFields); err != nil { + return fmt.Errorf("alias %s: %w", step.Alias, err) + } + for _, child := range step.Traversals { + if err := s.validateTraversal(ctx, project, authResourcePaths, step.ToResourceType, child, seenAliases); err != nil { + return err + } + } + return nil +} + +func validateNodeSelections(fields []FieldSelect, pivots []PivotSelect, aggregates []AggregateSelect, slices []RepresentativeSlice, discovered []catalog.PopulatedField, pivotable []catalog.PopulatedField) error { + seenFields := map[string]struct{}{} + for _, field := range fields { + if field.Name == "" || field.Select == "" { + return fmt.Errorf("field selections require name and select") + } + if _, ok := seenFields[field.Name]; ok { + return fmt.Errorf("field name %q is duplicated", field.Name) + } + seenFields[field.Name] = struct{}{} + if _, err := ParseSelector(field.Select); err != nil { + return fmt.Errorf("invalid selector for field %q: %w", field.Name, err) + } + for _, fallback := range field.FallbackSelects { + if _, err := ParseSelector(fallback); err != nil { + return fmt.Errorf("invalid fallback selector for field %q: %w", field.Name, err) + } + } + } + + seenPivots := map[string]struct{}{} + for _, pivot := range pivots { + if pivot.Name == "" || pivot.ColumnSelect == "" || pivot.ValueSelect == "" { + return fmt.Errorf("pivot selections require name, column selector, and value selector") + } + if _, ok := seenPivots[pivot.Name]; ok { + return fmt.Errorf("pivot name %q is duplicated", pivot.Name) + } + seenPivots[pivot.Name] = struct{}{} + + columnSel, err := ParseSelector(pivot.ColumnSelect) + if err != nil { + return fmt.Errorf("invalid column selector for pivot %q: %w", pivot.Name, err) + } + valueSel, err := ParseSelector(pivot.ValueSelect) + if err != nil { + return fmt.Errorf("invalid value selector for pivot %q: %w", pivot.Name, err) + } + + pivotSpec, err := fhirschema.ValidatePivotSelectors(resourceTypeFromDiscovered(discovered), selectorSpecFromSelector(columnSel), selectorSpecFromSelector(valueSel)) + if err != nil { + return fmt.Errorf("pivot %q: %w", pivot.Name, err) + } + match := findFieldByPath(pivotable, pivotSpec.CatalogRootPath) + if match == nil || !match.PivotCandidate { + return fmt.Errorf("pivot selector %q is not pivotable", pivot.ColumnSelect) + } + if len(pivot.Columns) == 0 && len(match.PivotColumns) == 0 { + return fmt.Errorf("pivot %q has no available pivot columns", pivot.Name) + } + pivot.PivotFamily = pivotSpec.Family + } + + seenAggregates := map[string]struct{}{} + for _, agg := range aggregates { + if strings.TrimSpace(agg.Name) == "" { + return fmt.Errorf("aggregate selections require name") + } + if _, ok := seenAggregates[agg.Name]; ok { + return fmt.Errorf("aggregate name %q is duplicated", agg.Name) + } + seenAggregates[agg.Name] = struct{}{} + switch strings.ToUpper(strings.TrimSpace(agg.Operation)) { + case "COUNT", "COUNT_DISTINCT", "EXISTS", "DISTINCT_VALUES": + default: + return fmt.Errorf("aggregate %q uses unsupported operation %q", agg.Name, agg.Operation) + } + if strings.TrimSpace(agg.Select) != "" { + sel, err := ParseSelector(agg.Select) + if err != nil { + return fmt.Errorf("invalid aggregate selector for %q: %w", agg.Name, err) + } + if findFieldByPath(discovered, sel.CanonicalPath()) == nil { + return fmt.Errorf("aggregate selector %q is not present in populated fields", agg.Select) + } + } + if strings.TrimSpace(agg.PredicatePath) != "" { + sel, err := ParseSelector(agg.PredicatePath) + if err != nil { + return fmt.Errorf("invalid aggregate predicate selector for %q: %w", agg.Name, err) + } + if findFieldByPath(discovered, sel.CanonicalPath()) == nil { + return fmt.Errorf("aggregate predicate selector %q is not present in populated fields", agg.PredicatePath) + } + } + } + + seenSlices := map[string]struct{}{} + for _, slice := range slices { + if strings.TrimSpace(slice.Name) == "" { + return fmt.Errorf("representative slices require name") + } + if _, ok := seenSlices[slice.Name]; ok { + return fmt.Errorf("representative slice name %q is duplicated", slice.Name) + } + seenSlices[slice.Name] = struct{}{} + if slice.Limit <= 0 { + return fmt.Errorf("representative slice %q requires positive limit", slice.Name) + } + if strings.TrimSpace(slice.PredicatePath) != "" { + sel, err := ParseSelector(slice.PredicatePath) + if err != nil { + return fmt.Errorf("invalid representative slice predicate for %q: %w", slice.Name, err) + } + if findFieldByPath(discovered, sel.CanonicalPath()) == nil { + return fmt.Errorf("representative slice predicate %q is not present in populated fields", slice.PredicatePath) + } + } + for _, field := range slice.Fields { + if strings.TrimSpace(field.Name) == "" || strings.TrimSpace(field.Select) == "" { + return fmt.Errorf("representative slice %q requires fields with name and select", slice.Name) + } + sel, err := ParseSelector(field.Select) + if err != nil { + return fmt.Errorf("invalid representative slice field for %q: %w", slice.Name, err) + } + if findFieldByPath(discovered, sel.CanonicalPath()) == nil { + return fmt.Errorf("representative slice selector %q is not present in populated fields", field.Select) + } + for _, fallback := range field.FallbackSelects { + fallbackSel, err := ParseSelector(fallback) + if err != nil { + return fmt.Errorf("invalid representative slice fallback selector for %q: %w", slice.Name, err) + } + if findFieldByPath(discovered, fallbackSel.CanonicalPath()) == nil { + return fmt.Errorf("representative slice fallback selector %q is not present in populated fields", fallback) + } + } + } + } + + for _, field := range fields { + sel, _ := ParseSelector(field.Select) + if findFieldByPath(discovered, sel.CanonicalPath()) == nil { + return fmt.Errorf("selector %q is not present in populated fields", field.Select) + } + for _, fallback := range field.FallbackSelects { + fallbackSel, _ := ParseSelector(fallback) + if findFieldByPath(discovered, fallbackSel.CanonicalPath()) == nil { + return fmt.Errorf("fallback selector %q is not present in populated fields", fallback) + } + } + } + return nil +} + +func selectorSpecFromSelector(sel Selector) fhirschema.FieldSelectorSpec { + sourcePath := "" + valuePath := "" + if len(sel.Steps) > 0 { + last := len(sel.Steps) - 1 + valuePath = selectorStepText(sel.Steps[last]) + if last > 0 { + parts := make([]string, 0, last) + for _, step := range sel.Steps[:last] { + parts = append(parts, selectorStepText(step)) + } + sourcePath = strings.Join(parts, ".") + } + } + var where *fhirschema.FieldPredicateSpec + if sel.Filter != nil { + where = &fhirschema.FieldPredicateSpec{ + Path: sel.Filter.Field, + Op: fhirschema.PredicateContains, + Value: sel.Filter.Needle, + } + } + return fhirschema.FieldSelectorSpec{ + SourcePath: sourcePath, + Where: where, + ValuePath: valuePath, + } +} + +func findFieldByPath(fields []catalog.PopulatedField, path string) *catalog.PopulatedField { + for i := range fields { + if fields[i].Path == path { + return &fields[i] + } + } + return nil +} diff --git a/internal/graphqlapi/fieldrefs.go b/internal/dataframebuilder/fieldrefs.go similarity index 61% rename from internal/graphqlapi/fieldrefs.go rename to internal/dataframebuilder/fieldrefs.go index 0815d38..457c58b 100644 --- a/internal/graphqlapi/fieldrefs.go +++ b/internal/dataframebuilder/fieldrefs.go @@ -1,21 +1,20 @@ -package graphqlapi +package dataframebuilder import ( "fmt" "regexp" "strings" - "arangodb-proto/internal/fhirschema" - "arangodb-proto/internal/fhirsemantics" - "arangodb-proto/internal/proto" + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/fhirschema" ) -type FieldHintResponse struct { +type FieldHint struct { ResourceType string FieldRef string Label string Path string - Selector FieldSelectorResponse + Selector FieldSelector Kind string DocCount int64 SampleCount int @@ -29,13 +28,13 @@ type FieldHintResponse struct { PivotValueSelect string } -type FieldSelectorResponse struct { +type FieldSelector struct { SourcePath string - Where *FieldPredicateResponse + Where *FieldPredicate ValuePath string } -type FieldPredicateResponse struct { +type FieldPredicate struct { Path string Op string Value string @@ -43,57 +42,24 @@ type FieldPredicateResponse struct { var fieldRefSanitizer = regexp.MustCompile(`[^a-z0-9]+`) -func discoveredFieldHints(resourceType string, fields []proto.PopulatedField) []FieldHintResponse { +func discoveredFieldHints(resourceType string, fields []catalog.PopulatedField) []FieldHint { if len(fields) == 0 { - return []FieldHintResponse{} - } - out := make([]FieldHintResponse, 0, len(fields)+8) - seen := map[string]struct{}{} - for _, spec := range fhirsemantics.AliasesForResource(resourceType) { - base := findFieldByPath(fields, fhirschema.CanonicalPath(spec.Selector)) - if base == nil { - continue - } - out = append(out, fieldHintFromSemantic(*base, spec)) - seen[spec.FieldRef] = struct{}{} + return []FieldHint{} } + out := make([]FieldHint, 0, len(fields)) for _, field := range fields { ref := defaultFieldRef(resourceType, field.Path) - if _, ok := seen[ref]; ok { - continue - } out = append(out, fieldHintFromDiscovered(field, ref, defaultFieldLabel(field.Path), field.Path)) } return out } -func fieldHintFromSemantic(field proto.PopulatedField, spec fhirsemantics.FieldSpec) FieldHintResponse { - return FieldHintResponse{ - ResourceType: field.ResourceType, - FieldRef: spec.FieldRef, - Label: spec.Label, - Path: field.Path, - Selector: fieldSelectorResponseFromSpec(spec.Selector), - Kind: field.Kind, - DocCount: field.DocCount, - SampleCount: field.SampleCount, - DistinctValues: cloneStrings(field.DistinctValues), - DistinctTruncated: field.DistinctTruncated, - PivotCandidate: field.PivotCandidate, - PivotKind: field.PivotKind, - PivotColumns: cloneStrings(field.PivotColumns), - PivotFamily: field.PivotFamily, - PivotColumnSelect: field.PivotColumnSelect, - PivotValueSelect: field.PivotValueSelect, - } -} - -func fieldHintFromDiscovered(field proto.PopulatedField, fieldRef string, label string, selector string) FieldHintResponse { +func fieldHintFromDiscovered(field catalog.PopulatedField, fieldRef string, label string, selector string) FieldHint { selectorResp := decomposeSelector(selector) if spec, ok := fhirschema.LookupField(field.ResourceType, field.Path); ok { - selectorResp = fieldSelectorResponseFromSpec(fhirschema.SelectorFromField(spec)) + selectorResp = fieldSelectorFromSpec(fhirschema.SelectorFromField(spec)) } - return FieldHintResponse{ + return FieldHint{ ResourceType: field.ResourceType, FieldRef: fieldRef, Label: label, @@ -113,14 +79,11 @@ func fieldHintFromDiscovered(field proto.PopulatedField, fieldRef string, label } } -func resolveFieldRef(resourceType string, discovered []proto.PopulatedField, fieldRef string) (string, error) { +func resolveFieldRef(resourceType string, discovered []catalog.PopulatedField, fieldRef string) (string, error) { fieldRef = strings.TrimSpace(fieldRef) if fieldRef == "" { return "", fmt.Errorf("fieldRef is required") } - if spec, ok := fhirsemantics.ResolveFieldRef(resourceType, fieldRef); ok { - return fhirschema.SelectorExpression(spec.Selector), nil - } for _, field := range discovered { if defaultFieldRef(resourceType, field.Path) == fieldRef { return field.Path, nil @@ -129,15 +92,6 @@ func resolveFieldRef(resourceType string, discovered []proto.PopulatedField, fie return "", fmt.Errorf("unknown fieldRef %q for resourceType %q", fieldRef, resourceType) } -func findFieldByPath(fields []proto.PopulatedField, path string) *proto.PopulatedField { - for i := range fields { - if fields[i].Path == path { - return &fields[i] - } - } - return nil -} - func defaultFieldRef(resourceType string, path string) string { key := strings.ToLower(path) key = strings.ReplaceAll(key, "[]", "_") @@ -160,10 +114,10 @@ func defaultFieldLabel(path string) string { return strings.Join(parts, " ") } -func decomposeSelector(expression string) FieldSelectorResponse { +func decomposeSelector(expression string) FieldSelector { sel, err := fhirschema.ParseSelector(expression) if err != nil { - return FieldSelectorResponse{ + return FieldSelector{ ValuePath: strings.TrimSpace(expression), } } @@ -180,31 +134,35 @@ func decomposeSelector(expression string) FieldSelectorResponse { sourcePath = strings.Join(sourceParts, ".") } } - var where *FieldPredicateResponse + var where *FieldPredicate if sel.Filter != nil { - where = &FieldPredicateResponse{ + where = &FieldPredicate{ Path: sel.Filter.Field, Op: fhirschema.PredicateContains, Value: sel.Filter.Needle, } } - return FieldSelectorResponse{ + return FieldSelector{ SourcePath: sourcePath, Where: where, ValuePath: valuePath, } } -func fieldSelectorResponseFromSpec(spec fhirschema.FieldSelectorSpec) FieldSelectorResponse { - var where *FieldPredicateResponse +func DecomposeSelector(expression string) FieldSelector { + return decomposeSelector(expression) +} + +func fieldSelectorFromSpec(spec fhirschema.FieldSelectorSpec) FieldSelector { + var where *FieldPredicate if spec.Where != nil { - where = &FieldPredicateResponse{ + where = &FieldPredicate{ Path: spec.Where.Path, Op: spec.Where.Op, Value: spec.Where.Value, } } - return FieldSelectorResponse{ + return FieldSelector{ SourcePath: spec.SourcePath, Where: where, ValuePath: spec.ValuePath, diff --git a/internal/dataframebuilder/fieldrefs_test.go b/internal/dataframebuilder/fieldrefs_test.go new file mode 100644 index 0000000..85a4691 --- /dev/null +++ b/internal/dataframebuilder/fieldrefs_test.go @@ -0,0 +1,60 @@ +package dataframebuilder + +import ( + "strings" + "testing" + + "github.com/calypr/loom/internal/catalog" +) + +func TestDiscoveredFieldHintsUseDefaultRefsOnly(t *testing.T) { + fields := []catalog.PopulatedField{ + {ResourceType: "Patient", Path: "identifier[].value", Kind: "scalar"}, + } + hints := discoveredFieldHints("Patient", fields) + if len(hints) != 1 { + t.Fatalf("hint count = %d, want 1", len(hints)) + } + if hints[0].FieldRef != "Patient.identifier_value" { + t.Fatalf("unexpected fieldRef: %q", hints[0].FieldRef) + } + if hints[0].Label != "Identifier Value" { + t.Fatalf("unexpected label: %q", hints[0].Label) + } + if hints[0].Selector.SourcePath != "identifier[]" || hints[0].Selector.ValuePath != "value" { + t.Fatalf("unexpected selector: %#v", hints[0].Selector) + } +} + +func TestResolveFieldRefAcceptsDefaultGeneratedRefs(t *testing.T) { + discovered := []catalog.PopulatedField{ + {ResourceType: "Patient", Path: "identifier[].value"}, + } + selector, err := resolveFieldRef("Patient", discovered, "Patient.identifier_value") + if err != nil { + t.Fatal(err) + } + if selector != "identifier[].value" { + t.Fatalf("unexpected selector: %q", selector) + } +} + +func TestResolveFieldRefRejectsCuratedAlias(t *testing.T) { + discovered := []catalog.PopulatedField{ + {ResourceType: "Patient", Path: "extension[].valueCode"}, + } + _, err := resolveFieldRef("Patient", discovered, "Patient.birth_sex") + if err == nil || !strings.Contains(err.Error(), `unknown fieldRef "Patient.birth_sex"`) { + t.Fatalf("expected curated alias rejection, got %v", err) + } +} + +func TestResolvePivotFieldRefRejectsCuratedAlias(t *testing.T) { + discovered := []catalog.PopulatedField{ + {ResourceType: "Patient", Path: "extension[].valueCode"}, + } + _, err := resolvePivotFieldRef("Patient", discovered, "Patient.birth_sex") + if err == nil || !strings.Contains(err.Error(), `unknown pivot fieldRef "Patient.birth_sex"`) { + t.Fatalf("expected curated pivot alias rejection, got %v", err) + } +} diff --git a/internal/dataframebuilder/helpers.go b/internal/dataframebuilder/helpers.go new file mode 100644 index 0000000..2411086 --- /dev/null +++ b/internal/dataframebuilder/helpers.go @@ -0,0 +1,17 @@ +package dataframebuilder + +import "github.com/calypr/loom/internal/catalog" + +func cloneStrings(in []string) []string { + if len(in) == 0 { + return []string{} + } + return append([]string(nil), in...) +} + +func cloneTraversals(in []catalog.PopulatedReference) []catalog.PopulatedReference { + if len(in) == 0 { + return []catalog.PopulatedReference{} + } + return append([]catalog.PopulatedReference(nil), in...) +} diff --git a/internal/dataframebuilder/input_mapping.go b/internal/dataframebuilder/input_mapping.go new file mode 100644 index 0000000..d0a3fea --- /dev/null +++ b/internal/dataframebuilder/input_mapping.go @@ -0,0 +1,197 @@ +package dataframebuilder + +import ( + "strings" + + "github.com/calypr/loom/internal/dataframe" + "github.com/calypr/loom/internal/graphqlapi/model" +) + +func BuilderFromInput(in model.FhirDataframeInput) dataframe.Builder { + authResourcePaths := cloneStrings(in.AuthResourcePaths) + if len(authResourcePaths) == 0 && strings.TrimSpace(derefString(in.AuthResourcePath)) != "" { + authResourcePaths = []string{strings.TrimSpace(derefString(in.AuthResourcePath))} + } + return dataframe.Builder{ + Project: in.Project, + AuthResourcePaths: authResourcePaths, + RootResourceType: in.RootResourceType, + Fields: fieldSelectsFromModel(in.RootFields), + Pivots: pivotSelectsFromModel(in.RootPivots), + Aggregates: aggregateSelectsFromModel(in.RootAggregates), + Slices: sliceSelectsFromModel(in.RootSlices), + Traversals: traversalStepsFromModel(in.Traverse), + } +} + +func fieldSelectsFromModel(in []*model.FhirFieldSelectInput) []dataframe.FieldSelect { + if len(in) == 0 { + return []dataframe.FieldSelect{} + } + out := make([]dataframe.FieldSelect, 0, len(in)) + for _, item := range in { + if item == nil { + continue + } + selectText := "" + if item.Selector != nil { + selectText = composeSelector( + derefString(item.Selector.SourcePath), + predicatePathFromInput(item.Selector.Where), + predicateOpFromInput(item.Selector.Where), + predicateValueFromInput(item.Selector.Where), + item.Selector.ValuePath, + ) + } + fallbackSelectors := make([]string, 0, len(item.FallbackSelectors)) + for _, fallback := range item.FallbackSelectors { + if fallback == nil { + continue + } + fallbackSelectors = append(fallbackSelectors, composeSelector( + derefString(fallback.SourcePath), + predicatePathFromInput(fallback.Where), + predicateOpFromInput(fallback.Where), + predicateValueFromInput(fallback.Where), + fallback.ValuePath, + )) + } + out = append(out, dataframe.FieldSelect{ + Name: item.Name, + FieldRef: derefString(item.FieldRef), + Select: selectText, + FallbackFieldRefs: cloneStrings(item.FallbackFieldRefs), + FallbackSelects: fallbackSelectors, + ValueMode: item.ValueMode.String(), + }) + } + return out +} + +func pivotSelectsFromModel(in []*model.FhirPivotInput) []dataframe.PivotSelect { + if len(in) == 0 { + return []dataframe.PivotSelect{} + } + out := make([]dataframe.PivotSelect, 0, len(in)) + for _, item := range in { + if item == nil { + continue + } + out = append(out, dataframe.PivotSelect{ + Name: item.Name, + FieldRef: derefString(item.FieldRef), + ColumnSelect: composeSelectorFromInput(item.ColumnSelector), + ValueSelect: composeSelectorFromInput(item.ValueSelector), + Columns: cloneStrings(item.Columns), + }) + } + return out +} + +func composeSelectorFromInput(in *model.FhirFieldSelectorInput) string { + if in == nil { + return "" + } + return composeSelector( + derefString(in.SourcePath), + predicatePathFromInput(in.Where), + predicateOpFromInput(in.Where), + predicateValueFromInput(in.Where), + in.ValuePath, + ) +} + +func aggregateSelectsFromModel(in []*model.FhirAggregateInput) []dataframe.AggregateSelect { + if len(in) == 0 { + return []dataframe.AggregateSelect{} + } + out := make([]dataframe.AggregateSelect, 0, len(in)) + for _, item := range in { + if item == nil { + continue + } + out = append(out, dataframe.AggregateSelect{ + Name: item.Name, + Operation: item.Operation.String(), + FieldRef: strings.TrimSpace(derefString(item.FieldRef)), + Select: strings.TrimSpace(derefString(item.FhirPath)), + PredicateFieldRef: strings.TrimSpace(derefString(item.PredicateFieldRef)), + PredicatePath: strings.TrimSpace(derefString(item.PredicatePath)), + PredicateEquals: derefString(item.PredicateEquals), + ValueMode: item.ValueMode.String(), + }) + } + return out +} + +func sliceSelectsFromModel(in []*model.FhirRepresentativeSliceInput) []dataframe.RepresentativeSlice { + if len(in) == 0 { + return []dataframe.RepresentativeSlice{} + } + out := make([]dataframe.RepresentativeSlice, 0, len(in)) + for _, item := range in { + if item == nil { + continue + } + out = append(out, dataframe.RepresentativeSlice{ + Name: item.Name, + Limit: item.Limit, + PredicateFieldRef: strings.TrimSpace(derefString(item.WhereFieldRef)), + PredicatePath: strings.TrimSpace(derefString(item.WherePath)), + PredicateEquals: derefString(item.WhereEquals), + Fields: fieldSelectsFromModel(item.Fields), + }) + } + return out +} + +func traversalStepsFromModel(in []*model.FhirTraversalStepInput) []dataframe.TraversalStep { + if len(in) == 0 { + return []dataframe.TraversalStep{} + } + out := make([]dataframe.TraversalStep, 0, len(in)) + for _, item := range in { + if item == nil { + continue + } + out = append(out, dataframe.TraversalStep{ + Label: item.EdgeLabel, + ToResourceType: item.ToResourceType, + Alias: item.Alias, + Fields: fieldSelectsFromModel(item.Fields), + Pivots: pivotSelectsFromModel(item.Pivots), + Aggregates: aggregateSelectsFromModel(item.Aggregates), + Slices: sliceSelectsFromModel(item.Slices), + Traversals: traversalStepsFromModel(item.Traverse), + }) + } + return out +} + +func derefString(in *string) string { + if in == nil { + return "" + } + return *in +} + +func predicatePathFromInput(in *model.FhirFieldPredicateInput) string { + if in == nil { + return "" + } + return in.Path +} + +func predicateOpFromInput(in *model.FhirFieldPredicateInput) string { + if in == nil { + return "" + } + return in.Op.String() +} + +func predicateValueFromInput(in *model.FhirFieldPredicateInput) string { + if in == nil { + return "" + } + return in.Value +} diff --git a/internal/graphqlapi/mappers_test.go b/internal/dataframebuilder/input_mapping_test.go similarity index 95% rename from internal/graphqlapi/mappers_test.go rename to internal/dataframebuilder/input_mapping_test.go index bafe691..175c345 100644 --- a/internal/graphqlapi/mappers_test.go +++ b/internal/dataframebuilder/input_mapping_test.go @@ -1,9 +1,9 @@ -package graphqlapi +package dataframebuilder import ( "testing" - "arangodb-proto/internal/graphqlapi/model" + "github.com/calypr/loom/internal/graphqlapi/model" ) func TestBuilderFromInputMapsAggregatesSlicesAndFallbacks(t *testing.T) { @@ -54,7 +54,7 @@ func TestBuilderFromInputMapsAggregatesSlicesAndFallbacks(t *testing.T) { }, } - builder := builderFromInput(input) + builder := BuilderFromInput(input) if len(builder.Fields) != 1 || len(builder.Fields[0].FallbackSelects) != 1 { t.Fatalf("unexpected root field mapping: %#v", builder.Fields) } diff --git a/internal/dataframebuilder/input_resolution.go b/internal/dataframebuilder/input_resolution.go new file mode 100644 index 0000000..e04eba4 --- /dev/null +++ b/internal/dataframebuilder/input_resolution.go @@ -0,0 +1,249 @@ +package dataframebuilder + +import ( + "context" + "fmt" + "strings" + + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/graphqlapi/model" +) + +func (s *Service) PrepareRunInput(ctx context.Context, input model.FhirDataframeInput) (model.FhirDataframeInput, error) { + if input.Project == "" { + return input, fmt.Errorf("project is required") + } + if input.RootResourceType == "" { + return input, fmt.Errorf("rootResourceType is required") + } + + principal, _ := authscope.PrincipalFromContext(ctx) + resolvedPaths, err := s.resolveAuthResourcePaths(ctx, principal, input.Project, input.AuthResourcePaths) + if err != nil { + return input, err + } + if err := authorizeProject(principal, input.Project, s.scopeResolver != nil); err != nil { + return input, err + } + + input.AuthResourcePaths = resolvedPaths + if len(input.AuthResourcePaths) == 0 { + input.AuthResourcePaths = nil + } + if err := s.resolveNodeInputRefs(ctx, input.Project, input.AuthResourcePaths, input.RootResourceType, input.RootFields, input.RootPivots, input.RootAggregates, input.RootSlices); err != nil { + return input, err + } + for _, step := range input.Traverse { + if err := s.resolveTraversalInputRefs(ctx, input.Project, input.AuthResourcePaths, step); err != nil { + return input, err + } + } + return input, nil +} + +func (s *Service) resolveTraversalInputRefs(ctx context.Context, project string, authResourcePaths []string, step *model.FhirTraversalStepInput) error { + if step == nil { + return nil + } + if err := s.resolveNodeInputRefs(ctx, project, authResourcePaths, step.ToResourceType, step.Fields, step.Pivots, step.Aggregates, step.Slices); err != nil { + return err + } + for _, child := range step.Traverse { + if err := s.resolveTraversalInputRefs(ctx, project, authResourcePaths, child); err != nil { + return err + } + } + return nil +} + +func (s *Service) resolveNodeInputRefs(ctx context.Context, project string, authResourcePaths []string, resourceType string, fields []*model.FhirFieldSelectInput, pivots []*model.FhirPivotInput, aggregates []*model.FhirAggregateInput, slices []*model.FhirRepresentativeSliceInput) error { + discovered, err := s.discoverFields(ctx, catalog.PopulatedFieldOptions{ + ConnectionOptions: s.connOpts, + Project: project, + AuthResourcePaths: authResourcePaths, + ResourceType: resourceType, + }) + if err != nil { + return err + } + + for _, field := range fields { + if field == nil { + continue + } + if strings.TrimSpace(derefString(field.FieldRef)) != "" { + selectorText, err := resolveFieldRef(resourceType, discovered, derefString(field.FieldRef)) + if err != nil { + return err + } + field.Selector = selectorInputFromExpression(selectorText) + } + if len(field.FallbackFieldRefs) > 0 { + fallbacks := make([]*model.FhirFieldSelectorInput, 0, len(field.FallbackFieldRefs)) + for _, ref := range field.FallbackFieldRefs { + selectorText, err := resolveFieldRef(resourceType, discovered, ref) + if err != nil { + return err + } + fallbacks = append(fallbacks, selectorInputFromExpression(selectorText)) + } + field.FallbackSelectors = fallbacks + } + } + + for _, pivot := range pivots { + if pivot == nil { + continue + } + if strings.TrimSpace(derefString(pivot.FieldRef)) != "" { + hint, err := resolvePivotFieldRef(resourceType, discovered, derefString(pivot.FieldRef)) + if err != nil { + return err + } + if pivot.ColumnSelector == nil { + pivot.ColumnSelector = selectorInputFromExpression(hint.PivotColumnSelect) + } + if pivot.ValueSelector == nil { + pivot.ValueSelector = selectorInputFromExpression(hint.PivotValueSelect) + } + } + } + + for _, aggregate := range aggregates { + if aggregate == nil { + continue + } + if strings.TrimSpace(derefString(aggregate.FieldRef)) != "" { + selector, err := resolveFieldRef(resourceType, discovered, derefString(aggregate.FieldRef)) + if err != nil { + return err + } + aggregate.FhirPath = &selector + } + if strings.TrimSpace(derefString(aggregate.PredicateFieldRef)) != "" { + selector, err := resolveFieldRef(resourceType, discovered, derefString(aggregate.PredicateFieldRef)) + if err != nil { + return err + } + aggregate.PredicatePath = &selector + } + } + + for _, slice := range slices { + if slice == nil { + continue + } + if strings.TrimSpace(derefString(slice.WhereFieldRef)) != "" { + selector, err := resolveFieldRef(resourceType, discovered, derefString(slice.WhereFieldRef)) + if err != nil { + return err + } + slice.WherePath = &selector + } + for _, field := range slice.Fields { + if field == nil { + continue + } + if strings.TrimSpace(derefString(field.FieldRef)) != "" { + selectorText, err := resolveFieldRef(resourceType, discovered, derefString(field.FieldRef)) + if err != nil { + return err + } + field.Selector = selectorInputFromExpression(selectorText) + } + if len(field.FallbackFieldRefs) > 0 { + fallbacks := make([]*model.FhirFieldSelectorInput, 0, len(field.FallbackFieldRefs)) + for _, ref := range field.FallbackFieldRefs { + selectorText, err := resolveFieldRef(resourceType, discovered, ref) + if err != nil { + return err + } + fallbacks = append(fallbacks, selectorInputFromExpression(selectorText)) + } + field.FallbackSelectors = fallbacks + } + } + } + + return nil +} + +func resolvePivotFieldRef(resourceType string, discovered []catalog.PopulatedField, fieldRef string) (catalog.PopulatedField, error) { + fieldRef = strings.TrimSpace(fieldRef) + if fieldRef == "" { + return catalog.PopulatedField{}, fmt.Errorf("fieldRef is required") + } + for _, field := range discovered { + if defaultFieldRef(resourceType, field.Path) == fieldRef { + return field, nil + } + } + return catalog.PopulatedField{}, fmt.Errorf("unknown pivot fieldRef %q for resourceType %q", fieldRef, resourceType) +} + +func authorizeProject(principal *authscope.Principal, project string, ignorePrincipalProjects bool) error { + if ignorePrincipalProjects { + return nil + } + if principal == nil || len(principal.Projects) == 0 { + return nil + } + for _, candidate := range principal.Projects { + if candidate == project { + return nil + } + } + return fmt.Errorf("principal is not authorized for project %q", project) +} + +func (s *Service) resolveAuthResourcePaths(ctx context.Context, principal *authscope.Principal, project string, requested []string) ([]string, error) { + if s.scopeResolver != nil { + return s.scopeResolver.ResolveReadAuthResourcePaths(ctx, principal, project, requested) + } + if len(requested) == 0 { + if principal == nil || len(principal.AuthResourcePaths) == 0 { + return nil, nil + } + return append([]string(nil), principal.AuthResourcePaths...), nil + } + if principal == nil || len(principal.AuthResourcePaths) == 0 { + return append([]string(nil), requested...), nil + } + for _, path := range requested { + found := false + for _, candidate := range principal.AuthResourcePaths { + if candidate == path { + found = true + break + } + } + if !found { + return nil, fmt.Errorf("authResourcePath %q is outside caller scope", path) + } + } + return append([]string(nil), requested...), nil +} + +func selectorInputFromExpression(expression string) *model.FhirFieldSelectorInput { + parts := decomposeSelector(expression) + var where *model.FhirFieldPredicateInput + if parts.Where != nil { + where = &model.FhirFieldPredicateInput{ + Path: parts.Where.Path, + Op: model.FhirFieldPredicateOperation(parts.Where.Op), + Value: parts.Where.Value, + } + } + + var sourcePath *string + if trimmed := strings.TrimSpace(parts.SourcePath); trimmed != "" { + sourcePath = &trimmed + } + + return &model.FhirFieldSelectorInput{ + SourcePath: sourcePath, + Where: where, + ValuePath: parts.ValuePath, + } +} diff --git a/internal/dataframebuilder/introspection.go b/internal/dataframebuilder/introspection.go new file mode 100644 index 0000000..1a4cf69 --- /dev/null +++ b/internal/dataframebuilder/introspection.go @@ -0,0 +1,133 @@ +package dataframebuilder + +import ( + "context" + "fmt" + + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/catalog" +) + +func (s *Service) Introspect(ctx context.Context, req IntrospectionRequest) (*IntrospectionResponse, error) { + if req.Project == "" { + return nil, fmt.Errorf("project is required") + } + if req.RootResourceType == "" { + return nil, fmt.Errorf("rootResourceType is required") + } + + principal, _ := authscope.PrincipalFromContext(ctx) + resolvedPaths, err := s.resolveAuthResourcePaths(ctx, principal, req.Project, req.AuthResourcePaths) + if err != nil { + return nil, err + } + if err := authorizeProject(principal, req.Project, s.scopeResolver != nil); err != nil { + return nil, err + } + + traversals, err := s.discoverReferences(ctx, catalog.PopulatedReferenceOptions{ + ConnectionOptions: s.connOpts, + Project: req.Project, + AuthResourcePaths: resolvedPaths, + NodeType: req.RootResourceType, + Mode: catalog.TraversalModeBuilder, + }) + if err != nil { + return nil, err + } + + rootHints, err := s.buildResourceHints(ctx, req.Project, resolvedPaths, req.RootResourceType, traversals, req.IncludePivotOnlyFields) + if err != nil { + return nil, err + } + relatedHints, err := s.buildRelatedResourceHints(ctx, req.Project, resolvedPaths, traversals, req.IncludePivotOnlyFields) + if err != nil { + return nil, err + } + + return &IntrospectionResponse{ + Project: req.Project, + RootResourceType: req.RootResourceType, + AuthResourcePaths: resolvedPaths, + Root: rootHints, + RelatedResources: relatedHints, + Traversals: rootHints.Traversals, + Fields: rootHints.Fields, + PivotFields: rootHints.PivotFields, + }, nil +} + +func (s *Service) buildResourceHints(ctx context.Context, project string, authResourcePaths []string, resourceType string, traversals []catalog.PopulatedReference, includePivotOnlyFields bool) (ResourceHints, error) { + fields, err := s.discoverFields(ctx, catalog.PopulatedFieldOptions{ + ConnectionOptions: s.connOpts, + Project: project, + AuthResourcePaths: authResourcePaths, + ResourceType: resourceType, + PivotOnly: false, + }) + if err != nil { + return ResourceHints{}, err + } + + pivotFields := []catalog.PopulatedField{} + if includePivotOnlyFields { + pivotFields, err = s.discoverFields(ctx, catalog.PopulatedFieldOptions{ + ConnectionOptions: s.connOpts, + Project: project, + AuthResourcePaths: authResourcePaths, + ResourceType: resourceType, + PivotOnly: true, + }) + if err != nil { + return ResourceHints{}, err + } + } + + return ResourceHints{ + ResourceType: resourceType, + Fields: discoveredFieldHints(resourceType, normalizeFieldSlice(fields)), + PivotFields: discoveredFieldHints(resourceType, normalizeFieldSlice(pivotFields)), + Traversals: cloneTraversals(traversals), + }, nil +} + +func (s *Service) buildRelatedResourceHints(ctx context.Context, project string, authResourcePaths []string, traversals []catalog.PopulatedReference, includePivotOnlyFields bool) ([]RelatedResourceHints, error) { + if len(traversals) == 0 { + return []RelatedResourceHints{}, nil + } + + typeCache := map[string]ResourceHints{} + out := make([]RelatedResourceHints, 0, len(traversals)) + for _, ref := range traversals { + target, ok := typeCache[ref.ToType] + if !ok { + hints, err := s.buildResourceHints(ctx, project, authResourcePaths, ref.ToType, nil, includePivotOnlyFields) + if err != nil { + return nil, err + } + typeCache[ref.ToType] = hints + target = hints + } + out = append(out, RelatedResourceHints{ + ViaLabel: ref.Label, + EdgeCount: ref.EdgeCount, + Target: target, + }) + } + return out, nil +} + +func normalizeFieldSlice(in []catalog.PopulatedField) []catalog.PopulatedField { + if len(in) == 0 { + return []catalog.PopulatedField{} + } + for i := range in { + if in[i].DistinctValues == nil { + in[i].DistinctValues = []string{} + } + if in[i].PivotColumns == nil { + in[i].PivotColumns = []string{} + } + } + return in +} diff --git a/internal/graphqlapi/service_test.go b/internal/dataframebuilder/introspection_test.go similarity index 60% rename from internal/graphqlapi/service_test.go rename to internal/dataframebuilder/introspection_test.go index 5ecd67d..f03c22f 100644 --- a/internal/graphqlapi/service_test.go +++ b/internal/dataframebuilder/introspection_test.go @@ -1,38 +1,38 @@ -package graphqlapi +package dataframebuilder import ( "context" "testing" - "arangodb-proto/internal/proto" - "arangodb-proto/internal/writeapi" + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/catalog" ) func TestServiceIntrospectUsesCallerScope(t *testing.T) { - var gotRefOpts proto.PopulatedReferenceOptions - var gotFieldOpts []proto.PopulatedFieldOptions + var gotRefOpts catalog.PopulatedReferenceOptions + var gotFieldOpts []catalog.PopulatedFieldOptions - svc := NewService(ServiceConfig{ - DiscoverReferences: func(ctx context.Context, opts proto.PopulatedReferenceOptions) ([]proto.PopulatedReference, error) { + service := NewService(Config{ + DiscoverReferences: func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { gotRefOpts = opts - return []proto.PopulatedReference{{FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 7}}, nil + return []catalog.PopulatedReference{{FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 7}}, nil }, - DiscoverFields: func(ctx context.Context, opts proto.PopulatedFieldOptions) ([]proto.PopulatedField, error) { + DiscoverFields: func(ctx context.Context, opts catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { gotFieldOpts = append(gotFieldOpts, opts) if opts.PivotOnly { - return []proto.PopulatedField{{ResourceType: opts.ResourceType, Path: "valueCodeableConcept", PivotCandidate: true, PivotKind: "codeable_concept_display_value", PivotColumns: []string{"A"}}}, nil + return []catalog.PopulatedField{{ResourceType: opts.ResourceType, Path: "valueCodeableConcept", PivotCandidate: true, PivotKind: "codeable_concept_display_value", PivotColumns: []string{"A"}}}, nil } - return []proto.PopulatedField{{ResourceType: opts.ResourceType, Path: "identifier[].value", Kind: "scalar", DistinctValues: []string{"x"}}}, nil + return []catalog.PopulatedField{{ResourceType: opts.ResourceType, Path: "identifier[].value", Kind: "scalar", DistinctValues: []string{"x"}}}, nil }, }) - ctx := writeapi.ContextWithPrincipal(context.Background(), &writeapi.Principal{ + ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{ Subject: "u1", Projects: []string{"P1"}, AuthResourcePaths: []string{"pathA", "pathB"}, }) - resp, err := svc.Introspect(ctx, IntrospectionRequest{ + resp, err := service.Introspect(ctx, IntrospectionRequest{ Project: "P1", RootResourceType: "Patient", IncludePivotOnlyFields: true, @@ -40,7 +40,7 @@ func TestServiceIntrospectUsesCallerScope(t *testing.T) { if err != nil { t.Fatal(err) } - if gotRefOpts.Project != "P1" || gotRefOpts.NodeType != "Patient" || gotRefOpts.Mode != proto.TraversalModeBuilder { + if gotRefOpts.Project != "P1" || gotRefOpts.NodeType != "Patient" || gotRefOpts.Mode != catalog.TraversalModeBuilder { t.Fatalf("unexpected reference opts: %+v", gotRefOpts) } if len(gotRefOpts.AuthResourcePaths) != 2 || gotRefOpts.AuthResourcePaths[0] != "pathA" || gotRefOpts.AuthResourcePaths[1] != "pathB" { @@ -67,14 +67,14 @@ func TestServiceIntrospectUsesCallerScope(t *testing.T) { } func TestServiceIntrospectRejectsUnauthorizedScope(t *testing.T) { - svc := NewService(ServiceConfig{}) - ctx := writeapi.ContextWithPrincipal(context.Background(), &writeapi.Principal{ + service := NewService(Config{}) + ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{ Subject: "u1", Projects: []string{"P1"}, AuthResourcePaths: []string{"pathA"}, }) - _, err := svc.Introspect(ctx, IntrospectionRequest{ + _, err := service.Introspect(ctx, IntrospectionRequest{ Project: "P1", RootResourceType: "Patient", AuthResourcePaths: []string{"pathB"}, @@ -85,13 +85,13 @@ func TestServiceIntrospectRejectsUnauthorizedScope(t *testing.T) { } func TestServiceIntrospectRejectsUnauthorizedProject(t *testing.T) { - svc := NewService(ServiceConfig{}) - ctx := writeapi.ContextWithPrincipal(context.Background(), &writeapi.Principal{ + service := NewService(Config{}) + ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{ Subject: "u1", Projects: []string{"P1"}, }) - _, err := svc.Introspect(ctx, IntrospectionRequest{ + _, err := service.Introspect(ctx, IntrospectionRequest{ Project: "P2", RootResourceType: "Patient", }) diff --git a/internal/dataframebuilder/service.go b/internal/dataframebuilder/service.go new file mode 100644 index 0000000..404eac7 --- /dev/null +++ b/internal/dataframebuilder/service.go @@ -0,0 +1,72 @@ +package dataframebuilder + +import ( + "context" + + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/dataframe" + "github.com/calypr/loom/internal/graphqlapi/model" + arangostore "github.com/calypr/loom/internal/store/arango" +) + +type Service struct { + connOpts arangostore.ConnectionOptions + discoverReferences func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) + discoverFields func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) + dataframes *dataframe.Service + scopeResolver *authscope.ScopeResolver +} + +type Config struct { + ConnectionOptions arangostore.ConnectionOptions + DiscoverReferences func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) + DiscoverFields func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) + Dataframes *dataframe.Service + ScopeResolver *authscope.ScopeResolver +} + +func NewService(cfg Config) *Service { + service := &Service{ + connOpts: cfg.ConnectionOptions, + scopeResolver: cfg.ScopeResolver, + } + if cfg.DiscoverReferences != nil { + service.discoverReferences = cfg.DiscoverReferences + } else { + service.discoverReferences = catalog.DiscoverPopulatedReferences + } + if cfg.DiscoverFields != nil { + service.discoverFields = cfg.DiscoverFields + } else { + service.discoverFields = catalog.DiscoverPopulatedFields + } + if cfg.Dataframes != nil { + service.dataframes = cfg.Dataframes + } else { + service.dataframes = dataframe.NewService(dataframe.ServiceConfig{ + ConnectionOptions: cfg.ConnectionOptions, + DiscoverReferences: service.discoverReferences, + DiscoverFields: service.discoverFields, + ScopeResolver: cfg.ScopeResolver, + }) + } + return service +} + +func (s *Service) Run(ctx context.Context, input model.FhirDataframeInput, limit *int) (*dataframe.Result, error) { + normalizedInput, err := s.PrepareRunInput(ctx, input) + if err != nil { + return nil, err + } + rowLimit := 0 + if limit != nil { + rowLimit = *limit + } else if normalizedInput.Limit != nil { + rowLimit = *normalizedInput.Limit + } + return s.dataframes.Run(ctx, dataframe.RunRequest{ + Builder: BuilderFromInput(normalizedInput), + Limit: rowLimit, + }) +} diff --git a/internal/dataframebuilder/types.go b/internal/dataframebuilder/types.go new file mode 100644 index 0000000..d1f9d39 --- /dev/null +++ b/internal/dataframebuilder/types.go @@ -0,0 +1,34 @@ +package dataframebuilder + +import "github.com/calypr/loom/internal/catalog" + +type IntrospectionRequest struct { + Project string + RootResourceType string + AuthResourcePaths []string + IncludePivotOnlyFields bool +} + +type IntrospectionResponse struct { + Project string + RootResourceType string + AuthResourcePaths []string + Root ResourceHints + RelatedResources []RelatedResourceHints + Traversals []catalog.PopulatedReference + Fields []FieldHint + PivotFields []FieldHint +} + +type ResourceHints struct { + ResourceType string + Fields []FieldHint + PivotFields []FieldHint + Traversals []catalog.PopulatedReference +} + +type RelatedResourceHints struct { + ViaLabel string + EdgeCount int64 + Target ResourceHints +} diff --git a/internal/dbio/dbio.go b/internal/dbio/dbio.go deleted file mode 100644 index 26aca70..0000000 --- a/internal/dbio/dbio.go +++ /dev/null @@ -1,49 +0,0 @@ -package dbio - -import ( - "context" - "fmt" - "strings" - - postgresstore "arangodb-proto/internal/experimental/store/postgres" - surrealstore "arangodb-proto/internal/experimental/store/surreal" - "arangodb-proto/internal/store" - arangostore "arangodb-proto/internal/store/arango" -) - -const ( - BackendArango = "arango" - BackendPostgres = "postgres" - BackendSurreal = "surreal" -) - -type ConnectionOptions struct { - Backend string - URL string - Namespace string - Database string - Username string - Password string - AuthToken string -} - -func BackendName(name string) string { - name = strings.TrimSpace(strings.ToLower(name)) - if name == "" { - return BackendArango - } - return name -} - -func OpenBackend(ctx context.Context, opts ConnectionOptions) (store.Backend, error) { - switch BackendName(opts.Backend) { - case BackendArango: - return arangostore.Open(ctx, opts.URL, opts.Database) - case BackendPostgres: - return postgresstore.Open(ctx, opts.URL, opts.Database, opts.Username, opts.Password) - case BackendSurreal: - return surrealstore.Open(ctx, opts.URL, opts.Namespace, opts.Database, opts.Username, opts.Password, opts.AuthToken) - default: - return nil, fmt.Errorf("unsupported backend %q", opts.Backend) - } -} diff --git a/internal/experimental/benchmark.go b/internal/experimental/benchmark.go deleted file mode 100644 index 3a64b5c..0000000 --- a/internal/experimental/benchmark.go +++ /dev/null @@ -1,200 +0,0 @@ -package experimental - -import ( - "context" - "os" - "strings" - "time" - - "arangodb-proto/internal/proto" -) - -type BenchmarkOptions struct { - proto.ConnectionOptions - Schema string - MetaDir string - Project string - AuthResourcePath string - Output string - BatchSize int - ProgressEvery int - WriterCount int - Truncate bool - WriteAPI string - QueryFile string - CursorBatchSize int - DatasetName string -} - -type BenchmarkSummary struct { - Backend string `json:"backend"` - Transport string `json:"transport"` - DatasetName string `json:"dataset_name"` - Project string `json:"project"` - BatchSize int `json:"batch_size"` - WriterCount int `json:"writer_count"` - BootstrapMode string `json:"bootstrap_mode"` - WriteAPI string `json:"write_api,omitempty"` - Load proto.LoadSummary `json:"load"` - LoadSeconds float64 `json:"load_seconds"` - PrepareSeconds float64 `json:"prepare_seconds,omitempty"` - DataframeSupported bool `json:"dataframe_supported"` - DataframeRows int `json:"dataframe_rows"` - DataframeSeconds float64 `json:"dataframe_seconds"` - DataframeError string `json:"dataframe_error,omitempty"` - Output string `json:"output,omitempty"` - QueryFile string `json:"query_file,omitempty"` - Comparable bool `json:"comparable"` - Notes []string `json:"notes,omitempty"` - StageSeconds map[string]float64 `json:"stage_seconds,omitempty"` -} - -func Benchmark(ctx context.Context, opts BenchmarkOptions) (BenchmarkSummary, error) { - if opts.QueryFile == "" { - opts.QueryFile = proto.DefaultCaseAssayQueryPathForBackend(opts.Backend) - } - if opts.DatasetName == "" { - opts.DatasetName = opts.MetaDir - } - summary := BenchmarkSummary{ - Backend: benchmarkBackendName(opts.Backend), - Transport: benchmarkTransport(opts.URL), - DatasetName: opts.DatasetName, - Project: opts.Project, - BatchSize: opts.BatchSize, - WriterCount: opts.WriterCount, - BootstrapMode: benchmarkBootstrapMode(opts.Truncate), - WriteAPI: opts.WriteAPI, - Output: opts.Output, - QueryFile: opts.QueryFile, - } - - loadStart := time.Now() - loadSummary, err := proto.Load(ctx, proto.LoadOptions{ - ConnectionOptions: proto.ConnectionOptions{ - Backend: opts.Backend, - URL: opts.URL, - Namespace: opts.Namespace, - Database: opts.Database, - Username: opts.Username, - Password: opts.Password, - AuthToken: opts.AuthToken, - }, - Schema: opts.Schema, - MetaDir: opts.MetaDir, - Project: opts.Project, - AuthResourcePath: opts.AuthResourcePath, - BatchSize: opts.BatchSize, - ProgressEvery: opts.ProgressEvery, - WriterCount: opts.WriterCount, - Truncate: opts.Truncate, - WriteAPI: opts.WriteAPI, - }) - if err != nil { - return summary, err - } - summary.Load = loadSummary - summary.LoadSeconds = time.Since(loadStart).Seconds() - summary.StageSeconds = loadSummary.StageSeconds - if benchmarkBackendName(opts.Backend) == "surreal" || benchmarkBackendName(opts.Backend) == "postgres" { - prepareStart := time.Now() - _, err := proto.PrepareGDCCaseAssayMatrix(ctx, proto.PrepareCaseAssayOptions{ - ConnectionOptions: proto.ConnectionOptions{ - Backend: opts.Backend, - URL: opts.URL, - Namespace: opts.Namespace, - Database: opts.Database, - Username: opts.Username, - Password: opts.Password, - AuthToken: opts.AuthToken, - }, - Project: opts.Project, - AuthResourcePath: opts.AuthResourcePath, - BatchSize: opts.BatchSize, - ProgressEvery: opts.ProgressEvery, - Truncate: true, - }) - if err != nil { - summary.Notes = append(summary.Notes, "prepare step failed; run is not comparable yet") - return summary, nil - } - summary.PrepareSeconds = time.Since(prepareStart).Seconds() - } - - if _, err := os.Stat(opts.QueryFile); err != nil { - summary.Notes = append(summary.Notes, "query file not found for backend; dataframe benchmark skipped") - return summary, nil - } - - outputPath := opts.Output - if outputPath == "" { - tmpOut, err := os.CreateTemp("", "arango-fhir-proto-benchmark-*.ndjson") - if err != nil { - return summary, err - } - outputPath = tmpOut.Name() - tmpOut.Close() - defer os.Remove(outputPath) - } - - queryStart := time.Now() - rows, err := proto.Query(ctx, proto.QueryOptions{ - ConnectionOptions: proto.ConnectionOptions{ - Backend: opts.Backend, - URL: opts.URL, - Namespace: opts.Namespace, - Database: opts.Database, - Username: opts.Username, - Password: opts.Password, - AuthToken: opts.AuthToken, - }, - QueryFile: opts.QueryFile, - Output: outputPath, - Index: proto.DefaultBulkIndex(), - Project: opts.Project, - AuthResourcePath: opts.AuthResourcePath, - BatchSize: opts.CursorBatchSize, - ProgressEvery: opts.ProgressEvery, - Bulk: false, - }) - if err != nil { - summary.DataframeError = err.Error() - summary.Notes = append(summary.Notes, "dataframe benchmark failed; run is not comparable yet") - return summary, nil - } - - summary.DataframeSupported = true - summary.DataframeRows = rows - summary.DataframeSeconds = time.Since(queryStart).Seconds() - summary.Comparable = true - return summary, nil -} - -func benchmarkBackendName(name string) string { - name = strings.TrimSpace(strings.ToLower(name)) - if name == "" { - return "arango" - } - return name -} - -func benchmarkTransport(rawURL string) string { - rawURL = strings.TrimSpace(strings.ToLower(rawURL)) - switch { - case strings.HasPrefix(rawURL, "ws://"), strings.HasPrefix(rawURL, "wss://"): - return "websocket" - case strings.HasPrefix(rawURL, "http://"), strings.HasPrefix(rawURL, "https://"): - return "http" - case rawURL == "": - return "default" - default: - return "custom" - } -} - -func benchmarkBootstrapMode(truncate bool) string { - if truncate { - return "truncate_records_keep_schema" - } - return "reuse_existing_data" -} diff --git a/internal/experimental/store/postgres/client.go b/internal/experimental/store/postgres/client.go deleted file mode 100644 index 833bbc4..0000000 --- a/internal/experimental/store/postgres/client.go +++ /dev/null @@ -1,818 +0,0 @@ -package postgres - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - "regexp" - "strings" - "time" - - "arangodb-proto/internal/store" - - "github.com/jackc/pgx/v5" - "github.com/jackc/pgx/v5/pgxpool" -) - -const ( - edgeCollection = "fhir_edge" - fieldCatalogCollection = "fhir_field_catalog" - patientFileRollupCollection = "patient_file_rollup" - scalarCollection = "fhir_scalar_index" -) - -type ScalarIndexRow struct { - Project string - ResourceKey string - ResourceType string - Path string - ValueText string - ValueNum any - System string - Code string - Display string - Ordinal int -} - -type Client struct { - pool *pgxpool.Pool -} - -var keyCleaner = regexp.MustCompile(`[^A-Za-z0-9_\-:.@()+,=;$!*'%]`) - -func Open(ctx context.Context, rawURL, database, username, password string) (*Client, error) { - dsn := postgresDSN(rawURL, database, username, password) - cfg, err := pgxpool.ParseConfig(dsn) - if err != nil { - return nil, err - } - cfg.MaxConns = 16 - cfg.MinConns = 1 - cfg.MaxConnLifetime = time.Hour - cfg.MaxConnIdleTime = 10 * time.Minute - pool, err := pgxpool.NewWithConfig(ctx, cfg) - if err != nil { - return nil, err - } - if err := pool.Ping(ctx); err != nil { - pool.Close() - return nil, err - } - return &Client{pool: pool}, nil -} - -func postgresDSN(rawURL, database, username, password string) string { - rawURL = strings.TrimSpace(rawURL) - if strings.HasPrefix(rawURL, "postgres://") || strings.HasPrefix(rawURL, "postgresql://") { - return rawURL - } - if rawURL == "" || strings.HasPrefix(rawURL, "http://") || strings.HasPrefix(rawURL, "https://") { - rawURL = "127.0.0.1:5432" - } - if database == "" { - database = "fhir_proto" - } - if username == "" { - username = "postgres" - } - u := &url.URL{ - Scheme: "postgres", - User: url.UserPassword(username, password), - Host: rawURL, - Path: "/" + database, - } - q := u.Query() - q.Set("sslmode", "disable") - u.RawQuery = q.Encode() - return u.String() -} - -func (c *Client) Bootstrap(ctx context.Context, spec store.BootstrapSpec) error { - if err := c.ensureSchema(ctx); err != nil { - return err - } - if collectionsToTruncate := truncateCollections(spec.Collections); len(collectionsToTruncate) > 0 { - reportBootstrap(spec, "go_bootstrap_postgres_truncate_start", map[string]any{"backend": "postgres"}) - if err := c.truncateCollections(ctx, collectionsToTruncate); err != nil { - return err - } - reportBootstrap(spec, "go_bootstrap_postgres_truncate_complete", map[string]any{"backend": "postgres"}) - } - - total := len(spec.Collections) - for i, collection := range spec.Collections { - reportBootstrap(spec, "go_bootstrap_collection_start", map[string]any{ - "backend": "postgres", - "collection": collection.Name, - "edge": collection.Edge, - "truncate": collection.Truncate, - "position": i + 1, - "total": total, - }) - reportBootstrap(spec, "go_bootstrap_collection_ready", map[string]any{ - "backend": "postgres", - "collection": collection.Name, - "position": i + 1, - "total": total, - }) - reportBootstrap(spec, "go_bootstrap_collection_indexes_start", map[string]any{ - "backend": "postgres", - "collection": collection.Name, - "indexes": len(collection.Indexes), - "position": i + 1, - "total": total, - }) - reportBootstrap(spec, "go_bootstrap_collection_complete", map[string]any{ - "backend": "postgres", - "collection": collection.Name, - "indexes": len(collection.Indexes), - "position": i + 1, - "total": total, - }) - } - return nil -} - -func (c *Client) ensureSchema(ctx context.Context) error { - stmts := []string{ - `CREATE TABLE IF NOT EXISTS fhir_resource ( - project text NOT NULL, - resource_key text NOT NULL, - resource_type text NOT NULL, - logical_id text NOT NULL, - auth_resource_path text, - source_collection text NOT NULL, - body jsonb NOT NULL, - updated_at timestamptz DEFAULT now(), - PRIMARY KEY (project, resource_key) - );`, - `CREATE INDEX IF NOT EXISTS fhir_resource_type_key_idx ON fhir_resource (project, resource_type, resource_key);`, - `CREATE INDEX IF NOT EXISTS fhir_resource_logical_idx ON fhir_resource (project, resource_type, logical_id);`, - `CREATE INDEX IF NOT EXISTS fhir_resource_auth_type_key_idx ON fhir_resource (project, auth_resource_path, resource_type, resource_key);`, - `CREATE TABLE IF NOT EXISTS fhir_edge ( - project text NOT NULL, - edge_key text NOT NULL, - src_key text NOT NULL, - src_type text NOT NULL, - edge_type text NOT NULL, - path text NOT NULL, - dst_key text NOT NULL, - dst_type text NOT NULL, - ordinal int, - created_at timestamptz DEFAULT now(), - PRIMARY KEY (project, edge_key) - );`, - `CREATE INDEX IF NOT EXISTS fhir_edge_forward_idx ON fhir_edge (project, src_key, edge_type, dst_type, dst_key);`, - `CREATE INDEX IF NOT EXISTS fhir_edge_forward_type_idx ON fhir_edge (project, src_type, edge_type, dst_type, src_key, dst_key);`, - `CREATE INDEX IF NOT EXISTS fhir_edge_reverse_idx ON fhir_edge (project, dst_key, edge_type, src_type, src_key);`, - `CREATE INDEX IF NOT EXISTS fhir_edge_reverse_type_idx ON fhir_edge (project, dst_type, edge_type, src_type, dst_key, src_key);`, - `CREATE INDEX IF NOT EXISTS fhir_edge_edge_type_idx ON fhir_edge (project, edge_type, src_type, dst_type);`, - `CREATE TABLE IF NOT EXISTS fhir_scalar_index ( - project text NOT NULL, - resource_key text NOT NULL, - resource_type text NOT NULL, - path text NOT NULL, - value_text text, - value_num double precision, - system text, - code text, - display text, - ordinal int, - PRIMARY KEY (project, resource_key, path, ordinal) - );`, - `CREATE INDEX IF NOT EXISTS fhir_scalar_path_text_idx ON fhir_scalar_index (project, resource_type, path, value_text);`, - `CREATE INDEX IF NOT EXISTS fhir_scalar_code_idx ON fhir_scalar_index (project, resource_type, path, system, code, display);`, - `CREATE TABLE IF NOT EXISTS fhir_field_catalog ( - key text PRIMARY KEY, - project text NOT NULL, - resource_type text NOT NULL, - path text NOT NULL, - kind text NOT NULL, - doc_count bigint NOT NULL, - sample_count bigint NOT NULL, - distinct_values text[], - distinct_truncated boolean NOT NULL, - pivot_candidate boolean NOT NULL, - pivot_kind text, - pivot_columns text[] - );`, - `CREATE INDEX IF NOT EXISTS fhir_field_catalog_project_resource_idx ON fhir_field_catalog (project, resource_type);`, - `CREATE INDEX IF NOT EXISTS fhir_field_catalog_project_resource_path_idx ON fhir_field_catalog (project, resource_type, path);`, - `CREATE INDEX IF NOT EXISTS fhir_field_catalog_pivot_idx ON fhir_field_catalog (project, resource_type, pivot_candidate);`, - `CREATE TABLE IF NOT EXISTS patient_file_rollup ( - key text PRIMARY KEY, - project text NOT NULL, - patient_key text NOT NULL, - auth_resource_path text, - specimen_count int NOT NULL, - group_count int NOT NULL, - file_count int NOT NULL, - specimen_types text[], - preservation_methods text[], - file_keys text[] - );`, - `CREATE INDEX IF NOT EXISTS patient_file_rollup_project_patient_idx ON patient_file_rollup (project, patient_key);`, - `CREATE INDEX IF NOT EXISTS patient_file_rollup_auth_patient_idx ON patient_file_rollup (project, auth_resource_path, patient_key);`, - } - for _, stmt := range stmts { - if _, err := c.pool.Exec(ctx, stmt); err != nil { - return err - } - } - return nil -} - -func (c *Client) InsertBatchRaw(ctx context.Context, collection string, docs []json.RawMessage, overwrite bool, writeAPI string) error { - if len(docs) == 0 { - return nil - } - switch collection { - case edgeCollection: - return c.insertEdges(ctx, docs, overwrite) - case scalarCollection: - return c.insertScalarIndexDocuments(ctx, docs, overwrite) - case fieldCatalogCollection: - return c.insertFieldCatalog(ctx, docs, overwrite) - case patientFileRollupCollection: - return c.insertPatientFileRollups(ctx, docs, overwrite) - default: - return c.insertResources(ctx, collection, docs, overwrite) - } -} - -func (c *Client) insertResources(ctx context.Context, collection string, docs []json.RawMessage, overwrite bool) error { - rows := make([][]any, 0, len(docs)) - for i, raw := range docs { - var doc map[string]any - if err := json.Unmarshal(raw, &doc); err != nil { - return fmt.Errorf("decode resource %s document %d: %w", collection, i, err) - } - key := stringValue(doc["_key"]) - logicalID := stringValue(doc["id"]) - resourceType := stringValue(doc["resourceType"]) - project := stringValue(doc["project"]) - authResourcePath := stringValue(doc["auth_resource_path"]) - payload := doc["payload"] - if key == "" || resourceType == "" || project == "" || payload == nil { - return fmt.Errorf("resource %s document %d missing _key/resourceType/project/payload", collection, i) - } - body, err := json.Marshal(payload) - if err != nil { - return fmt.Errorf("marshal resource payload %s/%s: %w", resourceType, key, err) - } - resourceKey := collectionID(resourceType, key) - rows = append(rows, []any{project, resourceKey, resourceType, logicalID, nullableText(authResourcePath), collection, string(body)}) - } - if !overwrite { - if _, err := c.pool.CopyFrom(ctx, pgx.Identifier{"fhir_resource"}, []string{ - "project", "resource_key", "resource_type", "logical_id", "auth_resource_path", "source_collection", "body", - }, pgx.CopyFromRows(rows)); err != nil { - return err - } - return nil - } - if err := c.batchExec(ctx, `INSERT INTO fhir_resource ( - project, resource_key, resource_type, logical_id, auth_resource_path, source_collection, body - ) VALUES ($1, $2, $3, $4, $5, $6, $7) - ON CONFLICT (project, resource_key) DO UPDATE SET - resource_type = EXCLUDED.resource_type, - logical_id = EXCLUDED.logical_id, - auth_resource_path = EXCLUDED.auth_resource_path, - source_collection = EXCLUDED.source_collection, - body = EXCLUDED.body, - updated_at = now()`, rows); err != nil { - return err - } - return nil -} - -func (c *Client) insertScalarRows(ctx context.Context, rows []ScalarIndexRow) error { - if len(rows) == 0 { - return nil - } - copyRows := make([][]any, 0, len(rows)) - for _, row := range rows { - copyRows = append(copyRows, []any{ - row.Project, - row.ResourceKey, - row.ResourceType, - row.Path, - nullableText(row.ValueText), - row.ValueNum, - nullableText(row.System), - nullableText(row.Code), - nullableText(row.Display), - row.Ordinal, - }) - } - _, err := c.pool.CopyFrom(ctx, pgx.Identifier{"fhir_scalar_index"}, []string{ - "project", "resource_key", "resource_type", "path", "value_text", "value_num", "system", "code", "display", "ordinal", - }, pgx.CopyFromRows(copyRows)) - return err -} - -func (c *Client) insertScalarIndexDocuments(ctx context.Context, docs []json.RawMessage, overwrite bool) error { - rows := make([]ScalarIndexRow, 0, len(docs)) - for i, raw := range docs { - var doc map[string]any - if err := json.Unmarshal(raw, &doc); err != nil { - return fmt.Errorf("decode scalar index document %d: %w", i, err) - } - rows = append(rows, ScalarIndexRow{ - Project: stringValue(doc["project"]), - ResourceKey: stringValue(doc["resource_key"]), - ResourceType: stringValue(doc["resource_type"]), - Path: stringValue(doc["path"]), - ValueText: stringValue(doc["value_text"]), - ValueNum: numericValue(doc["value_num"]), - System: stringValue(doc["system"]), - Code: stringValue(doc["code"]), - Display: stringValue(doc["display"]), - Ordinal: int(int64Value(doc["ordinal"])), - }) - } - if overwrite { - return fmt.Errorf("overwrite mode is not supported for %s inserts", scalarCollection) - } - return c.insertScalarRows(ctx, rows) -} - -func (c *Client) insertEdges(ctx context.Context, docs []json.RawMessage, overwrite bool) error { - rows := make([][]any, 0, len(docs)) - for i, raw := range docs { - var doc map[string]any - if err := json.Unmarshal(raw, &doc); err != nil { - return fmt.Errorf("decode edge document %d: %w", i, err) - } - key := stringValue(doc["_key"]) - from := stringValue(doc["_from"]) - to := stringValue(doc["_to"]) - label := stringValue(doc["label"]) - project := stringValue(doc["project"]) - fromType := stringValue(doc["from_type"]) - toType := stringValue(doc["to_type"]) - if key == "" || from == "" || to == "" || label == "" || project == "" { - return fmt.Errorf("edge document %d missing _key/_from/_to/label/project", i) - } - rows = append(rows, []any{project, key, from, fromType, label, label, to, toType, nil}) - } - if !overwrite { - _, err := c.pool.CopyFrom(ctx, pgx.Identifier{"fhir_edge"}, []string{ - "project", "edge_key", "src_key", "src_type", "edge_type", "path", "dst_key", "dst_type", "ordinal", - }, pgx.CopyFromRows(rows)) - return err - } - return c.batchExec(ctx, `INSERT INTO fhir_edge ( - project, edge_key, src_key, src_type, edge_type, path, dst_key, dst_type, ordinal - ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) - ON CONFLICT (project, edge_key) DO UPDATE SET - src_key = EXCLUDED.src_key, - src_type = EXCLUDED.src_type, - edge_type = EXCLUDED.edge_type, - path = EXCLUDED.path, - dst_key = EXCLUDED.dst_key, - dst_type = EXCLUDED.dst_type, - ordinal = EXCLUDED.ordinal`, rows) -} - -func (c *Client) insertFieldCatalog(ctx context.Context, docs []json.RawMessage, overwrite bool) error { - rows := make([][]any, 0, len(docs)) - for i, raw := range docs { - var doc map[string]any - if err := json.Unmarshal(raw, &doc); err != nil { - return fmt.Errorf("decode field catalog document %d: %w", i, err) - } - rows = append(rows, []any{ - stringValue(doc["_key"]), - stringValue(doc["project"]), - stringValue(doc["resource_type"]), - stringValue(doc["path"]), - stringValue(doc["kind"]), - int64Value(doc["doc_count"]), - int64Value(doc["sample_count"]), - stringSlice(doc["distinct_values"]), - boolValue(doc["distinct_truncated"]), - boolValue(doc["pivot_candidate"]), - nullableText(stringValue(doc["pivot_kind"])), - stringSlice(doc["pivot_columns"]), - }) - } - if !overwrite { - _, err := c.pool.CopyFrom(ctx, pgx.Identifier{"fhir_field_catalog"}, []string{ - "key", "project", "resource_type", "path", "kind", "doc_count", "sample_count", "distinct_values", "distinct_truncated", "pivot_candidate", "pivot_kind", "pivot_columns", - }, pgx.CopyFromRows(rows)) - return err - } - return c.batchExec(ctx, `INSERT INTO fhir_field_catalog ( - key, project, resource_type, path, kind, doc_count, sample_count, distinct_values, - distinct_truncated, pivot_candidate, pivot_kind, pivot_columns - ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) - ON CONFLICT (key) DO UPDATE SET - project = EXCLUDED.project, - resource_type = EXCLUDED.resource_type, - path = EXCLUDED.path, - kind = EXCLUDED.kind, - doc_count = EXCLUDED.doc_count, - sample_count = EXCLUDED.sample_count, - distinct_values = EXCLUDED.distinct_values, - distinct_truncated = EXCLUDED.distinct_truncated, - pivot_candidate = EXCLUDED.pivot_candidate, - pivot_kind = EXCLUDED.pivot_kind, - pivot_columns = EXCLUDED.pivot_columns`, rows) -} - -func (c *Client) insertPatientFileRollups(ctx context.Context, docs []json.RawMessage, overwrite bool) error { - rows := make([][]any, 0, len(docs)) - for i, raw := range docs { - var doc map[string]any - if err := json.Unmarshal(raw, &doc); err != nil { - return fmt.Errorf("decode patient file rollup document %d: %w", i, err) - } - rows = append(rows, []any{ - stringValue(doc["_key"]), - stringValue(doc["project"]), - stringValue(doc["patient_key"]), - nullableText(stringValue(doc["auth_resource_path"])), - int64Value(doc["specimen_count"]), - int64Value(doc["group_count"]), - int64Value(doc["file_count"]), - stringSlice(doc["specimen_types"]), - stringSlice(doc["preservation_methods"]), - stringSlice(doc["file_keys"]), - }) - } - if !overwrite { - _, err := c.pool.CopyFrom(ctx, pgx.Identifier{"patient_file_rollup"}, []string{ - "key", "project", "patient_key", "auth_resource_path", "specimen_count", "group_count", "file_count", "specimen_types", "preservation_methods", "file_keys", - }, pgx.CopyFromRows(rows)) - return err - } - return c.batchExec(ctx, `INSERT INTO patient_file_rollup ( - key, project, patient_key, auth_resource_path, specimen_count, group_count, file_count, - specimen_types, preservation_methods, file_keys - ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) - ON CONFLICT (key) DO UPDATE SET - project = EXCLUDED.project, - patient_key = EXCLUDED.patient_key, - auth_resource_path = EXCLUDED.auth_resource_path, - specimen_count = EXCLUDED.specimen_count, - group_count = EXCLUDED.group_count, - file_count = EXCLUDED.file_count, - specimen_types = EXCLUDED.specimen_types, - preservation_methods = EXCLUDED.preservation_methods, - file_keys = EXCLUDED.file_keys`, rows) -} - -func (c *Client) batchExec(ctx context.Context, sql string, rows [][]any) error { - batch := &pgx.Batch{} - for _, row := range rows { - batch.Queue(sql, row...) - } - br := c.pool.SendBatch(ctx, batch) - defer br.Close() - for range rows { - if _, err := br.Exec(); err != nil { - return err - } - } - return nil -} - -func (c *Client) QueryRows(ctx context.Context, query string, batchSize int, bindVars map[string]interface{}, visit store.RowVisitor) error { - args := pgx.NamedArgs{} - for key, value := range bindVars { - args[key] = value - } - rows, err := c.pool.Query(ctx, query, args) - if err != nil { - return err - } - defer rows.Close() - fields := rows.FieldDescriptions() - for rows.Next() { - values, err := rows.Values() - if err != nil { - return err - } - row := make(map[string]any, len(values)) - for i, value := range values { - row[string(fields[i].Name)] = normalizeValue(value) - } - if err := visit(row); err != nil { - return err - } - } - return rows.Err() -} - -func (c *Client) Close(ctx context.Context) error { - if c != nil && c.pool != nil { - c.pool.Close() - } - return nil -} - -func (c *Client) ResetScalarIndex(ctx context.Context, project, resourceType string, truncate bool) error { - if truncate && strings.TrimSpace(project) == "" && strings.TrimSpace(resourceType) == "" { - _, err := c.pool.Exec(ctx, `TRUNCATE fhir_scalar_index`) - return err - } - clauses := make([]string, 0, 2) - args := make([]any, 0, 2) - if strings.TrimSpace(project) != "" { - args = append(args, project) - clauses = append(clauses, fmt.Sprintf("project = $%d", len(args))) - } - if strings.TrimSpace(resourceType) != "" { - args = append(args, resourceType) - clauses = append(clauses, fmt.Sprintf("resource_type = $%d", len(args))) - } - if len(clauses) == 0 { - _, err := c.pool.Exec(ctx, `DELETE FROM fhir_scalar_index`) - return err - } - _, err := c.pool.Exec(ctx, `DELETE FROM fhir_scalar_index WHERE `+strings.Join(clauses, ` AND `), args...) - return err -} - -func (c *Client) InsertScalarIndexRows(ctx context.Context, rows []ScalarIndexRow) error { - return c.insertScalarRows(ctx, rows) -} - -func reportBootstrap(spec store.BootstrapSpec, event string, fields map[string]any) { - if spec.Reporter != nil { - spec.Reporter(event, fields) - } -} - -func hasTruncate(collections []store.CollectionSpec) bool { - for _, collection := range collections { - if collection.Truncate { - return true - } - } - return false -} - -func truncateCollections(collections []store.CollectionSpec) []string { - physical := make(map[string]struct{}) - hasResources := false - for _, collection := range collections { - if !collection.Truncate { - continue - } - switch collection.Name { - case edgeCollection, fieldCatalogCollection, patientFileRollupCollection, scalarCollection: - physical[collection.Name] = struct{}{} - default: - hasResources = true - } - } - if hasResources { - physical["fhir_resource"] = struct{}{} - physical[edgeCollection] = struct{}{} - physical[fieldCatalogCollection] = struct{}{} - physical[scalarCollection] = struct{}{} - physical[patientFileRollupCollection] = struct{}{} - } - if len(physical) == 0 { - return nil - } - out := make([]string, 0, len(physical)) - for name := range physical { - out = append(out, name) - } - return out -} - -func (c *Client) truncateCollections(ctx context.Context, collections []string) error { - if len(collections) == 0 { - return nil - } - quoted := make([]string, 0, len(collections)) - for _, name := range collections { - quoted = append(quoted, pgx.Identifier{name}.Sanitize()) - } - _, err := c.pool.Exec(ctx, `TRUNCATE `+strings.Join(quoted, `, `)) - return err -} - -func collectionID(resourceType, key string) string { - return cleanKey(resourceType) + "/" + cleanKey(key) -} - -func cleanKey(value string) string { - value = strings.TrimSpace(value) - if value == "" { - return "_" - } - return keyCleaner.ReplaceAllString(value, "_") -} - -func nullableText(value string) any { - if strings.TrimSpace(value) == "" { - return nil - } - return value -} - -func stringValue(value any) string { - if s, ok := value.(string); ok { - return s - } - return "" -} - -func boolValue(value any) bool { - v, _ := value.(bool) - return v -} - -func int64Value(value any) int64 { - switch v := value.(type) { - case int: - return int64(v) - case int32: - return int64(v) - case int64: - return v - case float64: - return int64(v) - case json.Number: - n, _ := v.Int64() - return n - default: - return 0 - } -} - -func stringSlice(value any) []string { - items, ok := value.([]any) - if !ok { - if items, ok := value.([]string); ok { - return items - } - return nil - } - out := make([]string, 0, len(items)) - for _, item := range items { - if text, ok := item.(string); ok { - out = append(out, text) - } - } - return out -} - -func ScalarIndexRows(project, resourceKey, resourceType string, payload map[string]any) []ScalarIndexRow { - rows := make([]ScalarIndexRow, 0, 32) - ordinals := make(map[string]int) - var walk func(path string, value any) - walk = func(path string, value any) { - switch typed := value.(type) { - case map[string]any: - if system, code, display, ok := codingTriple(typed); ok && path != "" { - ordinal := ordinals[path] - ordinals[path]++ - rows = append(rows, ScalarIndexRow{ - Project: project, - ResourceKey: resourceKey, - ResourceType: resourceType, - Path: path, - ValueText: firstNonEmpty(display, code), - System: system, - Code: code, - Display: display, - Ordinal: ordinal, - }) - } - for key, child := range typed { - if child == nil { - continue - } - childPath := key - if path != "" { - childPath = path + "." + key - } - walk(childPath, child) - } - case []any: - arrayPath := path + "[]" - for _, item := range typed { - if item == nil { - continue - } - walk(arrayPath, item) - } - default: - if path == "" { - return - } - text, num, ok := scalarIndexValue(typed) - if !ok { - return - } - ordinal := ordinals[path] - ordinals[path]++ - rows = append(rows, ScalarIndexRow{ - Project: project, - ResourceKey: resourceKey, - ResourceType: resourceType, - Path: path, - ValueText: text, - ValueNum: num, - Ordinal: ordinal, - }) - } - } - walk("", payload) - return rows -} - -func numericValue(value any) any { - switch typed := value.(type) { - case float64: - return typed - case float32: - return float64(typed) - case int: - return float64(typed) - case int32: - return float64(typed) - case int64: - return float64(typed) - case json.Number: - if num, err := typed.Float64(); err == nil { - return num - } - } - return nil -} - -func codingTriple(value map[string]any) (string, string, string, bool) { - system := stringValue(value["system"]) - code := stringValue(value["code"]) - display := stringValue(value["display"]) - return system, code, display, system != "" || code != "" || display != "" -} - -func scalarIndexValue(value any) (string, any, bool) { - switch typed := value.(type) { - case string: - return typed, nil, typed != "" - case bool: - if typed { - return "true", nil, true - } - return "false", nil, true - case float64: - return fmt.Sprintf("%v", typed), typed, true - case float32: - num := float64(typed) - return fmt.Sprintf("%v", typed), num, true - case int: - num := float64(typed) - return fmt.Sprintf("%d", typed), num, true - case int64: - num := float64(typed) - return fmt.Sprintf("%d", typed), num, true - case int32: - num := float64(typed) - return fmt.Sprintf("%d", typed), num, true - case json.Number: - if num, err := typed.Float64(); err == nil { - return typed.String(), num, true - } - return typed.String(), nil, true - default: - return "", nil, false - } -} - -func firstNonEmpty(values ...string) string { - for _, value := range values { - if strings.TrimSpace(value) != "" { - return value - } - } - return "" -} - -func normalizeValue(value any) any { - switch v := value.(type) { - case []byte: - var decoded any - if json.Unmarshal(v, &decoded) == nil { - return decoded - } - return string(v) - case []string: - out := make([]any, 0, len(v)) - for _, item := range v { - out = append(out, item) - } - return out - default: - return value - } -} diff --git a/internal/experimental/store/surreal/client.go b/internal/experimental/store/surreal/client.go deleted file mode 100644 index d5c173f..0000000 --- a/internal/experimental/store/surreal/client.go +++ /dev/null @@ -1,379 +0,0 @@ -package surreal - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - "regexp" - "strings" - "time" - - "arangodb-proto/internal/store" - - surrealdb "github.com/surrealdb/surrealdb.go" - "github.com/surrealdb/surrealdb.go/pkg/connection" - "github.com/surrealdb/surrealdb.go/pkg/connection/gorillaws" - surrealhttp "github.com/surrealdb/surrealdb.go/pkg/connection/http" - "github.com/surrealdb/surrealdb.go/pkg/models" -) - -type Client struct { - db *surrealdb.DB -} - -var identSanitizer = regexp.MustCompile(`[^A-Za-z0-9_]`) - -func Open(ctx context.Context, url, namespace, database, username, password, authToken string) (*Client, error) { - parsedURL, err := urlpkgParse(url) - if err != nil { - return nil, err - } - conf := connection.NewConfig(parsedURL) - - var conn connection.Connection - switch parsedURL.Scheme { - case "http", "https": - conn = surrealhttp.New(conf).SetTimeout(5 * time.Minute) - case "ws", "wss": - conn = gorillaws.New(conf).SetTimeOut(0) - default: - db, err := surrealdb.FromEndpointURLString(ctx, url) - if err != nil { - return nil, err - } - return openWithDB(ctx, db, namespace, database, username, password, authToken) - } - - db, err := surrealdb.FromConnection(ctx, conn) - if err != nil { - return nil, err - } - return openWithDB(ctx, db, namespace, database, username, password, authToken) -} - -func openWithDB(ctx context.Context, db *surrealdb.DB, namespace, database, username, password, authToken string) (*Client, error) { - if strings.TrimSpace(namespace) == "" { - namespace = "test" - } - if strings.TrimSpace(database) == "" { - database = "test" - } - - if strings.TrimSpace(username) != "" { - _, err := db.SignIn(ctx, surrealdb.Auth{ - Username: username, - Password: password, - }) - if err != nil { - _ = db.Close(ctx) - return nil, err - } - } - - if strings.TrimSpace(authToken) != "" { - if err := db.Authenticate(ctx, authToken); err != nil { - _ = db.Close(ctx) - return nil, err - } - } - nsIdent := sanitizeIdentifier(namespace) - dbIdent := sanitizeIdentifier(database) - setupQuery := fmt.Sprintf(` -DEFINE NAMESPACE IF NOT EXISTS %s; -USE NS %s; -DEFINE DATABASE IF NOT EXISTS %s; -USE DB %s; -`, nsIdent, nsIdent, dbIdent, dbIdent) - if _, err := surrealdb.Query[any](ctx, db, setupQuery, nil); err != nil { - _ = db.Close(ctx) - return nil, fmt.Errorf("setup namespace %s database %s: %w", namespace, database, err) - } - if err := db.Use(ctx, namespace, database); err != nil { - _ = db.Close(ctx) - return nil, fmt.Errorf("use namespace %s database %s: %w", namespace, database, err) - } - - return &Client{db: db}, nil -} - -func urlpkgParse(raw string) (*url.URL, error) { - return url.ParseRequestURI(raw) -} - -func (c *Client) Bootstrap(ctx context.Context, spec store.BootstrapSpec) error { - total := len(spec.Collections) - for i, collection := range spec.Collections { - tableName := sanitizeIdentifier(collection.Name) - tableKind := "SCHEMALESS" - if collection.Edge { - tableKind = "TYPE RELATION SCHEMALESS" - } - indexes := surrealBootstrapIndexes(collection) - reportBootstrap(spec, "go_bootstrap_collection_start", map[string]any{ - "backend": "surreal", - "collection": collection.Name, - "edge": collection.Edge, - "truncate": collection.Truncate, - "position": i + 1, - "total": total, - }) - - if _, err := surrealdb.Query[[]map[string]any](ctx, c.db, fmt.Sprintf("DEFINE TABLE IF NOT EXISTS %s %s;", tableName, tableKind), nil); err != nil { - return fmt.Errorf("define table %s: %w", collection.Name, err) - } - reportBootstrap(spec, "go_bootstrap_collection_ready", map[string]any{ - "backend": "surreal", - "collection": collection.Name, - "position": i + 1, - "total": total, - }) - if collection.Truncate { - reportBootstrap(spec, "go_bootstrap_collection_truncate_start", map[string]any{ - "backend": "surreal", - "collection": collection.Name, - "position": i + 1, - "total": total, - }) - if _, err := surrealdb.Query[[]map[string]any](ctx, c.db, fmt.Sprintf("DELETE %s RETURN NONE;", tableName), nil); err != nil { - return fmt.Errorf("truncate table %s: %w", collection.Name, err) - } - reportBootstrap(spec, "go_bootstrap_collection_truncate_complete", map[string]any{ - "backend": "surreal", - "collection": collection.Name, - "position": i + 1, - "total": total, - }) - } - reportBootstrap(spec, "go_bootstrap_collection_indexes_start", map[string]any{ - "backend": "surreal", - "collection": collection.Name, - "indexes": len(indexes), - "position": i + 1, - "total": total, - }) - for _, fields := range indexes { - if len(fields) == 0 { - continue - } - indexName := surrealIndexName(collection.Name, fields) - if _, err := surrealdb.Query[[]map[string]any](ctx, c.db, fmt.Sprintf( - "DEFINE INDEX IF NOT EXISTS %s ON TABLE %s FIELDS %s;", - indexName, - tableName, - strings.Join(fields, ", "), - ), nil); err != nil { - return fmt.Errorf("define index %s on %s: %w", indexName, collection.Name, err) - } - } - reportBootstrap(spec, "go_bootstrap_collection_complete", map[string]any{ - "backend": "surreal", - "collection": collection.Name, - "indexes": len(indexes), - "position": i + 1, - "total": total, - }) - } - return nil -} - -func (c *Client) InsertBatchRaw(ctx context.Context, collection string, docs []json.RawMessage, overwrite bool, writeAPI string) error { - if len(docs) == 0 { - return nil - } - if collection == "fhir_edge" { - return c.insertBatchRelationRaw(ctx, collection, docs, overwrite) - } - content := make([]map[string]any, 0, len(docs)) - for i, raw := range docs { - var doc map[string]any - if err := json.Unmarshal(raw, &doc); err != nil { - return fmt.Errorf("decode %s batch document %d: %w", collection, i, err) - } - key, _ := doc["_key"].(string) - if strings.TrimSpace(key) == "" { - return fmt.Errorf("%s batch document %d missing _key", collection, i) - } - content = append(content, doc) - } - - query := fmt.Sprintf(` -FOR $doc IN $content { - %s type::record(%q, $doc._key) CONTENT $doc RETURN NONE; -}; -`, surrealWriteVerb(overwrite), sanitizeIdentifier(collection)) - _, err := surrealdb.Query[any](ctx, c.db, query, map[string]any{"content": content}) - if err != nil { - return fmt.Errorf("insert %s batch: %w", collection, err) - } - return nil -} - -func (c *Client) insertBatchRelationRaw(ctx context.Context, collection string, docs []json.RawMessage, overwrite bool) error { - content := make([]map[string]any, 0, len(docs)) - ids := make([]any, 0, len(docs)) - for i, raw := range docs { - var doc map[string]any - if err := json.Unmarshal(raw, &doc); err != nil { - return fmt.Errorf("decode %s batch relation %d: %w", collection, i, err) - } - key, _ := doc["_key"].(string) - if strings.TrimSpace(key) == "" { - return fmt.Errorf("%s batch relation %d missing _key", collection, i) - } - inTable, inID, err := splitCollectionID(stringValue(doc["_from"])) - if err != nil { - return fmt.Errorf("decode relation _from for %s/%s: %w", collection, key, err) - } - outTable, outID, err := splitCollectionID(stringValue(doc["_to"])) - if err != nil { - return fmt.Errorf("decode relation _to for %s/%s: %w", collection, key, err) - } - content = append(content, map[string]any{ - "id": models.NewRecordID(collection, key), - "in": models.NewRecordID(inTable, inID), - "out": models.NewRecordID(outTable, outID), - "_from": stringValue(doc["_from"]), - "_to": stringValue(doc["_to"]), - "_key": key, - "label": stringValue(doc["label"]), - "project": stringValue(doc["project"]), - "from_type": stringValue(doc["from_type"]), - "to_type": stringValue(doc["to_type"]), - }) - ids = append(ids, models.NewRecordID(collection, key)) - } - query := fmt.Sprintf("INSERT RELATION INTO %s $content RETURN NONE", sanitizeIdentifier(collection)) - params := map[string]any{"content": content} - if overwrite { - query = fmt.Sprintf("DELETE $ids RETURN NONE; INSERT RELATION INTO %s $content RETURN NONE", sanitizeIdentifier(collection)) - params["ids"] = ids - } - _, err := surrealdb.Query[any](ctx, c.db, query, params) - if err != nil { - return fmt.Errorf("insert relation batch %s: %w", collection, err) - } - return nil -} - -func (c *Client) QueryRows(ctx context.Context, query string, batchSize int, bindVars map[string]interface{}, visit store.RowVisitor) error { - results, err := surrealdb.Query[any](ctx, c.db, query, bindVars) - if err != nil { - return err - } - if results == nil { - return nil - } - for _, result := range *results { - if result.Error != nil { - return result.Error - } - switch rows := result.Result.(type) { - case []any: - for _, item := range rows { - row, ok := item.(map[string]any) - if !ok { - continue - } - if err := visit(row); err != nil { - return err - } - } - case map[string]any: - if err := visit(rows); err != nil { - return err - } - } - } - return nil -} - -func (c *Client) Close(ctx context.Context) error { - if c == nil || c.db == nil { - return nil - } - return c.db.Close(ctx) -} - -func sanitizeIdentifier(value string) string { - value = strings.TrimSpace(value) - if value == "" { - return "x" - } - return identSanitizer.ReplaceAllString(value, "_") -} - -func surrealIndexName(collection string, fields []string) string { - parts := make([]string, 0, len(fields)+1) - parts = append(parts, collection) - parts = append(parts, fields...) - return sanitizeIdentifier(strings.Join(parts, "_")) -} - -func splitCollectionID(value string) (string, string, error) { - parts := strings.SplitN(value, "/", 2) - if len(parts) != 2 || strings.TrimSpace(parts[0]) == "" || strings.TrimSpace(parts[1]) == "" { - return "", "", fmt.Errorf("malformed collection id %q", value) - } - return parts[0], parts[1], nil -} - -func stringValue(value any) string { - if s, ok := value.(string); ok { - return s - } - return "" -} - -func surrealWriteVerb(overwrite bool) string { - if overwrite { - return "UPSERT" - } - return "CREATE" -} - -func surrealBootstrapIndexes(collection store.CollectionSpec) [][]string { - indexes := append([][]string(nil), collection.Indexes...) - if !collection.Edge { - return indexes - } - extra := [][][]string{ - {{"project", "label", "_to"}}, - {{"project", "label", "_from"}}, - {{"project", "from_type", "label", "_to"}}, - {{"project", "to_type", "label", "_from"}}, - } - for _, group := range extra { - for _, fields := range group { - if !hasIndexFields(indexes, fields) { - indexes = append(indexes, fields) - } - } - } - return indexes -} - -func hasIndexFields(indexes [][]string, fields []string) bool { - for _, existing := range indexes { - if len(existing) != len(fields) { - continue - } - match := true - for i := range fields { - if existing[i] != fields[i] { - match = false - break - } - } - if match { - return true - } - } - return false -} - -func reportBootstrap(spec store.BootstrapSpec, event string, fields map[string]any) { - if spec.Reporter != nil { - spec.Reporter(event, fields) - } -} diff --git a/internal/fhirschema/generated.go b/internal/fhirschema/generated.go index c893fe9..bbd4ab8 100644 --- a/internal/fhirschema/generated.go +++ b/internal/fhirschema/generated.go @@ -24,48 +24,48 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_city", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_country", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_district", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "_line", - Kind: "array", + Name: "_line", + Kind: "array", ItemKind: "object", - ItemRef: "FHIRPrimitiveExtension", + ItemRef: "FHIRPrimitiveExtension", }, { Name: "_postalCode", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_state", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_text", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_type", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_use", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "city", @@ -80,10 +80,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -94,20 +94,20 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "line", - Kind: "array", + Name: "line", + Kind: "array", ItemKind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "period", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "postalCode", @@ -140,27 +140,27 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_code", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_comparator", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_system", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_unit", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_value", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "code", @@ -171,10 +171,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -185,10 +185,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "resourceType", @@ -213,32 +213,32 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_authorString", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_text", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_time", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "authorReference", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "authorString", Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -249,10 +249,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "resourceType", @@ -273,67 +273,67 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_contentType", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_creation", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_data", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_duration", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_frames", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_hash", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_height", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_pages", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_size", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_title", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_url", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_width", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "contentType", @@ -352,10 +352,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "number", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -382,10 +382,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "pages", @@ -416,16 +416,16 @@ var generatedDefinitions = map[string]generatedDefinition{ "Availability": { Properties: []generatedProperty{ { - Name: "availableTime", - Kind: "array", + Name: "availableTime", + Kind: "array", ItemKind: "object", - ItemRef: "AvailabilityAvailableTime", + ItemRef: "AvailabilityAvailableTime", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -436,16 +436,16 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "notAvailableTime", - Kind: "array", + Name: "notAvailableTime", + Kind: "array", ItemKind: "object", - ItemRef: "AvailabilityNotAvailableTime", + ItemRef: "AvailabilityNotAvailableTime", }, { Name: "resourceType", @@ -458,23 +458,23 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_allDay", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_availableEndTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_availableStartTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "_daysOfWeek", - Kind: "array", + Name: "_daysOfWeek", + Kind: "array", ItemKind: "object", - ItemRef: "FHIRPrimitiveExtension", + ItemRef: "FHIRPrimitiveExtension", }, { Name: "allDay", @@ -489,15 +489,15 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "daysOfWeek", - Kind: "array", + Name: "daysOfWeek", + Kind: "array", ItemKind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -508,10 +508,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "resourceType", @@ -524,7 +524,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_description", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "description", @@ -533,13 +533,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "during", Kind: "object", - Ref: "Period", + Ref: "Period", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -550,10 +550,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "resourceType", @@ -566,48 +566,48 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_active", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_description", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "active", Kind: "boolean", }, { - Name: "contained", - Kind: "array", + Name: "contained", + Kind: "array", ItemKind: "object", - ItemRef: "Resource", + ItemRef: "Resource", }, { Name: "description", Kind: "string", }, { - Name: "excludedStructure", - Kind: "array", + Name: "excludedStructure", + Kind: "array", ItemKind: "object", - ItemRef: "BodyStructureIncludedStructure", + ItemRef: "BodyStructureIncludedStructure", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -618,57 +618,57 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { - Name: "image", - Kind: "array", + Name: "image", + Kind: "array", ItemKind: "object", - ItemRef: "Attachment", + ItemRef: "Attachment", }, { Name: "implicitRules", Kind: "string", }, { - Name: "includedStructure", - Kind: "array", + Name: "includedStructure", + Kind: "array", ItemKind: "object", - ItemRef: "BodyStructureIncludedStructure", + ItemRef: "BodyStructureIncludedStructure", }, { Name: "language", Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "morphology", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "patient", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "resourceType", @@ -677,23 +677,23 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "text", Kind: "object", - Ref: "Narrative", + Ref: "Narrative", }, }, }, "BodyStructureIncludedStructure": { Properties: []generatedProperty{ { - Name: "bodyLandmarkOrientation", - Kind: "array", + Name: "bodyLandmarkOrientation", + Kind: "array", ItemKind: "object", - ItemRef: "BodyStructureIncludedStructureBodyLandmarkOrientation", + ItemRef: "BodyStructureIncludedStructureBodyLandmarkOrientation", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -706,62 +706,62 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "laterality", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { - Name: "qualifier", - Kind: "array", + Name: "qualifier", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { Name: "resourceType", Kind: "string", }, { - Name: "spatialReference", - Kind: "array", + Name: "spatialReference", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "structure", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, }, }, "BodyStructureIncludedStructureBodyLandmarkOrientation": { Properties: []generatedProperty{ { - Name: "clockFacePosition", - Kind: "array", + Name: "clockFacePosition", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "distanceFromLandmark", - Kind: "array", + Name: "distanceFromLandmark", + Kind: "array", ItemKind: "object", - ItemRef: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + ItemRef: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -772,48 +772,48 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "landmarkDescription", - Kind: "array", + Name: "landmarkDescription", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", Kind: "string", }, { - Name: "surfaceOrientation", - Kind: "array", + Name: "surfaceOrientation", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, }, }, "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { Properties: []generatedProperty{ { - Name: "device", - Kind: "array", + Name: "device", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableReference", + ItemRef: "CodeableReference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -824,26 +824,26 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", Kind: "string", }, { - Name: "value", - Kind: "array", + Name: "value", + Kind: "array", ItemKind: "object", - ItemRef: "Quantity", + ItemRef: "Quantity", }, }, }, @@ -852,19 +852,19 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_text", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "coding", - Kind: "array", + Name: "coding", + Kind: "array", ItemKind: "object", - ItemRef: "Coding", + ItemRef: "Coding", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -875,10 +875,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "resourceType", @@ -895,13 +895,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "concept", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -912,15 +912,15 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "reference", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "resourceType", @@ -933,27 +933,27 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_code", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_display", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_system", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_userSelected", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_version", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "code", @@ -964,10 +964,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -978,10 +978,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "resourceType", @@ -1006,42 +1006,42 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_abatementDateTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_abatementString", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_onsetDateTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_onsetString", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_recordedDate", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "abatementAge", Kind: "object", - Ref: "Age", + Ref: "Age", }, { Name: "abatementDateTime", @@ -1050,61 +1050,61 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "abatementPeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "abatementRange", Kind: "object", - Ref: "Range", + Ref: "Range", }, { Name: "abatementString", Kind: "string", }, { - Name: "bodySite", - Kind: "array", + Name: "bodySite", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "category", - Kind: "array", + Name: "category", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { Name: "clinicalStatus", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "code", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "contained", - Kind: "array", + Name: "contained", + Kind: "array", ItemKind: "object", - ItemRef: "Resource", + ItemRef: "Resource", }, { Name: "encounter", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "evidence", - Kind: "array", + Name: "evidence", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableReference", + ItemRef: "CodeableReference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -1115,10 +1115,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "implicitRules", @@ -1129,32 +1129,32 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { - Name: "note", - Kind: "array", + Name: "note", + Kind: "array", ItemKind: "object", - ItemRef: "Annotation", + ItemRef: "Annotation", }, { Name: "onsetAge", Kind: "object", - Ref: "Age", + Ref: "Age", }, { Name: "onsetDateTime", @@ -1163,22 +1163,22 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "onsetPeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "onsetRange", Kind: "object", - Ref: "Range", + Ref: "Range", }, { Name: "onsetString", Kind: "string", }, { - Name: "participant", - Kind: "array", + Name: "participant", + Kind: "array", ItemKind: "object", - ItemRef: "ConditionParticipant", + ItemRef: "ConditionParticipant", }, { Name: "recordedDate", @@ -1191,28 +1191,28 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "severity", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "stage", - Kind: "array", + Name: "stage", + Kind: "array", ItemKind: "object", - ItemRef: "ConditionStage", + ItemRef: "ConditionStage", }, { Name: "subject", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "text", Kind: "object", - Ref: "Narrative", + Ref: "Narrative", }, { Name: "verificationStatus", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, }, }, @@ -1221,13 +1221,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "actor", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -1236,23 +1236,23 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "function", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "id", Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -1263,16 +1263,16 @@ var generatedDefinitions = map[string]generatedDefinition{ "ConditionStage": { Properties: []generatedProperty{ { - Name: "assessment", - Kind: "array", + Name: "assessment", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -1283,16 +1283,16 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -1301,12 +1301,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "summary", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "type", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, }, }, @@ -1315,13 +1315,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_name", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -1332,10 +1332,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "name", @@ -1346,10 +1346,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "telecom", - Kind: "array", + Name: "telecom", + Kind: "array", ItemKind: "object", - ItemRef: "ContactPoint", + ItemRef: "ContactPoint", }, }, }, @@ -1358,28 +1358,28 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_rank", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_system", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_use", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_value", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -1390,15 +1390,15 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "period", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "rank", @@ -1427,27 +1427,27 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_code", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_comparator", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_system", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_unit", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_value", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "code", @@ -1458,10 +1458,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -1472,10 +1472,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "resourceType", @@ -1500,42 +1500,42 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_limit", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "_mustSupport", - Kind: "array", + Name: "_mustSupport", + Kind: "array", ItemKind: "object", - ItemRef: "FHIRPrimitiveExtension", + ItemRef: "FHIRPrimitiveExtension", }, { - Name: "_profile", - Kind: "array", + Name: "_profile", + Kind: "array", ItemKind: "object", - ItemRef: "FHIRPrimitiveExtension", + ItemRef: "FHIRPrimitiveExtension", }, { Name: "_type", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "codeFilter", - Kind: "array", + Name: "codeFilter", + Kind: "array", ItemKind: "object", - ItemRef: "DataRequirementCodeFilter", + ItemRef: "DataRequirementCodeFilter", }, { - Name: "dateFilter", - Kind: "array", + Name: "dateFilter", + Kind: "array", ItemKind: "object", - ItemRef: "DataRequirementDateFilter", + ItemRef: "DataRequirementDateFilter", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -1550,19 +1550,19 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "integer", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "mustSupport", - Kind: "array", + Name: "mustSupport", + Kind: "array", ItemKind: "string", }, { - Name: "profile", - Kind: "array", + Name: "profile", + Kind: "array", ItemKind: "string", }, { @@ -1570,30 +1570,30 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "sort", - Kind: "array", + Name: "sort", + Kind: "array", ItemKind: "object", - ItemRef: "DataRequirementSort", + ItemRef: "DataRequirementSort", }, { Name: "subjectCodeableConcept", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "subjectReference", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "type", Kind: "string", }, { - Name: "valueFilter", - Kind: "array", + Name: "valueFilter", + Kind: "array", ItemKind: "object", - ItemRef: "DataRequirementValueFilter", + ItemRef: "DataRequirementValueFilter", }, }, }, @@ -1602,29 +1602,29 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_path", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_searchParam", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueSet", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "code", - Kind: "array", + Name: "code", + Kind: "array", ItemKind: "object", - ItemRef: "Coding", + ItemRef: "Coding", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -1635,10 +1635,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "path", @@ -1663,23 +1663,23 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_path", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_searchParam", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueDateTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -1690,10 +1690,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "path", @@ -1714,12 +1714,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueDuration", Kind: "object", - Ref: "Duration", + Ref: "Duration", }, { Name: "valuePeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, }, }, @@ -1728,22 +1728,22 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_direction", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_path", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "direction", Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -1754,10 +1754,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "path", @@ -1774,32 +1774,32 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_comparator", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_path", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_searchParam", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueDateTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "comparator", Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -1810,10 +1810,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "path", @@ -1834,12 +1834,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueDuration", Kind: "object", - Ref: "Duration", + Ref: "Duration", }, { Name: "valuePeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, }, }, @@ -1848,70 +1848,70 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_conclusion", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_effectiveDateTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_issued", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_status", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "basedOn", - Kind: "array", + Name: "basedOn", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "category", - Kind: "array", + Name: "category", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { Name: "code", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "composition", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "conclusion", Kind: "string", }, { - Name: "conclusionCode", - Kind: "array", + Name: "conclusionCode", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "contained", - Kind: "array", + Name: "contained", + Kind: "array", ItemKind: "object", - ItemRef: "Resource", + ItemRef: "Resource", }, { Name: "effectiveDateTime", @@ -1920,18 +1920,18 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "effectivePeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "encounter", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -1942,10 +1942,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "implicitRules", @@ -1960,93 +1960,93 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "media", - Kind: "array", + Name: "media", + Kind: "array", ItemKind: "object", - ItemRef: "DiagnosticReportMedia", + ItemRef: "DiagnosticReportMedia", }, { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { - Name: "note", - Kind: "array", + Name: "note", + Kind: "array", ItemKind: "object", - ItemRef: "Annotation", + ItemRef: "Annotation", }, { - Name: "performer", - Kind: "array", + Name: "performer", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "presentedForm", - Kind: "array", + Name: "presentedForm", + Kind: "array", ItemKind: "object", - ItemRef: "Attachment", + ItemRef: "Attachment", }, { Name: "resourceType", Kind: "string", }, { - Name: "result", - Kind: "array", + Name: "result", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "resultsInterpreter", - Kind: "array", + Name: "resultsInterpreter", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "specimen", - Kind: "array", + Name: "specimen", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "status", Kind: "string", }, { - Name: "study", - Kind: "array", + Name: "study", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "subject", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "supportingInfo", - Kind: "array", + Name: "supportingInfo", + Kind: "array", ItemKind: "object", - ItemRef: "DiagnosticReportSupportingInfo", + ItemRef: "DiagnosticReportSupportingInfo", }, { Name: "text", Kind: "object", - Ref: "Narrative", + Ref: "Narrative", }, }, }, @@ -2055,17 +2055,17 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_comment", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "comment", Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -2078,19 +2078,19 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "link", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -2101,10 +2101,10 @@ var generatedDefinitions = map[string]generatedDefinition{ "DiagnosticReportSupportingInfo": { Properties: []generatedProperty{ { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -2115,21 +2115,21 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "reference", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "resourceType", @@ -2138,27 +2138,27 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "type", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, }, }, "Directory": { Properties: []generatedProperty{ { - Name: "child", - Kind: "array", + Name: "child", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "id", Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "name", @@ -2179,27 +2179,27 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_code", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_comparator", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_system", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_unit", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_value", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "code", @@ -2210,10 +2210,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -2224,10 +2224,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "resourceType", @@ -2252,90 +2252,90 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_date", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_description", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_docStatus", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_status", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_version", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "attester", - Kind: "array", + Name: "attester", + Kind: "array", ItemKind: "object", - ItemRef: "DocumentReferenceAttester", + ItemRef: "DocumentReferenceAttester", }, { - Name: "author", - Kind: "array", + Name: "author", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "basedOn", - Kind: "array", + Name: "basedOn", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "bodySite", - Kind: "array", + Name: "bodySite", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableReference", + ItemRef: "CodeableReference", }, { - Name: "category", - Kind: "array", + Name: "category", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "contained", - Kind: "array", + Name: "contained", + Kind: "array", ItemKind: "object", - ItemRef: "Resource", + ItemRef: "Resource", }, { - Name: "content", - Kind: "array", + Name: "content", + Kind: "array", ItemKind: "object", - ItemRef: "DocumentReferenceContent", + ItemRef: "DocumentReferenceContent", }, { - Name: "context", - Kind: "array", + Name: "context", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "custodian", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "date", @@ -2350,21 +2350,21 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "event", - Kind: "array", + Name: "event", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableReference", + ItemRef: "CodeableReference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "facilityType", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "fhir_comments", @@ -2375,10 +2375,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "implicitRules", @@ -2389,53 +2389,53 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { - Name: "modality", - Kind: "array", + Name: "modality", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "period", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "practiceSetting", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "relatesTo", - Kind: "array", + Name: "relatesTo", + Kind: "array", ItemKind: "object", - ItemRef: "DocumentReferenceRelatesTo", + ItemRef: "DocumentReferenceRelatesTo", }, { Name: "resourceType", Kind: "string", }, { - Name: "securityLabel", - Kind: "array", + Name: "securityLabel", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { Name: "status", @@ -2444,17 +2444,17 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "subject", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "text", Kind: "object", - Ref: "Narrative", + Ref: "Narrative", }, { Name: "type", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "version", @@ -2467,13 +2467,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_time", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -2484,26 +2484,26 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "mode", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "party", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "resourceType", @@ -2520,13 +2520,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "attachment", Kind: "object", - Ref: "Attachment", + Ref: "Attachment", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -2537,22 +2537,22 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { - Name: "profile", - Kind: "array", + Name: "profile", + Kind: "array", ItemKind: "object", - ItemRef: "DocumentReferenceContentProfile", + ItemRef: "DocumentReferenceContentProfile", }, { Name: "resourceType", @@ -2565,18 +2565,18 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_valueCanonical", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueUri", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -2587,16 +2587,16 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -2609,7 +2609,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueCoding", Kind: "object", - Ref: "Coding", + Ref: "Coding", }, { Name: "valueUri", @@ -2622,13 +2622,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "code", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -2639,16 +2639,16 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -2657,7 +2657,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "target", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, }, }, @@ -2666,50 +2666,50 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_asNeeded", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_patientInstruction", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_sequence", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_text", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "additionalInstruction", - Kind: "array", + Name: "additionalInstruction", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { Name: "asNeeded", Kind: "boolean", }, { - Name: "asNeededFor", - Kind: "array", + Name: "asNeededFor", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "doseAndRate", - Kind: "array", + Name: "doseAndRate", + Kind: "array", ItemKind: "object", - ItemRef: "DosageDoseAndRate", + ItemRef: "DosageDoseAndRate", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -2720,37 +2720,37 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "maxDosePerAdministration", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "maxDosePerLifetime", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { - Name: "maxDosePerPeriod", - Kind: "array", + Name: "maxDosePerPeriod", + Kind: "array", ItemKind: "object", - ItemRef: "Ratio", + ItemRef: "Ratio", }, { Name: "method", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "patientInstruction", @@ -2763,7 +2763,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "route", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "sequence", @@ -2772,7 +2772,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "site", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "text", @@ -2781,7 +2781,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "timing", Kind: "object", - Ref: "Timing", + Ref: "Timing", }, }, }, @@ -2790,18 +2790,18 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "doseQuantity", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "doseRange", Kind: "object", - Ref: "Range", + Ref: "Range", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -2812,25 +2812,25 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "rateQuantity", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "rateRange", Kind: "object", - Ref: "Range", + Ref: "Range", }, { Name: "rateRatio", Kind: "object", - Ref: "Ratio", + Ref: "Ratio", }, { Name: "resourceType", @@ -2839,7 +2839,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "type", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, }, }, @@ -2848,27 +2848,27 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_code", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_comparator", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_system", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_unit", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_value", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "code", @@ -2879,10 +2879,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -2893,10 +2893,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "resourceType", @@ -2921,27 +2921,27 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_description", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_expression", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_name", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_reference", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "description", @@ -2952,10 +2952,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -2970,10 +2970,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "name", @@ -2994,13 +2994,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "address", Kind: "object", - Ref: "Address", + Ref: "Address", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -3011,51 +3011,51 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "name", - Kind: "array", + Name: "name", + Kind: "array", ItemKind: "object", - ItemRef: "HumanName", + ItemRef: "HumanName", }, { Name: "organization", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "period", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "purpose", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "resourceType", Kind: "string", }, { - Name: "telecom", - Kind: "array", + Name: "telecom", + Kind: "array", ItemKind: "object", - ItemRef: "ContactPoint", + ItemRef: "ContactPoint", }, }, }, "Extension": { Properties: []generatedProperty{ { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -3066,10 +3066,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "resourceType", @@ -3082,27 +3082,27 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueAddress", Kind: "object", - Ref: "Address", + Ref: "Address", }, { Name: "valueAge", Kind: "object", - Ref: "Age", + Ref: "Age", }, { Name: "valueAnnotation", Kind: "object", - Ref: "Annotation", + Ref: "Annotation", }, { Name: "valueAttachment", Kind: "object", - Ref: "Attachment", + Ref: "Attachment", }, { Name: "valueAvailability", Kind: "object", - Ref: "Availability", + Ref: "Availability", }, { Name: "valueBase64Binary", @@ -3123,37 +3123,37 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueCodeableConcept", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "valueCodeableReference", Kind: "object", - Ref: "CodeableReference", + Ref: "CodeableReference", }, { Name: "valueCoding", Kind: "object", - Ref: "Coding", + Ref: "Coding", }, { Name: "valueContactDetail", Kind: "object", - Ref: "ContactDetail", + Ref: "ContactDetail", }, { Name: "valueContactPoint", Kind: "object", - Ref: "ContactPoint", + Ref: "ContactPoint", }, { Name: "valueCount", Kind: "object", - Ref: "Count", + Ref: "Count", }, { Name: "valueDataRequirement", Kind: "object", - Ref: "DataRequirement", + Ref: "DataRequirement", }, { Name: "valueDate", @@ -3170,32 +3170,32 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueDistance", Kind: "object", - Ref: "Distance", + Ref: "Distance", }, { Name: "valueDosage", Kind: "object", - Ref: "Dosage", + Ref: "Dosage", }, { Name: "valueDuration", Kind: "object", - Ref: "Duration", + Ref: "Duration", }, { Name: "valueExpression", Kind: "object", - Ref: "Expression", + Ref: "Expression", }, { Name: "valueExtendedContactDetail", Kind: "object", - Ref: "ExtendedContactDetail", + Ref: "ExtendedContactDetail", }, { Name: "valueHumanName", Kind: "object", - Ref: "HumanName", + Ref: "HumanName", }, { Name: "valueId", @@ -3204,7 +3204,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueIdentifier", Kind: "object", - Ref: "Identifier", + Ref: "Identifier", }, { Name: "valueInstant", @@ -3225,12 +3225,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueMeta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { Name: "valueMoney", Kind: "object", - Ref: "Money", + Ref: "Money", }, { Name: "valueOid", @@ -3239,12 +3239,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueParameterDefinition", Kind: "object", - Ref: "ParameterDefinition", + Ref: "ParameterDefinition", }, { Name: "valuePeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "valuePositiveInt", @@ -3253,42 +3253,42 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueQuantity", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "valueRange", Kind: "object", - Ref: "Range", + Ref: "Range", }, { Name: "valueRatio", Kind: "object", - Ref: "Ratio", + Ref: "Ratio", }, { Name: "valueRatioRange", Kind: "object", - Ref: "RatioRange", + Ref: "RatioRange", }, { Name: "valueReference", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "valueRelatedArtifact", Kind: "object", - Ref: "RelatedArtifact", + Ref: "RelatedArtifact", }, { Name: "valueSampledData", Kind: "object", - Ref: "SampledData", + Ref: "SampledData", }, { Name: "valueSignature", Kind: "object", - Ref: "Signature", + Ref: "Signature", }, { Name: "valueString", @@ -3301,12 +3301,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueTiming", Kind: "object", - Ref: "Timing", + Ref: "Timing", }, { Name: "valueTriggerDefinition", Kind: "object", - Ref: "TriggerDefinition", + Ref: "TriggerDefinition", }, { Name: "valueUnsignedInt", @@ -3323,7 +3323,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueUsageContext", Kind: "object", - Ref: "UsageContext", + Ref: "UsageContext", }, { Name: "valueUuid", @@ -3334,10 +3334,10 @@ var generatedDefinitions = map[string]generatedDefinition{ "FHIRPrimitiveExtension": { Properties: []generatedProperty{ { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -3348,10 +3348,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "resourceType", @@ -3364,84 +3364,84 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_ageString", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_bornDate", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_bornString", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_date", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_deceasedBoolean", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_deceasedDate", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_deceasedString", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_estimatedAge", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "_instantiatesCanonical", - Kind: "array", + Name: "_instantiatesCanonical", + Kind: "array", ItemKind: "object", - ItemRef: "FHIRPrimitiveExtension", + ItemRef: "FHIRPrimitiveExtension", }, { - Name: "_instantiatesUri", - Kind: "array", + Name: "_instantiatesUri", + Kind: "array", ItemKind: "object", - ItemRef: "FHIRPrimitiveExtension", + ItemRef: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_name", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_status", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "ageAge", Kind: "object", - Ref: "Age", + Ref: "Age", }, { Name: "ageRange", Kind: "object", - Ref: "Range", + Ref: "Range", }, { Name: "ageString", @@ -3454,28 +3454,28 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "bornPeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "bornString", Kind: "string", }, { - Name: "condition", - Kind: "array", + Name: "condition", + Kind: "array", ItemKind: "object", - ItemRef: "FamilyMemberHistoryCondition", + ItemRef: "FamilyMemberHistoryCondition", }, { - Name: "contained", - Kind: "array", + Name: "contained", + Kind: "array", ItemKind: "object", - ItemRef: "Resource", + ItemRef: "Resource", }, { Name: "dataAbsentReason", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "date", @@ -3484,7 +3484,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "deceasedAge", Kind: "object", - Ref: "Age", + Ref: "Age", }, { Name: "deceasedBoolean", @@ -3497,7 +3497,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "deceasedRange", Kind: "object", - Ref: "Range", + Ref: "Range", }, { Name: "deceasedString", @@ -3508,10 +3508,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "boolean", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -3522,23 +3522,23 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "implicitRules", Kind: "string", }, { - Name: "instantiatesCanonical", - Kind: "array", + Name: "instantiatesCanonical", + Kind: "array", ItemKind: "string", }, { - Name: "instantiatesUri", - Kind: "array", + Name: "instantiatesUri", + Kind: "array", ItemKind: "string", }, { @@ -3546,59 +3546,59 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "name", Kind: "string", }, { - Name: "note", - Kind: "array", + Name: "note", + Kind: "array", ItemKind: "object", - ItemRef: "Annotation", + ItemRef: "Annotation", }, { - Name: "participant", - Kind: "array", + Name: "participant", + Kind: "array", ItemKind: "object", - ItemRef: "FamilyMemberHistoryParticipant", + ItemRef: "FamilyMemberHistoryParticipant", }, { Name: "patient", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "procedure", - Kind: "array", + Name: "procedure", + Kind: "array", ItemKind: "object", - ItemRef: "FamilyMemberHistoryProcedure", + ItemRef: "FamilyMemberHistoryProcedure", }, { - Name: "reason", - Kind: "array", + Name: "reason", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableReference", + ItemRef: "CodeableReference", }, { Name: "relationship", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "resourceType", @@ -3607,7 +3607,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "sex", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "status", @@ -3616,7 +3616,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "text", Kind: "object", - Ref: "Narrative", + Ref: "Narrative", }, }, }, @@ -3625,27 +3625,27 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_contributedToDeath", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_onsetString", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "code", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "contributedToDeath", Kind: "boolean", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -3656,37 +3656,37 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { - Name: "note", - Kind: "array", + Name: "note", + Kind: "array", ItemKind: "object", - ItemRef: "Annotation", + ItemRef: "Annotation", }, { Name: "onsetAge", Kind: "object", - Ref: "Age", + Ref: "Age", }, { Name: "onsetPeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "onsetRange", Kind: "object", - Ref: "Range", + Ref: "Range", }, { Name: "onsetString", @@ -3695,7 +3695,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "outcome", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "resourceType", @@ -3708,13 +3708,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "actor", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -3723,23 +3723,23 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "function", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "id", Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -3752,32 +3752,32 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_contributedToDeath", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_performedDateTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_performedString", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "code", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "contributedToDeath", Kind: "boolean", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -3788,32 +3788,32 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { - Name: "note", - Kind: "array", + Name: "note", + Kind: "array", ItemKind: "object", - ItemRef: "Annotation", + ItemRef: "Annotation", }, { Name: "outcome", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "performedAge", Kind: "object", - Ref: "Age", + Ref: "Age", }, { Name: "performedDateTime", @@ -3822,12 +3822,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "performedPeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "performedRange", Kind: "object", - Ref: "Range", + Ref: "Range", }, { Name: "performedString", @@ -3844,73 +3844,73 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_active", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_description", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_membership", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_name", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_quantity", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_type", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "active", Kind: "boolean", }, { - Name: "characteristic", - Kind: "array", + Name: "characteristic", + Kind: "array", ItemKind: "object", - ItemRef: "GroupCharacteristic", + ItemRef: "GroupCharacteristic", }, { Name: "code", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "contained", - Kind: "array", + Name: "contained", + Kind: "array", ItemKind: "object", - ItemRef: "Resource", + ItemRef: "Resource", }, { Name: "description", Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -3921,10 +3921,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "implicitRules", @@ -3935,21 +3935,21 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "managingEntity", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "member", - Kind: "array", + Name: "member", + Kind: "array", ItemKind: "object", - ItemRef: "GroupMember", + ItemRef: "GroupMember", }, { Name: "membership", @@ -3958,13 +3958,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "name", @@ -3981,7 +3981,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "text", Kind: "object", - Ref: "Narrative", + Ref: "Narrative", }, { Name: "type", @@ -3994,27 +3994,27 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_exclude", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueBoolean", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "code", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "exclude", Kind: "boolean", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -4025,21 +4025,21 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "period", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "resourceType", @@ -4052,22 +4052,22 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueCodeableConcept", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "valueQuantity", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "valueRange", Kind: "object", - Ref: "Range", + Ref: "Range", }, { Name: "valueReference", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, }, }, @@ -4076,18 +4076,18 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_inactive", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "entity", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -4102,21 +4102,21 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "boolean", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "period", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "resourceType", @@ -4129,41 +4129,41 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_family", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "_given", - Kind: "array", + Name: "_given", + Kind: "array", ItemKind: "object", - ItemRef: "FHIRPrimitiveExtension", + ItemRef: "FHIRPrimitiveExtension", }, { - Name: "_prefix", - Kind: "array", + Name: "_prefix", + Kind: "array", ItemKind: "object", - ItemRef: "FHIRPrimitiveExtension", + ItemRef: "FHIRPrimitiveExtension", }, { - Name: "_suffix", - Kind: "array", + Name: "_suffix", + Kind: "array", ItemKind: "object", - ItemRef: "FHIRPrimitiveExtension", + ItemRef: "FHIRPrimitiveExtension", }, { Name: "_text", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_use", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "family", @@ -4174,8 +4174,8 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "", }, { - Name: "given", - Kind: "array", + Name: "given", + Kind: "array", ItemKind: "string", }, { @@ -4183,19 +4183,19 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "period", Kind: "object", - Ref: "Period", + Ref: "Period", }, { - Name: "prefix", - Kind: "array", + Name: "prefix", + Kind: "array", ItemKind: "string", }, { @@ -4203,8 +4203,8 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "suffix", - Kind: "array", + Name: "suffix", + Kind: "array", ItemKind: "string", }, { @@ -4222,28 +4222,28 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_system", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_use", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_value", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "assigner", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -4254,15 +4254,15 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "period", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "resourceType", @@ -4275,7 +4275,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "type", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "use", @@ -4292,49 +4292,49 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_description", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_numberOfInstances", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_numberOfSeries", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_started", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_status", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "basedOn", - Kind: "array", + Name: "basedOn", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "contained", - Kind: "array", + Name: "contained", + Kind: "array", ItemKind: "object", - ItemRef: "Resource", + ItemRef: "Resource", }, { Name: "description", @@ -4343,19 +4343,19 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "encounter", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "endpoint", - Kind: "array", + Name: "endpoint", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -4366,10 +4366,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "implicitRules", @@ -4380,38 +4380,38 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "location", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { - Name: "modality", - Kind: "array", + Name: "modality", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { - Name: "note", - Kind: "array", + Name: "note", + Kind: "array", ItemKind: "object", - ItemRef: "Annotation", + ItemRef: "Annotation", }, { Name: "numberOfInstances", @@ -4422,37 +4422,37 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "integer", }, { - Name: "partOf", - Kind: "array", + Name: "partOf", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "procedure", - Kind: "array", + Name: "procedure", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableReference", + ItemRef: "CodeableReference", }, { - Name: "reason", - Kind: "array", + Name: "reason", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableReference", + ItemRef: "CodeableReference", }, { Name: "referrer", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "resourceType", Kind: "string", }, { - Name: "series", - Kind: "array", + Name: "series", + Kind: "array", ItemKind: "object", - ItemRef: "ImagingStudySeries", + ItemRef: "ImagingStudySeries", }, { Name: "started", @@ -4465,12 +4465,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "subject", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "text", Kind: "object", - Ref: "Narrative", + Ref: "Narrative", }, }, }, @@ -4479,48 +4479,48 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_description", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_number", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_numberOfInstances", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_started", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_uid", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "bodySite", Kind: "object", - Ref: "CodeableReference", + Ref: "CodeableReference", }, { Name: "description", Kind: "string", }, { - Name: "endpoint", - Kind: "array", + Name: "endpoint", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -4531,32 +4531,32 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "instance", - Kind: "array", + Name: "instance", + Kind: "array", ItemKind: "object", - ItemRef: "ImagingStudySeriesInstance", + ItemRef: "ImagingStudySeriesInstance", }, { Name: "laterality", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "modality", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "number", @@ -4567,20 +4567,20 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "integer", }, { - Name: "performer", - Kind: "array", + Name: "performer", + Kind: "array", ItemKind: "object", - ItemRef: "ImagingStudySeriesPerformer", + ItemRef: "ImagingStudySeriesPerformer", }, { Name: "resourceType", Kind: "string", }, { - Name: "specimen", - Kind: "array", + Name: "specimen", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "started", @@ -4597,23 +4597,23 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_number", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_title", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_uid", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -4624,16 +4624,16 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "number", @@ -4646,7 +4646,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "sopClass", Kind: "object", - Ref: "Coding", + Ref: "Coding", }, { Name: "title", @@ -4663,13 +4663,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "actor", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -4678,23 +4678,23 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "function", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "id", Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -4707,49 +4707,49 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_status", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "batch", Kind: "object", - Ref: "MedicationBatch", + Ref: "MedicationBatch", }, { Name: "code", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "contained", - Kind: "array", + Name: "contained", + Kind: "array", ItemKind: "object", - ItemRef: "Resource", + ItemRef: "Resource", }, { Name: "definition", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "doseForm", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -4760,46 +4760,46 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "implicitRules", Kind: "string", }, { - Name: "ingredient", - Kind: "array", + Name: "ingredient", + Kind: "array", ItemKind: "object", - ItemRef: "MedicationIngredient", + ItemRef: "MedicationIngredient", }, { Name: "language", Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "marketingAuthorizationHolder", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -4812,12 +4812,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "text", Kind: "object", - Ref: "Narrative", + Ref: "Narrative", }, { Name: "totalVolume", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, }, }, @@ -4826,78 +4826,78 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_isSubPotent", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_occurenceDateTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_recorded", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_status", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "basedOn", - Kind: "array", + Name: "basedOn", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "category", - Kind: "array", + Name: "category", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "contained", - Kind: "array", + Name: "contained", + Kind: "array", ItemKind: "object", - ItemRef: "Resource", + ItemRef: "Resource", }, { - Name: "device", - Kind: "array", + Name: "device", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableReference", + ItemRef: "CodeableReference", }, { Name: "dosage", Kind: "object", - Ref: "MedicationAdministrationDosage", + Ref: "MedicationAdministrationDosage", }, { Name: "encounter", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "eventHistory", - Kind: "array", + Name: "eventHistory", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -4908,10 +4908,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "implicitRules", @@ -4926,32 +4926,32 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "medication", Kind: "object", - Ref: "CodeableReference", + Ref: "CodeableReference", }, { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { - Name: "note", - Kind: "array", + Name: "note", + Kind: "array", ItemKind: "object", - ItemRef: "Annotation", + ItemRef: "Annotation", }, { Name: "occurenceDateTime", @@ -4960,30 +4960,30 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "occurencePeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "occurenceTiming", Kind: "object", - Ref: "Timing", + Ref: "Timing", }, { - Name: "partOf", - Kind: "array", + Name: "partOf", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "performer", - Kind: "array", + Name: "performer", + Kind: "array", ItemKind: "object", - ItemRef: "MedicationAdministrationPerformer", + ItemRef: "MedicationAdministrationPerformer", }, { - Name: "reason", - Kind: "array", + Name: "reason", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableReference", + ItemRef: "CodeableReference", }, { Name: "recorded", @@ -4992,7 +4992,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "request", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "resourceType", @@ -5003,32 +5003,32 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "statusReason", - Kind: "array", + Name: "statusReason", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "subPotentReason", - Kind: "array", + Name: "subPotentReason", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { Name: "subject", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "supportingInformation", - Kind: "array", + Name: "supportingInformation", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "text", Kind: "object", - Ref: "Narrative", + Ref: "Narrative", }, }, }, @@ -5037,18 +5037,18 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_text", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "dose", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -5059,31 +5059,31 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "method", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "rateQuantity", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "rateRatio", Kind: "object", - Ref: "Ratio", + Ref: "Ratio", }, { Name: "resourceType", @@ -5092,12 +5092,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "route", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "site", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "text", @@ -5110,13 +5110,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "actor", Kind: "object", - Ref: "CodeableReference", + Ref: "CodeableReference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -5125,23 +5125,23 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "function", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "id", Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -5154,22 +5154,22 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_expirationDate", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_lotNumber", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "expirationDate", Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -5180,20 +5180,20 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "lotNumber", Kind: "string", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -5206,13 +5206,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_isActive", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -5229,19 +5229,19 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "item", Kind: "object", - Ref: "CodeableReference", + Ref: "CodeableReference", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -5250,17 +5250,17 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "strengthCodeableConcept", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "strengthQuantity", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "strengthRatio", Kind: "object", - Ref: "Ratio", + Ref: "Ratio", }, }, }, @@ -5269,122 +5269,122 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_authoredOn", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_doNotPerform", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_intent", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_priority", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_renderedDosageInstruction", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_reported", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_status", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_statusChanged", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "authoredOn", Kind: "string", }, { - Name: "basedOn", - Kind: "array", + Name: "basedOn", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "category", - Kind: "array", + Name: "category", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "contained", - Kind: "array", + Name: "contained", + Kind: "array", ItemKind: "object", - ItemRef: "Resource", + ItemRef: "Resource", }, { Name: "courseOfTherapyType", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "device", - Kind: "array", + Name: "device", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableReference", + ItemRef: "CodeableReference", }, { Name: "dispenseRequest", Kind: "object", - Ref: "MedicationRequestDispenseRequest", + Ref: "MedicationRequestDispenseRequest", }, { Name: "doNotPerform", Kind: "boolean", }, { - Name: "dosageInstruction", - Kind: "array", + Name: "dosageInstruction", + Kind: "array", ItemKind: "object", - ItemRef: "Dosage", + ItemRef: "Dosage", }, { Name: "effectiveDosePeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "encounter", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "eventHistory", - Kind: "array", + Name: "eventHistory", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -5393,33 +5393,33 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "groupIdentifier", Kind: "object", - Ref: "Identifier", + Ref: "Identifier", }, { Name: "id", Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "implicitRules", Kind: "string", }, { - Name: "informationSource", - Kind: "array", + Name: "informationSource", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "insurance", - Kind: "array", + Name: "insurance", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "intent", @@ -5430,63 +5430,63 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "medication", Kind: "object", - Ref: "CodeableReference", + Ref: "CodeableReference", }, { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { - Name: "note", - Kind: "array", + Name: "note", + Kind: "array", ItemKind: "object", - ItemRef: "Annotation", + ItemRef: "Annotation", }, { - Name: "performer", - Kind: "array", + Name: "performer", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "performerType", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "priorPrescription", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "priority", Kind: "string", }, { - Name: "reason", - Kind: "array", + Name: "reason", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableReference", + ItemRef: "CodeableReference", }, { Name: "recorder", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "renderedDosageInstruction", @@ -5499,7 +5499,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "requester", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "resourceType", @@ -5516,28 +5516,28 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "statusReason", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "subject", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "substitution", Kind: "object", - Ref: "MedicationRequestSubstitution", + Ref: "MedicationRequestSubstitution", }, { - Name: "supportingInformation", - Kind: "array", + Name: "supportingInformation", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "text", Kind: "object", - Ref: "Narrative", + Ref: "Narrative", }, }, }, @@ -5546,39 +5546,39 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_numberOfRepeatsAllowed", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "dispenseInterval", Kind: "object", - Ref: "Duration", + Ref: "Duration", }, { Name: "dispenser", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "dispenserInstruction", - Kind: "array", + Name: "dispenserInstruction", + Kind: "array", ItemKind: "object", - ItemRef: "Annotation", + ItemRef: "Annotation", }, { Name: "doseAdministrationAid", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "expectedSupplyDuration", Kind: "object", - Ref: "Duration", + Ref: "Duration", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -5591,19 +5591,19 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "initialFill", Kind: "object", - Ref: "MedicationRequestDispenseRequestInitialFill", + Ref: "MedicationRequestDispenseRequestInitialFill", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "numberOfRepeatsAllowed", @@ -5612,7 +5612,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "quantity", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "resourceType", @@ -5621,7 +5621,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "validityPeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, }, }, @@ -5630,13 +5630,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "duration", Kind: "object", - Ref: "Duration", + Ref: "Duration", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -5647,21 +5647,21 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "quantity", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "resourceType", @@ -5674,7 +5674,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_allowedBoolean", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "allowedBoolean", @@ -5683,13 +5683,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "allowedCodeableConcept", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -5700,21 +5700,21 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "reason", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "resourceType", @@ -5727,65 +5727,65 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_dateAsserted", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_effectiveDateTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_renderedDosageInstruction", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_status", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "adherence", Kind: "object", - Ref: "MedicationStatementAdherence", + Ref: "MedicationStatementAdherence", }, { - Name: "category", - Kind: "array", + Name: "category", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "contained", - Kind: "array", + Name: "contained", + Kind: "array", ItemKind: "object", - ItemRef: "Resource", + ItemRef: "Resource", }, { Name: "dateAsserted", Kind: "string", }, { - Name: "derivedFrom", - Kind: "array", + Name: "derivedFrom", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "dosage", - Kind: "array", + Name: "dosage", + Kind: "array", ItemKind: "object", - ItemRef: "Dosage", + ItemRef: "Dosage", }, { Name: "effectiveDateTime", @@ -5794,23 +5794,23 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "effectivePeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "effectiveTiming", Kind: "object", - Ref: "Timing", + Ref: "Timing", }, { Name: "encounter", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -5821,70 +5821,70 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "implicitRules", Kind: "string", }, { - Name: "informationSource", - Kind: "array", + Name: "informationSource", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "language", Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "medication", Kind: "object", - Ref: "CodeableReference", + Ref: "CodeableReference", }, { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { - Name: "note", - Kind: "array", + Name: "note", + Kind: "array", ItemKind: "object", - ItemRef: "Annotation", + ItemRef: "Annotation", }, { - Name: "partOf", - Kind: "array", + Name: "partOf", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "reason", - Kind: "array", + Name: "reason", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableReference", + ItemRef: "CodeableReference", }, { - Name: "relatedClinicalInformation", - Kind: "array", + Name: "relatedClinicalInformation", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "renderedDosageInstruction", @@ -5901,12 +5901,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "subject", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "text", Kind: "object", - Ref: "Narrative", + Ref: "Narrative", }, }, }, @@ -5915,13 +5915,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "code", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -5932,21 +5932,21 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "reason", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "resourceType", @@ -5959,29 +5959,29 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_lastUpdated", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "_profile", - Kind: "array", + Name: "_profile", + Kind: "array", ItemKind: "object", - ItemRef: "FHIRPrimitiveExtension", + ItemRef: "FHIRPrimitiveExtension", }, { Name: "_source", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_versionId", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -5996,14 +5996,14 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "profile", - Kind: "array", + Name: "profile", + Kind: "array", ItemKind: "string", }, { @@ -6011,20 +6011,20 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "security", - Kind: "array", + Name: "security", + Kind: "array", ItemKind: "object", - ItemRef: "Coding", + ItemRef: "Coding", }, { Name: "source", Kind: "string", }, { - Name: "tag", - Kind: "array", + Name: "tag", + Kind: "array", ItemKind: "object", - ItemRef: "Coding", + ItemRef: "Coding", }, { Name: "versionId", @@ -6037,22 +6037,22 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_currency", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_value", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "currency", Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -6063,10 +6063,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "resourceType", @@ -6083,22 +6083,22 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_div", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_status", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "div", Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -6109,10 +6109,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "resourceType", @@ -6129,117 +6129,117 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_effectiveDateTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_effectiveInstant", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_instantiatesCanonical", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_issued", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_status", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueBoolean", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueDateTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueInteger", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueString", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "basedOn", - Kind: "array", + Name: "basedOn", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "bodySite", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "bodyStructure", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "category", - Kind: "array", + Name: "category", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { Name: "code", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "component", - Kind: "array", + Name: "component", + Kind: "array", ItemKind: "object", - ItemRef: "ObservationComponent", + ItemRef: "ObservationComponent", }, { - Name: "contained", - Kind: "array", + Name: "contained", + Kind: "array", ItemKind: "object", - ItemRef: "Resource", + ItemRef: "Resource", }, { Name: "dataAbsentReason", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "derivedFrom", - Kind: "array", + Name: "derivedFrom", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "device", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "effectiveDateTime", @@ -6252,49 +6252,49 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "effectivePeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "effectiveTiming", Kind: "object", - Ref: "Timing", + Ref: "Timing", }, { Name: "encounter", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", Kind: "", }, { - Name: "focus", - Kind: "array", + Name: "focus", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "hasMember", - Kind: "array", + Name: "hasMember", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "id", Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "implicitRules", @@ -6307,13 +6307,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "instantiatesReference", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "interpretation", - Kind: "array", + Name: "interpretation", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { Name: "issued", @@ -6324,50 +6324,50 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { Name: "method", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { - Name: "note", - Kind: "array", + Name: "note", + Kind: "array", ItemKind: "object", - ItemRef: "Annotation", + ItemRef: "Annotation", }, { - Name: "partOf", - Kind: "array", + Name: "partOf", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "performer", - Kind: "array", + Name: "performer", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "referenceRange", - Kind: "array", + Name: "referenceRange", + Kind: "array", ItemKind: "object", - ItemRef: "ObservationReferenceRange", + ItemRef: "ObservationReferenceRange", }, { Name: "resourceType", @@ -6376,7 +6376,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "specimen", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "status", @@ -6385,23 +6385,23 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "subject", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "text", Kind: "object", - Ref: "Narrative", + Ref: "Narrative", }, { - Name: "triggeredBy", - Kind: "array", + Name: "triggeredBy", + Kind: "array", ItemKind: "object", - ItemRef: "ObservationTriggeredBy", + ItemRef: "ObservationTriggeredBy", }, { Name: "valueAttachment", Kind: "object", - Ref: "Attachment", + Ref: "Attachment", }, { Name: "valueBoolean", @@ -6410,7 +6410,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueCodeableConcept", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "valueDateTime", @@ -6423,32 +6423,32 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valuePeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "valueQuantity", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "valueRange", Kind: "object", - Ref: "Range", + Ref: "Range", }, { Name: "valueRatio", Kind: "object", - Ref: "Ratio", + Ref: "Ratio", }, { Name: "valueReference", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "valueSampledData", Kind: "object", - Ref: "SampledData", + Ref: "SampledData", }, { Name: "valueString", @@ -6465,43 +6465,43 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_valueBoolean", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueDateTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueInteger", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueString", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "code", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "dataAbsentReason", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -6512,28 +6512,28 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "interpretation", - Kind: "array", + Name: "interpretation", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { - Name: "referenceRange", - Kind: "array", + Name: "referenceRange", + Kind: "array", ItemKind: "object", - ItemRef: "ObservationReferenceRange", + ItemRef: "ObservationReferenceRange", }, { Name: "resourceType", @@ -6542,7 +6542,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueAttachment", Kind: "object", - Ref: "Attachment", + Ref: "Attachment", }, { Name: "valueBoolean", @@ -6551,7 +6551,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueCodeableConcept", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "valueDateTime", @@ -6564,32 +6564,32 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valuePeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "valueQuantity", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "valueRange", Kind: "object", - Ref: "Range", + Ref: "Range", }, { Name: "valueRatio", Kind: "object", - Ref: "Ratio", + Ref: "Ratio", }, { Name: "valueReference", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "valueSampledData", Kind: "object", - Ref: "SampledData", + Ref: "SampledData", }, { Name: "valueString", @@ -6606,24 +6606,24 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_text", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "age", Kind: "object", - Ref: "Range", + Ref: "Range", }, { - Name: "appliesTo", - Kind: "array", + Name: "appliesTo", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -6632,33 +6632,33 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "high", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "id", Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "low", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "normalValue", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "resourceType", @@ -6671,7 +6671,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "type", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, }, }, @@ -6680,18 +6680,18 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_reason", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_type", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -6702,21 +6702,21 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "observation", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "reason", @@ -6737,70 +6737,70 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_active", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "_alias", - Kind: "array", + Name: "_alias", + Kind: "array", ItemKind: "object", - ItemRef: "FHIRPrimitiveExtension", + ItemRef: "FHIRPrimitiveExtension", }, { Name: "_description", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_name", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "active", Kind: "boolean", }, { - Name: "alias", - Kind: "array", + Name: "alias", + Kind: "array", ItemKind: "string", }, { - Name: "contact", - Kind: "array", + Name: "contact", + Kind: "array", ItemKind: "object", - ItemRef: "ExtendedContactDetail", + ItemRef: "ExtendedContactDetail", }, { - Name: "contained", - Kind: "array", + Name: "contained", + Kind: "array", ItemKind: "object", - ItemRef: "Resource", + ItemRef: "Resource", }, { Name: "description", Kind: "string", }, { - Name: "endpoint", - Kind: "array", + Name: "endpoint", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -6811,10 +6811,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "implicitRules", @@ -6825,21 +6825,21 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "name", @@ -6848,13 +6848,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "partOf", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "qualification", - Kind: "array", + Name: "qualification", + Kind: "array", ItemKind: "object", - ItemRef: "OrganizationQualification", + ItemRef: "OrganizationQualification", }, { Name: "resourceType", @@ -6863,13 +6863,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "text", Kind: "object", - Ref: "Narrative", + Ref: "Narrative", }, { - Name: "type", - Kind: "array", + Name: "type", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, }, }, @@ -6878,13 +6878,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "code", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -6895,32 +6895,32 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "issuer", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "period", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "resourceType", @@ -6933,47 +6933,47 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_documentation", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_max", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_min", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_name", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_profile", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_type", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_use", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "documentation", Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -6984,10 +6984,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "max", @@ -7024,79 +7024,79 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_active", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_birthDate", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_deceasedBoolean", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_deceasedDateTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_gender", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_multipleBirthBoolean", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_multipleBirthInteger", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "active", Kind: "boolean", }, { - Name: "address", - Kind: "array", + Name: "address", + Kind: "array", ItemKind: "object", - ItemRef: "Address", + ItemRef: "Address", }, { Name: "birthDate", Kind: "string", }, { - Name: "communication", - Kind: "array", + Name: "communication", + Kind: "array", ItemKind: "object", - ItemRef: "PatientCommunication", + ItemRef: "PatientCommunication", }, { - Name: "contact", - Kind: "array", + Name: "contact", + Kind: "array", ItemKind: "object", - ItemRef: "PatientContact", + ItemRef: "PatientContact", }, { - Name: "contained", - Kind: "array", + Name: "contained", + Kind: "array", ItemKind: "object", - ItemRef: "Resource", + ItemRef: "Resource", }, { Name: "deceasedBoolean", @@ -7107,10 +7107,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -7121,20 +7121,20 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "generalPractitioner", - Kind: "array", + Name: "generalPractitioner", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "id", Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "implicitRules", @@ -7145,37 +7145,37 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "link", - Kind: "array", + Name: "link", + Kind: "array", ItemKind: "object", - ItemRef: "PatientLink", + ItemRef: "PatientLink", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "managingOrganization", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "maritalStatus", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "multipleBirthBoolean", @@ -7186,31 +7186,31 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "integer", }, { - Name: "name", - Kind: "array", + Name: "name", + Kind: "array", ItemKind: "object", - ItemRef: "HumanName", + ItemRef: "HumanName", }, { - Name: "photo", - Kind: "array", + Name: "photo", + Kind: "array", ItemKind: "object", - ItemRef: "Attachment", + ItemRef: "Attachment", }, { Name: "resourceType", Kind: "string", }, { - Name: "telecom", - Kind: "array", + Name: "telecom", + Kind: "array", ItemKind: "object", - ItemRef: "ContactPoint", + ItemRef: "ContactPoint", }, { Name: "text", Kind: "object", - Ref: "Narrative", + Ref: "Narrative", }, }, }, @@ -7219,13 +7219,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_preferred", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -7238,19 +7238,19 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "language", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "preferred", @@ -7267,18 +7267,18 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_gender", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "address", Kind: "object", - Ref: "Address", + Ref: "Address", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -7293,47 +7293,47 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "name", Kind: "object", - Ref: "HumanName", + Ref: "HumanName", }, { Name: "organization", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "period", Kind: "object", - Ref: "Period", + Ref: "Period", }, { - Name: "relationship", - Kind: "array", + Name: "relationship", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { Name: "resourceType", Kind: "string", }, { - Name: "telecom", - Kind: "array", + Name: "telecom", + Kind: "array", ItemKind: "object", - ItemRef: "ContactPoint", + ItemRef: "ContactPoint", }, }, }, @@ -7342,13 +7342,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_type", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -7359,21 +7359,21 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "other", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "resourceType", @@ -7390,22 +7390,22 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_end", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_start", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "end", Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -7416,10 +7416,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "resourceType", @@ -7436,63 +7436,63 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_active", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_birthDate", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_deceasedBoolean", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_deceasedDateTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_gender", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "active", Kind: "boolean", }, { - Name: "address", - Kind: "array", + Name: "address", + Kind: "array", ItemKind: "object", - ItemRef: "Address", + ItemRef: "Address", }, { Name: "birthDate", Kind: "string", }, { - Name: "communication", - Kind: "array", + Name: "communication", + Kind: "array", ItemKind: "object", - ItemRef: "PractitionerCommunication", + ItemRef: "PractitionerCommunication", }, { - Name: "contained", - Kind: "array", + Name: "contained", + Kind: "array", ItemKind: "object", - ItemRef: "Resource", + ItemRef: "Resource", }, { Name: "deceasedBoolean", @@ -7503,10 +7503,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -7521,10 +7521,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "implicitRules", @@ -7535,54 +7535,54 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { - Name: "name", - Kind: "array", + Name: "name", + Kind: "array", ItemKind: "object", - ItemRef: "HumanName", + ItemRef: "HumanName", }, { - Name: "photo", - Kind: "array", + Name: "photo", + Kind: "array", ItemKind: "object", - ItemRef: "Attachment", + ItemRef: "Attachment", }, { - Name: "qualification", - Kind: "array", + Name: "qualification", + Kind: "array", ItemKind: "object", - ItemRef: "PractitionerQualification", + ItemRef: "PractitionerQualification", }, { Name: "resourceType", Kind: "string", }, { - Name: "telecom", - Kind: "array", + Name: "telecom", + Kind: "array", ItemKind: "object", - ItemRef: "ContactPoint", + ItemRef: "ContactPoint", }, { Name: "text", Kind: "object", - Ref: "Narrative", + Ref: "Narrative", }, }, }, @@ -7591,13 +7591,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_preferred", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -7610,19 +7610,19 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "language", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "preferred", @@ -7639,13 +7639,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "code", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -7656,32 +7656,32 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "issuer", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "period", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "resourceType", @@ -7694,89 +7694,89 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_active", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "active", Kind: "boolean", }, { - Name: "availability", - Kind: "array", + Name: "availability", + Kind: "array", ItemKind: "object", - ItemRef: "Availability", + ItemRef: "Availability", }, { - Name: "characteristic", - Kind: "array", + Name: "characteristic", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "code", - Kind: "array", + Name: "code", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "communication", - Kind: "array", + Name: "communication", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "contact", - Kind: "array", + Name: "contact", + Kind: "array", ItemKind: "object", - ItemRef: "ExtendedContactDetail", + ItemRef: "ExtendedContactDetail", }, { - Name: "contained", - Kind: "array", + Name: "contained", + Kind: "array", ItemKind: "object", - ItemRef: "Resource", + ItemRef: "Resource", }, { - Name: "endpoint", - Kind: "array", + Name: "endpoint", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", Kind: "", }, { - Name: "healthcareService", - Kind: "array", + Name: "healthcareService", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "id", Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "implicitRules", @@ -7787,57 +7787,57 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "location", - Kind: "array", + Name: "location", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "organization", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "period", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "practitioner", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "resourceType", Kind: "string", }, { - Name: "specialty", - Kind: "array", + Name: "specialty", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { Name: "text", Kind: "object", - Ref: "Narrative", + Ref: "Narrative", }, }, }, @@ -7846,139 +7846,139 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "_instantiatesCanonical", - Kind: "array", + Name: "_instantiatesCanonical", + Kind: "array", ItemKind: "object", - ItemRef: "FHIRPrimitiveExtension", + ItemRef: "FHIRPrimitiveExtension", }, { - Name: "_instantiatesUri", - Kind: "array", + Name: "_instantiatesUri", + Kind: "array", ItemKind: "object", - ItemRef: "FHIRPrimitiveExtension", + ItemRef: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_occurrenceDateTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_occurrenceString", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_recorded", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_reportedBoolean", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_status", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "basedOn", - Kind: "array", + Name: "basedOn", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "bodySite", - Kind: "array", + Name: "bodySite", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "category", - Kind: "array", + Name: "category", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { Name: "code", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "complication", - Kind: "array", + Name: "complication", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableReference", + ItemRef: "CodeableReference", }, { - Name: "contained", - Kind: "array", + Name: "contained", + Kind: "array", ItemKind: "object", - ItemRef: "Resource", + ItemRef: "Resource", }, { Name: "encounter", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", Kind: "", }, { - Name: "focalDevice", - Kind: "array", + Name: "focalDevice", + Kind: "array", ItemKind: "object", - ItemRef: "ProcedureFocalDevice", + ItemRef: "ProcedureFocalDevice", }, { Name: "focus", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "followUp", - Kind: "array", + Name: "followUp", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { Name: "id", Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "implicitRules", Kind: "string", }, { - Name: "instantiatesCanonical", - Kind: "array", + Name: "instantiatesCanonical", + Kind: "array", ItemKind: "string", }, { - Name: "instantiatesUri", - Kind: "array", + Name: "instantiatesUri", + Kind: "array", ItemKind: "string", }, { @@ -7986,37 +7986,37 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "location", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { - Name: "note", - Kind: "array", + Name: "note", + Kind: "array", ItemKind: "object", - ItemRef: "Annotation", + ItemRef: "Annotation", }, { Name: "occurrenceAge", Kind: "object", - Ref: "Age", + Ref: "Age", }, { Name: "occurrenceDateTime", @@ -8025,12 +8025,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "occurrencePeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "occurrenceRange", Kind: "object", - Ref: "Range", + Ref: "Range", }, { Name: "occurrenceString", @@ -8039,30 +8039,30 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "occurrenceTiming", Kind: "object", - Ref: "Timing", + Ref: "Timing", }, { Name: "outcome", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "partOf", - Kind: "array", + Name: "partOf", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "performer", - Kind: "array", + Name: "performer", + Kind: "array", ItemKind: "object", - ItemRef: "ProcedurePerformer", + ItemRef: "ProcedurePerformer", }, { - Name: "reason", - Kind: "array", + Name: "reason", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableReference", + ItemRef: "CodeableReference", }, { Name: "recorded", @@ -8071,13 +8071,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "recorder", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "report", - Kind: "array", + Name: "report", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "reportedBoolean", @@ -8086,7 +8086,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "reportedReference", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "resourceType", @@ -8099,29 +8099,29 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "statusReason", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "subject", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "supportingInfo", - Kind: "array", + Name: "supportingInfo", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "text", Kind: "object", - Ref: "Narrative", + Ref: "Narrative", }, { - Name: "used", - Kind: "array", + Name: "used", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableReference", + ItemRef: "CodeableReference", }, }, }, @@ -8130,13 +8130,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "action", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -8147,21 +8147,21 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "manipulated", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -8174,13 +8174,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "actor", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -8189,33 +8189,33 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "function", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "id", Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "onBehalfOf", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "period", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "resourceType", @@ -8228,27 +8228,27 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_code", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_comparator", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_system", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_unit", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_value", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "code", @@ -8259,10 +8259,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -8273,10 +8273,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "resourceType", @@ -8299,10 +8299,10 @@ var generatedDefinitions = map[string]generatedDefinition{ "Range": { Properties: []generatedProperty{ { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -8311,22 +8311,22 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "high", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "id", Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "low", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "resourceType", @@ -8339,13 +8339,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "denominator", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -8356,15 +8356,15 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "numerator", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "resourceType", @@ -8377,13 +8377,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "denominator", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -8392,22 +8392,22 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "highNumerator", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "id", Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "lowNumerator", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "resourceType", @@ -8420,27 +8420,27 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_display", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_reference", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_type", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "display", Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -8453,13 +8453,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "identifier", Kind: "object", - Ref: "Identifier", + Ref: "Identifier", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "reference", @@ -8480,47 +8480,47 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_citation", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_display", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_label", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_publicationDate", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_publicationStatus", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_resource", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_type", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "citation", Kind: "string", }, { - Name: "classifier", - Kind: "array", + Name: "classifier", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { Name: "display", @@ -8529,13 +8529,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "document", Kind: "object", - Ref: "Attachment", + Ref: "Attachment", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -8550,10 +8550,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "publicationDate", @@ -8570,7 +8570,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "resourceReference", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "resourceType", @@ -8587,82 +8587,82 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_date", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_description", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_descriptionSummary", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_name", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_status", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_title", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_url", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_version", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "associatedParty", - Kind: "array", + Name: "associatedParty", + Kind: "array", ItemKind: "object", - ItemRef: "ResearchStudyAssociatedParty", + ItemRef: "ResearchStudyAssociatedParty", }, { - Name: "classifier", - Kind: "array", + Name: "classifier", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "comparisonGroup", - Kind: "array", + Name: "comparisonGroup", + Kind: "array", ItemKind: "object", - ItemRef: "ResearchStudyComparisonGroup", + ItemRef: "ResearchStudyComparisonGroup", }, { - Name: "condition", - Kind: "array", + Name: "condition", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "contained", - Kind: "array", + Name: "contained", + Kind: "array", ItemKind: "object", - ItemRef: "Resource", + ItemRef: "Resource", }, { Name: "date", @@ -8677,175 +8677,175 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", Kind: "", }, { - Name: "focus", - Kind: "array", + Name: "focus", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableReference", + ItemRef: "CodeableReference", }, { Name: "id", Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "implicitRules", Kind: "string", }, { - Name: "keyword", - Kind: "array", + Name: "keyword", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "label", - Kind: "array", + Name: "label", + Kind: "array", ItemKind: "object", - ItemRef: "ResearchStudyLabel", + ItemRef: "ResearchStudyLabel", }, { Name: "language", Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "name", Kind: "string", }, { - Name: "note", - Kind: "array", + Name: "note", + Kind: "array", ItemKind: "object", - ItemRef: "Annotation", + ItemRef: "Annotation", }, { - Name: "objective", - Kind: "array", + Name: "objective", + Kind: "array", ItemKind: "object", - ItemRef: "ResearchStudyObjective", + ItemRef: "ResearchStudyObjective", }, { - Name: "outcomeMeasure", - Kind: "array", + Name: "outcomeMeasure", + Kind: "array", ItemKind: "object", - ItemRef: "ResearchStudyOutcomeMeasure", + ItemRef: "ResearchStudyOutcomeMeasure", }, { - Name: "partOf", - Kind: "array", + Name: "partOf", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "period", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "phase", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "primaryPurposeType", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "progressStatus", - Kind: "array", + Name: "progressStatus", + Kind: "array", ItemKind: "object", - ItemRef: "ResearchStudyProgressStatus", + ItemRef: "ResearchStudyProgressStatus", }, { - Name: "protocol", - Kind: "array", + Name: "protocol", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "recruitment", Kind: "object", - Ref: "ResearchStudyRecruitment", + Ref: "ResearchStudyRecruitment", }, { - Name: "region", - Kind: "array", + Name: "region", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "relatedArtifact", - Kind: "array", + Name: "relatedArtifact", + Kind: "array", ItemKind: "object", - ItemRef: "RelatedArtifact", + ItemRef: "RelatedArtifact", }, { Name: "resourceType", Kind: "string", }, { - Name: "result", - Kind: "array", + Name: "result", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "rootDir", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "site", - Kind: "array", + Name: "site", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "status", Kind: "string", }, { - Name: "studyDesign", - Kind: "array", + Name: "studyDesign", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { Name: "text", Kind: "object", - Ref: "Narrative", + Ref: "Narrative", }, { Name: "title", @@ -8862,7 +8862,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "whyStopped", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, }, }, @@ -8871,19 +8871,19 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_name", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "classifier", - Kind: "array", + Name: "classifier", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -8894,16 +8894,16 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "name", @@ -8912,13 +8912,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "party", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "period", - Kind: "array", + Name: "period", + Kind: "array", ItemKind: "object", - ItemRef: "Period", + ItemRef: "Period", }, { Name: "resourceType", @@ -8927,7 +8927,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "role", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, }, }, @@ -8936,27 +8936,27 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_description", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_linkId", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_name", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "description", Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -8967,26 +8967,26 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "intendedExposure", - Kind: "array", + Name: "intendedExposure", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "linkId", Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "name", @@ -8995,7 +8995,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "observedGroup", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "resourceType", @@ -9004,7 +9004,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "type", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, }, }, @@ -9013,13 +9013,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_value", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -9030,16 +9030,16 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -9048,7 +9048,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "type", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "value", @@ -9061,22 +9061,22 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_description", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_name", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "description", Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -9087,16 +9087,16 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "name", @@ -9109,7 +9109,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "type", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, }, }, @@ -9118,22 +9118,22 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_description", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_name", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "description", Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -9144,16 +9144,16 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "name", @@ -9162,17 +9162,17 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "reference", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "resourceType", Kind: "string", }, { - Name: "type", - Kind: "array", + Name: "type", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, }, }, @@ -9181,17 +9181,17 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_actual", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "actual", Kind: "boolean", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -9202,21 +9202,21 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "period", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "resourceType", @@ -9225,7 +9225,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "state", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, }, }, @@ -9234,17 +9234,17 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_actualNumber", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_targetNumber", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "actualGroup", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "actualNumber", @@ -9253,13 +9253,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "eligibility", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -9270,16 +9270,16 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -9296,27 +9296,27 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_actualComparisonGroup", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_assignedComparisonGroup", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_status", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "actualComparisonGroup", @@ -9327,22 +9327,22 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "consent", - Kind: "array", + Name: "consent", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "contained", - Kind: "array", + Name: "contained", + Kind: "array", ItemKind: "object", - ItemRef: "Resource", + ItemRef: "Resource", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -9353,10 +9353,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "implicitRules", @@ -9367,32 +9367,32 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "period", Kind: "object", - Ref: "Period", + Ref: "Period", }, { - Name: "progress", - Kind: "array", + Name: "progress", + Kind: "array", ItemKind: "object", - ItemRef: "ResearchSubjectProgress", + ItemRef: "ResearchSubjectProgress", }, { Name: "resourceType", @@ -9405,17 +9405,17 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "study", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "subject", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "text", Kind: "object", - Ref: "Narrative", + Ref: "Narrative", }, }, }, @@ -9424,22 +9424,22 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_endDate", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_startDate", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "endDate", Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -9450,26 +9450,26 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "milestone", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "reason", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "resourceType", @@ -9482,12 +9482,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "subjectState", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "type", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, }, }, @@ -9496,12 +9496,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "fhir_comments", @@ -9520,15 +9520,15 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { Name: "resourceType", @@ -9541,47 +9541,47 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_codeMap", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_data", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_dimensions", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_factor", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_interval", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_intervalUnit", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_lowerLimit", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_offsets", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_upperLimit", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "codeMap", @@ -9596,10 +9596,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "integer", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "factor", @@ -9622,10 +9622,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "lowerLimit", @@ -9638,7 +9638,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "origin", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "resourceType", @@ -9655,32 +9655,32 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_data", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_sigFormat", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_targetFormat", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_when", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "data", Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -9691,15 +9691,15 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "onBehalfOf", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "resourceType", @@ -9714,10 +9714,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "type", - Kind: "array", + Name: "type", + Kind: "array", ItemKind: "object", - ItemRef: "Coding", + ItemRef: "Coding", }, { Name: "when", @@ -9726,7 +9726,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "who", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, }, }, @@ -9735,71 +9735,71 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_combined", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_receivedTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_status", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "accessionIdentifier", Kind: "object", - Ref: "Identifier", + Ref: "Identifier", }, { Name: "collection", Kind: "object", - Ref: "SpecimenCollection", + Ref: "SpecimenCollection", }, { Name: "combined", Kind: "string", }, { - Name: "condition", - Kind: "array", + Name: "condition", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "contained", - Kind: "array", + Name: "contained", + Kind: "array", ItemKind: "object", - ItemRef: "Resource", + ItemRef: "Resource", }, { - Name: "container", - Kind: "array", + Name: "container", + Kind: "array", ItemKind: "object", - ItemRef: "SpecimenContainer", + ItemRef: "SpecimenContainer", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { - Name: "feature", - Kind: "array", + Name: "feature", + Kind: "array", ItemKind: "object", - ItemRef: "SpecimenFeature", + ItemRef: "SpecimenFeature", }, { Name: "fhir_comments", @@ -9810,10 +9810,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "implicitRules", @@ -9824,59 +9824,59 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { - Name: "note", - Kind: "array", + Name: "note", + Kind: "array", ItemKind: "object", - ItemRef: "Annotation", + ItemRef: "Annotation", }, { - Name: "parent", - Kind: "array", + Name: "parent", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "processing", - Kind: "array", + Name: "processing", + Kind: "array", ItemKind: "object", - ItemRef: "SpecimenProcessing", + ItemRef: "SpecimenProcessing", }, { Name: "receivedTime", Kind: "string", }, { - Name: "request", - Kind: "array", + Name: "request", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "resourceType", Kind: "string", }, { - Name: "role", - Kind: "array", + Name: "role", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { Name: "status", @@ -9885,17 +9885,17 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "subject", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "text", Kind: "object", - Ref: "Narrative", + Ref: "Narrative", }, { Name: "type", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, }, }, @@ -9904,12 +9904,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_collectedDateTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "bodySite", Kind: "object", - Ref: "CodeableReference", + Ref: "CodeableReference", }, { Name: "collectedDateTime", @@ -9918,38 +9918,38 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "collectedPeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "collector", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "device", Kind: "object", - Ref: "CodeableReference", + Ref: "CodeableReference", }, { Name: "duration", Kind: "object", - Ref: "Duration", + Ref: "Duration", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fastingStatusCodeableConcept", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "fastingStatusDuration", Kind: "object", - Ref: "Duration", + Ref: "Duration", }, { Name: "fhir_comments", @@ -9960,31 +9960,31 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "method", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "procedure", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "quantity", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "resourceType", @@ -9997,13 +9997,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "device", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -10014,21 +10014,21 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "location", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -10037,7 +10037,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "specimenQuantity", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, }, }, @@ -10046,17 +10046,17 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_description", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "description", Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -10067,16 +10067,16 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -10085,7 +10085,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "type", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, }, }, @@ -10094,28 +10094,28 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_description", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_timeDateTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "additive", - Kind: "array", + Name: "additive", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "description", Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -10126,21 +10126,21 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "method", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -10153,7 +10153,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "timePeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, }, }, @@ -10162,49 +10162,49 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_description", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_expiry", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_instance", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_status", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "category", - Kind: "array", + Name: "category", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { Name: "code", Kind: "object", - Ref: "CodeableReference", + Ref: "CodeableReference", }, { - Name: "contained", - Kind: "array", + Name: "contained", + Kind: "array", ItemKind: "object", - ItemRef: "Resource", + ItemRef: "Resource", }, { Name: "description", @@ -10215,10 +10215,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -10229,20 +10229,20 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "implicitRules", Kind: "string", }, { - Name: "ingredient", - Kind: "array", + Name: "ingredient", + Kind: "array", ItemKind: "object", - ItemRef: "SubstanceIngredient", + ItemRef: "SubstanceIngredient", }, { Name: "instance", @@ -10253,26 +10253,26 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "quantity", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "resourceType", @@ -10285,7 +10285,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "text", Kind: "object", - Ref: "Narrative", + Ref: "Narrative", }, }, }, @@ -10294,46 +10294,46 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_description", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_version", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "characterization", - Kind: "array", + Name: "characterization", + Kind: "array", ItemKind: "object", - ItemRef: "SubstanceDefinitionCharacterization", + ItemRef: "SubstanceDefinitionCharacterization", }, { - Name: "classification", - Kind: "array", + Name: "classification", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "code", - Kind: "array", + Name: "code", + Kind: "array", ItemKind: "object", - ItemRef: "SubstanceDefinitionCode", + ItemRef: "SubstanceDefinitionCode", }, { - Name: "contained", - Kind: "array", + Name: "contained", + Kind: "array", ItemKind: "object", - ItemRef: "Resource", + ItemRef: "Resource", }, { Name: "description", @@ -10342,126 +10342,126 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "domain", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", Kind: "", }, { - Name: "grade", - Kind: "array", + Name: "grade", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { Name: "id", Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "implicitRules", Kind: "string", }, { - Name: "informationSource", - Kind: "array", + Name: "informationSource", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "language", Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "manufacturer", - Kind: "array", + Name: "manufacturer", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { - Name: "moiety", - Kind: "array", + Name: "moiety", + Kind: "array", ItemKind: "object", - ItemRef: "SubstanceDefinitionMoiety", + ItemRef: "SubstanceDefinitionMoiety", }, { - Name: "molecularWeight", - Kind: "array", + Name: "molecularWeight", + Kind: "array", ItemKind: "object", - ItemRef: "SubstanceDefinitionMolecularWeight", + ItemRef: "SubstanceDefinitionMolecularWeight", }, { - Name: "name", - Kind: "array", + Name: "name", + Kind: "array", ItemKind: "object", - ItemRef: "SubstanceDefinitionName", + ItemRef: "SubstanceDefinitionName", }, { - Name: "note", - Kind: "array", + Name: "note", + Kind: "array", ItemKind: "object", - ItemRef: "Annotation", + ItemRef: "Annotation", }, { Name: "nucleicAcid", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "polymer", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "property", - Kind: "array", + Name: "property", + Kind: "array", ItemKind: "object", - ItemRef: "SubstanceDefinitionProperty", + ItemRef: "SubstanceDefinitionProperty", }, { Name: "protein", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "referenceInformation", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "relationship", - Kind: "array", + Name: "relationship", + Kind: "array", ItemKind: "object", - ItemRef: "SubstanceDefinitionRelationship", + ItemRef: "SubstanceDefinitionRelationship", }, { Name: "resourceType", @@ -10470,28 +10470,28 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "sourceMaterial", Kind: "object", - Ref: "SubstanceDefinitionSourceMaterial", + Ref: "SubstanceDefinitionSourceMaterial", }, { Name: "status", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "structure", Kind: "object", - Ref: "SubstanceDefinitionStructure", + Ref: "SubstanceDefinitionStructure", }, { - Name: "supplier", - Kind: "array", + Name: "supplier", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "text", Kind: "object", - Ref: "Narrative", + Ref: "Narrative", }, { Name: "version", @@ -10504,48 +10504,48 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_description", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "description", Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", Kind: "", }, { - Name: "file", - Kind: "array", + Name: "file", + Kind: "array", ItemKind: "object", - ItemRef: "Attachment", + ItemRef: "Attachment", }, { Name: "form", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "id", Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -10554,7 +10554,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "technique", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, }, }, @@ -10563,18 +10563,18 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_statusDate", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "code", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -10585,37 +10585,37 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { - Name: "note", - Kind: "array", + Name: "note", + Kind: "array", ItemKind: "object", - ItemRef: "Annotation", + ItemRef: "Annotation", }, { Name: "resourceType", Kind: "string", }, { - Name: "source", - Kind: "array", + Name: "source", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "status", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "statusDate", @@ -10628,32 +10628,32 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_amountString", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_molecularFormula", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_name", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "amountQuantity", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "amountString", Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -10666,24 +10666,24 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "identifier", Kind: "object", - Ref: "Identifier", + Ref: "Identifier", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "measurementType", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "molecularFormula", @@ -10696,7 +10696,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "opticalActivity", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "resourceType", @@ -10705,12 +10705,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "role", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "stereochemistry", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, }, }, @@ -10719,13 +10719,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "amount", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -10736,21 +10736,21 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "method", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -10759,7 +10759,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "type", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, }, }, @@ -10768,24 +10768,24 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_name", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_preferred", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "domain", - Kind: "array", + Name: "domain", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -10796,38 +10796,38 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "jurisdiction", - Kind: "array", + Name: "jurisdiction", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "language", - Kind: "array", + Name: "language", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "name", Kind: "string", }, { - Name: "official", - Kind: "array", + Name: "official", + Kind: "array", ItemKind: "object", - ItemRef: "SubstanceDefinitionNameOfficial", + ItemRef: "SubstanceDefinitionNameOfficial", }, { Name: "preferred", @@ -10838,32 +10838,32 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "source", - Kind: "array", + Name: "source", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "status", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "synonym", - Kind: "array", + Name: "synonym", + Kind: "array", ItemKind: "object", - ItemRef: "SubstanceDefinitionName", + ItemRef: "SubstanceDefinitionName", }, { - Name: "translation", - Kind: "array", + Name: "translation", + Kind: "array", ItemKind: "object", - ItemRef: "SubstanceDefinitionName", + ItemRef: "SubstanceDefinitionName", }, { Name: "type", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, }, }, @@ -10872,22 +10872,22 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_date", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "authority", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "date", Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -10898,16 +10898,16 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -10916,7 +10916,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "status", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, }, }, @@ -10925,18 +10925,18 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_valueBoolean", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueDate", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -10947,16 +10947,16 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -10965,12 +10965,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "type", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "valueAttachment", Kind: "object", - Ref: "Attachment", + Ref: "Attachment", }, { Name: "valueBoolean", @@ -10979,7 +10979,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueCodeableConcept", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "valueDate", @@ -10988,7 +10988,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueQuantity", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, }, }, @@ -10997,22 +10997,22 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_amountString", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_isDefining", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "amountQuantity", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "amountRatio", Kind: "object", - Ref: "Ratio", + Ref: "Ratio", }, { Name: "amountString", @@ -11021,13 +11021,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "comparator", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -11042,62 +11042,62 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "boolean", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "ratioHighLimitAmount", Kind: "object", - Ref: "Ratio", + Ref: "Ratio", }, { Name: "resourceType", Kind: "string", }, { - Name: "source", - Kind: "array", + Name: "source", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "substanceDefinitionCodeableConcept", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "substanceDefinitionReference", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "type", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, }, }, "SubstanceDefinitionSourceMaterial": { Properties: []generatedProperty{ { - Name: "countryOfOrigin", - Kind: "array", + Name: "countryOfOrigin", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -11106,28 +11106,28 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "genus", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "id", Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "part", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "resourceType", @@ -11136,12 +11136,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "species", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "type", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, }, }, @@ -11150,18 +11150,18 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_molecularFormula", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_molecularFormulaByMoiety", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -11172,16 +11172,16 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "molecularFormula", @@ -11194,39 +11194,39 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "molecularWeight", Kind: "object", - Ref: "SubstanceDefinitionMolecularWeight", + Ref: "SubstanceDefinitionMolecularWeight", }, { Name: "opticalActivity", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "representation", - Kind: "array", + Name: "representation", + Kind: "array", ItemKind: "object", - ItemRef: "SubstanceDefinitionStructureRepresentation", + ItemRef: "SubstanceDefinitionStructureRepresentation", }, { Name: "resourceType", Kind: "string", }, { - Name: "sourceDocument", - Kind: "array", + Name: "sourceDocument", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "stereochemistry", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "technique", - Kind: "array", + Name: "technique", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableConcept", + ItemRef: "CodeableConcept", }, }, }, @@ -11235,18 +11235,18 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_representation", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "document", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -11255,23 +11255,23 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "format", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "id", Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "representation", @@ -11284,17 +11284,17 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "type", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, }, }, "SubstanceIngredient": { Properties: []generatedProperty{ { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -11305,21 +11305,21 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "quantity", Kind: "object", - Ref: "Ratio", + Ref: "Ratio", }, { Name: "resourceType", @@ -11328,12 +11328,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "substanceCodeableConcept", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "substanceReference", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, }, }, @@ -11342,83 +11342,83 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_authoredOn", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_description", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_doNotPerform", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_implicitRules", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_instantiatesCanonical", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_instantiatesUri", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_intent", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_language", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_lastModified", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_priority", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_status", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "authoredOn", Kind: "string", }, { - Name: "basedOn", - Kind: "array", + Name: "basedOn", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "businessStatus", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "code", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "contained", - Kind: "array", + Name: "contained", + Kind: "array", ItemKind: "object", - ItemRef: "Resource", + ItemRef: "Resource", }, { Name: "description", @@ -11431,18 +11431,18 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "encounter", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "executionPeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -11451,37 +11451,37 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "focus", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "for_fhir", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "groupIdentifier", Kind: "object", - Ref: "Identifier", + Ref: "Identifier", }, { Name: "id", Kind: "string", }, { - Name: "identifier", - Kind: "array", + Name: "identifier", + Kind: "array", ItemKind: "object", - ItemRef: "Identifier", + ItemRef: "Identifier", }, { Name: "implicitRules", Kind: "string", }, { - Name: "input", - Kind: "array", + Name: "input", + Kind: "array", ItemKind: "object", - ItemRef: "TaskInput", + ItemRef: "TaskInput", }, { Name: "instantiatesCanonical", @@ -11492,10 +11492,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "insurance", - Kind: "array", + Name: "insurance", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "intent", @@ -11510,87 +11510,87 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "location", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "meta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { - Name: "note", - Kind: "array", + Name: "note", + Kind: "array", ItemKind: "object", - ItemRef: "Annotation", + ItemRef: "Annotation", }, { - Name: "output", - Kind: "array", + Name: "output", + Kind: "array", ItemKind: "object", - ItemRef: "TaskOutput", + ItemRef: "TaskOutput", }, { Name: "owner", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "partOf", - Kind: "array", + Name: "partOf", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "performer", - Kind: "array", + Name: "performer", + Kind: "array", ItemKind: "object", - ItemRef: "TaskPerformer", + ItemRef: "TaskPerformer", }, { Name: "priority", Kind: "string", }, { - Name: "reason", - Kind: "array", + Name: "reason", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableReference", + ItemRef: "CodeableReference", }, { - Name: "relevantHistory", - Kind: "array", + Name: "relevantHistory", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { - Name: "requestedPerformer", - Kind: "array", + Name: "requestedPerformer", + Kind: "array", ItemKind: "object", - ItemRef: "CodeableReference", + ItemRef: "CodeableReference", }, { Name: "requestedPeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "requester", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "resourceType", @@ -11599,7 +11599,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "restriction", Kind: "object", - Ref: "TaskRestriction", + Ref: "TaskRestriction", }, { Name: "status", @@ -11608,12 +11608,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "statusReason", Kind: "object", - Ref: "CodeableReference", + Ref: "CodeableReference", }, { Name: "text", Kind: "object", - Ref: "Narrative", + Ref: "Narrative", }, }, }, @@ -11622,108 +11622,108 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_valueBase64Binary", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueBoolean", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueCanonical", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueCode", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueDate", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueDateTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueDecimal", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueId", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueInstant", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueInteger", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueInteger64", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueMarkdown", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueOid", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valuePositiveInt", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueString", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueUnsignedInt", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueUri", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueUrl", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueUuid", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -11734,16 +11734,16 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -11752,32 +11752,32 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "type", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "valueAddress", Kind: "object", - Ref: "Address", + Ref: "Address", }, { Name: "valueAge", Kind: "object", - Ref: "Age", + Ref: "Age", }, { Name: "valueAnnotation", Kind: "object", - Ref: "Annotation", + Ref: "Annotation", }, { Name: "valueAttachment", Kind: "object", - Ref: "Attachment", + Ref: "Attachment", }, { Name: "valueAvailability", Kind: "object", - Ref: "Availability", + Ref: "Availability", }, { Name: "valueBase64Binary", @@ -11798,37 +11798,37 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueCodeableConcept", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "valueCodeableReference", Kind: "object", - Ref: "CodeableReference", + Ref: "CodeableReference", }, { Name: "valueCoding", Kind: "object", - Ref: "Coding", + Ref: "Coding", }, { Name: "valueContactDetail", Kind: "object", - Ref: "ContactDetail", + Ref: "ContactDetail", }, { Name: "valueContactPoint", Kind: "object", - Ref: "ContactPoint", + Ref: "ContactPoint", }, { Name: "valueCount", Kind: "object", - Ref: "Count", + Ref: "Count", }, { Name: "valueDataRequirement", Kind: "object", - Ref: "DataRequirement", + Ref: "DataRequirement", }, { Name: "valueDate", @@ -11845,32 +11845,32 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueDistance", Kind: "object", - Ref: "Distance", + Ref: "Distance", }, { Name: "valueDosage", Kind: "object", - Ref: "Dosage", + Ref: "Dosage", }, { Name: "valueDuration", Kind: "object", - Ref: "Duration", + Ref: "Duration", }, { Name: "valueExpression", Kind: "object", - Ref: "Expression", + Ref: "Expression", }, { Name: "valueExtendedContactDetail", Kind: "object", - Ref: "ExtendedContactDetail", + Ref: "ExtendedContactDetail", }, { Name: "valueHumanName", Kind: "object", - Ref: "HumanName", + Ref: "HumanName", }, { Name: "valueId", @@ -11879,7 +11879,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueIdentifier", Kind: "object", - Ref: "Identifier", + Ref: "Identifier", }, { Name: "valueInstant", @@ -11900,12 +11900,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueMeta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { Name: "valueMoney", Kind: "object", - Ref: "Money", + Ref: "Money", }, { Name: "valueOid", @@ -11914,12 +11914,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueParameterDefinition", Kind: "object", - Ref: "ParameterDefinition", + Ref: "ParameterDefinition", }, { Name: "valuePeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "valuePositiveInt", @@ -11928,42 +11928,42 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueQuantity", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "valueRange", Kind: "object", - Ref: "Range", + Ref: "Range", }, { Name: "valueRatio", Kind: "object", - Ref: "Ratio", + Ref: "Ratio", }, { Name: "valueRatioRange", Kind: "object", - Ref: "RatioRange", + Ref: "RatioRange", }, { Name: "valueReference", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "valueRelatedArtifact", Kind: "object", - Ref: "RelatedArtifact", + Ref: "RelatedArtifact", }, { Name: "valueSampledData", Kind: "object", - Ref: "SampledData", + Ref: "SampledData", }, { Name: "valueSignature", Kind: "object", - Ref: "Signature", + Ref: "Signature", }, { Name: "valueString", @@ -11976,12 +11976,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueTiming", Kind: "object", - Ref: "Timing", + Ref: "Timing", }, { Name: "valueTriggerDefinition", Kind: "object", - Ref: "TriggerDefinition", + Ref: "TriggerDefinition", }, { Name: "valueUnsignedInt", @@ -11998,7 +11998,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueUsageContext", Kind: "object", - Ref: "UsageContext", + Ref: "UsageContext", }, { Name: "valueUuid", @@ -12011,108 +12011,108 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_valueBase64Binary", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueBoolean", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueCanonical", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueCode", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueDate", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueDateTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueDecimal", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueId", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueInstant", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueInteger", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueInteger64", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueMarkdown", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueOid", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valuePositiveInt", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueString", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueUnsignedInt", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueUri", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueUrl", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_valueUuid", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -12123,16 +12123,16 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -12141,32 +12141,32 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "type", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "valueAddress", Kind: "object", - Ref: "Address", + Ref: "Address", }, { Name: "valueAge", Kind: "object", - Ref: "Age", + Ref: "Age", }, { Name: "valueAnnotation", Kind: "object", - Ref: "Annotation", + Ref: "Annotation", }, { Name: "valueAttachment", Kind: "object", - Ref: "Attachment", + Ref: "Attachment", }, { Name: "valueAvailability", Kind: "object", - Ref: "Availability", + Ref: "Availability", }, { Name: "valueBase64Binary", @@ -12187,37 +12187,37 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueCodeableConcept", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "valueCodeableReference", Kind: "object", - Ref: "CodeableReference", + Ref: "CodeableReference", }, { Name: "valueCoding", Kind: "object", - Ref: "Coding", + Ref: "Coding", }, { Name: "valueContactDetail", Kind: "object", - Ref: "ContactDetail", + Ref: "ContactDetail", }, { Name: "valueContactPoint", Kind: "object", - Ref: "ContactPoint", + Ref: "ContactPoint", }, { Name: "valueCount", Kind: "object", - Ref: "Count", + Ref: "Count", }, { Name: "valueDataRequirement", Kind: "object", - Ref: "DataRequirement", + Ref: "DataRequirement", }, { Name: "valueDate", @@ -12234,32 +12234,32 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueDistance", Kind: "object", - Ref: "Distance", + Ref: "Distance", }, { Name: "valueDosage", Kind: "object", - Ref: "Dosage", + Ref: "Dosage", }, { Name: "valueDuration", Kind: "object", - Ref: "Duration", + Ref: "Duration", }, { Name: "valueExpression", Kind: "object", - Ref: "Expression", + Ref: "Expression", }, { Name: "valueExtendedContactDetail", Kind: "object", - Ref: "ExtendedContactDetail", + Ref: "ExtendedContactDetail", }, { Name: "valueHumanName", Kind: "object", - Ref: "HumanName", + Ref: "HumanName", }, { Name: "valueId", @@ -12268,7 +12268,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueIdentifier", Kind: "object", - Ref: "Identifier", + Ref: "Identifier", }, { Name: "valueInstant", @@ -12289,12 +12289,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueMeta", Kind: "object", - Ref: "Meta", + Ref: "Meta", }, { Name: "valueMoney", Kind: "object", - Ref: "Money", + Ref: "Money", }, { Name: "valueOid", @@ -12303,12 +12303,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueParameterDefinition", Kind: "object", - Ref: "ParameterDefinition", + Ref: "ParameterDefinition", }, { Name: "valuePeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "valuePositiveInt", @@ -12317,42 +12317,42 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueQuantity", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "valueRange", Kind: "object", - Ref: "Range", + Ref: "Range", }, { Name: "valueRatio", Kind: "object", - Ref: "Ratio", + Ref: "Ratio", }, { Name: "valueRatioRange", Kind: "object", - Ref: "RatioRange", + Ref: "RatioRange", }, { Name: "valueReference", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "valueRelatedArtifact", Kind: "object", - Ref: "RelatedArtifact", + Ref: "RelatedArtifact", }, { Name: "valueSampledData", Kind: "object", - Ref: "SampledData", + Ref: "SampledData", }, { Name: "valueSignature", Kind: "object", - Ref: "Signature", + Ref: "Signature", }, { Name: "valueString", @@ -12365,12 +12365,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueTiming", Kind: "object", - Ref: "Timing", + Ref: "Timing", }, { Name: "valueTriggerDefinition", Kind: "object", - Ref: "TriggerDefinition", + Ref: "TriggerDefinition", }, { Name: "valueUnsignedInt", @@ -12387,7 +12387,7 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueUsageContext", Kind: "object", - Ref: "UsageContext", + Ref: "UsageContext", }, { Name: "valueUuid", @@ -12400,13 +12400,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "actor", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -12415,23 +12415,23 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "function", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "id", Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "resourceType", @@ -12444,13 +12444,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_repetitions", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -12461,27 +12461,27 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "period", Kind: "object", - Ref: "Period", + Ref: "Period", }, { - Name: "recipient", - Kind: "array", + Name: "recipient", + Kind: "array", ItemKind: "object", - ItemRef: "Reference", + ItemRef: "Reference", }, { Name: "repetitions", @@ -12496,26 +12496,26 @@ var generatedDefinitions = map[string]generatedDefinition{ "Timing": { Properties: []generatedProperty{ { - Name: "_event", - Kind: "array", + Name: "_event", + Kind: "array", ItemKind: "object", - ItemRef: "FHIRPrimitiveExtension", + ItemRef: "FHIRPrimitiveExtension", }, { Name: "code", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { - Name: "event", - Kind: "array", + Name: "event", + Kind: "array", ItemKind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -12526,21 +12526,21 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { - Name: "modifierExtension", - Kind: "array", + Name: "modifierExtension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "repeat", Kind: "object", - Ref: "TimingRepeat", + Ref: "TimingRepeat", }, { Name: "resourceType", @@ -12553,90 +12553,90 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_count", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_countMax", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "_dayOfWeek", - Kind: "array", + Name: "_dayOfWeek", + Kind: "array", ItemKind: "object", - ItemRef: "FHIRPrimitiveExtension", + ItemRef: "FHIRPrimitiveExtension", }, { Name: "_duration", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_durationMax", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_durationUnit", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_frequency", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_frequencyMax", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_offset", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_period", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_periodMax", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_periodUnit", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { - Name: "_timeOfDay", - Kind: "array", + Name: "_timeOfDay", + Kind: "array", ItemKind: "object", - ItemRef: "FHIRPrimitiveExtension", + ItemRef: "FHIRPrimitiveExtension", }, { - Name: "_when", - Kind: "array", + Name: "_when", + Kind: "array", ItemKind: "object", - ItemRef: "FHIRPrimitiveExtension", + ItemRef: "FHIRPrimitiveExtension", }, { Name: "boundsDuration", Kind: "object", - Ref: "Duration", + Ref: "Duration", }, { Name: "boundsPeriod", Kind: "object", - Ref: "Period", + Ref: "Period", }, { Name: "boundsRange", Kind: "object", - Ref: "Range", + Ref: "Range", }, { Name: "count", @@ -12647,8 +12647,8 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "integer", }, { - Name: "dayOfWeek", - Kind: "array", + Name: "dayOfWeek", + Kind: "array", ItemKind: "string", }, { @@ -12664,10 +12664,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -12686,10 +12686,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "offset", @@ -12712,13 +12712,13 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "timeOfDay", - Kind: "array", + Name: "timeOfDay", + Kind: "array", ItemKind: "string", }, { - Name: "when", - Kind: "array", + Name: "when", + Kind: "array", ItemKind: "string", }, }, @@ -12728,49 +12728,49 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "_name", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_subscriptionTopic", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_timingDate", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_timingDateTime", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "_type", Kind: "object", - Ref: "FHIRPrimitiveExtension", + Ref: "FHIRPrimitiveExtension", }, { Name: "code", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "condition", Kind: "object", - Ref: "Expression", + Ref: "Expression", }, { - Name: "data", - Kind: "array", + Name: "data", + Kind: "array", ItemKind: "object", - ItemRef: "DataRequirement", + ItemRef: "DataRequirement", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -12781,10 +12781,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "name", @@ -12809,12 +12809,12 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "timingReference", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, { Name: "timingTiming", Kind: "object", - Ref: "Timing", + Ref: "Timing", }, { Name: "type", @@ -12827,13 +12827,13 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "code", Kind: "object", - Ref: "Coding", + Ref: "Coding", }, { - Name: "extension", - Kind: "array", + Name: "extension", + Kind: "array", ItemKind: "object", - ItemRef: "Extension", + ItemRef: "Extension", }, { Name: "fhir_comments", @@ -12844,10 +12844,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "links", - Kind: "array", + Name: "links", + Kind: "array", ItemKind: "object", - ItemRef: "links", + ItemRef: "links", }, { Name: "resourceType", @@ -12856,23 +12856,55011 @@ var generatedDefinitions = map[string]generatedDefinition{ { Name: "valueCodeableConcept", Kind: "object", - Ref: "CodeableConcept", + Ref: "CodeableConcept", }, { Name: "valueQuantity", Kind: "object", - Ref: "Quantity", + Ref: "Quantity", }, { Name: "valueRange", Kind: "object", - Ref: "Range", + Ref: "Range", }, { Name: "valueReference", Kind: "object", - Ref: "Reference", + Ref: "Reference", }, }, }, } + +var generatedTraversals = map[string]TraversalSpec{ + "Annotation|authorReference_Practitioner|Practitioner": { + FromType: "Annotation", + EdgeLabel: "authorReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|authorReference_Practitioner|Annotation": { + FromType: "Practitioner", + EdgeLabel: "authorReference_Practitioner", + ToType: "Annotation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Annotation|authorReference_PractitionerRole|PractitionerRole": { + FromType: "Annotation", + EdgeLabel: "authorReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|authorReference_PractitionerRole|Annotation": { + FromType: "PractitionerRole", + EdgeLabel: "authorReference_PractitionerRole", + ToType: "Annotation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Annotation|authorReference_Patient|Patient": { + FromType: "Annotation", + EdgeLabel: "authorReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|authorReference_Patient|Annotation": { + FromType: "Patient", + EdgeLabel: "authorReference_Patient", + ToType: "Annotation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Annotation|authorReference_Organization|Organization": { + FromType: "Annotation", + EdgeLabel: "authorReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|authorReference_Organization|Annotation": { + FromType: "Organization", + EdgeLabel: "authorReference_Organization", + ToType: "Annotation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "BodyStructure|patient|Patient": { + FromType: "BodyStructure", + EdgeLabel: "patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "body_structure", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|patient|BodyStructure": { + FromType: "Patient", + EdgeLabel: "patient", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "body_structure", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark|device_reference_Organization|Organization": { + FromType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + EdgeLabel: "device_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|device_reference_Organization|BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + FromType: "Organization", + EdgeLabel: "device_reference_Organization", + ToType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark|device_reference_Group|Group": { + FromType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + EdgeLabel: "device_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|device_reference_Group|BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + FromType: "Group", + EdgeLabel: "device_reference_Group", + ToType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark|device_reference_Practitioner|Practitioner": { + FromType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + EdgeLabel: "device_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|device_reference_Practitioner|BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + FromType: "Practitioner", + EdgeLabel: "device_reference_Practitioner", + ToType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark|device_reference_PractitionerRole|PractitionerRole": { + FromType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + EdgeLabel: "device_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|device_reference_PractitionerRole|BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + FromType: "PractitionerRole", + EdgeLabel: "device_reference_PractitionerRole", + ToType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark|device_reference_ResearchStudy|ResearchStudy": { + FromType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + EdgeLabel: "device_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|device_reference_ResearchStudy|BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + FromType: "ResearchStudy", + EdgeLabel: "device_reference_ResearchStudy", + ToType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark|device_reference_Patient|Patient": { + FromType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + EdgeLabel: "device_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|device_reference_Patient|BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + FromType: "Patient", + EdgeLabel: "device_reference_Patient", + ToType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark|device_reference_ResearchSubject|ResearchSubject": { + FromType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + EdgeLabel: "device_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|device_reference_ResearchSubject|BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + FromType: "ResearchSubject", + EdgeLabel: "device_reference_ResearchSubject", + ToType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark|device_reference_Substance|Substance": { + FromType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + EdgeLabel: "device_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|device_reference_Substance|BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + FromType: "Substance", + EdgeLabel: "device_reference_Substance", + ToType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark|device_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + EdgeLabel: "device_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|device_reference_SubstanceDefinition|BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + FromType: "SubstanceDefinition", + EdgeLabel: "device_reference_SubstanceDefinition", + ToType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark|device_reference_Specimen|Specimen": { + FromType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + EdgeLabel: "device_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|device_reference_Specimen|BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + FromType: "Specimen", + EdgeLabel: "device_reference_Specimen", + ToType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark|device_reference_Observation|Observation": { + FromType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + EdgeLabel: "device_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|device_reference_Observation|BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + FromType: "Observation", + EdgeLabel: "device_reference_Observation", + ToType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark|device_reference_DiagnosticReport|DiagnosticReport": { + FromType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + EdgeLabel: "device_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|device_reference_DiagnosticReport|BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + FromType: "DiagnosticReport", + EdgeLabel: "device_reference_DiagnosticReport", + ToType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark|device_reference_Condition|Condition": { + FromType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + EdgeLabel: "device_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|device_reference_Condition|BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + FromType: "Condition", + EdgeLabel: "device_reference_Condition", + ToType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark|device_reference_Medication|Medication": { + FromType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + EdgeLabel: "device_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|device_reference_Medication|BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + FromType: "Medication", + EdgeLabel: "device_reference_Medication", + ToType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark|device_reference_MedicationAdministration|MedicationAdministration": { + FromType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + EdgeLabel: "device_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|device_reference_MedicationAdministration|BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_MedicationAdministration", + ToType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark|device_reference_MedicationStatement|MedicationStatement": { + FromType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + EdgeLabel: "device_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|device_reference_MedicationStatement|BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + FromType: "MedicationStatement", + EdgeLabel: "device_reference_MedicationStatement", + ToType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark|device_reference_MedicationRequest|MedicationRequest": { + FromType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + EdgeLabel: "device_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|device_reference_MedicationRequest|BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_MedicationRequest", + ToType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark|device_reference_Procedure|Procedure": { + FromType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + EdgeLabel: "device_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|device_reference_Procedure|BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + FromType: "Procedure", + EdgeLabel: "device_reference_Procedure", + ToType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark|device_reference_DocumentReference|DocumentReference": { + FromType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + EdgeLabel: "device_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|device_reference_DocumentReference|BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + FromType: "DocumentReference", + EdgeLabel: "device_reference_DocumentReference", + ToType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark|device_reference_Task|Task": { + FromType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + EdgeLabel: "device_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|device_reference_Task|BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + FromType: "Task", + EdgeLabel: "device_reference_Task", + ToType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark|device_reference_ImagingStudy|ImagingStudy": { + FromType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + EdgeLabel: "device_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|device_reference_ImagingStudy|BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + FromType: "ImagingStudy", + EdgeLabel: "device_reference_ImagingStudy", + ToType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark|device_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + EdgeLabel: "device_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|device_reference_FamilyMemberHistory|BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + FromType: "FamilyMemberHistory", + EdgeLabel: "device_reference_FamilyMemberHistory", + ToType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark|device_reference_BodyStructure|BodyStructure": { + FromType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + EdgeLabel: "device_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|device_reference_BodyStructure|BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + FromType: "BodyStructure", + EdgeLabel: "device_reference_BodyStructure", + ToType: "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "CodeableReference|reference_Organization|Organization": { + FromType: "CodeableReference", + EdgeLabel: "reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|reference_Organization|CodeableReference": { + FromType: "Organization", + EdgeLabel: "reference_Organization", + ToType: "CodeableReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "CodeableReference|reference_Group|Group": { + FromType: "CodeableReference", + EdgeLabel: "reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|reference_Group|CodeableReference": { + FromType: "Group", + EdgeLabel: "reference_Group", + ToType: "CodeableReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "CodeableReference|reference_Practitioner|Practitioner": { + FromType: "CodeableReference", + EdgeLabel: "reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|reference_Practitioner|CodeableReference": { + FromType: "Practitioner", + EdgeLabel: "reference_Practitioner", + ToType: "CodeableReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "CodeableReference|reference_PractitionerRole|PractitionerRole": { + FromType: "CodeableReference", + EdgeLabel: "reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|reference_PractitionerRole|CodeableReference": { + FromType: "PractitionerRole", + EdgeLabel: "reference_PractitionerRole", + ToType: "CodeableReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "CodeableReference|reference_ResearchStudy|ResearchStudy": { + FromType: "CodeableReference", + EdgeLabel: "reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|reference_ResearchStudy|CodeableReference": { + FromType: "ResearchStudy", + EdgeLabel: "reference_ResearchStudy", + ToType: "CodeableReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "CodeableReference|reference_Patient|Patient": { + FromType: "CodeableReference", + EdgeLabel: "reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|reference_Patient|CodeableReference": { + FromType: "Patient", + EdgeLabel: "reference_Patient", + ToType: "CodeableReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "CodeableReference|reference_ResearchSubject|ResearchSubject": { + FromType: "CodeableReference", + EdgeLabel: "reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|reference_ResearchSubject|CodeableReference": { + FromType: "ResearchSubject", + EdgeLabel: "reference_ResearchSubject", + ToType: "CodeableReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "CodeableReference|reference_Substance|Substance": { + FromType: "CodeableReference", + EdgeLabel: "reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|reference_Substance|CodeableReference": { + FromType: "Substance", + EdgeLabel: "reference_Substance", + ToType: "CodeableReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "CodeableReference|reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "CodeableReference", + EdgeLabel: "reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|reference_SubstanceDefinition|CodeableReference": { + FromType: "SubstanceDefinition", + EdgeLabel: "reference_SubstanceDefinition", + ToType: "CodeableReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "CodeableReference|reference_Specimen|Specimen": { + FromType: "CodeableReference", + EdgeLabel: "reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|reference_Specimen|CodeableReference": { + FromType: "Specimen", + EdgeLabel: "reference_Specimen", + ToType: "CodeableReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "CodeableReference|reference_Observation|Observation": { + FromType: "CodeableReference", + EdgeLabel: "reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|reference_Observation|CodeableReference": { + FromType: "Observation", + EdgeLabel: "reference_Observation", + ToType: "CodeableReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "CodeableReference|reference_DiagnosticReport|DiagnosticReport": { + FromType: "CodeableReference", + EdgeLabel: "reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|reference_DiagnosticReport|CodeableReference": { + FromType: "DiagnosticReport", + EdgeLabel: "reference_DiagnosticReport", + ToType: "CodeableReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "CodeableReference|reference_Condition|Condition": { + FromType: "CodeableReference", + EdgeLabel: "reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|reference_Condition|CodeableReference": { + FromType: "Condition", + EdgeLabel: "reference_Condition", + ToType: "CodeableReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "CodeableReference|reference_Medication|Medication": { + FromType: "CodeableReference", + EdgeLabel: "reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|reference_Medication|CodeableReference": { + FromType: "Medication", + EdgeLabel: "reference_Medication", + ToType: "CodeableReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "CodeableReference|reference_MedicationAdministration|MedicationAdministration": { + FromType: "CodeableReference", + EdgeLabel: "reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|reference_MedicationAdministration|CodeableReference": { + FromType: "MedicationAdministration", + EdgeLabel: "reference_MedicationAdministration", + ToType: "CodeableReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "CodeableReference|reference_MedicationStatement|MedicationStatement": { + FromType: "CodeableReference", + EdgeLabel: "reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|reference_MedicationStatement|CodeableReference": { + FromType: "MedicationStatement", + EdgeLabel: "reference_MedicationStatement", + ToType: "CodeableReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "CodeableReference|reference_MedicationRequest|MedicationRequest": { + FromType: "CodeableReference", + EdgeLabel: "reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|reference_MedicationRequest|CodeableReference": { + FromType: "MedicationRequest", + EdgeLabel: "reference_MedicationRequest", + ToType: "CodeableReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "CodeableReference|reference_Procedure|Procedure": { + FromType: "CodeableReference", + EdgeLabel: "reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|reference_Procedure|CodeableReference": { + FromType: "Procedure", + EdgeLabel: "reference_Procedure", + ToType: "CodeableReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "CodeableReference|reference_DocumentReference|DocumentReference": { + FromType: "CodeableReference", + EdgeLabel: "reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|reference_DocumentReference|CodeableReference": { + FromType: "DocumentReference", + EdgeLabel: "reference_DocumentReference", + ToType: "CodeableReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "CodeableReference|reference_Task|Task": { + FromType: "CodeableReference", + EdgeLabel: "reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|reference_Task|CodeableReference": { + FromType: "Task", + EdgeLabel: "reference_Task", + ToType: "CodeableReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "CodeableReference|reference_ImagingStudy|ImagingStudy": { + FromType: "CodeableReference", + EdgeLabel: "reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|reference_ImagingStudy|CodeableReference": { + FromType: "ImagingStudy", + EdgeLabel: "reference_ImagingStudy", + ToType: "CodeableReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "CodeableReference|reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "CodeableReference", + EdgeLabel: "reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|reference_FamilyMemberHistory|CodeableReference": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reference_FamilyMemberHistory", + ToType: "CodeableReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "CodeableReference|reference_BodyStructure|BodyStructure": { + FromType: "CodeableReference", + EdgeLabel: "reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|reference_BodyStructure|CodeableReference": { + FromType: "BodyStructure", + EdgeLabel: "reference_BodyStructure", + ToType: "CodeableReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "Condition|subject_Patient|Patient": { + FromType: "Condition", + EdgeLabel: "subject_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "condition", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|subject_Patient|Condition": { + FromType: "Patient", + EdgeLabel: "subject_Patient", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "condition", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Condition|subject_Group|Group": { + FromType: "Condition", + EdgeLabel: "subject_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "condition", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|subject_Group|Condition": { + FromType: "Group", + EdgeLabel: "subject_Group", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "condition", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Condition|evidence_reference_Organization|Organization": { + FromType: "Condition", + EdgeLabel: "evidence_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|evidence_reference_Organization|Condition": { + FromType: "Organization", + EdgeLabel: "evidence_reference_Organization", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Condition|evidence_reference_Group|Group": { + FromType: "Condition", + EdgeLabel: "evidence_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|evidence_reference_Group|Condition": { + FromType: "Group", + EdgeLabel: "evidence_reference_Group", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Condition|evidence_reference_Practitioner|Practitioner": { + FromType: "Condition", + EdgeLabel: "evidence_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|evidence_reference_Practitioner|Condition": { + FromType: "Practitioner", + EdgeLabel: "evidence_reference_Practitioner", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Condition|evidence_reference_PractitionerRole|PractitionerRole": { + FromType: "Condition", + EdgeLabel: "evidence_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|evidence_reference_PractitionerRole|Condition": { + FromType: "PractitionerRole", + EdgeLabel: "evidence_reference_PractitionerRole", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Condition|evidence_reference_ResearchStudy|ResearchStudy": { + FromType: "Condition", + EdgeLabel: "evidence_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|evidence_reference_ResearchStudy|Condition": { + FromType: "ResearchStudy", + EdgeLabel: "evidence_reference_ResearchStudy", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "Condition|evidence_reference_Patient|Patient": { + FromType: "Condition", + EdgeLabel: "evidence_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|evidence_reference_Patient|Condition": { + FromType: "Patient", + EdgeLabel: "evidence_reference_Patient", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Condition|evidence_reference_ResearchSubject|ResearchSubject": { + FromType: "Condition", + EdgeLabel: "evidence_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|evidence_reference_ResearchSubject|Condition": { + FromType: "ResearchSubject", + EdgeLabel: "evidence_reference_ResearchSubject", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "Condition|evidence_reference_Substance|Substance": { + FromType: "Condition", + EdgeLabel: "evidence_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|evidence_reference_Substance|Condition": { + FromType: "Substance", + EdgeLabel: "evidence_reference_Substance", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Condition|evidence_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "Condition", + EdgeLabel: "evidence_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|evidence_reference_SubstanceDefinition|Condition": { + FromType: "SubstanceDefinition", + EdgeLabel: "evidence_reference_SubstanceDefinition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "Condition|evidence_reference_Specimen|Specimen": { + FromType: "Condition", + EdgeLabel: "evidence_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|evidence_reference_Specimen|Condition": { + FromType: "Specimen", + EdgeLabel: "evidence_reference_Specimen", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Condition|evidence_reference_Observation|Observation": { + FromType: "Condition", + EdgeLabel: "evidence_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|evidence_reference_Observation|Condition": { + FromType: "Observation", + EdgeLabel: "evidence_reference_Observation", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Condition|evidence_reference_DiagnosticReport|DiagnosticReport": { + FromType: "Condition", + EdgeLabel: "evidence_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|evidence_reference_DiagnosticReport|Condition": { + FromType: "DiagnosticReport", + EdgeLabel: "evidence_reference_DiagnosticReport", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "Condition|evidence_reference_Condition|Condition": { + FromType: "Condition", + EdgeLabel: "evidence_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|evidence_reference_Medication|Medication": { + FromType: "Condition", + EdgeLabel: "evidence_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|evidence_reference_Medication|Condition": { + FromType: "Medication", + EdgeLabel: "evidence_reference_Medication", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Condition|evidence_reference_MedicationAdministration|MedicationAdministration": { + FromType: "Condition", + EdgeLabel: "evidence_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|evidence_reference_MedicationAdministration|Condition": { + FromType: "MedicationAdministration", + EdgeLabel: "evidence_reference_MedicationAdministration", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "Condition|evidence_reference_MedicationStatement|MedicationStatement": { + FromType: "Condition", + EdgeLabel: "evidence_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|evidence_reference_MedicationStatement|Condition": { + FromType: "MedicationStatement", + EdgeLabel: "evidence_reference_MedicationStatement", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "Condition|evidence_reference_MedicationRequest|MedicationRequest": { + FromType: "Condition", + EdgeLabel: "evidence_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|evidence_reference_MedicationRequest|Condition": { + FromType: "MedicationRequest", + EdgeLabel: "evidence_reference_MedicationRequest", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "Condition|evidence_reference_Procedure|Procedure": { + FromType: "Condition", + EdgeLabel: "evidence_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|evidence_reference_Procedure|Condition": { + FromType: "Procedure", + EdgeLabel: "evidence_reference_Procedure", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Condition|evidence_reference_DocumentReference|DocumentReference": { + FromType: "Condition", + EdgeLabel: "evidence_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|evidence_reference_DocumentReference|Condition": { + FromType: "DocumentReference", + EdgeLabel: "evidence_reference_DocumentReference", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "Condition|evidence_reference_Task|Task": { + FromType: "Condition", + EdgeLabel: "evidence_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|evidence_reference_Task|Condition": { + FromType: "Task", + EdgeLabel: "evidence_reference_Task", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Condition|evidence_reference_ImagingStudy|ImagingStudy": { + FromType: "Condition", + EdgeLabel: "evidence_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|evidence_reference_ImagingStudy|Condition": { + FromType: "ImagingStudy", + EdgeLabel: "evidence_reference_ImagingStudy", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "Condition|evidence_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "Condition", + EdgeLabel: "evidence_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|evidence_reference_FamilyMemberHistory|Condition": { + FromType: "FamilyMemberHistory", + EdgeLabel: "evidence_reference_FamilyMemberHistory", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "Condition|evidence_reference_BodyStructure|BodyStructure": { + FromType: "Condition", + EdgeLabel: "evidence_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|evidence_reference_BodyStructure|Condition": { + FromType: "BodyStructure", + EdgeLabel: "evidence_reference_BodyStructure", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "Condition|note_authorReference_Practitioner|Practitioner": { + FromType: "Condition", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|note_authorReference_Practitioner|Condition": { + FromType: "Practitioner", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Condition|note_authorReference_PractitionerRole|PractitionerRole": { + FromType: "Condition", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|note_authorReference_PractitionerRole|Condition": { + FromType: "PractitionerRole", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Condition|note_authorReference_Patient|Patient": { + FromType: "Condition", + EdgeLabel: "note_authorReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|note_authorReference_Patient|Condition": { + FromType: "Patient", + EdgeLabel: "note_authorReference_Patient", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Condition|note_authorReference_Organization|Organization": { + FromType: "Condition", + EdgeLabel: "note_authorReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|note_authorReference_Organization|Condition": { + FromType: "Organization", + EdgeLabel: "note_authorReference_Organization", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Condition|participant_actor_Practitioner|Practitioner": { + FromType: "Condition", + EdgeLabel: "participant_actor_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "condition_participant", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|participant_actor_Practitioner|Condition": { + FromType: "Practitioner", + EdgeLabel: "participant_actor_Practitioner", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "condition_participant", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Condition|participant_actor_PractitionerRole|PractitionerRole": { + FromType: "Condition", + EdgeLabel: "participant_actor_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "condition_participant", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|participant_actor_PractitionerRole|Condition": { + FromType: "PractitionerRole", + EdgeLabel: "participant_actor_PractitionerRole", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "condition_participant", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Condition|participant_actor_Patient|Patient": { + FromType: "Condition", + EdgeLabel: "participant_actor_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "condition_participant", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|participant_actor_Patient|Condition": { + FromType: "Patient", + EdgeLabel: "participant_actor_Patient", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "condition_participant", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Condition|participant_actor_Organization|Organization": { + FromType: "Condition", + EdgeLabel: "participant_actor_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "condition_participant", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|participant_actor_Organization|Condition": { + FromType: "Organization", + EdgeLabel: "participant_actor_Organization", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "condition_participant", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Condition|stage_assessment_DiagnosticReport|DiagnosticReport": { + FromType: "Condition", + EdgeLabel: "stage_assessment_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "assessment_condition_stage", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|stage_assessment_DiagnosticReport|Condition": { + FromType: "DiagnosticReport", + EdgeLabel: "stage_assessment_DiagnosticReport", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "assessment_condition_stage", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "Condition|stage_assessment_Observation|Observation": { + FromType: "Condition", + EdgeLabel: "stage_assessment_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "assessment_condition_stage", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|stage_assessment_Observation|Condition": { + FromType: "Observation", + EdgeLabel: "stage_assessment_Observation", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "assessment_condition_stage", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "ConditionParticipant|actor_Practitioner|Practitioner": { + FromType: "ConditionParticipant", + EdgeLabel: "actor_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "condition_participant", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|actor_Practitioner|ConditionParticipant": { + FromType: "Practitioner", + EdgeLabel: "actor_Practitioner", + ToType: "ConditionParticipant", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "condition_participant", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "ConditionParticipant|actor_PractitionerRole|PractitionerRole": { + FromType: "ConditionParticipant", + EdgeLabel: "actor_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "condition_participant", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|actor_PractitionerRole|ConditionParticipant": { + FromType: "PractitionerRole", + EdgeLabel: "actor_PractitionerRole", + ToType: "ConditionParticipant", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "condition_participant", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "ConditionParticipant|actor_Patient|Patient": { + FromType: "ConditionParticipant", + EdgeLabel: "actor_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "condition_participant", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|actor_Patient|ConditionParticipant": { + FromType: "Patient", + EdgeLabel: "actor_Patient", + ToType: "ConditionParticipant", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "condition_participant", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "ConditionParticipant|actor_Organization|Organization": { + FromType: "ConditionParticipant", + EdgeLabel: "actor_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "condition_participant", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|actor_Organization|ConditionParticipant": { + FromType: "Organization", + EdgeLabel: "actor_Organization", + ToType: "ConditionParticipant", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "condition_participant", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "ConditionStage|assessment_DiagnosticReport|DiagnosticReport": { + FromType: "ConditionStage", + EdgeLabel: "assessment_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "assessment_condition_stage", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|assessment_DiagnosticReport|ConditionStage": { + FromType: "DiagnosticReport", + EdgeLabel: "assessment_DiagnosticReport", + ToType: "ConditionStage", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "assessment_condition_stage", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "ConditionStage|assessment_Observation|Observation": { + FromType: "ConditionStage", + EdgeLabel: "assessment_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "assessment_condition_stage", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|assessment_Observation|ConditionStage": { + FromType: "Observation", + EdgeLabel: "assessment_Observation", + ToType: "ConditionStage", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "assessment_condition_stage", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "DataRequirement|subjectReference|Group": { + FromType: "DataRequirement", + EdgeLabel: "subjectReference", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "data_requirement", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|subjectReference|DataRequirement": { + FromType: "Group", + EdgeLabel: "subjectReference", + ToType: "DataRequirement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "data_requirement", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "DiagnosticReport|basedOn_MedicationRequest|MedicationRequest": { + FromType: "DiagnosticReport", + EdgeLabel: "basedOn_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_diagnostic_report", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|basedOn_MedicationRequest|DiagnosticReport": { + FromType: "MedicationRequest", + EdgeLabel: "basedOn_MedicationRequest", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_diagnostic_report", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "DiagnosticReport|performer_Practitioner|Practitioner": { + FromType: "DiagnosticReport", + EdgeLabel: "performer_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "performer_diagnostic_report", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|performer_Practitioner|DiagnosticReport": { + FromType: "Practitioner", + EdgeLabel: "performer_Practitioner", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "performer_diagnostic_report", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "DiagnosticReport|performer_PractitionerRole|PractitionerRole": { + FromType: "DiagnosticReport", + EdgeLabel: "performer_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "performer_diagnostic_report", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|performer_PractitionerRole|DiagnosticReport": { + FromType: "PractitionerRole", + EdgeLabel: "performer_PractitionerRole", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "performer_diagnostic_report", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "DiagnosticReport|performer_Organization|Organization": { + FromType: "DiagnosticReport", + EdgeLabel: "performer_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "performer_diagnostic_report", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|performer_Organization|DiagnosticReport": { + FromType: "Organization", + EdgeLabel: "performer_Organization", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "performer_diagnostic_report", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "DiagnosticReport|result|Observation": { + FromType: "DiagnosticReport", + EdgeLabel: "result", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "result_diagnostic_report", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|result|DiagnosticReport": { + FromType: "Observation", + EdgeLabel: "result", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "result_diagnostic_report", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "DiagnosticReport|resultsInterpreter_Practitioner|Practitioner": { + FromType: "DiagnosticReport", + EdgeLabel: "resultsInterpreter_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "resultsInterpreter_diagnostic_report", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|resultsInterpreter_Practitioner|DiagnosticReport": { + FromType: "Practitioner", + EdgeLabel: "resultsInterpreter_Practitioner", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "resultsInterpreter_diagnostic_report", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "DiagnosticReport|resultsInterpreter_PractitionerRole|PractitionerRole": { + FromType: "DiagnosticReport", + EdgeLabel: "resultsInterpreter_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "resultsInterpreter_diagnostic_report", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|resultsInterpreter_PractitionerRole|DiagnosticReport": { + FromType: "PractitionerRole", + EdgeLabel: "resultsInterpreter_PractitionerRole", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "resultsInterpreter_diagnostic_report", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "DiagnosticReport|resultsInterpreter_Organization|Organization": { + FromType: "DiagnosticReport", + EdgeLabel: "resultsInterpreter_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "resultsInterpreter_diagnostic_report", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|resultsInterpreter_Organization|DiagnosticReport": { + FromType: "Organization", + EdgeLabel: "resultsInterpreter_Organization", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "resultsInterpreter_diagnostic_report", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "DiagnosticReport|specimen|Specimen": { + FromType: "DiagnosticReport", + EdgeLabel: "specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "specimen_diagnostic_report", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|specimen|DiagnosticReport": { + FromType: "Specimen", + EdgeLabel: "specimen", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "specimen_diagnostic_report", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "DiagnosticReport|study_ImagingStudy|ImagingStudy": { + FromType: "DiagnosticReport", + EdgeLabel: "study_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "study_diagnostic_report", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|study_ImagingStudy|DiagnosticReport": { + FromType: "ImagingStudy", + EdgeLabel: "study_ImagingStudy", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "study_diagnostic_report", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "DiagnosticReport|subject_Patient|Patient": { + FromType: "DiagnosticReport", + EdgeLabel: "subject_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_diagnostic_report", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|subject_Patient|DiagnosticReport": { + FromType: "Patient", + EdgeLabel: "subject_Patient", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_diagnostic_report", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "DiagnosticReport|subject_Group|Group": { + FromType: "DiagnosticReport", + EdgeLabel: "subject_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_diagnostic_report", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|subject_Group|DiagnosticReport": { + FromType: "Group", + EdgeLabel: "subject_Group", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_diagnostic_report", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "DiagnosticReport|subject_Organization|Organization": { + FromType: "DiagnosticReport", + EdgeLabel: "subject_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_diagnostic_report", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|subject_Organization|DiagnosticReport": { + FromType: "Organization", + EdgeLabel: "subject_Organization", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_diagnostic_report", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "DiagnosticReport|subject_Practitioner|Practitioner": { + FromType: "DiagnosticReport", + EdgeLabel: "subject_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_diagnostic_report", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|subject_Practitioner|DiagnosticReport": { + FromType: "Practitioner", + EdgeLabel: "subject_Practitioner", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_diagnostic_report", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "DiagnosticReport|subject_Medication|Medication": { + FromType: "DiagnosticReport", + EdgeLabel: "subject_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_diagnostic_report", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|subject_Medication|DiagnosticReport": { + FromType: "Medication", + EdgeLabel: "subject_Medication", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_diagnostic_report", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "DiagnosticReport|subject_Substance|Substance": { + FromType: "DiagnosticReport", + EdgeLabel: "subject_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_diagnostic_report", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|subject_Substance|DiagnosticReport": { + FromType: "Substance", + EdgeLabel: "subject_Substance", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_diagnostic_report", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "DiagnosticReport|media_link|DocumentReference": { + FromType: "DiagnosticReport", + EdgeLabel: "media_link", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "diagnostic_report_media", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|media_link|DiagnosticReport": { + FromType: "DocumentReference", + EdgeLabel: "media_link", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "diagnostic_report_media", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DiagnosticReport|note_authorReference_Practitioner|Practitioner": { + FromType: "DiagnosticReport", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|note_authorReference_Practitioner|DiagnosticReport": { + FromType: "Practitioner", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "DiagnosticReport|note_authorReference_PractitionerRole|PractitionerRole": { + FromType: "DiagnosticReport", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|note_authorReference_PractitionerRole|DiagnosticReport": { + FromType: "PractitionerRole", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "DiagnosticReport|note_authorReference_Patient|Patient": { + FromType: "DiagnosticReport", + EdgeLabel: "note_authorReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|note_authorReference_Patient|DiagnosticReport": { + FromType: "Patient", + EdgeLabel: "note_authorReference_Patient", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "DiagnosticReport|note_authorReference_Organization|Organization": { + FromType: "DiagnosticReport", + EdgeLabel: "note_authorReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|note_authorReference_Organization|DiagnosticReport": { + FromType: "Organization", + EdgeLabel: "note_authorReference_Organization", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "DiagnosticReport|supportingInfo_reference_Procedure|Procedure": { + FromType: "DiagnosticReport", + EdgeLabel: "supportingInfo_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "diagnostic_report_supporting_info", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|supportingInfo_reference_Procedure|DiagnosticReport": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_reference_Procedure", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "diagnostic_report_supporting_info", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "DiagnosticReport|supportingInfo_reference_Observation|Observation": { + FromType: "DiagnosticReport", + EdgeLabel: "supportingInfo_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "diagnostic_report_supporting_info", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|supportingInfo_reference_Observation|DiagnosticReport": { + FromType: "Observation", + EdgeLabel: "supportingInfo_reference_Observation", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "diagnostic_report_supporting_info", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "DiagnosticReport|supportingInfo_reference_DiagnosticReport|DiagnosticReport": { + FromType: "DiagnosticReport", + EdgeLabel: "supportingInfo_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "diagnostic_report_supporting_info", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReportMedia|link|DocumentReference": { + FromType: "DiagnosticReportMedia", + EdgeLabel: "link", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "diagnostic_report_media", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|link|DiagnosticReportMedia": { + FromType: "DocumentReference", + EdgeLabel: "link", + ToType: "DiagnosticReportMedia", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "diagnostic_report_media", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DiagnosticReportSupportingInfo|reference_Procedure|Procedure": { + FromType: "DiagnosticReportSupportingInfo", + EdgeLabel: "reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "diagnostic_report_supporting_info", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|reference_Procedure|DiagnosticReportSupportingInfo": { + FromType: "Procedure", + EdgeLabel: "reference_Procedure", + ToType: "DiagnosticReportSupportingInfo", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "diagnostic_report_supporting_info", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "DiagnosticReportSupportingInfo|reference_Observation|Observation": { + FromType: "DiagnosticReportSupportingInfo", + EdgeLabel: "reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "diagnostic_report_supporting_info", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|reference_Observation|DiagnosticReportSupportingInfo": { + FromType: "Observation", + EdgeLabel: "reference_Observation", + ToType: "DiagnosticReportSupportingInfo", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "diagnostic_report_supporting_info", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "DiagnosticReportSupportingInfo|reference_DiagnosticReport|DiagnosticReport": { + FromType: "DiagnosticReportSupportingInfo", + EdgeLabel: "reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "diagnostic_report_supporting_info", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|reference_DiagnosticReport|DiagnosticReportSupportingInfo": { + FromType: "DiagnosticReport", + EdgeLabel: "reference_DiagnosticReport", + ToType: "DiagnosticReportSupportingInfo", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "diagnostic_report_supporting_info", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "Directory|child_Directory|Directory": { + FromType: "Directory", + EdgeLabel: "child_Directory", + ToType: "Directory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{}, + RegexMatch: []string{ + "Directory/*", + }, + }, + "Directory|child_DocumentReference|DocumentReference": { + FromType: "Directory", + EdgeLabel: "child_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{}, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|child_DocumentReference|Directory": { + FromType: "DocumentReference", + EdgeLabel: "child_DocumentReference", + ToType: "Directory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{}, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|author_Practitioner|Practitioner": { + FromType: "DocumentReference", + EdgeLabel: "author_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "author_document_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|author_Practitioner|DocumentReference": { + FromType: "Practitioner", + EdgeLabel: "author_Practitioner", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "author_document_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "DocumentReference|author_PractitionerRole|PractitionerRole": { + FromType: "DocumentReference", + EdgeLabel: "author_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "author_document_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|author_PractitionerRole|DocumentReference": { + FromType: "PractitionerRole", + EdgeLabel: "author_PractitionerRole", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "author_document_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "DocumentReference|author_Organization|Organization": { + FromType: "DocumentReference", + EdgeLabel: "author_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "author_document_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|author_Organization|DocumentReference": { + FromType: "Organization", + EdgeLabel: "author_Organization", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "author_document_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "DocumentReference|author_Patient|Patient": { + FromType: "DocumentReference", + EdgeLabel: "author_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "author_document_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|author_Patient|DocumentReference": { + FromType: "Patient", + EdgeLabel: "author_Patient", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "author_document_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "DocumentReference|basedOn_MedicationRequest|MedicationRequest": { + FromType: "DocumentReference", + EdgeLabel: "basedOn_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_document_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|basedOn_MedicationRequest|DocumentReference": { + FromType: "MedicationRequest", + EdgeLabel: "basedOn_MedicationRequest", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_document_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "DocumentReference|custodian|Organization": { + FromType: "DocumentReference", + EdgeLabel: "custodian", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "custodian_document_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|custodian|DocumentReference": { + FromType: "Organization", + EdgeLabel: "custodian", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "custodian_document_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "DocumentReference|subject_Organization|Organization": { + FromType: "DocumentReference", + EdgeLabel: "subject_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|subject_Organization|DocumentReference": { + FromType: "Organization", + EdgeLabel: "subject_Organization", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "DocumentReference|subject_Group|Group": { + FromType: "DocumentReference", + EdgeLabel: "subject_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|subject_Group|DocumentReference": { + FromType: "Group", + EdgeLabel: "subject_Group", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "DocumentReference|subject_Practitioner|Practitioner": { + FromType: "DocumentReference", + EdgeLabel: "subject_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|subject_Practitioner|DocumentReference": { + FromType: "Practitioner", + EdgeLabel: "subject_Practitioner", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "DocumentReference|subject_PractitionerRole|PractitionerRole": { + FromType: "DocumentReference", + EdgeLabel: "subject_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|subject_PractitionerRole|DocumentReference": { + FromType: "PractitionerRole", + EdgeLabel: "subject_PractitionerRole", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "DocumentReference|subject_ResearchStudy|ResearchStudy": { + FromType: "DocumentReference", + EdgeLabel: "subject_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|subject_ResearchStudy|DocumentReference": { + FromType: "ResearchStudy", + EdgeLabel: "subject_ResearchStudy", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "DocumentReference|subject_Patient|Patient": { + FromType: "DocumentReference", + EdgeLabel: "subject_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|subject_Patient|DocumentReference": { + FromType: "Patient", + EdgeLabel: "subject_Patient", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "DocumentReference|subject_ResearchSubject|ResearchSubject": { + FromType: "DocumentReference", + EdgeLabel: "subject_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|subject_ResearchSubject|DocumentReference": { + FromType: "ResearchSubject", + EdgeLabel: "subject_ResearchSubject", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "DocumentReference|subject_Substance|Substance": { + FromType: "DocumentReference", + EdgeLabel: "subject_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|subject_Substance|DocumentReference": { + FromType: "Substance", + EdgeLabel: "subject_Substance", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "DocumentReference|subject_SubstanceDefinition|SubstanceDefinition": { + FromType: "DocumentReference", + EdgeLabel: "subject_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|subject_SubstanceDefinition|DocumentReference": { + FromType: "SubstanceDefinition", + EdgeLabel: "subject_SubstanceDefinition", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "DocumentReference|subject_Specimen|Specimen": { + FromType: "DocumentReference", + EdgeLabel: "subject_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|subject_Specimen|DocumentReference": { + FromType: "Specimen", + EdgeLabel: "subject_Specimen", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "DocumentReference|subject_Observation|Observation": { + FromType: "DocumentReference", + EdgeLabel: "subject_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|subject_Observation|DocumentReference": { + FromType: "Observation", + EdgeLabel: "subject_Observation", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "DocumentReference|subject_DiagnosticReport|DiagnosticReport": { + FromType: "DocumentReference", + EdgeLabel: "subject_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|subject_DiagnosticReport|DocumentReference": { + FromType: "DiagnosticReport", + EdgeLabel: "subject_DiagnosticReport", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DocumentReference|subject_Condition|Condition": { + FromType: "DocumentReference", + EdgeLabel: "subject_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|subject_Condition|DocumentReference": { + FromType: "Condition", + EdgeLabel: "subject_Condition", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "DocumentReference|subject_Medication|Medication": { + FromType: "DocumentReference", + EdgeLabel: "subject_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|subject_Medication|DocumentReference": { + FromType: "Medication", + EdgeLabel: "subject_Medication", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "DocumentReference|subject_MedicationAdministration|MedicationAdministration": { + FromType: "DocumentReference", + EdgeLabel: "subject_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|subject_MedicationAdministration|DocumentReference": { + FromType: "MedicationAdministration", + EdgeLabel: "subject_MedicationAdministration", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "DocumentReference|subject_MedicationStatement|MedicationStatement": { + FromType: "DocumentReference", + EdgeLabel: "subject_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|subject_MedicationStatement|DocumentReference": { + FromType: "MedicationStatement", + EdgeLabel: "subject_MedicationStatement", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "DocumentReference|subject_MedicationRequest|MedicationRequest": { + FromType: "DocumentReference", + EdgeLabel: "subject_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|subject_MedicationRequest|DocumentReference": { + FromType: "MedicationRequest", + EdgeLabel: "subject_MedicationRequest", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "DocumentReference|subject_Procedure|Procedure": { + FromType: "DocumentReference", + EdgeLabel: "subject_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|subject_Procedure|DocumentReference": { + FromType: "Procedure", + EdgeLabel: "subject_Procedure", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "DocumentReference|subject_DocumentReference|DocumentReference": { + FromType: "DocumentReference", + EdgeLabel: "subject_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|subject_Task|Task": { + FromType: "DocumentReference", + EdgeLabel: "subject_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|subject_Task|DocumentReference": { + FromType: "Task", + EdgeLabel: "subject_Task", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "DocumentReference|subject_ImagingStudy|ImagingStudy": { + FromType: "DocumentReference", + EdgeLabel: "subject_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|subject_ImagingStudy|DocumentReference": { + FromType: "ImagingStudy", + EdgeLabel: "subject_ImagingStudy", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "DocumentReference|subject_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "DocumentReference", + EdgeLabel: "subject_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|subject_FamilyMemberHistory|DocumentReference": { + FromType: "FamilyMemberHistory", + EdgeLabel: "subject_FamilyMemberHistory", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "DocumentReference|subject_BodyStructure|BodyStructure": { + FromType: "DocumentReference", + EdgeLabel: "subject_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|subject_BodyStructure|DocumentReference": { + FromType: "BodyStructure", + EdgeLabel: "subject_BodyStructure", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "DocumentReference|attester_party_Patient|Patient": { + FromType: "DocumentReference", + EdgeLabel: "attester_party_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference_attester", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|attester_party_Patient|DocumentReference": { + FromType: "Patient", + EdgeLabel: "attester_party_Patient", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference_attester", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "DocumentReference|attester_party_Practitioner|Practitioner": { + FromType: "DocumentReference", + EdgeLabel: "attester_party_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference_attester", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|attester_party_Practitioner|DocumentReference": { + FromType: "Practitioner", + EdgeLabel: "attester_party_Practitioner", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference_attester", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "DocumentReference|attester_party_PractitionerRole|PractitionerRole": { + FromType: "DocumentReference", + EdgeLabel: "attester_party_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference_attester", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|attester_party_PractitionerRole|DocumentReference": { + FromType: "PractitionerRole", + EdgeLabel: "attester_party_PractitionerRole", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference_attester", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "DocumentReference|attester_party_Organization|Organization": { + FromType: "DocumentReference", + EdgeLabel: "attester_party_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference_attester", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|attester_party_Organization|DocumentReference": { + FromType: "Organization", + EdgeLabel: "attester_party_Organization", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference_attester", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "DocumentReference|bodySite_reference_Organization|Organization": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|bodySite_reference_Organization|DocumentReference": { + FromType: "Organization", + EdgeLabel: "bodySite_reference_Organization", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "DocumentReference|bodySite_reference_Group|Group": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|bodySite_reference_Group|DocumentReference": { + FromType: "Group", + EdgeLabel: "bodySite_reference_Group", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "DocumentReference|bodySite_reference_Practitioner|Practitioner": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|bodySite_reference_Practitioner|DocumentReference": { + FromType: "Practitioner", + EdgeLabel: "bodySite_reference_Practitioner", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "DocumentReference|bodySite_reference_PractitionerRole|PractitionerRole": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|bodySite_reference_PractitionerRole|DocumentReference": { + FromType: "PractitionerRole", + EdgeLabel: "bodySite_reference_PractitionerRole", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "DocumentReference|bodySite_reference_ResearchStudy|ResearchStudy": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|bodySite_reference_ResearchStudy|DocumentReference": { + FromType: "ResearchStudy", + EdgeLabel: "bodySite_reference_ResearchStudy", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "DocumentReference|bodySite_reference_Patient|Patient": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|bodySite_reference_Patient|DocumentReference": { + FromType: "Patient", + EdgeLabel: "bodySite_reference_Patient", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "DocumentReference|bodySite_reference_ResearchSubject|ResearchSubject": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|bodySite_reference_ResearchSubject|DocumentReference": { + FromType: "ResearchSubject", + EdgeLabel: "bodySite_reference_ResearchSubject", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "DocumentReference|bodySite_reference_Substance|Substance": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|bodySite_reference_Substance|DocumentReference": { + FromType: "Substance", + EdgeLabel: "bodySite_reference_Substance", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "DocumentReference|bodySite_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|bodySite_reference_SubstanceDefinition|DocumentReference": { + FromType: "SubstanceDefinition", + EdgeLabel: "bodySite_reference_SubstanceDefinition", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "DocumentReference|bodySite_reference_Specimen|Specimen": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|bodySite_reference_Specimen|DocumentReference": { + FromType: "Specimen", + EdgeLabel: "bodySite_reference_Specimen", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "DocumentReference|bodySite_reference_Observation|Observation": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|bodySite_reference_Observation|DocumentReference": { + FromType: "Observation", + EdgeLabel: "bodySite_reference_Observation", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "DocumentReference|bodySite_reference_DiagnosticReport|DiagnosticReport": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|bodySite_reference_DiagnosticReport|DocumentReference": { + FromType: "DiagnosticReport", + EdgeLabel: "bodySite_reference_DiagnosticReport", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DocumentReference|bodySite_reference_Condition|Condition": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|bodySite_reference_Condition|DocumentReference": { + FromType: "Condition", + EdgeLabel: "bodySite_reference_Condition", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "DocumentReference|bodySite_reference_Medication|Medication": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|bodySite_reference_Medication|DocumentReference": { + FromType: "Medication", + EdgeLabel: "bodySite_reference_Medication", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "DocumentReference|bodySite_reference_MedicationAdministration|MedicationAdministration": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|bodySite_reference_MedicationAdministration|DocumentReference": { + FromType: "MedicationAdministration", + EdgeLabel: "bodySite_reference_MedicationAdministration", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "DocumentReference|bodySite_reference_MedicationStatement|MedicationStatement": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|bodySite_reference_MedicationStatement|DocumentReference": { + FromType: "MedicationStatement", + EdgeLabel: "bodySite_reference_MedicationStatement", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "DocumentReference|bodySite_reference_MedicationRequest|MedicationRequest": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|bodySite_reference_MedicationRequest|DocumentReference": { + FromType: "MedicationRequest", + EdgeLabel: "bodySite_reference_MedicationRequest", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "DocumentReference|bodySite_reference_Procedure|Procedure": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|bodySite_reference_Procedure|DocumentReference": { + FromType: "Procedure", + EdgeLabel: "bodySite_reference_Procedure", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "DocumentReference|bodySite_reference_DocumentReference|DocumentReference": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|bodySite_reference_Task|Task": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|bodySite_reference_Task|DocumentReference": { + FromType: "Task", + EdgeLabel: "bodySite_reference_Task", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "DocumentReference|bodySite_reference_ImagingStudy|ImagingStudy": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|bodySite_reference_ImagingStudy|DocumentReference": { + FromType: "ImagingStudy", + EdgeLabel: "bodySite_reference_ImagingStudy", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "DocumentReference|bodySite_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|bodySite_reference_FamilyMemberHistory|DocumentReference": { + FromType: "FamilyMemberHistory", + EdgeLabel: "bodySite_reference_FamilyMemberHistory", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "DocumentReference|bodySite_reference_BodyStructure|BodyStructure": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|bodySite_reference_BodyStructure|DocumentReference": { + FromType: "BodyStructure", + EdgeLabel: "bodySite_reference_BodyStructure", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "DocumentReference|event_reference_Organization|Organization": { + FromType: "DocumentReference", + EdgeLabel: "event_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|event_reference_Organization|DocumentReference": { + FromType: "Organization", + EdgeLabel: "event_reference_Organization", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "DocumentReference|event_reference_Group|Group": { + FromType: "DocumentReference", + EdgeLabel: "event_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|event_reference_Group|DocumentReference": { + FromType: "Group", + EdgeLabel: "event_reference_Group", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "DocumentReference|event_reference_Practitioner|Practitioner": { + FromType: "DocumentReference", + EdgeLabel: "event_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|event_reference_Practitioner|DocumentReference": { + FromType: "Practitioner", + EdgeLabel: "event_reference_Practitioner", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "DocumentReference|event_reference_PractitionerRole|PractitionerRole": { + FromType: "DocumentReference", + EdgeLabel: "event_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|event_reference_PractitionerRole|DocumentReference": { + FromType: "PractitionerRole", + EdgeLabel: "event_reference_PractitionerRole", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "DocumentReference|event_reference_ResearchStudy|ResearchStudy": { + FromType: "DocumentReference", + EdgeLabel: "event_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|event_reference_ResearchStudy|DocumentReference": { + FromType: "ResearchStudy", + EdgeLabel: "event_reference_ResearchStudy", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "DocumentReference|event_reference_Patient|Patient": { + FromType: "DocumentReference", + EdgeLabel: "event_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|event_reference_Patient|DocumentReference": { + FromType: "Patient", + EdgeLabel: "event_reference_Patient", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "DocumentReference|event_reference_ResearchSubject|ResearchSubject": { + FromType: "DocumentReference", + EdgeLabel: "event_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|event_reference_ResearchSubject|DocumentReference": { + FromType: "ResearchSubject", + EdgeLabel: "event_reference_ResearchSubject", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "DocumentReference|event_reference_Substance|Substance": { + FromType: "DocumentReference", + EdgeLabel: "event_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|event_reference_Substance|DocumentReference": { + FromType: "Substance", + EdgeLabel: "event_reference_Substance", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "DocumentReference|event_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "DocumentReference", + EdgeLabel: "event_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|event_reference_SubstanceDefinition|DocumentReference": { + FromType: "SubstanceDefinition", + EdgeLabel: "event_reference_SubstanceDefinition", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "DocumentReference|event_reference_Specimen|Specimen": { + FromType: "DocumentReference", + EdgeLabel: "event_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|event_reference_Specimen|DocumentReference": { + FromType: "Specimen", + EdgeLabel: "event_reference_Specimen", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "DocumentReference|event_reference_Observation|Observation": { + FromType: "DocumentReference", + EdgeLabel: "event_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|event_reference_Observation|DocumentReference": { + FromType: "Observation", + EdgeLabel: "event_reference_Observation", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "DocumentReference|event_reference_DiagnosticReport|DiagnosticReport": { + FromType: "DocumentReference", + EdgeLabel: "event_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|event_reference_DiagnosticReport|DocumentReference": { + FromType: "DiagnosticReport", + EdgeLabel: "event_reference_DiagnosticReport", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DocumentReference|event_reference_Condition|Condition": { + FromType: "DocumentReference", + EdgeLabel: "event_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|event_reference_Condition|DocumentReference": { + FromType: "Condition", + EdgeLabel: "event_reference_Condition", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "DocumentReference|event_reference_Medication|Medication": { + FromType: "DocumentReference", + EdgeLabel: "event_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|event_reference_Medication|DocumentReference": { + FromType: "Medication", + EdgeLabel: "event_reference_Medication", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "DocumentReference|event_reference_MedicationAdministration|MedicationAdministration": { + FromType: "DocumentReference", + EdgeLabel: "event_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|event_reference_MedicationAdministration|DocumentReference": { + FromType: "MedicationAdministration", + EdgeLabel: "event_reference_MedicationAdministration", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "DocumentReference|event_reference_MedicationStatement|MedicationStatement": { + FromType: "DocumentReference", + EdgeLabel: "event_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|event_reference_MedicationStatement|DocumentReference": { + FromType: "MedicationStatement", + EdgeLabel: "event_reference_MedicationStatement", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "DocumentReference|event_reference_MedicationRequest|MedicationRequest": { + FromType: "DocumentReference", + EdgeLabel: "event_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|event_reference_MedicationRequest|DocumentReference": { + FromType: "MedicationRequest", + EdgeLabel: "event_reference_MedicationRequest", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "DocumentReference|event_reference_Procedure|Procedure": { + FromType: "DocumentReference", + EdgeLabel: "event_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|event_reference_Procedure|DocumentReference": { + FromType: "Procedure", + EdgeLabel: "event_reference_Procedure", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "DocumentReference|event_reference_DocumentReference|DocumentReference": { + FromType: "DocumentReference", + EdgeLabel: "event_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|event_reference_Task|Task": { + FromType: "DocumentReference", + EdgeLabel: "event_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|event_reference_Task|DocumentReference": { + FromType: "Task", + EdgeLabel: "event_reference_Task", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "DocumentReference|event_reference_ImagingStudy|ImagingStudy": { + FromType: "DocumentReference", + EdgeLabel: "event_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|event_reference_ImagingStudy|DocumentReference": { + FromType: "ImagingStudy", + EdgeLabel: "event_reference_ImagingStudy", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "DocumentReference|event_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "DocumentReference", + EdgeLabel: "event_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|event_reference_FamilyMemberHistory|DocumentReference": { + FromType: "FamilyMemberHistory", + EdgeLabel: "event_reference_FamilyMemberHistory", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "DocumentReference|event_reference_BodyStructure|BodyStructure": { + FromType: "DocumentReference", + EdgeLabel: "event_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|event_reference_BodyStructure|DocumentReference": { + FromType: "BodyStructure", + EdgeLabel: "event_reference_BodyStructure", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "DocumentReference|relatesTo_target|DocumentReference": { + FromType: "DocumentReference", + EdgeLabel: "relatesTo_target", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference_relates_to", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReferenceAttester|party_Patient|Patient": { + FromType: "DocumentReferenceAttester", + EdgeLabel: "party_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference_attester", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|party_Patient|DocumentReferenceAttester": { + FromType: "Patient", + EdgeLabel: "party_Patient", + ToType: "DocumentReferenceAttester", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference_attester", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "DocumentReferenceAttester|party_Practitioner|Practitioner": { + FromType: "DocumentReferenceAttester", + EdgeLabel: "party_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference_attester", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|party_Practitioner|DocumentReferenceAttester": { + FromType: "Practitioner", + EdgeLabel: "party_Practitioner", + ToType: "DocumentReferenceAttester", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference_attester", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "DocumentReferenceAttester|party_PractitionerRole|PractitionerRole": { + FromType: "DocumentReferenceAttester", + EdgeLabel: "party_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference_attester", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|party_PractitionerRole|DocumentReferenceAttester": { + FromType: "PractitionerRole", + EdgeLabel: "party_PractitionerRole", + ToType: "DocumentReferenceAttester", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference_attester", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "DocumentReferenceAttester|party_Organization|Organization": { + FromType: "DocumentReferenceAttester", + EdgeLabel: "party_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference_attester", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|party_Organization|DocumentReferenceAttester": { + FromType: "Organization", + EdgeLabel: "party_Organization", + ToType: "DocumentReferenceAttester", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference_attester", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "DocumentReferenceRelatesTo|target|DocumentReference": { + FromType: "DocumentReferenceRelatesTo", + EdgeLabel: "target", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference_relates_to", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|target|DocumentReferenceRelatesTo": { + FromType: "DocumentReference", + EdgeLabel: "target", + ToType: "DocumentReferenceRelatesTo", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "document_reference_relates_to", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "ExtendedContactDetail|organization|Organization": { + FromType: "ExtendedContactDetail", + EdgeLabel: "organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extended_contact_detail", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|organization|ExtendedContactDetail": { + FromType: "Organization", + EdgeLabel: "organization", + ToType: "ExtendedContactDetail", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extended_contact_detail", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Extension|valueReference_Organization|Organization": { + FromType: "Extension", + EdgeLabel: "valueReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueReference_Organization|Extension": { + FromType: "Organization", + EdgeLabel: "valueReference_Organization", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Extension|valueReference_Group|Group": { + FromType: "Extension", + EdgeLabel: "valueReference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|valueReference_Group|Extension": { + FromType: "Group", + EdgeLabel: "valueReference_Group", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Extension|valueReference_Practitioner|Practitioner": { + FromType: "Extension", + EdgeLabel: "valueReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|valueReference_Practitioner|Extension": { + FromType: "Practitioner", + EdgeLabel: "valueReference_Practitioner", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Extension|valueReference_PractitionerRole|PractitionerRole": { + FromType: "Extension", + EdgeLabel: "valueReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|valueReference_PractitionerRole|Extension": { + FromType: "PractitionerRole", + EdgeLabel: "valueReference_PractitionerRole", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Extension|valueReference_ResearchStudy|ResearchStudy": { + FromType: "Extension", + EdgeLabel: "valueReference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|valueReference_ResearchStudy|Extension": { + FromType: "ResearchStudy", + EdgeLabel: "valueReference_ResearchStudy", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "Extension|valueReference_Patient|Patient": { + FromType: "Extension", + EdgeLabel: "valueReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|valueReference_Patient|Extension": { + FromType: "Patient", + EdgeLabel: "valueReference_Patient", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Extension|valueReference_ResearchSubject|ResearchSubject": { + FromType: "Extension", + EdgeLabel: "valueReference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|valueReference_ResearchSubject|Extension": { + FromType: "ResearchSubject", + EdgeLabel: "valueReference_ResearchSubject", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "Extension|valueReference_Substance|Substance": { + FromType: "Extension", + EdgeLabel: "valueReference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|valueReference_Substance|Extension": { + FromType: "Substance", + EdgeLabel: "valueReference_Substance", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Extension|valueReference_SubstanceDefinition|SubstanceDefinition": { + FromType: "Extension", + EdgeLabel: "valueReference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|valueReference_SubstanceDefinition|Extension": { + FromType: "SubstanceDefinition", + EdgeLabel: "valueReference_SubstanceDefinition", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "Extension|valueReference_Specimen|Specimen": { + FromType: "Extension", + EdgeLabel: "valueReference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|valueReference_Specimen|Extension": { + FromType: "Specimen", + EdgeLabel: "valueReference_Specimen", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Extension|valueReference_Observation|Observation": { + FromType: "Extension", + EdgeLabel: "valueReference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|valueReference_Observation|Extension": { + FromType: "Observation", + EdgeLabel: "valueReference_Observation", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Extension|valueReference_DiagnosticReport|DiagnosticReport": { + FromType: "Extension", + EdgeLabel: "valueReference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|valueReference_DiagnosticReport|Extension": { + FromType: "DiagnosticReport", + EdgeLabel: "valueReference_DiagnosticReport", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "Extension|valueReference_Condition|Condition": { + FromType: "Extension", + EdgeLabel: "valueReference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|valueReference_Condition|Extension": { + FromType: "Condition", + EdgeLabel: "valueReference_Condition", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Extension|valueReference_Medication|Medication": { + FromType: "Extension", + EdgeLabel: "valueReference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|valueReference_Medication|Extension": { + FromType: "Medication", + EdgeLabel: "valueReference_Medication", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Extension|valueReference_MedicationAdministration|MedicationAdministration": { + FromType: "Extension", + EdgeLabel: "valueReference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|valueReference_MedicationAdministration|Extension": { + FromType: "MedicationAdministration", + EdgeLabel: "valueReference_MedicationAdministration", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "Extension|valueReference_MedicationStatement|MedicationStatement": { + FromType: "Extension", + EdgeLabel: "valueReference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|valueReference_MedicationStatement|Extension": { + FromType: "MedicationStatement", + EdgeLabel: "valueReference_MedicationStatement", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "Extension|valueReference_MedicationRequest|MedicationRequest": { + FromType: "Extension", + EdgeLabel: "valueReference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|valueReference_MedicationRequest|Extension": { + FromType: "MedicationRequest", + EdgeLabel: "valueReference_MedicationRequest", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "Extension|valueReference_Procedure|Procedure": { + FromType: "Extension", + EdgeLabel: "valueReference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|valueReference_Procedure|Extension": { + FromType: "Procedure", + EdgeLabel: "valueReference_Procedure", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Extension|valueReference_DocumentReference|DocumentReference": { + FromType: "Extension", + EdgeLabel: "valueReference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|valueReference_DocumentReference|Extension": { + FromType: "DocumentReference", + EdgeLabel: "valueReference_DocumentReference", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "Extension|valueReference_Task|Task": { + FromType: "Extension", + EdgeLabel: "valueReference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|valueReference_Task|Extension": { + FromType: "Task", + EdgeLabel: "valueReference_Task", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Extension|valueReference_ImagingStudy|ImagingStudy": { + FromType: "Extension", + EdgeLabel: "valueReference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|valueReference_ImagingStudy|Extension": { + FromType: "ImagingStudy", + EdgeLabel: "valueReference_ImagingStudy", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "Extension|valueReference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "Extension", + EdgeLabel: "valueReference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|valueReference_FamilyMemberHistory|Extension": { + FromType: "FamilyMemberHistory", + EdgeLabel: "valueReference_FamilyMemberHistory", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "Extension|valueReference_BodyStructure|BodyStructure": { + FromType: "Extension", + EdgeLabel: "valueReference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|valueReference_BodyStructure|Extension": { + FromType: "BodyStructure", + EdgeLabel: "valueReference_BodyStructure", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extension", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "Extension|valueAnnotation_authorReference_Practitioner|Practitioner": { + FromType: "Extension", + EdgeLabel: "valueAnnotation_authorReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|valueAnnotation_authorReference_Practitioner|Extension": { + FromType: "Practitioner", + EdgeLabel: "valueAnnotation_authorReference_Practitioner", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Extension|valueAnnotation_authorReference_PractitionerRole|PractitionerRole": { + FromType: "Extension", + EdgeLabel: "valueAnnotation_authorReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|valueAnnotation_authorReference_PractitionerRole|Extension": { + FromType: "PractitionerRole", + EdgeLabel: "valueAnnotation_authorReference_PractitionerRole", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Extension|valueAnnotation_authorReference_Patient|Patient": { + FromType: "Extension", + EdgeLabel: "valueAnnotation_authorReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|valueAnnotation_authorReference_Patient|Extension": { + FromType: "Patient", + EdgeLabel: "valueAnnotation_authorReference_Patient", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Extension|valueAnnotation_authorReference_Organization|Organization": { + FromType: "Extension", + EdgeLabel: "valueAnnotation_authorReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueAnnotation_authorReference_Organization|Extension": { + FromType: "Organization", + EdgeLabel: "valueAnnotation_authorReference_Organization", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Extension|valueCodeableReference_reference_Organization|Organization": { + FromType: "Extension", + EdgeLabel: "valueCodeableReference_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueCodeableReference_reference_Organization|Extension": { + FromType: "Organization", + EdgeLabel: "valueCodeableReference_reference_Organization", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Extension|valueCodeableReference_reference_Group|Group": { + FromType: "Extension", + EdgeLabel: "valueCodeableReference_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|valueCodeableReference_reference_Group|Extension": { + FromType: "Group", + EdgeLabel: "valueCodeableReference_reference_Group", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Extension|valueCodeableReference_reference_Practitioner|Practitioner": { + FromType: "Extension", + EdgeLabel: "valueCodeableReference_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|valueCodeableReference_reference_Practitioner|Extension": { + FromType: "Practitioner", + EdgeLabel: "valueCodeableReference_reference_Practitioner", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Extension|valueCodeableReference_reference_PractitionerRole|PractitionerRole": { + FromType: "Extension", + EdgeLabel: "valueCodeableReference_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|valueCodeableReference_reference_PractitionerRole|Extension": { + FromType: "PractitionerRole", + EdgeLabel: "valueCodeableReference_reference_PractitionerRole", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Extension|valueCodeableReference_reference_ResearchStudy|ResearchStudy": { + FromType: "Extension", + EdgeLabel: "valueCodeableReference_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|valueCodeableReference_reference_ResearchStudy|Extension": { + FromType: "ResearchStudy", + EdgeLabel: "valueCodeableReference_reference_ResearchStudy", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "Extension|valueCodeableReference_reference_Patient|Patient": { + FromType: "Extension", + EdgeLabel: "valueCodeableReference_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|valueCodeableReference_reference_Patient|Extension": { + FromType: "Patient", + EdgeLabel: "valueCodeableReference_reference_Patient", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Extension|valueCodeableReference_reference_ResearchSubject|ResearchSubject": { + FromType: "Extension", + EdgeLabel: "valueCodeableReference_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|valueCodeableReference_reference_ResearchSubject|Extension": { + FromType: "ResearchSubject", + EdgeLabel: "valueCodeableReference_reference_ResearchSubject", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "Extension|valueCodeableReference_reference_Substance|Substance": { + FromType: "Extension", + EdgeLabel: "valueCodeableReference_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|valueCodeableReference_reference_Substance|Extension": { + FromType: "Substance", + EdgeLabel: "valueCodeableReference_reference_Substance", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Extension|valueCodeableReference_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "Extension", + EdgeLabel: "valueCodeableReference_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|valueCodeableReference_reference_SubstanceDefinition|Extension": { + FromType: "SubstanceDefinition", + EdgeLabel: "valueCodeableReference_reference_SubstanceDefinition", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "Extension|valueCodeableReference_reference_Specimen|Specimen": { + FromType: "Extension", + EdgeLabel: "valueCodeableReference_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|valueCodeableReference_reference_Specimen|Extension": { + FromType: "Specimen", + EdgeLabel: "valueCodeableReference_reference_Specimen", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Extension|valueCodeableReference_reference_Observation|Observation": { + FromType: "Extension", + EdgeLabel: "valueCodeableReference_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|valueCodeableReference_reference_Observation|Extension": { + FromType: "Observation", + EdgeLabel: "valueCodeableReference_reference_Observation", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Extension|valueCodeableReference_reference_DiagnosticReport|DiagnosticReport": { + FromType: "Extension", + EdgeLabel: "valueCodeableReference_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|valueCodeableReference_reference_DiagnosticReport|Extension": { + FromType: "DiagnosticReport", + EdgeLabel: "valueCodeableReference_reference_DiagnosticReport", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "Extension|valueCodeableReference_reference_Condition|Condition": { + FromType: "Extension", + EdgeLabel: "valueCodeableReference_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|valueCodeableReference_reference_Condition|Extension": { + FromType: "Condition", + EdgeLabel: "valueCodeableReference_reference_Condition", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Extension|valueCodeableReference_reference_Medication|Medication": { + FromType: "Extension", + EdgeLabel: "valueCodeableReference_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|valueCodeableReference_reference_Medication|Extension": { + FromType: "Medication", + EdgeLabel: "valueCodeableReference_reference_Medication", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Extension|valueCodeableReference_reference_MedicationAdministration|MedicationAdministration": { + FromType: "Extension", + EdgeLabel: "valueCodeableReference_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|valueCodeableReference_reference_MedicationAdministration|Extension": { + FromType: "MedicationAdministration", + EdgeLabel: "valueCodeableReference_reference_MedicationAdministration", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "Extension|valueCodeableReference_reference_MedicationStatement|MedicationStatement": { + FromType: "Extension", + EdgeLabel: "valueCodeableReference_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|valueCodeableReference_reference_MedicationStatement|Extension": { + FromType: "MedicationStatement", + EdgeLabel: "valueCodeableReference_reference_MedicationStatement", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "Extension|valueCodeableReference_reference_MedicationRequest|MedicationRequest": { + FromType: "Extension", + EdgeLabel: "valueCodeableReference_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|valueCodeableReference_reference_MedicationRequest|Extension": { + FromType: "MedicationRequest", + EdgeLabel: "valueCodeableReference_reference_MedicationRequest", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "Extension|valueCodeableReference_reference_Procedure|Procedure": { + FromType: "Extension", + EdgeLabel: "valueCodeableReference_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|valueCodeableReference_reference_Procedure|Extension": { + FromType: "Procedure", + EdgeLabel: "valueCodeableReference_reference_Procedure", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Extension|valueCodeableReference_reference_DocumentReference|DocumentReference": { + FromType: "Extension", + EdgeLabel: "valueCodeableReference_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|valueCodeableReference_reference_DocumentReference|Extension": { + FromType: "DocumentReference", + EdgeLabel: "valueCodeableReference_reference_DocumentReference", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "Extension|valueCodeableReference_reference_Task|Task": { + FromType: "Extension", + EdgeLabel: "valueCodeableReference_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|valueCodeableReference_reference_Task|Extension": { + FromType: "Task", + EdgeLabel: "valueCodeableReference_reference_Task", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Extension|valueCodeableReference_reference_ImagingStudy|ImagingStudy": { + FromType: "Extension", + EdgeLabel: "valueCodeableReference_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|valueCodeableReference_reference_ImagingStudy|Extension": { + FromType: "ImagingStudy", + EdgeLabel: "valueCodeableReference_reference_ImagingStudy", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "Extension|valueCodeableReference_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "Extension", + EdgeLabel: "valueCodeableReference_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|valueCodeableReference_reference_FamilyMemberHistory|Extension": { + FromType: "FamilyMemberHistory", + EdgeLabel: "valueCodeableReference_reference_FamilyMemberHistory", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "Extension|valueCodeableReference_reference_BodyStructure|BodyStructure": { + FromType: "Extension", + EdgeLabel: "valueCodeableReference_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|valueCodeableReference_reference_BodyStructure|Extension": { + FromType: "BodyStructure", + EdgeLabel: "valueCodeableReference_reference_BodyStructure", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "Extension|valueDataRequirement_subjectReference|Group": { + FromType: "Extension", + EdgeLabel: "valueDataRequirement_subjectReference", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "data_requirement", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|valueDataRequirement_subjectReference|Extension": { + FromType: "Group", + EdgeLabel: "valueDataRequirement_subjectReference", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "data_requirement", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Extension|valueExtendedContactDetail_organization|Organization": { + FromType: "Extension", + EdgeLabel: "valueExtendedContactDetail_organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extended_contact_detail", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueExtendedContactDetail_organization|Extension": { + FromType: "Organization", + EdgeLabel: "valueExtendedContactDetail_organization", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extended_contact_detail", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Extension|valueRelatedArtifact_resourceReference_Organization|Organization": { + FromType: "Extension", + EdgeLabel: "valueRelatedArtifact_resourceReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueRelatedArtifact_resourceReference_Organization|Extension": { + FromType: "Organization", + EdgeLabel: "valueRelatedArtifact_resourceReference_Organization", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Extension|valueRelatedArtifact_resourceReference_Group|Group": { + FromType: "Extension", + EdgeLabel: "valueRelatedArtifact_resourceReference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|valueRelatedArtifact_resourceReference_Group|Extension": { + FromType: "Group", + EdgeLabel: "valueRelatedArtifact_resourceReference_Group", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Extension|valueRelatedArtifact_resourceReference_Practitioner|Practitioner": { + FromType: "Extension", + EdgeLabel: "valueRelatedArtifact_resourceReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|valueRelatedArtifact_resourceReference_Practitioner|Extension": { + FromType: "Practitioner", + EdgeLabel: "valueRelatedArtifact_resourceReference_Practitioner", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Extension|valueRelatedArtifact_resourceReference_PractitionerRole|PractitionerRole": { + FromType: "Extension", + EdgeLabel: "valueRelatedArtifact_resourceReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|valueRelatedArtifact_resourceReference_PractitionerRole|Extension": { + FromType: "PractitionerRole", + EdgeLabel: "valueRelatedArtifact_resourceReference_PractitionerRole", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Extension|valueRelatedArtifact_resourceReference_ResearchStudy|ResearchStudy": { + FromType: "Extension", + EdgeLabel: "valueRelatedArtifact_resourceReference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|valueRelatedArtifact_resourceReference_ResearchStudy|Extension": { + FromType: "ResearchStudy", + EdgeLabel: "valueRelatedArtifact_resourceReference_ResearchStudy", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "Extension|valueRelatedArtifact_resourceReference_Patient|Patient": { + FromType: "Extension", + EdgeLabel: "valueRelatedArtifact_resourceReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|valueRelatedArtifact_resourceReference_Patient|Extension": { + FromType: "Patient", + EdgeLabel: "valueRelatedArtifact_resourceReference_Patient", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Extension|valueRelatedArtifact_resourceReference_ResearchSubject|ResearchSubject": { + FromType: "Extension", + EdgeLabel: "valueRelatedArtifact_resourceReference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|valueRelatedArtifact_resourceReference_ResearchSubject|Extension": { + FromType: "ResearchSubject", + EdgeLabel: "valueRelatedArtifact_resourceReference_ResearchSubject", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "Extension|valueRelatedArtifact_resourceReference_Substance|Substance": { + FromType: "Extension", + EdgeLabel: "valueRelatedArtifact_resourceReference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|valueRelatedArtifact_resourceReference_Substance|Extension": { + FromType: "Substance", + EdgeLabel: "valueRelatedArtifact_resourceReference_Substance", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Extension|valueRelatedArtifact_resourceReference_SubstanceDefinition|SubstanceDefinition": { + FromType: "Extension", + EdgeLabel: "valueRelatedArtifact_resourceReference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|valueRelatedArtifact_resourceReference_SubstanceDefinition|Extension": { + FromType: "SubstanceDefinition", + EdgeLabel: "valueRelatedArtifact_resourceReference_SubstanceDefinition", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "Extension|valueRelatedArtifact_resourceReference_Specimen|Specimen": { + FromType: "Extension", + EdgeLabel: "valueRelatedArtifact_resourceReference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|valueRelatedArtifact_resourceReference_Specimen|Extension": { + FromType: "Specimen", + EdgeLabel: "valueRelatedArtifact_resourceReference_Specimen", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Extension|valueRelatedArtifact_resourceReference_Observation|Observation": { + FromType: "Extension", + EdgeLabel: "valueRelatedArtifact_resourceReference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|valueRelatedArtifact_resourceReference_Observation|Extension": { + FromType: "Observation", + EdgeLabel: "valueRelatedArtifact_resourceReference_Observation", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Extension|valueRelatedArtifact_resourceReference_DiagnosticReport|DiagnosticReport": { + FromType: "Extension", + EdgeLabel: "valueRelatedArtifact_resourceReference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|valueRelatedArtifact_resourceReference_DiagnosticReport|Extension": { + FromType: "DiagnosticReport", + EdgeLabel: "valueRelatedArtifact_resourceReference_DiagnosticReport", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "Extension|valueRelatedArtifact_resourceReference_Condition|Condition": { + FromType: "Extension", + EdgeLabel: "valueRelatedArtifact_resourceReference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|valueRelatedArtifact_resourceReference_Condition|Extension": { + FromType: "Condition", + EdgeLabel: "valueRelatedArtifact_resourceReference_Condition", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Extension|valueRelatedArtifact_resourceReference_Medication|Medication": { + FromType: "Extension", + EdgeLabel: "valueRelatedArtifact_resourceReference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|valueRelatedArtifact_resourceReference_Medication|Extension": { + FromType: "Medication", + EdgeLabel: "valueRelatedArtifact_resourceReference_Medication", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Extension|valueRelatedArtifact_resourceReference_MedicationAdministration|MedicationAdministration": { + FromType: "Extension", + EdgeLabel: "valueRelatedArtifact_resourceReference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|valueRelatedArtifact_resourceReference_MedicationAdministration|Extension": { + FromType: "MedicationAdministration", + EdgeLabel: "valueRelatedArtifact_resourceReference_MedicationAdministration", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "Extension|valueRelatedArtifact_resourceReference_MedicationStatement|MedicationStatement": { + FromType: "Extension", + EdgeLabel: "valueRelatedArtifact_resourceReference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|valueRelatedArtifact_resourceReference_MedicationStatement|Extension": { + FromType: "MedicationStatement", + EdgeLabel: "valueRelatedArtifact_resourceReference_MedicationStatement", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "Extension|valueRelatedArtifact_resourceReference_MedicationRequest|MedicationRequest": { + FromType: "Extension", + EdgeLabel: "valueRelatedArtifact_resourceReference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|valueRelatedArtifact_resourceReference_MedicationRequest|Extension": { + FromType: "MedicationRequest", + EdgeLabel: "valueRelatedArtifact_resourceReference_MedicationRequest", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "Extension|valueRelatedArtifact_resourceReference_Procedure|Procedure": { + FromType: "Extension", + EdgeLabel: "valueRelatedArtifact_resourceReference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|valueRelatedArtifact_resourceReference_Procedure|Extension": { + FromType: "Procedure", + EdgeLabel: "valueRelatedArtifact_resourceReference_Procedure", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Extension|valueRelatedArtifact_resourceReference_DocumentReference|DocumentReference": { + FromType: "Extension", + EdgeLabel: "valueRelatedArtifact_resourceReference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|valueRelatedArtifact_resourceReference_DocumentReference|Extension": { + FromType: "DocumentReference", + EdgeLabel: "valueRelatedArtifact_resourceReference_DocumentReference", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "Extension|valueRelatedArtifact_resourceReference_Task|Task": { + FromType: "Extension", + EdgeLabel: "valueRelatedArtifact_resourceReference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|valueRelatedArtifact_resourceReference_Task|Extension": { + FromType: "Task", + EdgeLabel: "valueRelatedArtifact_resourceReference_Task", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Extension|valueRelatedArtifact_resourceReference_ImagingStudy|ImagingStudy": { + FromType: "Extension", + EdgeLabel: "valueRelatedArtifact_resourceReference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|valueRelatedArtifact_resourceReference_ImagingStudy|Extension": { + FromType: "ImagingStudy", + EdgeLabel: "valueRelatedArtifact_resourceReference_ImagingStudy", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "Extension|valueRelatedArtifact_resourceReference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "Extension", + EdgeLabel: "valueRelatedArtifact_resourceReference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|valueRelatedArtifact_resourceReference_FamilyMemberHistory|Extension": { + FromType: "FamilyMemberHistory", + EdgeLabel: "valueRelatedArtifact_resourceReference_FamilyMemberHistory", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "Extension|valueRelatedArtifact_resourceReference_BodyStructure|BodyStructure": { + FromType: "Extension", + EdgeLabel: "valueRelatedArtifact_resourceReference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|valueRelatedArtifact_resourceReference_BodyStructure|Extension": { + FromType: "BodyStructure", + EdgeLabel: "valueRelatedArtifact_resourceReference_BodyStructure", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "Extension|valueSignature_onBehalfOf_Practitioner|Practitioner": { + FromType: "Extension", + EdgeLabel: "valueSignature_onBehalfOf_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|valueSignature_onBehalfOf_Practitioner|Extension": { + FromType: "Practitioner", + EdgeLabel: "valueSignature_onBehalfOf_Practitioner", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Extension|valueSignature_onBehalfOf_PractitionerRole|PractitionerRole": { + FromType: "Extension", + EdgeLabel: "valueSignature_onBehalfOf_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|valueSignature_onBehalfOf_PractitionerRole|Extension": { + FromType: "PractitionerRole", + EdgeLabel: "valueSignature_onBehalfOf_PractitionerRole", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Extension|valueSignature_onBehalfOf_Patient|Patient": { + FromType: "Extension", + EdgeLabel: "valueSignature_onBehalfOf_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|valueSignature_onBehalfOf_Patient|Extension": { + FromType: "Patient", + EdgeLabel: "valueSignature_onBehalfOf_Patient", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Extension|valueSignature_onBehalfOf_Organization|Organization": { + FromType: "Extension", + EdgeLabel: "valueSignature_onBehalfOf_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueSignature_onBehalfOf_Organization|Extension": { + FromType: "Organization", + EdgeLabel: "valueSignature_onBehalfOf_Organization", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Extension|valueSignature_who_Practitioner|Practitioner": { + FromType: "Extension", + EdgeLabel: "valueSignature_who_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|valueSignature_who_Practitioner|Extension": { + FromType: "Practitioner", + EdgeLabel: "valueSignature_who_Practitioner", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Extension|valueSignature_who_PractitionerRole|PractitionerRole": { + FromType: "Extension", + EdgeLabel: "valueSignature_who_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|valueSignature_who_PractitionerRole|Extension": { + FromType: "PractitionerRole", + EdgeLabel: "valueSignature_who_PractitionerRole", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Extension|valueSignature_who_Patient|Patient": { + FromType: "Extension", + EdgeLabel: "valueSignature_who_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|valueSignature_who_Patient|Extension": { + FromType: "Patient", + EdgeLabel: "valueSignature_who_Patient", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Extension|valueSignature_who_Organization|Organization": { + FromType: "Extension", + EdgeLabel: "valueSignature_who_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueSignature_who_Organization|Extension": { + FromType: "Organization", + EdgeLabel: "valueSignature_who_Organization", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Extension|valueUsageContext_valueReference_ResearchStudy|ResearchStudy": { + FromType: "Extension", + EdgeLabel: "valueUsageContext_valueReference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|valueUsageContext_valueReference_ResearchStudy|Extension": { + FromType: "ResearchStudy", + EdgeLabel: "valueUsageContext_valueReference_ResearchStudy", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "Extension|valueUsageContext_valueReference_Group|Group": { + FromType: "Extension", + EdgeLabel: "valueUsageContext_valueReference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|valueUsageContext_valueReference_Group|Extension": { + FromType: "Group", + EdgeLabel: "valueUsageContext_valueReference_Group", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Extension|valueUsageContext_valueReference_Organization|Organization": { + FromType: "Extension", + EdgeLabel: "valueUsageContext_valueReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueUsageContext_valueReference_Organization|Extension": { + FromType: "Organization", + EdgeLabel: "valueUsageContext_valueReference_Organization", + ToType: "Extension", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "FamilyMemberHistory|patient|Patient": { + FromType: "FamilyMemberHistory", + EdgeLabel: "patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "family_member_history", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|patient|FamilyMemberHistory": { + FromType: "Patient", + EdgeLabel: "patient", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "family_member_history", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "FamilyMemberHistory|note_authorReference_Practitioner|Practitioner": { + FromType: "FamilyMemberHistory", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|note_authorReference_Practitioner|FamilyMemberHistory": { + FromType: "Practitioner", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "FamilyMemberHistory|note_authorReference_PractitionerRole|PractitionerRole": { + FromType: "FamilyMemberHistory", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|note_authorReference_PractitionerRole|FamilyMemberHistory": { + FromType: "PractitionerRole", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "FamilyMemberHistory|note_authorReference_Patient|Patient": { + FromType: "FamilyMemberHistory", + EdgeLabel: "note_authorReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|note_authorReference_Patient|FamilyMemberHistory": { + FromType: "Patient", + EdgeLabel: "note_authorReference_Patient", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "FamilyMemberHistory|note_authorReference_Organization|Organization": { + FromType: "FamilyMemberHistory", + EdgeLabel: "note_authorReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|note_authorReference_Organization|FamilyMemberHistory": { + FromType: "Organization", + EdgeLabel: "note_authorReference_Organization", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "FamilyMemberHistory|participant_actor_Practitioner|Practitioner": { + FromType: "FamilyMemberHistory", + EdgeLabel: "participant_actor_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "family_member_history_participant", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|participant_actor_Practitioner|FamilyMemberHistory": { + FromType: "Practitioner", + EdgeLabel: "participant_actor_Practitioner", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "family_member_history_participant", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "FamilyMemberHistory|participant_actor_PractitionerRole|PractitionerRole": { + FromType: "FamilyMemberHistory", + EdgeLabel: "participant_actor_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "family_member_history_participant", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|participant_actor_PractitionerRole|FamilyMemberHistory": { + FromType: "PractitionerRole", + EdgeLabel: "participant_actor_PractitionerRole", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "family_member_history_participant", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "FamilyMemberHistory|participant_actor_Patient|Patient": { + FromType: "FamilyMemberHistory", + EdgeLabel: "participant_actor_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "family_member_history_participant", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|participant_actor_Patient|FamilyMemberHistory": { + FromType: "Patient", + EdgeLabel: "participant_actor_Patient", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "family_member_history_participant", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "FamilyMemberHistory|participant_actor_Organization|Organization": { + FromType: "FamilyMemberHistory", + EdgeLabel: "participant_actor_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "family_member_history_participant", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|participant_actor_Organization|FamilyMemberHistory": { + FromType: "Organization", + EdgeLabel: "participant_actor_Organization", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "family_member_history_participant", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "FamilyMemberHistory|reason_reference_Organization|Organization": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|reason_reference_Organization|FamilyMemberHistory": { + FromType: "Organization", + EdgeLabel: "reason_reference_Organization", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "FamilyMemberHistory|reason_reference_Group|Group": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|reason_reference_Group|FamilyMemberHistory": { + FromType: "Group", + EdgeLabel: "reason_reference_Group", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "FamilyMemberHistory|reason_reference_Practitioner|Practitioner": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|reason_reference_Practitioner|FamilyMemberHistory": { + FromType: "Practitioner", + EdgeLabel: "reason_reference_Practitioner", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "FamilyMemberHistory|reason_reference_PractitionerRole|PractitionerRole": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|reason_reference_PractitionerRole|FamilyMemberHistory": { + FromType: "PractitionerRole", + EdgeLabel: "reason_reference_PractitionerRole", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "FamilyMemberHistory|reason_reference_ResearchStudy|ResearchStudy": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|reason_reference_ResearchStudy|FamilyMemberHistory": { + FromType: "ResearchStudy", + EdgeLabel: "reason_reference_ResearchStudy", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "FamilyMemberHistory|reason_reference_Patient|Patient": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|reason_reference_Patient|FamilyMemberHistory": { + FromType: "Patient", + EdgeLabel: "reason_reference_Patient", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "FamilyMemberHistory|reason_reference_ResearchSubject|ResearchSubject": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|reason_reference_ResearchSubject|FamilyMemberHistory": { + FromType: "ResearchSubject", + EdgeLabel: "reason_reference_ResearchSubject", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "FamilyMemberHistory|reason_reference_Substance|Substance": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|reason_reference_Substance|FamilyMemberHistory": { + FromType: "Substance", + EdgeLabel: "reason_reference_Substance", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "FamilyMemberHistory|reason_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|reason_reference_SubstanceDefinition|FamilyMemberHistory": { + FromType: "SubstanceDefinition", + EdgeLabel: "reason_reference_SubstanceDefinition", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "FamilyMemberHistory|reason_reference_Specimen|Specimen": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|reason_reference_Specimen|FamilyMemberHistory": { + FromType: "Specimen", + EdgeLabel: "reason_reference_Specimen", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "FamilyMemberHistory|reason_reference_Observation|Observation": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|reason_reference_Observation|FamilyMemberHistory": { + FromType: "Observation", + EdgeLabel: "reason_reference_Observation", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "FamilyMemberHistory|reason_reference_DiagnosticReport|DiagnosticReport": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|reason_reference_DiagnosticReport|FamilyMemberHistory": { + FromType: "DiagnosticReport", + EdgeLabel: "reason_reference_DiagnosticReport", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "FamilyMemberHistory|reason_reference_Condition|Condition": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|reason_reference_Condition|FamilyMemberHistory": { + FromType: "Condition", + EdgeLabel: "reason_reference_Condition", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "FamilyMemberHistory|reason_reference_Medication|Medication": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|reason_reference_Medication|FamilyMemberHistory": { + FromType: "Medication", + EdgeLabel: "reason_reference_Medication", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "FamilyMemberHistory|reason_reference_MedicationAdministration|MedicationAdministration": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|reason_reference_MedicationAdministration|FamilyMemberHistory": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_MedicationAdministration", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "FamilyMemberHistory|reason_reference_MedicationStatement|MedicationStatement": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|reason_reference_MedicationStatement|FamilyMemberHistory": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_MedicationStatement", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "FamilyMemberHistory|reason_reference_MedicationRequest|MedicationRequest": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|reason_reference_MedicationRequest|FamilyMemberHistory": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_MedicationRequest", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "FamilyMemberHistory|reason_reference_Procedure|Procedure": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|reason_reference_Procedure|FamilyMemberHistory": { + FromType: "Procedure", + EdgeLabel: "reason_reference_Procedure", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "FamilyMemberHistory|reason_reference_DocumentReference|DocumentReference": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|reason_reference_DocumentReference|FamilyMemberHistory": { + FromType: "DocumentReference", + EdgeLabel: "reason_reference_DocumentReference", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "FamilyMemberHistory|reason_reference_Task|Task": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|reason_reference_Task|FamilyMemberHistory": { + FromType: "Task", + EdgeLabel: "reason_reference_Task", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "FamilyMemberHistory|reason_reference_ImagingStudy|ImagingStudy": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|reason_reference_ImagingStudy|FamilyMemberHistory": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_ImagingStudy", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "FamilyMemberHistory|reason_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|reason_reference_BodyStructure|BodyStructure": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|reason_reference_BodyStructure|FamilyMemberHistory": { + FromType: "BodyStructure", + EdgeLabel: "reason_reference_BodyStructure", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "FamilyMemberHistoryCondition|note_authorReference_Practitioner|Practitioner": { + FromType: "FamilyMemberHistoryCondition", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|note_authorReference_Practitioner|FamilyMemberHistoryCondition": { + FromType: "Practitioner", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "FamilyMemberHistoryCondition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "FamilyMemberHistoryCondition|note_authorReference_PractitionerRole|PractitionerRole": { + FromType: "FamilyMemberHistoryCondition", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|note_authorReference_PractitionerRole|FamilyMemberHistoryCondition": { + FromType: "PractitionerRole", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "FamilyMemberHistoryCondition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "FamilyMemberHistoryCondition|note_authorReference_Patient|Patient": { + FromType: "FamilyMemberHistoryCondition", + EdgeLabel: "note_authorReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|note_authorReference_Patient|FamilyMemberHistoryCondition": { + FromType: "Patient", + EdgeLabel: "note_authorReference_Patient", + ToType: "FamilyMemberHistoryCondition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "FamilyMemberHistoryCondition|note_authorReference_Organization|Organization": { + FromType: "FamilyMemberHistoryCondition", + EdgeLabel: "note_authorReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|note_authorReference_Organization|FamilyMemberHistoryCondition": { + FromType: "Organization", + EdgeLabel: "note_authorReference_Organization", + ToType: "FamilyMemberHistoryCondition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "FamilyMemberHistoryParticipant|actor_Practitioner|Practitioner": { + FromType: "FamilyMemberHistoryParticipant", + EdgeLabel: "actor_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "family_member_history_participant", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|actor_Practitioner|FamilyMemberHistoryParticipant": { + FromType: "Practitioner", + EdgeLabel: "actor_Practitioner", + ToType: "FamilyMemberHistoryParticipant", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "family_member_history_participant", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "FamilyMemberHistoryParticipant|actor_PractitionerRole|PractitionerRole": { + FromType: "FamilyMemberHistoryParticipant", + EdgeLabel: "actor_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "family_member_history_participant", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|actor_PractitionerRole|FamilyMemberHistoryParticipant": { + FromType: "PractitionerRole", + EdgeLabel: "actor_PractitionerRole", + ToType: "FamilyMemberHistoryParticipant", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "family_member_history_participant", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "FamilyMemberHistoryParticipant|actor_Patient|Patient": { + FromType: "FamilyMemberHistoryParticipant", + EdgeLabel: "actor_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "family_member_history_participant", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|actor_Patient|FamilyMemberHistoryParticipant": { + FromType: "Patient", + EdgeLabel: "actor_Patient", + ToType: "FamilyMemberHistoryParticipant", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "family_member_history_participant", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "FamilyMemberHistoryParticipant|actor_Organization|Organization": { + FromType: "FamilyMemberHistoryParticipant", + EdgeLabel: "actor_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "family_member_history_participant", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|actor_Organization|FamilyMemberHistoryParticipant": { + FromType: "Organization", + EdgeLabel: "actor_Organization", + ToType: "FamilyMemberHistoryParticipant", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "family_member_history_participant", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "FamilyMemberHistoryProcedure|note_authorReference_Practitioner|Practitioner": { + FromType: "FamilyMemberHistoryProcedure", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|note_authorReference_Practitioner|FamilyMemberHistoryProcedure": { + FromType: "Practitioner", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "FamilyMemberHistoryProcedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "FamilyMemberHistoryProcedure|note_authorReference_PractitionerRole|PractitionerRole": { + FromType: "FamilyMemberHistoryProcedure", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|note_authorReference_PractitionerRole|FamilyMemberHistoryProcedure": { + FromType: "PractitionerRole", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "FamilyMemberHistoryProcedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "FamilyMemberHistoryProcedure|note_authorReference_Patient|Patient": { + FromType: "FamilyMemberHistoryProcedure", + EdgeLabel: "note_authorReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|note_authorReference_Patient|FamilyMemberHistoryProcedure": { + FromType: "Patient", + EdgeLabel: "note_authorReference_Patient", + ToType: "FamilyMemberHistoryProcedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "FamilyMemberHistoryProcedure|note_authorReference_Organization|Organization": { + FromType: "FamilyMemberHistoryProcedure", + EdgeLabel: "note_authorReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|note_authorReference_Organization|FamilyMemberHistoryProcedure": { + FromType: "Organization", + EdgeLabel: "note_authorReference_Organization", + ToType: "FamilyMemberHistoryProcedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Group|managingEntity_Organization|Organization": { + FromType: "Group", + EdgeLabel: "managingEntity_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|managingEntity_Organization|Group": { + FromType: "Organization", + EdgeLabel: "managingEntity_Organization", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Group|managingEntity_Practitioner|Practitioner": { + FromType: "Group", + EdgeLabel: "managingEntity_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|managingEntity_Practitioner|Group": { + FromType: "Practitioner", + EdgeLabel: "managingEntity_Practitioner", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Group|managingEntity_PractitionerRole|PractitionerRole": { + FromType: "Group", + EdgeLabel: "managingEntity_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|managingEntity_PractitionerRole|Group": { + FromType: "PractitionerRole", + EdgeLabel: "managingEntity_PractitionerRole", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Group|characteristic_valueReference_Organization|Organization": { + FromType: "Group", + EdgeLabel: "characteristic_valueReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|characteristic_valueReference_Organization|Group": { + FromType: "Organization", + EdgeLabel: "characteristic_valueReference_Organization", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Group|characteristic_valueReference_Group|Group": { + FromType: "Group", + EdgeLabel: "characteristic_valueReference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|characteristic_valueReference_Practitioner|Practitioner": { + FromType: "Group", + EdgeLabel: "characteristic_valueReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|characteristic_valueReference_Practitioner|Group": { + FromType: "Practitioner", + EdgeLabel: "characteristic_valueReference_Practitioner", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Group|characteristic_valueReference_PractitionerRole|PractitionerRole": { + FromType: "Group", + EdgeLabel: "characteristic_valueReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|characteristic_valueReference_PractitionerRole|Group": { + FromType: "PractitionerRole", + EdgeLabel: "characteristic_valueReference_PractitionerRole", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Group|characteristic_valueReference_ResearchStudy|ResearchStudy": { + FromType: "Group", + EdgeLabel: "characteristic_valueReference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|characteristic_valueReference_ResearchStudy|Group": { + FromType: "ResearchStudy", + EdgeLabel: "characteristic_valueReference_ResearchStudy", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "Group|characteristic_valueReference_Patient|Patient": { + FromType: "Group", + EdgeLabel: "characteristic_valueReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|characteristic_valueReference_Patient|Group": { + FromType: "Patient", + EdgeLabel: "characteristic_valueReference_Patient", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Group|characteristic_valueReference_ResearchSubject|ResearchSubject": { + FromType: "Group", + EdgeLabel: "characteristic_valueReference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|characteristic_valueReference_ResearchSubject|Group": { + FromType: "ResearchSubject", + EdgeLabel: "characteristic_valueReference_ResearchSubject", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "Group|characteristic_valueReference_Substance|Substance": { + FromType: "Group", + EdgeLabel: "characteristic_valueReference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|characteristic_valueReference_Substance|Group": { + FromType: "Substance", + EdgeLabel: "characteristic_valueReference_Substance", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Group|characteristic_valueReference_SubstanceDefinition|SubstanceDefinition": { + FromType: "Group", + EdgeLabel: "characteristic_valueReference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|characteristic_valueReference_SubstanceDefinition|Group": { + FromType: "SubstanceDefinition", + EdgeLabel: "characteristic_valueReference_SubstanceDefinition", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "Group|characteristic_valueReference_Specimen|Specimen": { + FromType: "Group", + EdgeLabel: "characteristic_valueReference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|characteristic_valueReference_Specimen|Group": { + FromType: "Specimen", + EdgeLabel: "characteristic_valueReference_Specimen", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Group|characteristic_valueReference_Observation|Observation": { + FromType: "Group", + EdgeLabel: "characteristic_valueReference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|characteristic_valueReference_Observation|Group": { + FromType: "Observation", + EdgeLabel: "characteristic_valueReference_Observation", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Group|characteristic_valueReference_DiagnosticReport|DiagnosticReport": { + FromType: "Group", + EdgeLabel: "characteristic_valueReference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|characteristic_valueReference_DiagnosticReport|Group": { + FromType: "DiagnosticReport", + EdgeLabel: "characteristic_valueReference_DiagnosticReport", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "Group|characteristic_valueReference_Condition|Condition": { + FromType: "Group", + EdgeLabel: "characteristic_valueReference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|characteristic_valueReference_Condition|Group": { + FromType: "Condition", + EdgeLabel: "characteristic_valueReference_Condition", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Group|characteristic_valueReference_Medication|Medication": { + FromType: "Group", + EdgeLabel: "characteristic_valueReference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|characteristic_valueReference_Medication|Group": { + FromType: "Medication", + EdgeLabel: "characteristic_valueReference_Medication", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Group|characteristic_valueReference_MedicationAdministration|MedicationAdministration": { + FromType: "Group", + EdgeLabel: "characteristic_valueReference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|characteristic_valueReference_MedicationAdministration|Group": { + FromType: "MedicationAdministration", + EdgeLabel: "characteristic_valueReference_MedicationAdministration", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "Group|characteristic_valueReference_MedicationStatement|MedicationStatement": { + FromType: "Group", + EdgeLabel: "characteristic_valueReference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|characteristic_valueReference_MedicationStatement|Group": { + FromType: "MedicationStatement", + EdgeLabel: "characteristic_valueReference_MedicationStatement", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "Group|characteristic_valueReference_MedicationRequest|MedicationRequest": { + FromType: "Group", + EdgeLabel: "characteristic_valueReference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|characteristic_valueReference_MedicationRequest|Group": { + FromType: "MedicationRequest", + EdgeLabel: "characteristic_valueReference_MedicationRequest", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "Group|characteristic_valueReference_Procedure|Procedure": { + FromType: "Group", + EdgeLabel: "characteristic_valueReference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|characteristic_valueReference_Procedure|Group": { + FromType: "Procedure", + EdgeLabel: "characteristic_valueReference_Procedure", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Group|characteristic_valueReference_DocumentReference|DocumentReference": { + FromType: "Group", + EdgeLabel: "characteristic_valueReference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|characteristic_valueReference_DocumentReference|Group": { + FromType: "DocumentReference", + EdgeLabel: "characteristic_valueReference_DocumentReference", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "Group|characteristic_valueReference_Task|Task": { + FromType: "Group", + EdgeLabel: "characteristic_valueReference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|characteristic_valueReference_Task|Group": { + FromType: "Task", + EdgeLabel: "characteristic_valueReference_Task", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Group|characteristic_valueReference_ImagingStudy|ImagingStudy": { + FromType: "Group", + EdgeLabel: "characteristic_valueReference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|characteristic_valueReference_ImagingStudy|Group": { + FromType: "ImagingStudy", + EdgeLabel: "characteristic_valueReference_ImagingStudy", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "Group|characteristic_valueReference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "Group", + EdgeLabel: "characteristic_valueReference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|characteristic_valueReference_FamilyMemberHistory|Group": { + FromType: "FamilyMemberHistory", + EdgeLabel: "characteristic_valueReference_FamilyMemberHistory", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "Group|characteristic_valueReference_BodyStructure|BodyStructure": { + FromType: "Group", + EdgeLabel: "characteristic_valueReference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|characteristic_valueReference_BodyStructure|Group": { + FromType: "BodyStructure", + EdgeLabel: "characteristic_valueReference_BodyStructure", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "Group|member_entity_Group|Group": { + FromType: "Group", + EdgeLabel: "member_entity_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_member", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|member_entity_Organization|Organization": { + FromType: "Group", + EdgeLabel: "member_entity_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_member", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|member_entity_Organization|Group": { + FromType: "Organization", + EdgeLabel: "member_entity_Organization", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_member", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Group|member_entity_Patient|Patient": { + FromType: "Group", + EdgeLabel: "member_entity_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_member", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|member_entity_Patient|Group": { + FromType: "Patient", + EdgeLabel: "member_entity_Patient", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_member", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Group|member_entity_Practitioner|Practitioner": { + FromType: "Group", + EdgeLabel: "member_entity_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_member", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|member_entity_Practitioner|Group": { + FromType: "Practitioner", + EdgeLabel: "member_entity_Practitioner", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_member", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Group|member_entity_PractitionerRole|PractitionerRole": { + FromType: "Group", + EdgeLabel: "member_entity_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_member", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|member_entity_PractitionerRole|Group": { + FromType: "PractitionerRole", + EdgeLabel: "member_entity_PractitionerRole", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_member", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Group|member_entity_Specimen|Specimen": { + FromType: "Group", + EdgeLabel: "member_entity_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_member", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|member_entity_Specimen|Group": { + FromType: "Specimen", + EdgeLabel: "member_entity_Specimen", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_member", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "GroupCharacteristic|valueReference_Organization|Organization": { + FromType: "GroupCharacteristic", + EdgeLabel: "valueReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueReference_Organization|GroupCharacteristic": { + FromType: "Organization", + EdgeLabel: "valueReference_Organization", + ToType: "GroupCharacteristic", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "GroupCharacteristic|valueReference_Group|Group": { + FromType: "GroupCharacteristic", + EdgeLabel: "valueReference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|valueReference_Group|GroupCharacteristic": { + FromType: "Group", + EdgeLabel: "valueReference_Group", + ToType: "GroupCharacteristic", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "GroupCharacteristic|valueReference_Practitioner|Practitioner": { + FromType: "GroupCharacteristic", + EdgeLabel: "valueReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|valueReference_Practitioner|GroupCharacteristic": { + FromType: "Practitioner", + EdgeLabel: "valueReference_Practitioner", + ToType: "GroupCharacteristic", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "GroupCharacteristic|valueReference_PractitionerRole|PractitionerRole": { + FromType: "GroupCharacteristic", + EdgeLabel: "valueReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|valueReference_PractitionerRole|GroupCharacteristic": { + FromType: "PractitionerRole", + EdgeLabel: "valueReference_PractitionerRole", + ToType: "GroupCharacteristic", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "GroupCharacteristic|valueReference_ResearchStudy|ResearchStudy": { + FromType: "GroupCharacteristic", + EdgeLabel: "valueReference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|valueReference_ResearchStudy|GroupCharacteristic": { + FromType: "ResearchStudy", + EdgeLabel: "valueReference_ResearchStudy", + ToType: "GroupCharacteristic", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "GroupCharacteristic|valueReference_Patient|Patient": { + FromType: "GroupCharacteristic", + EdgeLabel: "valueReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|valueReference_Patient|GroupCharacteristic": { + FromType: "Patient", + EdgeLabel: "valueReference_Patient", + ToType: "GroupCharacteristic", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "GroupCharacteristic|valueReference_ResearchSubject|ResearchSubject": { + FromType: "GroupCharacteristic", + EdgeLabel: "valueReference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|valueReference_ResearchSubject|GroupCharacteristic": { + FromType: "ResearchSubject", + EdgeLabel: "valueReference_ResearchSubject", + ToType: "GroupCharacteristic", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "GroupCharacteristic|valueReference_Substance|Substance": { + FromType: "GroupCharacteristic", + EdgeLabel: "valueReference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|valueReference_Substance|GroupCharacteristic": { + FromType: "Substance", + EdgeLabel: "valueReference_Substance", + ToType: "GroupCharacteristic", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "GroupCharacteristic|valueReference_SubstanceDefinition|SubstanceDefinition": { + FromType: "GroupCharacteristic", + EdgeLabel: "valueReference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|valueReference_SubstanceDefinition|GroupCharacteristic": { + FromType: "SubstanceDefinition", + EdgeLabel: "valueReference_SubstanceDefinition", + ToType: "GroupCharacteristic", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "GroupCharacteristic|valueReference_Specimen|Specimen": { + FromType: "GroupCharacteristic", + EdgeLabel: "valueReference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|valueReference_Specimen|GroupCharacteristic": { + FromType: "Specimen", + EdgeLabel: "valueReference_Specimen", + ToType: "GroupCharacteristic", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "GroupCharacteristic|valueReference_Observation|Observation": { + FromType: "GroupCharacteristic", + EdgeLabel: "valueReference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|valueReference_Observation|GroupCharacteristic": { + FromType: "Observation", + EdgeLabel: "valueReference_Observation", + ToType: "GroupCharacteristic", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "GroupCharacteristic|valueReference_DiagnosticReport|DiagnosticReport": { + FromType: "GroupCharacteristic", + EdgeLabel: "valueReference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|valueReference_DiagnosticReport|GroupCharacteristic": { + FromType: "DiagnosticReport", + EdgeLabel: "valueReference_DiagnosticReport", + ToType: "GroupCharacteristic", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "GroupCharacteristic|valueReference_Condition|Condition": { + FromType: "GroupCharacteristic", + EdgeLabel: "valueReference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|valueReference_Condition|GroupCharacteristic": { + FromType: "Condition", + EdgeLabel: "valueReference_Condition", + ToType: "GroupCharacteristic", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "GroupCharacteristic|valueReference_Medication|Medication": { + FromType: "GroupCharacteristic", + EdgeLabel: "valueReference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|valueReference_Medication|GroupCharacteristic": { + FromType: "Medication", + EdgeLabel: "valueReference_Medication", + ToType: "GroupCharacteristic", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "GroupCharacteristic|valueReference_MedicationAdministration|MedicationAdministration": { + FromType: "GroupCharacteristic", + EdgeLabel: "valueReference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|valueReference_MedicationAdministration|GroupCharacteristic": { + FromType: "MedicationAdministration", + EdgeLabel: "valueReference_MedicationAdministration", + ToType: "GroupCharacteristic", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "GroupCharacteristic|valueReference_MedicationStatement|MedicationStatement": { + FromType: "GroupCharacteristic", + EdgeLabel: "valueReference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|valueReference_MedicationStatement|GroupCharacteristic": { + FromType: "MedicationStatement", + EdgeLabel: "valueReference_MedicationStatement", + ToType: "GroupCharacteristic", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "GroupCharacteristic|valueReference_MedicationRequest|MedicationRequest": { + FromType: "GroupCharacteristic", + EdgeLabel: "valueReference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|valueReference_MedicationRequest|GroupCharacteristic": { + FromType: "MedicationRequest", + EdgeLabel: "valueReference_MedicationRequest", + ToType: "GroupCharacteristic", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "GroupCharacteristic|valueReference_Procedure|Procedure": { + FromType: "GroupCharacteristic", + EdgeLabel: "valueReference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|valueReference_Procedure|GroupCharacteristic": { + FromType: "Procedure", + EdgeLabel: "valueReference_Procedure", + ToType: "GroupCharacteristic", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "GroupCharacteristic|valueReference_DocumentReference|DocumentReference": { + FromType: "GroupCharacteristic", + EdgeLabel: "valueReference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|valueReference_DocumentReference|GroupCharacteristic": { + FromType: "DocumentReference", + EdgeLabel: "valueReference_DocumentReference", + ToType: "GroupCharacteristic", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "GroupCharacteristic|valueReference_Task|Task": { + FromType: "GroupCharacteristic", + EdgeLabel: "valueReference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|valueReference_Task|GroupCharacteristic": { + FromType: "Task", + EdgeLabel: "valueReference_Task", + ToType: "GroupCharacteristic", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "GroupCharacteristic|valueReference_ImagingStudy|ImagingStudy": { + FromType: "GroupCharacteristic", + EdgeLabel: "valueReference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|valueReference_ImagingStudy|GroupCharacteristic": { + FromType: "ImagingStudy", + EdgeLabel: "valueReference_ImagingStudy", + ToType: "GroupCharacteristic", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "GroupCharacteristic|valueReference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "GroupCharacteristic", + EdgeLabel: "valueReference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|valueReference_FamilyMemberHistory|GroupCharacteristic": { + FromType: "FamilyMemberHistory", + EdgeLabel: "valueReference_FamilyMemberHistory", + ToType: "GroupCharacteristic", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "GroupCharacteristic|valueReference_BodyStructure|BodyStructure": { + FromType: "GroupCharacteristic", + EdgeLabel: "valueReference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|valueReference_BodyStructure|GroupCharacteristic": { + FromType: "BodyStructure", + EdgeLabel: "valueReference_BodyStructure", + ToType: "GroupCharacteristic", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_characteristic", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "GroupMember|entity_Group|Group": { + FromType: "GroupMember", + EdgeLabel: "entity_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_member", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|entity_Group|GroupMember": { + FromType: "Group", + EdgeLabel: "entity_Group", + ToType: "GroupMember", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_member", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "GroupMember|entity_Organization|Organization": { + FromType: "GroupMember", + EdgeLabel: "entity_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_member", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|entity_Organization|GroupMember": { + FromType: "Organization", + EdgeLabel: "entity_Organization", + ToType: "GroupMember", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_member", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "GroupMember|entity_Patient|Patient": { + FromType: "GroupMember", + EdgeLabel: "entity_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_member", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|entity_Patient|GroupMember": { + FromType: "Patient", + EdgeLabel: "entity_Patient", + ToType: "GroupMember", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_member", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "GroupMember|entity_Practitioner|Practitioner": { + FromType: "GroupMember", + EdgeLabel: "entity_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_member", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|entity_Practitioner|GroupMember": { + FromType: "Practitioner", + EdgeLabel: "entity_Practitioner", + ToType: "GroupMember", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_member", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "GroupMember|entity_PractitionerRole|PractitionerRole": { + FromType: "GroupMember", + EdgeLabel: "entity_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_member", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|entity_PractitionerRole|GroupMember": { + FromType: "PractitionerRole", + EdgeLabel: "entity_PractitionerRole", + ToType: "GroupMember", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_member", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "GroupMember|entity_Specimen|Specimen": { + FromType: "GroupMember", + EdgeLabel: "entity_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_member", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|entity_Specimen|GroupMember": { + FromType: "Specimen", + EdgeLabel: "entity_Specimen", + ToType: "GroupMember", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "group_member", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Identifier|assigner|Organization": { + FromType: "Identifier", + EdgeLabel: "assigner", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "identifier", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|assigner|Identifier": { + FromType: "Organization", + EdgeLabel: "assigner", + ToType: "Identifier", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "identifier", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "ImagingStudy|basedOn_Task|Task": { + FromType: "ImagingStudy", + EdgeLabel: "basedOn_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_imaging_study", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|basedOn_Task|ImagingStudy": { + FromType: "Task", + EdgeLabel: "basedOn_Task", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_imaging_study", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "ImagingStudy|partOf|Procedure": { + FromType: "ImagingStudy", + EdgeLabel: "partOf", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "partOf_imaging_study", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|partOf|ImagingStudy": { + FromType: "Procedure", + EdgeLabel: "partOf", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "partOf_imaging_study", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "ImagingStudy|referrer_Practitioner|Practitioner": { + FromType: "ImagingStudy", + EdgeLabel: "referrer_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|referrer_Practitioner|ImagingStudy": { + FromType: "Practitioner", + EdgeLabel: "referrer_Practitioner", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "ImagingStudy|referrer_PractitionerRole|PractitionerRole": { + FromType: "ImagingStudy", + EdgeLabel: "referrer_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|referrer_PractitionerRole|ImagingStudy": { + FromType: "PractitionerRole", + EdgeLabel: "referrer_PractitionerRole", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "ImagingStudy|subject_Patient|Patient": { + FromType: "ImagingStudy", + EdgeLabel: "subject_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|subject_Patient|ImagingStudy": { + FromType: "Patient", + EdgeLabel: "subject_Patient", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "ImagingStudy|subject_Group|Group": { + FromType: "ImagingStudy", + EdgeLabel: "subject_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|subject_Group|ImagingStudy": { + FromType: "Group", + EdgeLabel: "subject_Group", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "ImagingStudy|note_authorReference_Practitioner|Practitioner": { + FromType: "ImagingStudy", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|note_authorReference_Practitioner|ImagingStudy": { + FromType: "Practitioner", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "ImagingStudy|note_authorReference_PractitionerRole|PractitionerRole": { + FromType: "ImagingStudy", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|note_authorReference_PractitionerRole|ImagingStudy": { + FromType: "PractitionerRole", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "ImagingStudy|note_authorReference_Patient|Patient": { + FromType: "ImagingStudy", + EdgeLabel: "note_authorReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|note_authorReference_Patient|ImagingStudy": { + FromType: "Patient", + EdgeLabel: "note_authorReference_Patient", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "ImagingStudy|note_authorReference_Organization|Organization": { + FromType: "ImagingStudy", + EdgeLabel: "note_authorReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|note_authorReference_Organization|ImagingStudy": { + FromType: "Organization", + EdgeLabel: "note_authorReference_Organization", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "ImagingStudy|procedure_reference_Organization|Organization": { + FromType: "ImagingStudy", + EdgeLabel: "procedure_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|procedure_reference_Organization|ImagingStudy": { + FromType: "Organization", + EdgeLabel: "procedure_reference_Organization", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "ImagingStudy|procedure_reference_Group|Group": { + FromType: "ImagingStudy", + EdgeLabel: "procedure_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|procedure_reference_Group|ImagingStudy": { + FromType: "Group", + EdgeLabel: "procedure_reference_Group", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "ImagingStudy|procedure_reference_Practitioner|Practitioner": { + FromType: "ImagingStudy", + EdgeLabel: "procedure_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|procedure_reference_Practitioner|ImagingStudy": { + FromType: "Practitioner", + EdgeLabel: "procedure_reference_Practitioner", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "ImagingStudy|procedure_reference_PractitionerRole|PractitionerRole": { + FromType: "ImagingStudy", + EdgeLabel: "procedure_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|procedure_reference_PractitionerRole|ImagingStudy": { + FromType: "PractitionerRole", + EdgeLabel: "procedure_reference_PractitionerRole", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "ImagingStudy|procedure_reference_ResearchStudy|ResearchStudy": { + FromType: "ImagingStudy", + EdgeLabel: "procedure_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|procedure_reference_ResearchStudy|ImagingStudy": { + FromType: "ResearchStudy", + EdgeLabel: "procedure_reference_ResearchStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ImagingStudy|procedure_reference_Patient|Patient": { + FromType: "ImagingStudy", + EdgeLabel: "procedure_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|procedure_reference_Patient|ImagingStudy": { + FromType: "Patient", + EdgeLabel: "procedure_reference_Patient", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "ImagingStudy|procedure_reference_ResearchSubject|ResearchSubject": { + FromType: "ImagingStudy", + EdgeLabel: "procedure_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|procedure_reference_ResearchSubject|ImagingStudy": { + FromType: "ResearchSubject", + EdgeLabel: "procedure_reference_ResearchSubject", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ImagingStudy|procedure_reference_Substance|Substance": { + FromType: "ImagingStudy", + EdgeLabel: "procedure_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|procedure_reference_Substance|ImagingStudy": { + FromType: "Substance", + EdgeLabel: "procedure_reference_Substance", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "ImagingStudy|procedure_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "ImagingStudy", + EdgeLabel: "procedure_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|procedure_reference_SubstanceDefinition|ImagingStudy": { + FromType: "SubstanceDefinition", + EdgeLabel: "procedure_reference_SubstanceDefinition", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "ImagingStudy|procedure_reference_Specimen|Specimen": { + FromType: "ImagingStudy", + EdgeLabel: "procedure_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|procedure_reference_Specimen|ImagingStudy": { + FromType: "Specimen", + EdgeLabel: "procedure_reference_Specimen", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "ImagingStudy|procedure_reference_Observation|Observation": { + FromType: "ImagingStudy", + EdgeLabel: "procedure_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|procedure_reference_Observation|ImagingStudy": { + FromType: "Observation", + EdgeLabel: "procedure_reference_Observation", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "ImagingStudy|procedure_reference_DiagnosticReport|DiagnosticReport": { + FromType: "ImagingStudy", + EdgeLabel: "procedure_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|procedure_reference_DiagnosticReport|ImagingStudy": { + FromType: "DiagnosticReport", + EdgeLabel: "procedure_reference_DiagnosticReport", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "ImagingStudy|procedure_reference_Condition|Condition": { + FromType: "ImagingStudy", + EdgeLabel: "procedure_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|procedure_reference_Condition|ImagingStudy": { + FromType: "Condition", + EdgeLabel: "procedure_reference_Condition", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "ImagingStudy|procedure_reference_Medication|Medication": { + FromType: "ImagingStudy", + EdgeLabel: "procedure_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|procedure_reference_Medication|ImagingStudy": { + FromType: "Medication", + EdgeLabel: "procedure_reference_Medication", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "ImagingStudy|procedure_reference_MedicationAdministration|MedicationAdministration": { + FromType: "ImagingStudy", + EdgeLabel: "procedure_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|procedure_reference_MedicationAdministration|ImagingStudy": { + FromType: "MedicationAdministration", + EdgeLabel: "procedure_reference_MedicationAdministration", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "ImagingStudy|procedure_reference_MedicationStatement|MedicationStatement": { + FromType: "ImagingStudy", + EdgeLabel: "procedure_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|procedure_reference_MedicationStatement|ImagingStudy": { + FromType: "MedicationStatement", + EdgeLabel: "procedure_reference_MedicationStatement", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "ImagingStudy|procedure_reference_MedicationRequest|MedicationRequest": { + FromType: "ImagingStudy", + EdgeLabel: "procedure_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|procedure_reference_MedicationRequest|ImagingStudy": { + FromType: "MedicationRequest", + EdgeLabel: "procedure_reference_MedicationRequest", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "ImagingStudy|procedure_reference_Procedure|Procedure": { + FromType: "ImagingStudy", + EdgeLabel: "procedure_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|procedure_reference_Procedure|ImagingStudy": { + FromType: "Procedure", + EdgeLabel: "procedure_reference_Procedure", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "ImagingStudy|procedure_reference_DocumentReference|DocumentReference": { + FromType: "ImagingStudy", + EdgeLabel: "procedure_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|procedure_reference_DocumentReference|ImagingStudy": { + FromType: "DocumentReference", + EdgeLabel: "procedure_reference_DocumentReference", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "ImagingStudy|procedure_reference_Task|Task": { + FromType: "ImagingStudy", + EdgeLabel: "procedure_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|procedure_reference_Task|ImagingStudy": { + FromType: "Task", + EdgeLabel: "procedure_reference_Task", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "ImagingStudy|procedure_reference_ImagingStudy|ImagingStudy": { + FromType: "ImagingStudy", + EdgeLabel: "procedure_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|procedure_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "ImagingStudy", + EdgeLabel: "procedure_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|procedure_reference_FamilyMemberHistory|ImagingStudy": { + FromType: "FamilyMemberHistory", + EdgeLabel: "procedure_reference_FamilyMemberHistory", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "ImagingStudy|procedure_reference_BodyStructure|BodyStructure": { + FromType: "ImagingStudy", + EdgeLabel: "procedure_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|procedure_reference_BodyStructure|ImagingStudy": { + FromType: "BodyStructure", + EdgeLabel: "procedure_reference_BodyStructure", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "ImagingStudy|reason_reference_Organization|Organization": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|reason_reference_Organization|ImagingStudy": { + FromType: "Organization", + EdgeLabel: "reason_reference_Organization", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "ImagingStudy|reason_reference_Group|Group": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|reason_reference_Group|ImagingStudy": { + FromType: "Group", + EdgeLabel: "reason_reference_Group", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "ImagingStudy|reason_reference_Practitioner|Practitioner": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|reason_reference_Practitioner|ImagingStudy": { + FromType: "Practitioner", + EdgeLabel: "reason_reference_Practitioner", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "ImagingStudy|reason_reference_PractitionerRole|PractitionerRole": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|reason_reference_PractitionerRole|ImagingStudy": { + FromType: "PractitionerRole", + EdgeLabel: "reason_reference_PractitionerRole", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "ImagingStudy|reason_reference_ResearchStudy|ResearchStudy": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|reason_reference_ResearchStudy|ImagingStudy": { + FromType: "ResearchStudy", + EdgeLabel: "reason_reference_ResearchStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ImagingStudy|reason_reference_Patient|Patient": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|reason_reference_Patient|ImagingStudy": { + FromType: "Patient", + EdgeLabel: "reason_reference_Patient", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "ImagingStudy|reason_reference_ResearchSubject|ResearchSubject": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|reason_reference_ResearchSubject|ImagingStudy": { + FromType: "ResearchSubject", + EdgeLabel: "reason_reference_ResearchSubject", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ImagingStudy|reason_reference_Substance|Substance": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|reason_reference_Substance|ImagingStudy": { + FromType: "Substance", + EdgeLabel: "reason_reference_Substance", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "ImagingStudy|reason_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|reason_reference_SubstanceDefinition|ImagingStudy": { + FromType: "SubstanceDefinition", + EdgeLabel: "reason_reference_SubstanceDefinition", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "ImagingStudy|reason_reference_Specimen|Specimen": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|reason_reference_Specimen|ImagingStudy": { + FromType: "Specimen", + EdgeLabel: "reason_reference_Specimen", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "ImagingStudy|reason_reference_Observation|Observation": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|reason_reference_Observation|ImagingStudy": { + FromType: "Observation", + EdgeLabel: "reason_reference_Observation", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "ImagingStudy|reason_reference_DiagnosticReport|DiagnosticReport": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|reason_reference_DiagnosticReport|ImagingStudy": { + FromType: "DiagnosticReport", + EdgeLabel: "reason_reference_DiagnosticReport", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "ImagingStudy|reason_reference_Condition|Condition": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|reason_reference_Condition|ImagingStudy": { + FromType: "Condition", + EdgeLabel: "reason_reference_Condition", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "ImagingStudy|reason_reference_Medication|Medication": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|reason_reference_Medication|ImagingStudy": { + FromType: "Medication", + EdgeLabel: "reason_reference_Medication", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "ImagingStudy|reason_reference_MedicationAdministration|MedicationAdministration": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|reason_reference_MedicationAdministration|ImagingStudy": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_MedicationAdministration", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "ImagingStudy|reason_reference_MedicationStatement|MedicationStatement": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|reason_reference_MedicationStatement|ImagingStudy": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_MedicationStatement", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "ImagingStudy|reason_reference_MedicationRequest|MedicationRequest": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|reason_reference_MedicationRequest|ImagingStudy": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_MedicationRequest", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "ImagingStudy|reason_reference_Procedure|Procedure": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|reason_reference_Procedure|ImagingStudy": { + FromType: "Procedure", + EdgeLabel: "reason_reference_Procedure", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "ImagingStudy|reason_reference_DocumentReference|DocumentReference": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|reason_reference_DocumentReference|ImagingStudy": { + FromType: "DocumentReference", + EdgeLabel: "reason_reference_DocumentReference", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "ImagingStudy|reason_reference_Task|Task": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|reason_reference_Task|ImagingStudy": { + FromType: "Task", + EdgeLabel: "reason_reference_Task", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "ImagingStudy|reason_reference_ImagingStudy|ImagingStudy": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|reason_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|reason_reference_FamilyMemberHistory|ImagingStudy": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_FamilyMemberHistory", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "ImagingStudy|reason_reference_BodyStructure|BodyStructure": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|reason_reference_BodyStructure|ImagingStudy": { + FromType: "BodyStructure", + EdgeLabel: "reason_reference_BodyStructure", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "ImagingStudy|series_specimen|Specimen": { + FromType: "ImagingStudy", + EdgeLabel: "series_specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "specimen_imaging_study_series", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|series_specimen|ImagingStudy": { + FromType: "Specimen", + EdgeLabel: "series_specimen", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "specimen_imaging_study_series", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "ImagingStudySeries|specimen|Specimen": { + FromType: "ImagingStudySeries", + EdgeLabel: "specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "specimen_imaging_study_series", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|specimen|ImagingStudySeries": { + FromType: "Specimen", + EdgeLabel: "specimen", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "specimen_imaging_study_series", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "ImagingStudySeries|bodySite_reference_Organization|Organization": { + FromType: "ImagingStudySeries", + EdgeLabel: "bodySite_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|bodySite_reference_Organization|ImagingStudySeries": { + FromType: "Organization", + EdgeLabel: "bodySite_reference_Organization", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "ImagingStudySeries|bodySite_reference_Group|Group": { + FromType: "ImagingStudySeries", + EdgeLabel: "bodySite_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|bodySite_reference_Group|ImagingStudySeries": { + FromType: "Group", + EdgeLabel: "bodySite_reference_Group", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "ImagingStudySeries|bodySite_reference_Practitioner|Practitioner": { + FromType: "ImagingStudySeries", + EdgeLabel: "bodySite_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|bodySite_reference_Practitioner|ImagingStudySeries": { + FromType: "Practitioner", + EdgeLabel: "bodySite_reference_Practitioner", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "ImagingStudySeries|bodySite_reference_PractitionerRole|PractitionerRole": { + FromType: "ImagingStudySeries", + EdgeLabel: "bodySite_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|bodySite_reference_PractitionerRole|ImagingStudySeries": { + FromType: "PractitionerRole", + EdgeLabel: "bodySite_reference_PractitionerRole", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "ImagingStudySeries|bodySite_reference_ResearchStudy|ResearchStudy": { + FromType: "ImagingStudySeries", + EdgeLabel: "bodySite_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|bodySite_reference_ResearchStudy|ImagingStudySeries": { + FromType: "ResearchStudy", + EdgeLabel: "bodySite_reference_ResearchStudy", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ImagingStudySeries|bodySite_reference_Patient|Patient": { + FromType: "ImagingStudySeries", + EdgeLabel: "bodySite_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|bodySite_reference_Patient|ImagingStudySeries": { + FromType: "Patient", + EdgeLabel: "bodySite_reference_Patient", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "ImagingStudySeries|bodySite_reference_ResearchSubject|ResearchSubject": { + FromType: "ImagingStudySeries", + EdgeLabel: "bodySite_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|bodySite_reference_ResearchSubject|ImagingStudySeries": { + FromType: "ResearchSubject", + EdgeLabel: "bodySite_reference_ResearchSubject", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ImagingStudySeries|bodySite_reference_Substance|Substance": { + FromType: "ImagingStudySeries", + EdgeLabel: "bodySite_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|bodySite_reference_Substance|ImagingStudySeries": { + FromType: "Substance", + EdgeLabel: "bodySite_reference_Substance", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "ImagingStudySeries|bodySite_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "ImagingStudySeries", + EdgeLabel: "bodySite_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|bodySite_reference_SubstanceDefinition|ImagingStudySeries": { + FromType: "SubstanceDefinition", + EdgeLabel: "bodySite_reference_SubstanceDefinition", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "ImagingStudySeries|bodySite_reference_Specimen|Specimen": { + FromType: "ImagingStudySeries", + EdgeLabel: "bodySite_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|bodySite_reference_Specimen|ImagingStudySeries": { + FromType: "Specimen", + EdgeLabel: "bodySite_reference_Specimen", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "ImagingStudySeries|bodySite_reference_Observation|Observation": { + FromType: "ImagingStudySeries", + EdgeLabel: "bodySite_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|bodySite_reference_Observation|ImagingStudySeries": { + FromType: "Observation", + EdgeLabel: "bodySite_reference_Observation", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "ImagingStudySeries|bodySite_reference_DiagnosticReport|DiagnosticReport": { + FromType: "ImagingStudySeries", + EdgeLabel: "bodySite_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|bodySite_reference_DiagnosticReport|ImagingStudySeries": { + FromType: "DiagnosticReport", + EdgeLabel: "bodySite_reference_DiagnosticReport", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "ImagingStudySeries|bodySite_reference_Condition|Condition": { + FromType: "ImagingStudySeries", + EdgeLabel: "bodySite_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|bodySite_reference_Condition|ImagingStudySeries": { + FromType: "Condition", + EdgeLabel: "bodySite_reference_Condition", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "ImagingStudySeries|bodySite_reference_Medication|Medication": { + FromType: "ImagingStudySeries", + EdgeLabel: "bodySite_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|bodySite_reference_Medication|ImagingStudySeries": { + FromType: "Medication", + EdgeLabel: "bodySite_reference_Medication", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "ImagingStudySeries|bodySite_reference_MedicationAdministration|MedicationAdministration": { + FromType: "ImagingStudySeries", + EdgeLabel: "bodySite_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|bodySite_reference_MedicationAdministration|ImagingStudySeries": { + FromType: "MedicationAdministration", + EdgeLabel: "bodySite_reference_MedicationAdministration", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "ImagingStudySeries|bodySite_reference_MedicationStatement|MedicationStatement": { + FromType: "ImagingStudySeries", + EdgeLabel: "bodySite_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|bodySite_reference_MedicationStatement|ImagingStudySeries": { + FromType: "MedicationStatement", + EdgeLabel: "bodySite_reference_MedicationStatement", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "ImagingStudySeries|bodySite_reference_MedicationRequest|MedicationRequest": { + FromType: "ImagingStudySeries", + EdgeLabel: "bodySite_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|bodySite_reference_MedicationRequest|ImagingStudySeries": { + FromType: "MedicationRequest", + EdgeLabel: "bodySite_reference_MedicationRequest", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "ImagingStudySeries|bodySite_reference_Procedure|Procedure": { + FromType: "ImagingStudySeries", + EdgeLabel: "bodySite_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|bodySite_reference_Procedure|ImagingStudySeries": { + FromType: "Procedure", + EdgeLabel: "bodySite_reference_Procedure", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "ImagingStudySeries|bodySite_reference_DocumentReference|DocumentReference": { + FromType: "ImagingStudySeries", + EdgeLabel: "bodySite_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|bodySite_reference_DocumentReference|ImagingStudySeries": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_DocumentReference", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "ImagingStudySeries|bodySite_reference_Task|Task": { + FromType: "ImagingStudySeries", + EdgeLabel: "bodySite_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|bodySite_reference_Task|ImagingStudySeries": { + FromType: "Task", + EdgeLabel: "bodySite_reference_Task", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "ImagingStudySeries|bodySite_reference_ImagingStudy|ImagingStudy": { + FromType: "ImagingStudySeries", + EdgeLabel: "bodySite_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|bodySite_reference_ImagingStudy|ImagingStudySeries": { + FromType: "ImagingStudy", + EdgeLabel: "bodySite_reference_ImagingStudy", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudySeries|bodySite_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "ImagingStudySeries", + EdgeLabel: "bodySite_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|bodySite_reference_FamilyMemberHistory|ImagingStudySeries": { + FromType: "FamilyMemberHistory", + EdgeLabel: "bodySite_reference_FamilyMemberHistory", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "ImagingStudySeries|bodySite_reference_BodyStructure|BodyStructure": { + FromType: "ImagingStudySeries", + EdgeLabel: "bodySite_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|bodySite_reference_BodyStructure|ImagingStudySeries": { + FromType: "BodyStructure", + EdgeLabel: "bodySite_reference_BodyStructure", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "ImagingStudySeries|performer_actor_Practitioner|Practitioner": { + FromType: "ImagingStudySeries", + EdgeLabel: "performer_actor_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study_series_performer", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|performer_actor_Practitioner|ImagingStudySeries": { + FromType: "Practitioner", + EdgeLabel: "performer_actor_Practitioner", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study_series_performer", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "ImagingStudySeries|performer_actor_PractitionerRole|PractitionerRole": { + FromType: "ImagingStudySeries", + EdgeLabel: "performer_actor_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study_series_performer", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|performer_actor_PractitionerRole|ImagingStudySeries": { + FromType: "PractitionerRole", + EdgeLabel: "performer_actor_PractitionerRole", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study_series_performer", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "ImagingStudySeries|performer_actor_Organization|Organization": { + FromType: "ImagingStudySeries", + EdgeLabel: "performer_actor_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study_series_performer", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|performer_actor_Organization|ImagingStudySeries": { + FromType: "Organization", + EdgeLabel: "performer_actor_Organization", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study_series_performer", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "ImagingStudySeries|performer_actor_Patient|Patient": { + FromType: "ImagingStudySeries", + EdgeLabel: "performer_actor_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study_series_performer", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|performer_actor_Patient|ImagingStudySeries": { + FromType: "Patient", + EdgeLabel: "performer_actor_Patient", + ToType: "ImagingStudySeries", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study_series_performer", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "ImagingStudySeriesPerformer|actor_Practitioner|Practitioner": { + FromType: "ImagingStudySeriesPerformer", + EdgeLabel: "actor_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study_series_performer", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|actor_Practitioner|ImagingStudySeriesPerformer": { + FromType: "Practitioner", + EdgeLabel: "actor_Practitioner", + ToType: "ImagingStudySeriesPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study_series_performer", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "ImagingStudySeriesPerformer|actor_PractitionerRole|PractitionerRole": { + FromType: "ImagingStudySeriesPerformer", + EdgeLabel: "actor_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study_series_performer", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|actor_PractitionerRole|ImagingStudySeriesPerformer": { + FromType: "PractitionerRole", + EdgeLabel: "actor_PractitionerRole", + ToType: "ImagingStudySeriesPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study_series_performer", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "ImagingStudySeriesPerformer|actor_Organization|Organization": { + FromType: "ImagingStudySeriesPerformer", + EdgeLabel: "actor_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study_series_performer", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|actor_Organization|ImagingStudySeriesPerformer": { + FromType: "Organization", + EdgeLabel: "actor_Organization", + ToType: "ImagingStudySeriesPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study_series_performer", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "ImagingStudySeriesPerformer|actor_Patient|Patient": { + FromType: "ImagingStudySeriesPerformer", + EdgeLabel: "actor_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study_series_performer", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|actor_Patient|ImagingStudySeriesPerformer": { + FromType: "Patient", + EdgeLabel: "actor_Patient", + ToType: "ImagingStudySeriesPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "imaging_study_series_performer", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Medication|marketingAuthorizationHolder|Organization": { + FromType: "Medication", + EdgeLabel: "marketingAuthorizationHolder", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "medication", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|marketingAuthorizationHolder|Medication": { + FromType: "Organization", + EdgeLabel: "marketingAuthorizationHolder", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "medication", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationAdministration|partOf_MedicationAdministration|MedicationAdministration": { + FromType: "MedicationAdministration", + EdgeLabel: "partOf_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "partOf_medication_administration", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|partOf_Procedure|Procedure": { + FromType: "MedicationAdministration", + EdgeLabel: "partOf_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "partOf_medication_administration", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|partOf_Procedure|MedicationAdministration": { + FromType: "Procedure", + EdgeLabel: "partOf_Procedure", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "partOf_medication_administration", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "MedicationAdministration|request|MedicationRequest": { + FromType: "MedicationAdministration", + EdgeLabel: "request", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "medication_administration", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|request|MedicationAdministration": { + FromType: "MedicationRequest", + EdgeLabel: "request", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "medication_administration", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationAdministration|subject_Patient|Patient": { + FromType: "MedicationAdministration", + EdgeLabel: "subject_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "medication_administration", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|subject_Patient|MedicationAdministration": { + FromType: "Patient", + EdgeLabel: "subject_Patient", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "medication_administration", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationAdministration|subject_Group|Group": { + FromType: "MedicationAdministration", + EdgeLabel: "subject_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "medication_administration", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|subject_Group|MedicationAdministration": { + FromType: "Group", + EdgeLabel: "subject_Group", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "medication_administration", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "MedicationAdministration|supportingInformation_Organization|Organization": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|supportingInformation_Organization|MedicationAdministration": { + FromType: "Organization", + EdgeLabel: "supportingInformation_Organization", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationAdministration|supportingInformation_Group|Group": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|supportingInformation_Group|MedicationAdministration": { + FromType: "Group", + EdgeLabel: "supportingInformation_Group", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "MedicationAdministration|supportingInformation_Practitioner|Practitioner": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|supportingInformation_Practitioner|MedicationAdministration": { + FromType: "Practitioner", + EdgeLabel: "supportingInformation_Practitioner", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "MedicationAdministration|supportingInformation_PractitionerRole|PractitionerRole": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|supportingInformation_PractitionerRole|MedicationAdministration": { + FromType: "PractitionerRole", + EdgeLabel: "supportingInformation_PractitionerRole", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "MedicationAdministration|supportingInformation_ResearchStudy|ResearchStudy": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|supportingInformation_ResearchStudy|MedicationAdministration": { + FromType: "ResearchStudy", + EdgeLabel: "supportingInformation_ResearchStudy", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "MedicationAdministration|supportingInformation_Patient|Patient": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|supportingInformation_Patient|MedicationAdministration": { + FromType: "Patient", + EdgeLabel: "supportingInformation_Patient", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationAdministration|supportingInformation_ResearchSubject|ResearchSubject": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|supportingInformation_ResearchSubject|MedicationAdministration": { + FromType: "ResearchSubject", + EdgeLabel: "supportingInformation_ResearchSubject", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "MedicationAdministration|supportingInformation_Substance|Substance": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|supportingInformation_Substance|MedicationAdministration": { + FromType: "Substance", + EdgeLabel: "supportingInformation_Substance", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "MedicationAdministration|supportingInformation_SubstanceDefinition|SubstanceDefinition": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|supportingInformation_SubstanceDefinition|MedicationAdministration": { + FromType: "SubstanceDefinition", + EdgeLabel: "supportingInformation_SubstanceDefinition", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "MedicationAdministration|supportingInformation_Specimen|Specimen": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|supportingInformation_Specimen|MedicationAdministration": { + FromType: "Specimen", + EdgeLabel: "supportingInformation_Specimen", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "MedicationAdministration|supportingInformation_Observation|Observation": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|supportingInformation_Observation|MedicationAdministration": { + FromType: "Observation", + EdgeLabel: "supportingInformation_Observation", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "MedicationAdministration|supportingInformation_DiagnosticReport|DiagnosticReport": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|supportingInformation_DiagnosticReport|MedicationAdministration": { + FromType: "DiagnosticReport", + EdgeLabel: "supportingInformation_DiagnosticReport", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "MedicationAdministration|supportingInformation_Condition|Condition": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|supportingInformation_Condition|MedicationAdministration": { + FromType: "Condition", + EdgeLabel: "supportingInformation_Condition", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "MedicationAdministration|supportingInformation_Medication|Medication": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|supportingInformation_Medication|MedicationAdministration": { + FromType: "Medication", + EdgeLabel: "supportingInformation_Medication", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "MedicationAdministration|supportingInformation_MedicationAdministration|MedicationAdministration": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|supportingInformation_MedicationStatement|MedicationStatement": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|supportingInformation_MedicationStatement|MedicationAdministration": { + FromType: "MedicationStatement", + EdgeLabel: "supportingInformation_MedicationStatement", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationAdministration|supportingInformation_MedicationRequest|MedicationRequest": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|supportingInformation_MedicationRequest|MedicationAdministration": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_MedicationRequest", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationAdministration|supportingInformation_Procedure|Procedure": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|supportingInformation_Procedure|MedicationAdministration": { + FromType: "Procedure", + EdgeLabel: "supportingInformation_Procedure", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "MedicationAdministration|supportingInformation_DocumentReference|DocumentReference": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|supportingInformation_DocumentReference|MedicationAdministration": { + FromType: "DocumentReference", + EdgeLabel: "supportingInformation_DocumentReference", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "MedicationAdministration|supportingInformation_Task|Task": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|supportingInformation_Task|MedicationAdministration": { + FromType: "Task", + EdgeLabel: "supportingInformation_Task", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "MedicationAdministration|supportingInformation_ImagingStudy|ImagingStudy": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|supportingInformation_ImagingStudy|MedicationAdministration": { + FromType: "ImagingStudy", + EdgeLabel: "supportingInformation_ImagingStudy", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "MedicationAdministration|supportingInformation_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|supportingInformation_FamilyMemberHistory|MedicationAdministration": { + FromType: "FamilyMemberHistory", + EdgeLabel: "supportingInformation_FamilyMemberHistory", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "MedicationAdministration|supportingInformation_BodyStructure|BodyStructure": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|supportingInformation_BodyStructure|MedicationAdministration": { + FromType: "BodyStructure", + EdgeLabel: "supportingInformation_BodyStructure", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_administration", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "MedicationAdministration|device_reference_Organization|Organization": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|device_reference_Organization|MedicationAdministration": { + FromType: "Organization", + EdgeLabel: "device_reference_Organization", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationAdministration|device_reference_Group|Group": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|device_reference_Group|MedicationAdministration": { + FromType: "Group", + EdgeLabel: "device_reference_Group", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "MedicationAdministration|device_reference_Practitioner|Practitioner": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|device_reference_Practitioner|MedicationAdministration": { + FromType: "Practitioner", + EdgeLabel: "device_reference_Practitioner", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "MedicationAdministration|device_reference_PractitionerRole|PractitionerRole": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|device_reference_PractitionerRole|MedicationAdministration": { + FromType: "PractitionerRole", + EdgeLabel: "device_reference_PractitionerRole", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "MedicationAdministration|device_reference_ResearchStudy|ResearchStudy": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|device_reference_ResearchStudy|MedicationAdministration": { + FromType: "ResearchStudy", + EdgeLabel: "device_reference_ResearchStudy", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "MedicationAdministration|device_reference_Patient|Patient": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|device_reference_Patient|MedicationAdministration": { + FromType: "Patient", + EdgeLabel: "device_reference_Patient", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationAdministration|device_reference_ResearchSubject|ResearchSubject": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|device_reference_ResearchSubject|MedicationAdministration": { + FromType: "ResearchSubject", + EdgeLabel: "device_reference_ResearchSubject", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "MedicationAdministration|device_reference_Substance|Substance": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|device_reference_Substance|MedicationAdministration": { + FromType: "Substance", + EdgeLabel: "device_reference_Substance", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "MedicationAdministration|device_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|device_reference_SubstanceDefinition|MedicationAdministration": { + FromType: "SubstanceDefinition", + EdgeLabel: "device_reference_SubstanceDefinition", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "MedicationAdministration|device_reference_Specimen|Specimen": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|device_reference_Specimen|MedicationAdministration": { + FromType: "Specimen", + EdgeLabel: "device_reference_Specimen", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "MedicationAdministration|device_reference_Observation|Observation": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|device_reference_Observation|MedicationAdministration": { + FromType: "Observation", + EdgeLabel: "device_reference_Observation", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "MedicationAdministration|device_reference_DiagnosticReport|DiagnosticReport": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|device_reference_DiagnosticReport|MedicationAdministration": { + FromType: "DiagnosticReport", + EdgeLabel: "device_reference_DiagnosticReport", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "MedicationAdministration|device_reference_Condition|Condition": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|device_reference_Condition|MedicationAdministration": { + FromType: "Condition", + EdgeLabel: "device_reference_Condition", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "MedicationAdministration|device_reference_Medication|Medication": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|device_reference_Medication|MedicationAdministration": { + FromType: "Medication", + EdgeLabel: "device_reference_Medication", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "MedicationAdministration|device_reference_MedicationAdministration|MedicationAdministration": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|device_reference_MedicationStatement|MedicationStatement": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|device_reference_MedicationStatement|MedicationAdministration": { + FromType: "MedicationStatement", + EdgeLabel: "device_reference_MedicationStatement", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationAdministration|device_reference_MedicationRequest|MedicationRequest": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|device_reference_MedicationRequest|MedicationAdministration": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_MedicationRequest", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationAdministration|device_reference_Procedure|Procedure": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|device_reference_Procedure|MedicationAdministration": { + FromType: "Procedure", + EdgeLabel: "device_reference_Procedure", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "MedicationAdministration|device_reference_DocumentReference|DocumentReference": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|device_reference_DocumentReference|MedicationAdministration": { + FromType: "DocumentReference", + EdgeLabel: "device_reference_DocumentReference", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "MedicationAdministration|device_reference_Task|Task": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|device_reference_Task|MedicationAdministration": { + FromType: "Task", + EdgeLabel: "device_reference_Task", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "MedicationAdministration|device_reference_ImagingStudy|ImagingStudy": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|device_reference_ImagingStudy|MedicationAdministration": { + FromType: "ImagingStudy", + EdgeLabel: "device_reference_ImagingStudy", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "MedicationAdministration|device_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|device_reference_FamilyMemberHistory|MedicationAdministration": { + FromType: "FamilyMemberHistory", + EdgeLabel: "device_reference_FamilyMemberHistory", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "MedicationAdministration|device_reference_BodyStructure|BodyStructure": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|device_reference_BodyStructure|MedicationAdministration": { + FromType: "BodyStructure", + EdgeLabel: "device_reference_BodyStructure", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "MedicationAdministration|medication_reference_Organization|Organization": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|medication_reference_Organization|MedicationAdministration": { + FromType: "Organization", + EdgeLabel: "medication_reference_Organization", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationAdministration|medication_reference_Group|Group": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|medication_reference_Group|MedicationAdministration": { + FromType: "Group", + EdgeLabel: "medication_reference_Group", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "MedicationAdministration|medication_reference_Practitioner|Practitioner": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|medication_reference_Practitioner|MedicationAdministration": { + FromType: "Practitioner", + EdgeLabel: "medication_reference_Practitioner", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "MedicationAdministration|medication_reference_PractitionerRole|PractitionerRole": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|medication_reference_PractitionerRole|MedicationAdministration": { + FromType: "PractitionerRole", + EdgeLabel: "medication_reference_PractitionerRole", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "MedicationAdministration|medication_reference_ResearchStudy|ResearchStudy": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|medication_reference_ResearchStudy|MedicationAdministration": { + FromType: "ResearchStudy", + EdgeLabel: "medication_reference_ResearchStudy", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "MedicationAdministration|medication_reference_Patient|Patient": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|medication_reference_Patient|MedicationAdministration": { + FromType: "Patient", + EdgeLabel: "medication_reference_Patient", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationAdministration|medication_reference_ResearchSubject|ResearchSubject": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|medication_reference_ResearchSubject|MedicationAdministration": { + FromType: "ResearchSubject", + EdgeLabel: "medication_reference_ResearchSubject", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "MedicationAdministration|medication_reference_Substance|Substance": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|medication_reference_Substance|MedicationAdministration": { + FromType: "Substance", + EdgeLabel: "medication_reference_Substance", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "MedicationAdministration|medication_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|medication_reference_SubstanceDefinition|MedicationAdministration": { + FromType: "SubstanceDefinition", + EdgeLabel: "medication_reference_SubstanceDefinition", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "MedicationAdministration|medication_reference_Specimen|Specimen": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|medication_reference_Specimen|MedicationAdministration": { + FromType: "Specimen", + EdgeLabel: "medication_reference_Specimen", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "MedicationAdministration|medication_reference_Observation|Observation": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|medication_reference_Observation|MedicationAdministration": { + FromType: "Observation", + EdgeLabel: "medication_reference_Observation", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "MedicationAdministration|medication_reference_DiagnosticReport|DiagnosticReport": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|medication_reference_DiagnosticReport|MedicationAdministration": { + FromType: "DiagnosticReport", + EdgeLabel: "medication_reference_DiagnosticReport", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "MedicationAdministration|medication_reference_Condition|Condition": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|medication_reference_Condition|MedicationAdministration": { + FromType: "Condition", + EdgeLabel: "medication_reference_Condition", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "MedicationAdministration|medication_reference_Medication|Medication": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|medication_reference_Medication|MedicationAdministration": { + FromType: "Medication", + EdgeLabel: "medication_reference_Medication", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "MedicationAdministration|medication_reference_MedicationAdministration|MedicationAdministration": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|medication_reference_MedicationStatement|MedicationStatement": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|medication_reference_MedicationStatement|MedicationAdministration": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_MedicationStatement", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationAdministration|medication_reference_MedicationRequest|MedicationRequest": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|medication_reference_MedicationRequest|MedicationAdministration": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_MedicationRequest", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationAdministration|medication_reference_Procedure|Procedure": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|medication_reference_Procedure|MedicationAdministration": { + FromType: "Procedure", + EdgeLabel: "medication_reference_Procedure", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "MedicationAdministration|medication_reference_DocumentReference|DocumentReference": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|medication_reference_DocumentReference|MedicationAdministration": { + FromType: "DocumentReference", + EdgeLabel: "medication_reference_DocumentReference", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "MedicationAdministration|medication_reference_Task|Task": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|medication_reference_Task|MedicationAdministration": { + FromType: "Task", + EdgeLabel: "medication_reference_Task", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "MedicationAdministration|medication_reference_ImagingStudy|ImagingStudy": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|medication_reference_ImagingStudy|MedicationAdministration": { + FromType: "ImagingStudy", + EdgeLabel: "medication_reference_ImagingStudy", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "MedicationAdministration|medication_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|medication_reference_FamilyMemberHistory|MedicationAdministration": { + FromType: "FamilyMemberHistory", + EdgeLabel: "medication_reference_FamilyMemberHistory", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "MedicationAdministration|medication_reference_BodyStructure|BodyStructure": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|medication_reference_BodyStructure|MedicationAdministration": { + FromType: "BodyStructure", + EdgeLabel: "medication_reference_BodyStructure", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "MedicationAdministration|note_authorReference_Practitioner|Practitioner": { + FromType: "MedicationAdministration", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|note_authorReference_Practitioner|MedicationAdministration": { + FromType: "Practitioner", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "MedicationAdministration|note_authorReference_PractitionerRole|PractitionerRole": { + FromType: "MedicationAdministration", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|note_authorReference_PractitionerRole|MedicationAdministration": { + FromType: "PractitionerRole", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "MedicationAdministration|note_authorReference_Patient|Patient": { + FromType: "MedicationAdministration", + EdgeLabel: "note_authorReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|note_authorReference_Patient|MedicationAdministration": { + FromType: "Patient", + EdgeLabel: "note_authorReference_Patient", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationAdministration|note_authorReference_Organization|Organization": { + FromType: "MedicationAdministration", + EdgeLabel: "note_authorReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|note_authorReference_Organization|MedicationAdministration": { + FromType: "Organization", + EdgeLabel: "note_authorReference_Organization", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationAdministration|reason_reference_Organization|Organization": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|reason_reference_Organization|MedicationAdministration": { + FromType: "Organization", + EdgeLabel: "reason_reference_Organization", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationAdministration|reason_reference_Group|Group": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|reason_reference_Group|MedicationAdministration": { + FromType: "Group", + EdgeLabel: "reason_reference_Group", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "MedicationAdministration|reason_reference_Practitioner|Practitioner": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|reason_reference_Practitioner|MedicationAdministration": { + FromType: "Practitioner", + EdgeLabel: "reason_reference_Practitioner", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "MedicationAdministration|reason_reference_PractitionerRole|PractitionerRole": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|reason_reference_PractitionerRole|MedicationAdministration": { + FromType: "PractitionerRole", + EdgeLabel: "reason_reference_PractitionerRole", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "MedicationAdministration|reason_reference_ResearchStudy|ResearchStudy": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|reason_reference_ResearchStudy|MedicationAdministration": { + FromType: "ResearchStudy", + EdgeLabel: "reason_reference_ResearchStudy", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "MedicationAdministration|reason_reference_Patient|Patient": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|reason_reference_Patient|MedicationAdministration": { + FromType: "Patient", + EdgeLabel: "reason_reference_Patient", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationAdministration|reason_reference_ResearchSubject|ResearchSubject": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|reason_reference_ResearchSubject|MedicationAdministration": { + FromType: "ResearchSubject", + EdgeLabel: "reason_reference_ResearchSubject", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "MedicationAdministration|reason_reference_Substance|Substance": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|reason_reference_Substance|MedicationAdministration": { + FromType: "Substance", + EdgeLabel: "reason_reference_Substance", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "MedicationAdministration|reason_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|reason_reference_SubstanceDefinition|MedicationAdministration": { + FromType: "SubstanceDefinition", + EdgeLabel: "reason_reference_SubstanceDefinition", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "MedicationAdministration|reason_reference_Specimen|Specimen": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|reason_reference_Specimen|MedicationAdministration": { + FromType: "Specimen", + EdgeLabel: "reason_reference_Specimen", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "MedicationAdministration|reason_reference_Observation|Observation": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|reason_reference_Observation|MedicationAdministration": { + FromType: "Observation", + EdgeLabel: "reason_reference_Observation", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "MedicationAdministration|reason_reference_DiagnosticReport|DiagnosticReport": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|reason_reference_DiagnosticReport|MedicationAdministration": { + FromType: "DiagnosticReport", + EdgeLabel: "reason_reference_DiagnosticReport", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "MedicationAdministration|reason_reference_Condition|Condition": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|reason_reference_Condition|MedicationAdministration": { + FromType: "Condition", + EdgeLabel: "reason_reference_Condition", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "MedicationAdministration|reason_reference_Medication|Medication": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|reason_reference_Medication|MedicationAdministration": { + FromType: "Medication", + EdgeLabel: "reason_reference_Medication", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "MedicationAdministration|reason_reference_MedicationAdministration|MedicationAdministration": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|reason_reference_MedicationStatement|MedicationStatement": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|reason_reference_MedicationStatement|MedicationAdministration": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_MedicationStatement", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationAdministration|reason_reference_MedicationRequest|MedicationRequest": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|reason_reference_MedicationRequest|MedicationAdministration": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_MedicationRequest", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationAdministration|reason_reference_Procedure|Procedure": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|reason_reference_Procedure|MedicationAdministration": { + FromType: "Procedure", + EdgeLabel: "reason_reference_Procedure", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "MedicationAdministration|reason_reference_DocumentReference|DocumentReference": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|reason_reference_DocumentReference|MedicationAdministration": { + FromType: "DocumentReference", + EdgeLabel: "reason_reference_DocumentReference", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "MedicationAdministration|reason_reference_Task|Task": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|reason_reference_Task|MedicationAdministration": { + FromType: "Task", + EdgeLabel: "reason_reference_Task", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "MedicationAdministration|reason_reference_ImagingStudy|ImagingStudy": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|reason_reference_ImagingStudy|MedicationAdministration": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_ImagingStudy", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "MedicationAdministration|reason_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|reason_reference_FamilyMemberHistory|MedicationAdministration": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_FamilyMemberHistory", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "MedicationAdministration|reason_reference_BodyStructure|BodyStructure": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|reason_reference_BodyStructure|MedicationAdministration": { + FromType: "BodyStructure", + EdgeLabel: "reason_reference_BodyStructure", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "MedicationAdministrationPerformer|actor_reference_Organization|Organization": { + FromType: "MedicationAdministrationPerformer", + EdgeLabel: "actor_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|actor_reference_Organization|MedicationAdministrationPerformer": { + FromType: "Organization", + EdgeLabel: "actor_reference_Organization", + ToType: "MedicationAdministrationPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationAdministrationPerformer|actor_reference_Group|Group": { + FromType: "MedicationAdministrationPerformer", + EdgeLabel: "actor_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|actor_reference_Group|MedicationAdministrationPerformer": { + FromType: "Group", + EdgeLabel: "actor_reference_Group", + ToType: "MedicationAdministrationPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "MedicationAdministrationPerformer|actor_reference_Practitioner|Practitioner": { + FromType: "MedicationAdministrationPerformer", + EdgeLabel: "actor_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|actor_reference_Practitioner|MedicationAdministrationPerformer": { + FromType: "Practitioner", + EdgeLabel: "actor_reference_Practitioner", + ToType: "MedicationAdministrationPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "MedicationAdministrationPerformer|actor_reference_PractitionerRole|PractitionerRole": { + FromType: "MedicationAdministrationPerformer", + EdgeLabel: "actor_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|actor_reference_PractitionerRole|MedicationAdministrationPerformer": { + FromType: "PractitionerRole", + EdgeLabel: "actor_reference_PractitionerRole", + ToType: "MedicationAdministrationPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "MedicationAdministrationPerformer|actor_reference_ResearchStudy|ResearchStudy": { + FromType: "MedicationAdministrationPerformer", + EdgeLabel: "actor_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|actor_reference_ResearchStudy|MedicationAdministrationPerformer": { + FromType: "ResearchStudy", + EdgeLabel: "actor_reference_ResearchStudy", + ToType: "MedicationAdministrationPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "MedicationAdministrationPerformer|actor_reference_Patient|Patient": { + FromType: "MedicationAdministrationPerformer", + EdgeLabel: "actor_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|actor_reference_Patient|MedicationAdministrationPerformer": { + FromType: "Patient", + EdgeLabel: "actor_reference_Patient", + ToType: "MedicationAdministrationPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationAdministrationPerformer|actor_reference_ResearchSubject|ResearchSubject": { + FromType: "MedicationAdministrationPerformer", + EdgeLabel: "actor_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|actor_reference_ResearchSubject|MedicationAdministrationPerformer": { + FromType: "ResearchSubject", + EdgeLabel: "actor_reference_ResearchSubject", + ToType: "MedicationAdministrationPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "MedicationAdministrationPerformer|actor_reference_Substance|Substance": { + FromType: "MedicationAdministrationPerformer", + EdgeLabel: "actor_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|actor_reference_Substance|MedicationAdministrationPerformer": { + FromType: "Substance", + EdgeLabel: "actor_reference_Substance", + ToType: "MedicationAdministrationPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "MedicationAdministrationPerformer|actor_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "MedicationAdministrationPerformer", + EdgeLabel: "actor_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|actor_reference_SubstanceDefinition|MedicationAdministrationPerformer": { + FromType: "SubstanceDefinition", + EdgeLabel: "actor_reference_SubstanceDefinition", + ToType: "MedicationAdministrationPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "MedicationAdministrationPerformer|actor_reference_Specimen|Specimen": { + FromType: "MedicationAdministrationPerformer", + EdgeLabel: "actor_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|actor_reference_Specimen|MedicationAdministrationPerformer": { + FromType: "Specimen", + EdgeLabel: "actor_reference_Specimen", + ToType: "MedicationAdministrationPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "MedicationAdministrationPerformer|actor_reference_Observation|Observation": { + FromType: "MedicationAdministrationPerformer", + EdgeLabel: "actor_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|actor_reference_Observation|MedicationAdministrationPerformer": { + FromType: "Observation", + EdgeLabel: "actor_reference_Observation", + ToType: "MedicationAdministrationPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "MedicationAdministrationPerformer|actor_reference_DiagnosticReport|DiagnosticReport": { + FromType: "MedicationAdministrationPerformer", + EdgeLabel: "actor_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|actor_reference_DiagnosticReport|MedicationAdministrationPerformer": { + FromType: "DiagnosticReport", + EdgeLabel: "actor_reference_DiagnosticReport", + ToType: "MedicationAdministrationPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "MedicationAdministrationPerformer|actor_reference_Condition|Condition": { + FromType: "MedicationAdministrationPerformer", + EdgeLabel: "actor_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|actor_reference_Condition|MedicationAdministrationPerformer": { + FromType: "Condition", + EdgeLabel: "actor_reference_Condition", + ToType: "MedicationAdministrationPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "MedicationAdministrationPerformer|actor_reference_Medication|Medication": { + FromType: "MedicationAdministrationPerformer", + EdgeLabel: "actor_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|actor_reference_Medication|MedicationAdministrationPerformer": { + FromType: "Medication", + EdgeLabel: "actor_reference_Medication", + ToType: "MedicationAdministrationPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "MedicationAdministrationPerformer|actor_reference_MedicationAdministration|MedicationAdministration": { + FromType: "MedicationAdministrationPerformer", + EdgeLabel: "actor_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|actor_reference_MedicationAdministration|MedicationAdministrationPerformer": { + FromType: "MedicationAdministration", + EdgeLabel: "actor_reference_MedicationAdministration", + ToType: "MedicationAdministrationPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministrationPerformer|actor_reference_MedicationStatement|MedicationStatement": { + FromType: "MedicationAdministrationPerformer", + EdgeLabel: "actor_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|actor_reference_MedicationStatement|MedicationAdministrationPerformer": { + FromType: "MedicationStatement", + EdgeLabel: "actor_reference_MedicationStatement", + ToType: "MedicationAdministrationPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationAdministrationPerformer|actor_reference_MedicationRequest|MedicationRequest": { + FromType: "MedicationAdministrationPerformer", + EdgeLabel: "actor_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|actor_reference_MedicationRequest|MedicationAdministrationPerformer": { + FromType: "MedicationRequest", + EdgeLabel: "actor_reference_MedicationRequest", + ToType: "MedicationAdministrationPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationAdministrationPerformer|actor_reference_Procedure|Procedure": { + FromType: "MedicationAdministrationPerformer", + EdgeLabel: "actor_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|actor_reference_Procedure|MedicationAdministrationPerformer": { + FromType: "Procedure", + EdgeLabel: "actor_reference_Procedure", + ToType: "MedicationAdministrationPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "MedicationAdministrationPerformer|actor_reference_DocumentReference|DocumentReference": { + FromType: "MedicationAdministrationPerformer", + EdgeLabel: "actor_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|actor_reference_DocumentReference|MedicationAdministrationPerformer": { + FromType: "DocumentReference", + EdgeLabel: "actor_reference_DocumentReference", + ToType: "MedicationAdministrationPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "MedicationAdministrationPerformer|actor_reference_Task|Task": { + FromType: "MedicationAdministrationPerformer", + EdgeLabel: "actor_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|actor_reference_Task|MedicationAdministrationPerformer": { + FromType: "Task", + EdgeLabel: "actor_reference_Task", + ToType: "MedicationAdministrationPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "MedicationAdministrationPerformer|actor_reference_ImagingStudy|ImagingStudy": { + FromType: "MedicationAdministrationPerformer", + EdgeLabel: "actor_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|actor_reference_ImagingStudy|MedicationAdministrationPerformer": { + FromType: "ImagingStudy", + EdgeLabel: "actor_reference_ImagingStudy", + ToType: "MedicationAdministrationPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "MedicationAdministrationPerformer|actor_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "MedicationAdministrationPerformer", + EdgeLabel: "actor_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|actor_reference_FamilyMemberHistory|MedicationAdministrationPerformer": { + FromType: "FamilyMemberHistory", + EdgeLabel: "actor_reference_FamilyMemberHistory", + ToType: "MedicationAdministrationPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "MedicationAdministrationPerformer|actor_reference_BodyStructure|BodyStructure": { + FromType: "MedicationAdministrationPerformer", + EdgeLabel: "actor_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|actor_reference_BodyStructure|MedicationAdministrationPerformer": { + FromType: "BodyStructure", + EdgeLabel: "actor_reference_BodyStructure", + ToType: "MedicationAdministrationPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "MedicationIngredient|item_reference_Organization|Organization": { + FromType: "MedicationIngredient", + EdgeLabel: "item_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|item_reference_Organization|MedicationIngredient": { + FromType: "Organization", + EdgeLabel: "item_reference_Organization", + ToType: "MedicationIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationIngredient|item_reference_Group|Group": { + FromType: "MedicationIngredient", + EdgeLabel: "item_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|item_reference_Group|MedicationIngredient": { + FromType: "Group", + EdgeLabel: "item_reference_Group", + ToType: "MedicationIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "MedicationIngredient|item_reference_Practitioner|Practitioner": { + FromType: "MedicationIngredient", + EdgeLabel: "item_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|item_reference_Practitioner|MedicationIngredient": { + FromType: "Practitioner", + EdgeLabel: "item_reference_Practitioner", + ToType: "MedicationIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "MedicationIngredient|item_reference_PractitionerRole|PractitionerRole": { + FromType: "MedicationIngredient", + EdgeLabel: "item_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|item_reference_PractitionerRole|MedicationIngredient": { + FromType: "PractitionerRole", + EdgeLabel: "item_reference_PractitionerRole", + ToType: "MedicationIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "MedicationIngredient|item_reference_ResearchStudy|ResearchStudy": { + FromType: "MedicationIngredient", + EdgeLabel: "item_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|item_reference_ResearchStudy|MedicationIngredient": { + FromType: "ResearchStudy", + EdgeLabel: "item_reference_ResearchStudy", + ToType: "MedicationIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "MedicationIngredient|item_reference_Patient|Patient": { + FromType: "MedicationIngredient", + EdgeLabel: "item_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|item_reference_Patient|MedicationIngredient": { + FromType: "Patient", + EdgeLabel: "item_reference_Patient", + ToType: "MedicationIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationIngredient|item_reference_ResearchSubject|ResearchSubject": { + FromType: "MedicationIngredient", + EdgeLabel: "item_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|item_reference_ResearchSubject|MedicationIngredient": { + FromType: "ResearchSubject", + EdgeLabel: "item_reference_ResearchSubject", + ToType: "MedicationIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "MedicationIngredient|item_reference_Substance|Substance": { + FromType: "MedicationIngredient", + EdgeLabel: "item_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|item_reference_Substance|MedicationIngredient": { + FromType: "Substance", + EdgeLabel: "item_reference_Substance", + ToType: "MedicationIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "MedicationIngredient|item_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "MedicationIngredient", + EdgeLabel: "item_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|item_reference_SubstanceDefinition|MedicationIngredient": { + FromType: "SubstanceDefinition", + EdgeLabel: "item_reference_SubstanceDefinition", + ToType: "MedicationIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "MedicationIngredient|item_reference_Specimen|Specimen": { + FromType: "MedicationIngredient", + EdgeLabel: "item_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|item_reference_Specimen|MedicationIngredient": { + FromType: "Specimen", + EdgeLabel: "item_reference_Specimen", + ToType: "MedicationIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "MedicationIngredient|item_reference_Observation|Observation": { + FromType: "MedicationIngredient", + EdgeLabel: "item_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|item_reference_Observation|MedicationIngredient": { + FromType: "Observation", + EdgeLabel: "item_reference_Observation", + ToType: "MedicationIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "MedicationIngredient|item_reference_DiagnosticReport|DiagnosticReport": { + FromType: "MedicationIngredient", + EdgeLabel: "item_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|item_reference_DiagnosticReport|MedicationIngredient": { + FromType: "DiagnosticReport", + EdgeLabel: "item_reference_DiagnosticReport", + ToType: "MedicationIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "MedicationIngredient|item_reference_Condition|Condition": { + FromType: "MedicationIngredient", + EdgeLabel: "item_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|item_reference_Condition|MedicationIngredient": { + FromType: "Condition", + EdgeLabel: "item_reference_Condition", + ToType: "MedicationIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "MedicationIngredient|item_reference_Medication|Medication": { + FromType: "MedicationIngredient", + EdgeLabel: "item_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|item_reference_Medication|MedicationIngredient": { + FromType: "Medication", + EdgeLabel: "item_reference_Medication", + ToType: "MedicationIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "MedicationIngredient|item_reference_MedicationAdministration|MedicationAdministration": { + FromType: "MedicationIngredient", + EdgeLabel: "item_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|item_reference_MedicationAdministration|MedicationIngredient": { + FromType: "MedicationAdministration", + EdgeLabel: "item_reference_MedicationAdministration", + ToType: "MedicationIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationIngredient|item_reference_MedicationStatement|MedicationStatement": { + FromType: "MedicationIngredient", + EdgeLabel: "item_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|item_reference_MedicationStatement|MedicationIngredient": { + FromType: "MedicationStatement", + EdgeLabel: "item_reference_MedicationStatement", + ToType: "MedicationIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationIngredient|item_reference_MedicationRequest|MedicationRequest": { + FromType: "MedicationIngredient", + EdgeLabel: "item_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|item_reference_MedicationRequest|MedicationIngredient": { + FromType: "MedicationRequest", + EdgeLabel: "item_reference_MedicationRequest", + ToType: "MedicationIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationIngredient|item_reference_Procedure|Procedure": { + FromType: "MedicationIngredient", + EdgeLabel: "item_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|item_reference_Procedure|MedicationIngredient": { + FromType: "Procedure", + EdgeLabel: "item_reference_Procedure", + ToType: "MedicationIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "MedicationIngredient|item_reference_DocumentReference|DocumentReference": { + FromType: "MedicationIngredient", + EdgeLabel: "item_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|item_reference_DocumentReference|MedicationIngredient": { + FromType: "DocumentReference", + EdgeLabel: "item_reference_DocumentReference", + ToType: "MedicationIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "MedicationIngredient|item_reference_Task|Task": { + FromType: "MedicationIngredient", + EdgeLabel: "item_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|item_reference_Task|MedicationIngredient": { + FromType: "Task", + EdgeLabel: "item_reference_Task", + ToType: "MedicationIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "MedicationIngredient|item_reference_ImagingStudy|ImagingStudy": { + FromType: "MedicationIngredient", + EdgeLabel: "item_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|item_reference_ImagingStudy|MedicationIngredient": { + FromType: "ImagingStudy", + EdgeLabel: "item_reference_ImagingStudy", + ToType: "MedicationIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "MedicationIngredient|item_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "MedicationIngredient", + EdgeLabel: "item_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|item_reference_FamilyMemberHistory|MedicationIngredient": { + FromType: "FamilyMemberHistory", + EdgeLabel: "item_reference_FamilyMemberHistory", + ToType: "MedicationIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "MedicationIngredient|item_reference_BodyStructure|BodyStructure": { + FromType: "MedicationIngredient", + EdgeLabel: "item_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|item_reference_BodyStructure|MedicationIngredient": { + FromType: "BodyStructure", + EdgeLabel: "item_reference_BodyStructure", + ToType: "MedicationIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "MedicationRequest|basedOn_MedicationRequest|MedicationRequest": { + FromType: "MedicationRequest", + EdgeLabel: "basedOn_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_medication_request", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|informationSource_Patient|Patient": { + FromType: "MedicationRequest", + EdgeLabel: "informationSource_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "informationSource_medication_request", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|informationSource_Patient|MedicationRequest": { + FromType: "Patient", + EdgeLabel: "informationSource_Patient", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "informationSource_medication_request", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationRequest|informationSource_Practitioner|Practitioner": { + FromType: "MedicationRequest", + EdgeLabel: "informationSource_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "informationSource_medication_request", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|informationSource_Practitioner|MedicationRequest": { + FromType: "Practitioner", + EdgeLabel: "informationSource_Practitioner", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "informationSource_medication_request", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "MedicationRequest|informationSource_PractitionerRole|PractitionerRole": { + FromType: "MedicationRequest", + EdgeLabel: "informationSource_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "informationSource_medication_request", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|informationSource_PractitionerRole|MedicationRequest": { + FromType: "PractitionerRole", + EdgeLabel: "informationSource_PractitionerRole", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "informationSource_medication_request", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "MedicationRequest|informationSource_Organization|Organization": { + FromType: "MedicationRequest", + EdgeLabel: "informationSource_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "informationSource_medication_request", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|informationSource_Organization|MedicationRequest": { + FromType: "Organization", + EdgeLabel: "informationSource_Organization", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "informationSource_medication_request", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationRequest|performer_Practitioner|Practitioner": { + FromType: "MedicationRequest", + EdgeLabel: "performer_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "performer_medication_request", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|performer_Practitioner|MedicationRequest": { + FromType: "Practitioner", + EdgeLabel: "performer_Practitioner", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "performer_medication_request", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "MedicationRequest|performer_PractitionerRole|PractitionerRole": { + FromType: "MedicationRequest", + EdgeLabel: "performer_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "performer_medication_request", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|performer_PractitionerRole|MedicationRequest": { + FromType: "PractitionerRole", + EdgeLabel: "performer_PractitionerRole", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "performer_medication_request", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "MedicationRequest|performer_Organization|Organization": { + FromType: "MedicationRequest", + EdgeLabel: "performer_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "performer_medication_request", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|performer_Organization|MedicationRequest": { + FromType: "Organization", + EdgeLabel: "performer_Organization", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "performer_medication_request", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationRequest|performer_Patient|Patient": { + FromType: "MedicationRequest", + EdgeLabel: "performer_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "performer_medication_request", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|performer_Patient|MedicationRequest": { + FromType: "Patient", + EdgeLabel: "performer_Patient", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "performer_medication_request", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationRequest|priorPrescription|MedicationRequest": { + FromType: "MedicationRequest", + EdgeLabel: "priorPrescription", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "priorPrescription_medication_request", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|recorder_Practitioner|Practitioner": { + FromType: "MedicationRequest", + EdgeLabel: "recorder_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "recorder_medication_request", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|recorder_Practitioner|MedicationRequest": { + FromType: "Practitioner", + EdgeLabel: "recorder_Practitioner", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "recorder_medication_request", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "MedicationRequest|recorder_PractitionerRole|PractitionerRole": { + FromType: "MedicationRequest", + EdgeLabel: "recorder_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "recorder_medication_request", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|recorder_PractitionerRole|MedicationRequest": { + FromType: "PractitionerRole", + EdgeLabel: "recorder_PractitionerRole", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "recorder_medication_request", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "MedicationRequest|requester_Practitioner|Practitioner": { + FromType: "MedicationRequest", + EdgeLabel: "requester_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "requester_medication_request", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|requester_Practitioner|MedicationRequest": { + FromType: "Practitioner", + EdgeLabel: "requester_Practitioner", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "requester_medication_request", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "MedicationRequest|requester_PractitionerRole|PractitionerRole": { + FromType: "MedicationRequest", + EdgeLabel: "requester_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "requester_medication_request", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|requester_PractitionerRole|MedicationRequest": { + FromType: "PractitionerRole", + EdgeLabel: "requester_PractitionerRole", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "requester_medication_request", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "MedicationRequest|requester_Organization|Organization": { + FromType: "MedicationRequest", + EdgeLabel: "requester_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "requester_medication_request", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|requester_Organization|MedicationRequest": { + FromType: "Organization", + EdgeLabel: "requester_Organization", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "requester_medication_request", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationRequest|requester_Patient|Patient": { + FromType: "MedicationRequest", + EdgeLabel: "requester_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "requester_medication_request", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|requester_Patient|MedicationRequest": { + FromType: "Patient", + EdgeLabel: "requester_Patient", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "requester_medication_request", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationRequest|subject_Patient|Patient": { + FromType: "MedicationRequest", + EdgeLabel: "subject_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_medication_request", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|subject_Patient|MedicationRequest": { + FromType: "Patient", + EdgeLabel: "subject_Patient", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_medication_request", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationRequest|subject_Group|Group": { + FromType: "MedicationRequest", + EdgeLabel: "subject_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_medication_request", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|subject_Group|MedicationRequest": { + FromType: "Group", + EdgeLabel: "subject_Group", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_medication_request", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "MedicationRequest|supportingInformation_Organization|Organization": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|supportingInformation_Organization|MedicationRequest": { + FromType: "Organization", + EdgeLabel: "supportingInformation_Organization", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationRequest|supportingInformation_Group|Group": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|supportingInformation_Group|MedicationRequest": { + FromType: "Group", + EdgeLabel: "supportingInformation_Group", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "MedicationRequest|supportingInformation_Practitioner|Practitioner": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|supportingInformation_Practitioner|MedicationRequest": { + FromType: "Practitioner", + EdgeLabel: "supportingInformation_Practitioner", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "MedicationRequest|supportingInformation_PractitionerRole|PractitionerRole": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|supportingInformation_PractitionerRole|MedicationRequest": { + FromType: "PractitionerRole", + EdgeLabel: "supportingInformation_PractitionerRole", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "MedicationRequest|supportingInformation_ResearchStudy|ResearchStudy": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|supportingInformation_ResearchStudy|MedicationRequest": { + FromType: "ResearchStudy", + EdgeLabel: "supportingInformation_ResearchStudy", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "MedicationRequest|supportingInformation_Patient|Patient": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|supportingInformation_Patient|MedicationRequest": { + FromType: "Patient", + EdgeLabel: "supportingInformation_Patient", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationRequest|supportingInformation_ResearchSubject|ResearchSubject": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|supportingInformation_ResearchSubject|MedicationRequest": { + FromType: "ResearchSubject", + EdgeLabel: "supportingInformation_ResearchSubject", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "MedicationRequest|supportingInformation_Substance|Substance": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|supportingInformation_Substance|MedicationRequest": { + FromType: "Substance", + EdgeLabel: "supportingInformation_Substance", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "MedicationRequest|supportingInformation_SubstanceDefinition|SubstanceDefinition": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|supportingInformation_SubstanceDefinition|MedicationRequest": { + FromType: "SubstanceDefinition", + EdgeLabel: "supportingInformation_SubstanceDefinition", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "MedicationRequest|supportingInformation_Specimen|Specimen": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|supportingInformation_Specimen|MedicationRequest": { + FromType: "Specimen", + EdgeLabel: "supportingInformation_Specimen", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "MedicationRequest|supportingInformation_Observation|Observation": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|supportingInformation_Observation|MedicationRequest": { + FromType: "Observation", + EdgeLabel: "supportingInformation_Observation", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "MedicationRequest|supportingInformation_DiagnosticReport|DiagnosticReport": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|supportingInformation_DiagnosticReport|MedicationRequest": { + FromType: "DiagnosticReport", + EdgeLabel: "supportingInformation_DiagnosticReport", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "MedicationRequest|supportingInformation_Condition|Condition": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|supportingInformation_Condition|MedicationRequest": { + FromType: "Condition", + EdgeLabel: "supportingInformation_Condition", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "MedicationRequest|supportingInformation_Medication|Medication": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|supportingInformation_Medication|MedicationRequest": { + FromType: "Medication", + EdgeLabel: "supportingInformation_Medication", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "MedicationRequest|supportingInformation_MedicationAdministration|MedicationAdministration": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|supportingInformation_MedicationAdministration|MedicationRequest": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInformation_MedicationAdministration", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationRequest|supportingInformation_MedicationStatement|MedicationStatement": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|supportingInformation_MedicationStatement|MedicationRequest": { + FromType: "MedicationStatement", + EdgeLabel: "supportingInformation_MedicationStatement", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationRequest|supportingInformation_MedicationRequest|MedicationRequest": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|supportingInformation_Procedure|Procedure": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|supportingInformation_Procedure|MedicationRequest": { + FromType: "Procedure", + EdgeLabel: "supportingInformation_Procedure", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "MedicationRequest|supportingInformation_DocumentReference|DocumentReference": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|supportingInformation_DocumentReference|MedicationRequest": { + FromType: "DocumentReference", + EdgeLabel: "supportingInformation_DocumentReference", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "MedicationRequest|supportingInformation_Task|Task": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|supportingInformation_Task|MedicationRequest": { + FromType: "Task", + EdgeLabel: "supportingInformation_Task", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "MedicationRequest|supportingInformation_ImagingStudy|ImagingStudy": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|supportingInformation_ImagingStudy|MedicationRequest": { + FromType: "ImagingStudy", + EdgeLabel: "supportingInformation_ImagingStudy", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "MedicationRequest|supportingInformation_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|supportingInformation_FamilyMemberHistory|MedicationRequest": { + FromType: "FamilyMemberHistory", + EdgeLabel: "supportingInformation_FamilyMemberHistory", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "MedicationRequest|supportingInformation_BodyStructure|BodyStructure": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInformation_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|supportingInformation_BodyStructure|MedicationRequest": { + FromType: "BodyStructure", + EdgeLabel: "supportingInformation_BodyStructure", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInformation_medication_request", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "MedicationRequest|device_reference_Organization|Organization": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|device_reference_Organization|MedicationRequest": { + FromType: "Organization", + EdgeLabel: "device_reference_Organization", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationRequest|device_reference_Group|Group": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|device_reference_Group|MedicationRequest": { + FromType: "Group", + EdgeLabel: "device_reference_Group", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "MedicationRequest|device_reference_Practitioner|Practitioner": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|device_reference_Practitioner|MedicationRequest": { + FromType: "Practitioner", + EdgeLabel: "device_reference_Practitioner", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "MedicationRequest|device_reference_PractitionerRole|PractitionerRole": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|device_reference_PractitionerRole|MedicationRequest": { + FromType: "PractitionerRole", + EdgeLabel: "device_reference_PractitionerRole", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "MedicationRequest|device_reference_ResearchStudy|ResearchStudy": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|device_reference_ResearchStudy|MedicationRequest": { + FromType: "ResearchStudy", + EdgeLabel: "device_reference_ResearchStudy", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "MedicationRequest|device_reference_Patient|Patient": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|device_reference_Patient|MedicationRequest": { + FromType: "Patient", + EdgeLabel: "device_reference_Patient", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationRequest|device_reference_ResearchSubject|ResearchSubject": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|device_reference_ResearchSubject|MedicationRequest": { + FromType: "ResearchSubject", + EdgeLabel: "device_reference_ResearchSubject", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "MedicationRequest|device_reference_Substance|Substance": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|device_reference_Substance|MedicationRequest": { + FromType: "Substance", + EdgeLabel: "device_reference_Substance", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "MedicationRequest|device_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|device_reference_SubstanceDefinition|MedicationRequest": { + FromType: "SubstanceDefinition", + EdgeLabel: "device_reference_SubstanceDefinition", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "MedicationRequest|device_reference_Specimen|Specimen": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|device_reference_Specimen|MedicationRequest": { + FromType: "Specimen", + EdgeLabel: "device_reference_Specimen", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "MedicationRequest|device_reference_Observation|Observation": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|device_reference_Observation|MedicationRequest": { + FromType: "Observation", + EdgeLabel: "device_reference_Observation", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "MedicationRequest|device_reference_DiagnosticReport|DiagnosticReport": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|device_reference_DiagnosticReport|MedicationRequest": { + FromType: "DiagnosticReport", + EdgeLabel: "device_reference_DiagnosticReport", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "MedicationRequest|device_reference_Condition|Condition": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|device_reference_Condition|MedicationRequest": { + FromType: "Condition", + EdgeLabel: "device_reference_Condition", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "MedicationRequest|device_reference_Medication|Medication": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|device_reference_Medication|MedicationRequest": { + FromType: "Medication", + EdgeLabel: "device_reference_Medication", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "MedicationRequest|device_reference_MedicationAdministration|MedicationAdministration": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|device_reference_MedicationAdministration|MedicationRequest": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_MedicationAdministration", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationRequest|device_reference_MedicationStatement|MedicationStatement": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|device_reference_MedicationStatement|MedicationRequest": { + FromType: "MedicationStatement", + EdgeLabel: "device_reference_MedicationStatement", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationRequest|device_reference_MedicationRequest|MedicationRequest": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|device_reference_Procedure|Procedure": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|device_reference_Procedure|MedicationRequest": { + FromType: "Procedure", + EdgeLabel: "device_reference_Procedure", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "MedicationRequest|device_reference_DocumentReference|DocumentReference": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|device_reference_DocumentReference|MedicationRequest": { + FromType: "DocumentReference", + EdgeLabel: "device_reference_DocumentReference", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "MedicationRequest|device_reference_Task|Task": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|device_reference_Task|MedicationRequest": { + FromType: "Task", + EdgeLabel: "device_reference_Task", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "MedicationRequest|device_reference_ImagingStudy|ImagingStudy": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|device_reference_ImagingStudy|MedicationRequest": { + FromType: "ImagingStudy", + EdgeLabel: "device_reference_ImagingStudy", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "MedicationRequest|device_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|device_reference_FamilyMemberHistory|MedicationRequest": { + FromType: "FamilyMemberHistory", + EdgeLabel: "device_reference_FamilyMemberHistory", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "MedicationRequest|device_reference_BodyStructure|BodyStructure": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|device_reference_BodyStructure|MedicationRequest": { + FromType: "BodyStructure", + EdgeLabel: "device_reference_BodyStructure", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "MedicationRequest|dispenseRequest_dispenser|Organization": { + FromType: "MedicationRequest", + EdgeLabel: "dispenseRequest_dispenser", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "medication_request_dispense_request", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|dispenseRequest_dispenser|MedicationRequest": { + FromType: "Organization", + EdgeLabel: "dispenseRequest_dispenser", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "medication_request_dispense_request", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationRequest|medication_reference_Organization|Organization": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|medication_reference_Organization|MedicationRequest": { + FromType: "Organization", + EdgeLabel: "medication_reference_Organization", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationRequest|medication_reference_Group|Group": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|medication_reference_Group|MedicationRequest": { + FromType: "Group", + EdgeLabel: "medication_reference_Group", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "MedicationRequest|medication_reference_Practitioner|Practitioner": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|medication_reference_Practitioner|MedicationRequest": { + FromType: "Practitioner", + EdgeLabel: "medication_reference_Practitioner", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "MedicationRequest|medication_reference_PractitionerRole|PractitionerRole": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|medication_reference_PractitionerRole|MedicationRequest": { + FromType: "PractitionerRole", + EdgeLabel: "medication_reference_PractitionerRole", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "MedicationRequest|medication_reference_ResearchStudy|ResearchStudy": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|medication_reference_ResearchStudy|MedicationRequest": { + FromType: "ResearchStudy", + EdgeLabel: "medication_reference_ResearchStudy", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "MedicationRequest|medication_reference_Patient|Patient": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|medication_reference_Patient|MedicationRequest": { + FromType: "Patient", + EdgeLabel: "medication_reference_Patient", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationRequest|medication_reference_ResearchSubject|ResearchSubject": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|medication_reference_ResearchSubject|MedicationRequest": { + FromType: "ResearchSubject", + EdgeLabel: "medication_reference_ResearchSubject", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "MedicationRequest|medication_reference_Substance|Substance": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|medication_reference_Substance|MedicationRequest": { + FromType: "Substance", + EdgeLabel: "medication_reference_Substance", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "MedicationRequest|medication_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|medication_reference_SubstanceDefinition|MedicationRequest": { + FromType: "SubstanceDefinition", + EdgeLabel: "medication_reference_SubstanceDefinition", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "MedicationRequest|medication_reference_Specimen|Specimen": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|medication_reference_Specimen|MedicationRequest": { + FromType: "Specimen", + EdgeLabel: "medication_reference_Specimen", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "MedicationRequest|medication_reference_Observation|Observation": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|medication_reference_Observation|MedicationRequest": { + FromType: "Observation", + EdgeLabel: "medication_reference_Observation", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "MedicationRequest|medication_reference_DiagnosticReport|DiagnosticReport": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|medication_reference_DiagnosticReport|MedicationRequest": { + FromType: "DiagnosticReport", + EdgeLabel: "medication_reference_DiagnosticReport", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "MedicationRequest|medication_reference_Condition|Condition": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|medication_reference_Condition|MedicationRequest": { + FromType: "Condition", + EdgeLabel: "medication_reference_Condition", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "MedicationRequest|medication_reference_Medication|Medication": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|medication_reference_Medication|MedicationRequest": { + FromType: "Medication", + EdgeLabel: "medication_reference_Medication", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "MedicationRequest|medication_reference_MedicationAdministration|MedicationAdministration": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|medication_reference_MedicationAdministration|MedicationRequest": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_MedicationAdministration", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationRequest|medication_reference_MedicationStatement|MedicationStatement": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|medication_reference_MedicationStatement|MedicationRequest": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_MedicationStatement", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationRequest|medication_reference_MedicationRequest|MedicationRequest": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|medication_reference_Procedure|Procedure": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|medication_reference_Procedure|MedicationRequest": { + FromType: "Procedure", + EdgeLabel: "medication_reference_Procedure", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "MedicationRequest|medication_reference_DocumentReference|DocumentReference": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|medication_reference_DocumentReference|MedicationRequest": { + FromType: "DocumentReference", + EdgeLabel: "medication_reference_DocumentReference", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "MedicationRequest|medication_reference_Task|Task": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|medication_reference_Task|MedicationRequest": { + FromType: "Task", + EdgeLabel: "medication_reference_Task", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "MedicationRequest|medication_reference_ImagingStudy|ImagingStudy": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|medication_reference_ImagingStudy|MedicationRequest": { + FromType: "ImagingStudy", + EdgeLabel: "medication_reference_ImagingStudy", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "MedicationRequest|medication_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|medication_reference_FamilyMemberHistory|MedicationRequest": { + FromType: "FamilyMemberHistory", + EdgeLabel: "medication_reference_FamilyMemberHistory", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "MedicationRequest|medication_reference_BodyStructure|BodyStructure": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|medication_reference_BodyStructure|MedicationRequest": { + FromType: "BodyStructure", + EdgeLabel: "medication_reference_BodyStructure", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "MedicationRequest|note_authorReference_Practitioner|Practitioner": { + FromType: "MedicationRequest", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|note_authorReference_Practitioner|MedicationRequest": { + FromType: "Practitioner", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "MedicationRequest|note_authorReference_PractitionerRole|PractitionerRole": { + FromType: "MedicationRequest", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|note_authorReference_PractitionerRole|MedicationRequest": { + FromType: "PractitionerRole", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "MedicationRequest|note_authorReference_Patient|Patient": { + FromType: "MedicationRequest", + EdgeLabel: "note_authorReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|note_authorReference_Patient|MedicationRequest": { + FromType: "Patient", + EdgeLabel: "note_authorReference_Patient", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationRequest|note_authorReference_Organization|Organization": { + FromType: "MedicationRequest", + EdgeLabel: "note_authorReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|note_authorReference_Organization|MedicationRequest": { + FromType: "Organization", + EdgeLabel: "note_authorReference_Organization", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationRequest|reason_reference_Organization|Organization": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|reason_reference_Organization|MedicationRequest": { + FromType: "Organization", + EdgeLabel: "reason_reference_Organization", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationRequest|reason_reference_Group|Group": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|reason_reference_Group|MedicationRequest": { + FromType: "Group", + EdgeLabel: "reason_reference_Group", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "MedicationRequest|reason_reference_Practitioner|Practitioner": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|reason_reference_Practitioner|MedicationRequest": { + FromType: "Practitioner", + EdgeLabel: "reason_reference_Practitioner", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "MedicationRequest|reason_reference_PractitionerRole|PractitionerRole": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|reason_reference_PractitionerRole|MedicationRequest": { + FromType: "PractitionerRole", + EdgeLabel: "reason_reference_PractitionerRole", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "MedicationRequest|reason_reference_ResearchStudy|ResearchStudy": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|reason_reference_ResearchStudy|MedicationRequest": { + FromType: "ResearchStudy", + EdgeLabel: "reason_reference_ResearchStudy", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "MedicationRequest|reason_reference_Patient|Patient": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|reason_reference_Patient|MedicationRequest": { + FromType: "Patient", + EdgeLabel: "reason_reference_Patient", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationRequest|reason_reference_ResearchSubject|ResearchSubject": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|reason_reference_ResearchSubject|MedicationRequest": { + FromType: "ResearchSubject", + EdgeLabel: "reason_reference_ResearchSubject", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "MedicationRequest|reason_reference_Substance|Substance": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|reason_reference_Substance|MedicationRequest": { + FromType: "Substance", + EdgeLabel: "reason_reference_Substance", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "MedicationRequest|reason_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|reason_reference_SubstanceDefinition|MedicationRequest": { + FromType: "SubstanceDefinition", + EdgeLabel: "reason_reference_SubstanceDefinition", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "MedicationRequest|reason_reference_Specimen|Specimen": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|reason_reference_Specimen|MedicationRequest": { + FromType: "Specimen", + EdgeLabel: "reason_reference_Specimen", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "MedicationRequest|reason_reference_Observation|Observation": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|reason_reference_Observation|MedicationRequest": { + FromType: "Observation", + EdgeLabel: "reason_reference_Observation", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "MedicationRequest|reason_reference_DiagnosticReport|DiagnosticReport": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|reason_reference_DiagnosticReport|MedicationRequest": { + FromType: "DiagnosticReport", + EdgeLabel: "reason_reference_DiagnosticReport", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "MedicationRequest|reason_reference_Condition|Condition": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|reason_reference_Condition|MedicationRequest": { + FromType: "Condition", + EdgeLabel: "reason_reference_Condition", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "MedicationRequest|reason_reference_Medication|Medication": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|reason_reference_Medication|MedicationRequest": { + FromType: "Medication", + EdgeLabel: "reason_reference_Medication", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "MedicationRequest|reason_reference_MedicationAdministration|MedicationAdministration": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|reason_reference_MedicationAdministration|MedicationRequest": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_MedicationAdministration", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationRequest|reason_reference_MedicationStatement|MedicationStatement": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|reason_reference_MedicationStatement|MedicationRequest": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_MedicationStatement", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationRequest|reason_reference_MedicationRequest|MedicationRequest": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|reason_reference_Procedure|Procedure": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|reason_reference_Procedure|MedicationRequest": { + FromType: "Procedure", + EdgeLabel: "reason_reference_Procedure", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "MedicationRequest|reason_reference_DocumentReference|DocumentReference": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|reason_reference_DocumentReference|MedicationRequest": { + FromType: "DocumentReference", + EdgeLabel: "reason_reference_DocumentReference", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "MedicationRequest|reason_reference_Task|Task": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|reason_reference_Task|MedicationRequest": { + FromType: "Task", + EdgeLabel: "reason_reference_Task", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "MedicationRequest|reason_reference_ImagingStudy|ImagingStudy": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|reason_reference_ImagingStudy|MedicationRequest": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_ImagingStudy", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "MedicationRequest|reason_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|reason_reference_FamilyMemberHistory|MedicationRequest": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_FamilyMemberHistory", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "MedicationRequest|reason_reference_BodyStructure|BodyStructure": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|reason_reference_BodyStructure|MedicationRequest": { + FromType: "BodyStructure", + EdgeLabel: "reason_reference_BodyStructure", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "MedicationRequestDispenseRequest|dispenser|Organization": { + FromType: "MedicationRequestDispenseRequest", + EdgeLabel: "dispenser", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "medication_request_dispense_request", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|dispenser|MedicationRequestDispenseRequest": { + FromType: "Organization", + EdgeLabel: "dispenser", + ToType: "MedicationRequestDispenseRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "medication_request_dispense_request", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationRequestDispenseRequest|dispenserInstruction_authorReference_Practitioner|Practitioner": { + FromType: "MedicationRequestDispenseRequest", + EdgeLabel: "dispenserInstruction_authorReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|dispenserInstruction_authorReference_Practitioner|MedicationRequestDispenseRequest": { + FromType: "Practitioner", + EdgeLabel: "dispenserInstruction_authorReference_Practitioner", + ToType: "MedicationRequestDispenseRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "MedicationRequestDispenseRequest|dispenserInstruction_authorReference_PractitionerRole|PractitionerRole": { + FromType: "MedicationRequestDispenseRequest", + EdgeLabel: "dispenserInstruction_authorReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|dispenserInstruction_authorReference_PractitionerRole|MedicationRequestDispenseRequest": { + FromType: "PractitionerRole", + EdgeLabel: "dispenserInstruction_authorReference_PractitionerRole", + ToType: "MedicationRequestDispenseRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "MedicationRequestDispenseRequest|dispenserInstruction_authorReference_Patient|Patient": { + FromType: "MedicationRequestDispenseRequest", + EdgeLabel: "dispenserInstruction_authorReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|dispenserInstruction_authorReference_Patient|MedicationRequestDispenseRequest": { + FromType: "Patient", + EdgeLabel: "dispenserInstruction_authorReference_Patient", + ToType: "MedicationRequestDispenseRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationRequestDispenseRequest|dispenserInstruction_authorReference_Organization|Organization": { + FromType: "MedicationRequestDispenseRequest", + EdgeLabel: "dispenserInstruction_authorReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|dispenserInstruction_authorReference_Organization|MedicationRequestDispenseRequest": { + FromType: "Organization", + EdgeLabel: "dispenserInstruction_authorReference_Organization", + ToType: "MedicationRequestDispenseRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationStatement|derivedFrom_Organization|Organization": { + FromType: "MedicationStatement", + EdgeLabel: "derivedFrom_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|derivedFrom_Organization|MedicationStatement": { + FromType: "Organization", + EdgeLabel: "derivedFrom_Organization", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationStatement|derivedFrom_Group|Group": { + FromType: "MedicationStatement", + EdgeLabel: "derivedFrom_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|derivedFrom_Group|MedicationStatement": { + FromType: "Group", + EdgeLabel: "derivedFrom_Group", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "MedicationStatement|derivedFrom_Practitioner|Practitioner": { + FromType: "MedicationStatement", + EdgeLabel: "derivedFrom_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|derivedFrom_Practitioner|MedicationStatement": { + FromType: "Practitioner", + EdgeLabel: "derivedFrom_Practitioner", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "MedicationStatement|derivedFrom_PractitionerRole|PractitionerRole": { + FromType: "MedicationStatement", + EdgeLabel: "derivedFrom_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|derivedFrom_PractitionerRole|MedicationStatement": { + FromType: "PractitionerRole", + EdgeLabel: "derivedFrom_PractitionerRole", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "MedicationStatement|derivedFrom_ResearchStudy|ResearchStudy": { + FromType: "MedicationStatement", + EdgeLabel: "derivedFrom_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|derivedFrom_ResearchStudy|MedicationStatement": { + FromType: "ResearchStudy", + EdgeLabel: "derivedFrom_ResearchStudy", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "MedicationStatement|derivedFrom_Patient|Patient": { + FromType: "MedicationStatement", + EdgeLabel: "derivedFrom_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|derivedFrom_Patient|MedicationStatement": { + FromType: "Patient", + EdgeLabel: "derivedFrom_Patient", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationStatement|derivedFrom_ResearchSubject|ResearchSubject": { + FromType: "MedicationStatement", + EdgeLabel: "derivedFrom_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|derivedFrom_ResearchSubject|MedicationStatement": { + FromType: "ResearchSubject", + EdgeLabel: "derivedFrom_ResearchSubject", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "MedicationStatement|derivedFrom_Substance|Substance": { + FromType: "MedicationStatement", + EdgeLabel: "derivedFrom_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|derivedFrom_Substance|MedicationStatement": { + FromType: "Substance", + EdgeLabel: "derivedFrom_Substance", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "MedicationStatement|derivedFrom_SubstanceDefinition|SubstanceDefinition": { + FromType: "MedicationStatement", + EdgeLabel: "derivedFrom_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|derivedFrom_SubstanceDefinition|MedicationStatement": { + FromType: "SubstanceDefinition", + EdgeLabel: "derivedFrom_SubstanceDefinition", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "MedicationStatement|derivedFrom_Specimen|Specimen": { + FromType: "MedicationStatement", + EdgeLabel: "derivedFrom_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|derivedFrom_Specimen|MedicationStatement": { + FromType: "Specimen", + EdgeLabel: "derivedFrom_Specimen", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "MedicationStatement|derivedFrom_Observation|Observation": { + FromType: "MedicationStatement", + EdgeLabel: "derivedFrom_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|derivedFrom_Observation|MedicationStatement": { + FromType: "Observation", + EdgeLabel: "derivedFrom_Observation", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "MedicationStatement|derivedFrom_DiagnosticReport|DiagnosticReport": { + FromType: "MedicationStatement", + EdgeLabel: "derivedFrom_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|derivedFrom_DiagnosticReport|MedicationStatement": { + FromType: "DiagnosticReport", + EdgeLabel: "derivedFrom_DiagnosticReport", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "MedicationStatement|derivedFrom_Condition|Condition": { + FromType: "MedicationStatement", + EdgeLabel: "derivedFrom_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|derivedFrom_Condition|MedicationStatement": { + FromType: "Condition", + EdgeLabel: "derivedFrom_Condition", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "MedicationStatement|derivedFrom_Medication|Medication": { + FromType: "MedicationStatement", + EdgeLabel: "derivedFrom_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|derivedFrom_Medication|MedicationStatement": { + FromType: "Medication", + EdgeLabel: "derivedFrom_Medication", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "MedicationStatement|derivedFrom_MedicationAdministration|MedicationAdministration": { + FromType: "MedicationStatement", + EdgeLabel: "derivedFrom_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|derivedFrom_MedicationAdministration|MedicationStatement": { + FromType: "MedicationAdministration", + EdgeLabel: "derivedFrom_MedicationAdministration", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationStatement|derivedFrom_MedicationStatement|MedicationStatement": { + FromType: "MedicationStatement", + EdgeLabel: "derivedFrom_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|derivedFrom_MedicationRequest|MedicationRequest": { + FromType: "MedicationStatement", + EdgeLabel: "derivedFrom_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|derivedFrom_MedicationRequest|MedicationStatement": { + FromType: "MedicationRequest", + EdgeLabel: "derivedFrom_MedicationRequest", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationStatement|derivedFrom_Procedure|Procedure": { + FromType: "MedicationStatement", + EdgeLabel: "derivedFrom_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|derivedFrom_Procedure|MedicationStatement": { + FromType: "Procedure", + EdgeLabel: "derivedFrom_Procedure", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "MedicationStatement|derivedFrom_DocumentReference|DocumentReference": { + FromType: "MedicationStatement", + EdgeLabel: "derivedFrom_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|derivedFrom_DocumentReference|MedicationStatement": { + FromType: "DocumentReference", + EdgeLabel: "derivedFrom_DocumentReference", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "MedicationStatement|derivedFrom_Task|Task": { + FromType: "MedicationStatement", + EdgeLabel: "derivedFrom_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|derivedFrom_Task|MedicationStatement": { + FromType: "Task", + EdgeLabel: "derivedFrom_Task", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "MedicationStatement|derivedFrom_ImagingStudy|ImagingStudy": { + FromType: "MedicationStatement", + EdgeLabel: "derivedFrom_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|derivedFrom_ImagingStudy|MedicationStatement": { + FromType: "ImagingStudy", + EdgeLabel: "derivedFrom_ImagingStudy", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "MedicationStatement|derivedFrom_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "MedicationStatement", + EdgeLabel: "derivedFrom_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|derivedFrom_FamilyMemberHistory|MedicationStatement": { + FromType: "FamilyMemberHistory", + EdgeLabel: "derivedFrom_FamilyMemberHistory", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "MedicationStatement|derivedFrom_BodyStructure|BodyStructure": { + FromType: "MedicationStatement", + EdgeLabel: "derivedFrom_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|derivedFrom_BodyStructure|MedicationStatement": { + FromType: "BodyStructure", + EdgeLabel: "derivedFrom_BodyStructure", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_medication_statement", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "MedicationStatement|informationSource_Patient|Patient": { + FromType: "MedicationStatement", + EdgeLabel: "informationSource_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "informationSource_medication_statement", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|informationSource_Patient|MedicationStatement": { + FromType: "Patient", + EdgeLabel: "informationSource_Patient", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "informationSource_medication_statement", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationStatement|informationSource_Practitioner|Practitioner": { + FromType: "MedicationStatement", + EdgeLabel: "informationSource_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "informationSource_medication_statement", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|informationSource_Practitioner|MedicationStatement": { + FromType: "Practitioner", + EdgeLabel: "informationSource_Practitioner", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "informationSource_medication_statement", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "MedicationStatement|informationSource_PractitionerRole|PractitionerRole": { + FromType: "MedicationStatement", + EdgeLabel: "informationSource_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "informationSource_medication_statement", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|informationSource_PractitionerRole|MedicationStatement": { + FromType: "PractitionerRole", + EdgeLabel: "informationSource_PractitionerRole", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "informationSource_medication_statement", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "MedicationStatement|informationSource_Organization|Organization": { + FromType: "MedicationStatement", + EdgeLabel: "informationSource_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "informationSource_medication_statement", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|informationSource_Organization|MedicationStatement": { + FromType: "Organization", + EdgeLabel: "informationSource_Organization", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "informationSource_medication_statement", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationStatement|partOf_Procedure|Procedure": { + FromType: "MedicationStatement", + EdgeLabel: "partOf_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "partOf_medication_statement", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|partOf_Procedure|MedicationStatement": { + FromType: "Procedure", + EdgeLabel: "partOf_Procedure", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "partOf_medication_statement", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "MedicationStatement|partOf_MedicationStatement|MedicationStatement": { + FromType: "MedicationStatement", + EdgeLabel: "partOf_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "partOf_medication_statement", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|relatedClinicalInformation_Observation|Observation": { + FromType: "MedicationStatement", + EdgeLabel: "relatedClinicalInformation_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "relatedClinicalInformation_medication_statement", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|relatedClinicalInformation_Observation|MedicationStatement": { + FromType: "Observation", + EdgeLabel: "relatedClinicalInformation_Observation", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "relatedClinicalInformation_medication_statement", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "MedicationStatement|relatedClinicalInformation_Condition|Condition": { + FromType: "MedicationStatement", + EdgeLabel: "relatedClinicalInformation_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "relatedClinicalInformation_medication_statement", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|relatedClinicalInformation_Condition|MedicationStatement": { + FromType: "Condition", + EdgeLabel: "relatedClinicalInformation_Condition", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "relatedClinicalInformation_medication_statement", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "MedicationStatement|subject_Patient|Patient": { + FromType: "MedicationStatement", + EdgeLabel: "subject_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_medication_statement", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|subject_Patient|MedicationStatement": { + FromType: "Patient", + EdgeLabel: "subject_Patient", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_medication_statement", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationStatement|subject_Group|Group": { + FromType: "MedicationStatement", + EdgeLabel: "subject_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_medication_statement", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|subject_Group|MedicationStatement": { + FromType: "Group", + EdgeLabel: "subject_Group", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_medication_statement", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "MedicationStatement|medication_reference_Organization|Organization": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|medication_reference_Organization|MedicationStatement": { + FromType: "Organization", + EdgeLabel: "medication_reference_Organization", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationStatement|medication_reference_Group|Group": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|medication_reference_Group|MedicationStatement": { + FromType: "Group", + EdgeLabel: "medication_reference_Group", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "MedicationStatement|medication_reference_Practitioner|Practitioner": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|medication_reference_Practitioner|MedicationStatement": { + FromType: "Practitioner", + EdgeLabel: "medication_reference_Practitioner", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "MedicationStatement|medication_reference_PractitionerRole|PractitionerRole": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|medication_reference_PractitionerRole|MedicationStatement": { + FromType: "PractitionerRole", + EdgeLabel: "medication_reference_PractitionerRole", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "MedicationStatement|medication_reference_ResearchStudy|ResearchStudy": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|medication_reference_ResearchStudy|MedicationStatement": { + FromType: "ResearchStudy", + EdgeLabel: "medication_reference_ResearchStudy", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "MedicationStatement|medication_reference_Patient|Patient": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|medication_reference_Patient|MedicationStatement": { + FromType: "Patient", + EdgeLabel: "medication_reference_Patient", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationStatement|medication_reference_ResearchSubject|ResearchSubject": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|medication_reference_ResearchSubject|MedicationStatement": { + FromType: "ResearchSubject", + EdgeLabel: "medication_reference_ResearchSubject", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "MedicationStatement|medication_reference_Substance|Substance": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|medication_reference_Substance|MedicationStatement": { + FromType: "Substance", + EdgeLabel: "medication_reference_Substance", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "MedicationStatement|medication_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|medication_reference_SubstanceDefinition|MedicationStatement": { + FromType: "SubstanceDefinition", + EdgeLabel: "medication_reference_SubstanceDefinition", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "MedicationStatement|medication_reference_Specimen|Specimen": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|medication_reference_Specimen|MedicationStatement": { + FromType: "Specimen", + EdgeLabel: "medication_reference_Specimen", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "MedicationStatement|medication_reference_Observation|Observation": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|medication_reference_Observation|MedicationStatement": { + FromType: "Observation", + EdgeLabel: "medication_reference_Observation", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "MedicationStatement|medication_reference_DiagnosticReport|DiagnosticReport": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|medication_reference_DiagnosticReport|MedicationStatement": { + FromType: "DiagnosticReport", + EdgeLabel: "medication_reference_DiagnosticReport", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "MedicationStatement|medication_reference_Condition|Condition": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|medication_reference_Condition|MedicationStatement": { + FromType: "Condition", + EdgeLabel: "medication_reference_Condition", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "MedicationStatement|medication_reference_Medication|Medication": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|medication_reference_Medication|MedicationStatement": { + FromType: "Medication", + EdgeLabel: "medication_reference_Medication", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "MedicationStatement|medication_reference_MedicationAdministration|MedicationAdministration": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|medication_reference_MedicationAdministration|MedicationStatement": { + FromType: "MedicationAdministration", + EdgeLabel: "medication_reference_MedicationAdministration", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationStatement|medication_reference_MedicationStatement|MedicationStatement": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|medication_reference_MedicationRequest|MedicationRequest": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|medication_reference_MedicationRequest|MedicationStatement": { + FromType: "MedicationRequest", + EdgeLabel: "medication_reference_MedicationRequest", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationStatement|medication_reference_Procedure|Procedure": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|medication_reference_Procedure|MedicationStatement": { + FromType: "Procedure", + EdgeLabel: "medication_reference_Procedure", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "MedicationStatement|medication_reference_DocumentReference|DocumentReference": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|medication_reference_DocumentReference|MedicationStatement": { + FromType: "DocumentReference", + EdgeLabel: "medication_reference_DocumentReference", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "MedicationStatement|medication_reference_Task|Task": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|medication_reference_Task|MedicationStatement": { + FromType: "Task", + EdgeLabel: "medication_reference_Task", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "MedicationStatement|medication_reference_ImagingStudy|ImagingStudy": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|medication_reference_ImagingStudy|MedicationStatement": { + FromType: "ImagingStudy", + EdgeLabel: "medication_reference_ImagingStudy", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "MedicationStatement|medication_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|medication_reference_FamilyMemberHistory|MedicationStatement": { + FromType: "FamilyMemberHistory", + EdgeLabel: "medication_reference_FamilyMemberHistory", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "MedicationStatement|medication_reference_BodyStructure|BodyStructure": { + FromType: "MedicationStatement", + EdgeLabel: "medication_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|medication_reference_BodyStructure|MedicationStatement": { + FromType: "BodyStructure", + EdgeLabel: "medication_reference_BodyStructure", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "MedicationStatement|note_authorReference_Practitioner|Practitioner": { + FromType: "MedicationStatement", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|note_authorReference_Practitioner|MedicationStatement": { + FromType: "Practitioner", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "MedicationStatement|note_authorReference_PractitionerRole|PractitionerRole": { + FromType: "MedicationStatement", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|note_authorReference_PractitionerRole|MedicationStatement": { + FromType: "PractitionerRole", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "MedicationStatement|note_authorReference_Patient|Patient": { + FromType: "MedicationStatement", + EdgeLabel: "note_authorReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|note_authorReference_Patient|MedicationStatement": { + FromType: "Patient", + EdgeLabel: "note_authorReference_Patient", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationStatement|note_authorReference_Organization|Organization": { + FromType: "MedicationStatement", + EdgeLabel: "note_authorReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|note_authorReference_Organization|MedicationStatement": { + FromType: "Organization", + EdgeLabel: "note_authorReference_Organization", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationStatement|reason_reference_Organization|Organization": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|reason_reference_Organization|MedicationStatement": { + FromType: "Organization", + EdgeLabel: "reason_reference_Organization", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "MedicationStatement|reason_reference_Group|Group": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|reason_reference_Group|MedicationStatement": { + FromType: "Group", + EdgeLabel: "reason_reference_Group", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "MedicationStatement|reason_reference_Practitioner|Practitioner": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|reason_reference_Practitioner|MedicationStatement": { + FromType: "Practitioner", + EdgeLabel: "reason_reference_Practitioner", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "MedicationStatement|reason_reference_PractitionerRole|PractitionerRole": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|reason_reference_PractitionerRole|MedicationStatement": { + FromType: "PractitionerRole", + EdgeLabel: "reason_reference_PractitionerRole", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "MedicationStatement|reason_reference_ResearchStudy|ResearchStudy": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|reason_reference_ResearchStudy|MedicationStatement": { + FromType: "ResearchStudy", + EdgeLabel: "reason_reference_ResearchStudy", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "MedicationStatement|reason_reference_Patient|Patient": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|reason_reference_Patient|MedicationStatement": { + FromType: "Patient", + EdgeLabel: "reason_reference_Patient", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "MedicationStatement|reason_reference_ResearchSubject|ResearchSubject": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|reason_reference_ResearchSubject|MedicationStatement": { + FromType: "ResearchSubject", + EdgeLabel: "reason_reference_ResearchSubject", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "MedicationStatement|reason_reference_Substance|Substance": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|reason_reference_Substance|MedicationStatement": { + FromType: "Substance", + EdgeLabel: "reason_reference_Substance", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "MedicationStatement|reason_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|reason_reference_SubstanceDefinition|MedicationStatement": { + FromType: "SubstanceDefinition", + EdgeLabel: "reason_reference_SubstanceDefinition", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "MedicationStatement|reason_reference_Specimen|Specimen": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|reason_reference_Specimen|MedicationStatement": { + FromType: "Specimen", + EdgeLabel: "reason_reference_Specimen", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "MedicationStatement|reason_reference_Observation|Observation": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|reason_reference_Observation|MedicationStatement": { + FromType: "Observation", + EdgeLabel: "reason_reference_Observation", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "MedicationStatement|reason_reference_DiagnosticReport|DiagnosticReport": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|reason_reference_DiagnosticReport|MedicationStatement": { + FromType: "DiagnosticReport", + EdgeLabel: "reason_reference_DiagnosticReport", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "MedicationStatement|reason_reference_Condition|Condition": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|reason_reference_Condition|MedicationStatement": { + FromType: "Condition", + EdgeLabel: "reason_reference_Condition", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "MedicationStatement|reason_reference_Medication|Medication": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|reason_reference_Medication|MedicationStatement": { + FromType: "Medication", + EdgeLabel: "reason_reference_Medication", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "MedicationStatement|reason_reference_MedicationAdministration|MedicationAdministration": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|reason_reference_MedicationAdministration|MedicationStatement": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_MedicationAdministration", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationStatement|reason_reference_MedicationStatement|MedicationStatement": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|reason_reference_MedicationRequest|MedicationRequest": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|reason_reference_MedicationRequest|MedicationStatement": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_MedicationRequest", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationStatement|reason_reference_Procedure|Procedure": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|reason_reference_Procedure|MedicationStatement": { + FromType: "Procedure", + EdgeLabel: "reason_reference_Procedure", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "MedicationStatement|reason_reference_DocumentReference|DocumentReference": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|reason_reference_DocumentReference|MedicationStatement": { + FromType: "DocumentReference", + EdgeLabel: "reason_reference_DocumentReference", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "MedicationStatement|reason_reference_Task|Task": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|reason_reference_Task|MedicationStatement": { + FromType: "Task", + EdgeLabel: "reason_reference_Task", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "MedicationStatement|reason_reference_ImagingStudy|ImagingStudy": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|reason_reference_ImagingStudy|MedicationStatement": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_ImagingStudy", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "MedicationStatement|reason_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|reason_reference_FamilyMemberHistory|MedicationStatement": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_FamilyMemberHistory", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "MedicationStatement|reason_reference_BodyStructure|BodyStructure": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|reason_reference_BodyStructure|MedicationStatement": { + FromType: "BodyStructure", + EdgeLabel: "reason_reference_BodyStructure", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "Observation|basedOn_MedicationRequest|MedicationRequest": { + FromType: "Observation", + EdgeLabel: "basedOn_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_observation", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|basedOn_MedicationRequest|Observation": { + FromType: "MedicationRequest", + EdgeLabel: "basedOn_MedicationRequest", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_observation", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "Observation|bodyStructure|BodyStructure": { + FromType: "Observation", + EdgeLabel: "bodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "observation", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|bodyStructure|Observation": { + FromType: "BodyStructure", + EdgeLabel: "bodyStructure", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "observation", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "Observation|derivedFrom_DocumentReference|DocumentReference": { + FromType: "Observation", + EdgeLabel: "derivedFrom_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_observation", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|derivedFrom_DocumentReference|Observation": { + FromType: "DocumentReference", + EdgeLabel: "derivedFrom_DocumentReference", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_observation", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "Observation|derivedFrom_ImagingStudy|ImagingStudy": { + FromType: "Observation", + EdgeLabel: "derivedFrom_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_observation", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|derivedFrom_ImagingStudy|Observation": { + FromType: "ImagingStudy", + EdgeLabel: "derivedFrom_ImagingStudy", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_observation", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "Observation|derivedFrom_Observation|Observation": { + FromType: "Observation", + EdgeLabel: "derivedFrom_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "derivedFrom_observation", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|focus_Organization|Organization": { + FromType: "Observation", + EdgeLabel: "focus_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|focus_Organization|Observation": { + FromType: "Organization", + EdgeLabel: "focus_Organization", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Observation|focus_Group|Group": { + FromType: "Observation", + EdgeLabel: "focus_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|focus_Group|Observation": { + FromType: "Group", + EdgeLabel: "focus_Group", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Observation|focus_Practitioner|Practitioner": { + FromType: "Observation", + EdgeLabel: "focus_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|focus_Practitioner|Observation": { + FromType: "Practitioner", + EdgeLabel: "focus_Practitioner", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Observation|focus_PractitionerRole|PractitionerRole": { + FromType: "Observation", + EdgeLabel: "focus_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|focus_PractitionerRole|Observation": { + FromType: "PractitionerRole", + EdgeLabel: "focus_PractitionerRole", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Observation|focus_ResearchStudy|ResearchStudy": { + FromType: "Observation", + EdgeLabel: "focus_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|focus_ResearchStudy|Observation": { + FromType: "ResearchStudy", + EdgeLabel: "focus_ResearchStudy", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "Observation|focus_Patient|Patient": { + FromType: "Observation", + EdgeLabel: "focus_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|focus_Patient|Observation": { + FromType: "Patient", + EdgeLabel: "focus_Patient", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Observation|focus_ResearchSubject|ResearchSubject": { + FromType: "Observation", + EdgeLabel: "focus_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|focus_ResearchSubject|Observation": { + FromType: "ResearchSubject", + EdgeLabel: "focus_ResearchSubject", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "Observation|focus_Substance|Substance": { + FromType: "Observation", + EdgeLabel: "focus_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|focus_Substance|Observation": { + FromType: "Substance", + EdgeLabel: "focus_Substance", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Observation|focus_SubstanceDefinition|SubstanceDefinition": { + FromType: "Observation", + EdgeLabel: "focus_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|focus_SubstanceDefinition|Observation": { + FromType: "SubstanceDefinition", + EdgeLabel: "focus_SubstanceDefinition", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "Observation|focus_Specimen|Specimen": { + FromType: "Observation", + EdgeLabel: "focus_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|focus_Specimen|Observation": { + FromType: "Specimen", + EdgeLabel: "focus_Specimen", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Observation|focus_Observation|Observation": { + FromType: "Observation", + EdgeLabel: "focus_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|focus_DiagnosticReport|DiagnosticReport": { + FromType: "Observation", + EdgeLabel: "focus_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|focus_DiagnosticReport|Observation": { + FromType: "DiagnosticReport", + EdgeLabel: "focus_DiagnosticReport", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "Observation|focus_Condition|Condition": { + FromType: "Observation", + EdgeLabel: "focus_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|focus_Condition|Observation": { + FromType: "Condition", + EdgeLabel: "focus_Condition", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Observation|focus_Medication|Medication": { + FromType: "Observation", + EdgeLabel: "focus_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|focus_Medication|Observation": { + FromType: "Medication", + EdgeLabel: "focus_Medication", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Observation|focus_MedicationAdministration|MedicationAdministration": { + FromType: "Observation", + EdgeLabel: "focus_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|focus_MedicationAdministration|Observation": { + FromType: "MedicationAdministration", + EdgeLabel: "focus_MedicationAdministration", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "Observation|focus_MedicationStatement|MedicationStatement": { + FromType: "Observation", + EdgeLabel: "focus_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|focus_MedicationStatement|Observation": { + FromType: "MedicationStatement", + EdgeLabel: "focus_MedicationStatement", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "Observation|focus_MedicationRequest|MedicationRequest": { + FromType: "Observation", + EdgeLabel: "focus_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|focus_MedicationRequest|Observation": { + FromType: "MedicationRequest", + EdgeLabel: "focus_MedicationRequest", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "Observation|focus_Procedure|Procedure": { + FromType: "Observation", + EdgeLabel: "focus_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|focus_Procedure|Observation": { + FromType: "Procedure", + EdgeLabel: "focus_Procedure", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Observation|focus_DocumentReference|DocumentReference": { + FromType: "Observation", + EdgeLabel: "focus_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|focus_DocumentReference|Observation": { + FromType: "DocumentReference", + EdgeLabel: "focus_DocumentReference", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "Observation|focus_Task|Task": { + FromType: "Observation", + EdgeLabel: "focus_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|focus_Task|Observation": { + FromType: "Task", + EdgeLabel: "focus_Task", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Observation|focus_ImagingStudy|ImagingStudy": { + FromType: "Observation", + EdgeLabel: "focus_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|focus_ImagingStudy|Observation": { + FromType: "ImagingStudy", + EdgeLabel: "focus_ImagingStudy", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "Observation|focus_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "Observation", + EdgeLabel: "focus_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|focus_FamilyMemberHistory|Observation": { + FromType: "FamilyMemberHistory", + EdgeLabel: "focus_FamilyMemberHistory", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "Observation|focus_BodyStructure|BodyStructure": { + FromType: "Observation", + EdgeLabel: "focus_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|focus_BodyStructure|Observation": { + FromType: "BodyStructure", + EdgeLabel: "focus_BodyStructure", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "focus_observation", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "Observation|hasMember_Observation|Observation": { + FromType: "Observation", + EdgeLabel: "hasMember_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "hasMember_observation", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|partOf_MedicationAdministration|MedicationAdministration": { + FromType: "Observation", + EdgeLabel: "partOf_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "partOf_observation", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|partOf_MedicationAdministration|Observation": { + FromType: "MedicationAdministration", + EdgeLabel: "partOf_MedicationAdministration", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "partOf_observation", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "Observation|partOf_MedicationStatement|MedicationStatement": { + FromType: "Observation", + EdgeLabel: "partOf_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "partOf_observation", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|partOf_MedicationStatement|Observation": { + FromType: "MedicationStatement", + EdgeLabel: "partOf_MedicationStatement", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "partOf_observation", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "Observation|partOf_Procedure|Procedure": { + FromType: "Observation", + EdgeLabel: "partOf_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "partOf_observation", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|partOf_Procedure|Observation": { + FromType: "Procedure", + EdgeLabel: "partOf_Procedure", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "partOf_observation", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Observation|partOf_ImagingStudy|ImagingStudy": { + FromType: "Observation", + EdgeLabel: "partOf_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "partOf_observation", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|partOf_ImagingStudy|Observation": { + FromType: "ImagingStudy", + EdgeLabel: "partOf_ImagingStudy", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "partOf_observation", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "Observation|performer_Practitioner|Practitioner": { + FromType: "Observation", + EdgeLabel: "performer_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "performer_observation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|performer_Practitioner|Observation": { + FromType: "Practitioner", + EdgeLabel: "performer_Practitioner", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "performer_observation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Observation|performer_PractitionerRole|PractitionerRole": { + FromType: "Observation", + EdgeLabel: "performer_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "performer_observation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|performer_PractitionerRole|Observation": { + FromType: "PractitionerRole", + EdgeLabel: "performer_PractitionerRole", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "performer_observation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Observation|performer_Organization|Organization": { + FromType: "Observation", + EdgeLabel: "performer_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "performer_observation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|performer_Organization|Observation": { + FromType: "Organization", + EdgeLabel: "performer_Organization", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "performer_observation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Observation|performer_Patient|Patient": { + FromType: "Observation", + EdgeLabel: "performer_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "performer_observation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|performer_Patient|Observation": { + FromType: "Patient", + EdgeLabel: "performer_Patient", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "performer_observation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Observation|specimen_Specimen|Specimen": { + FromType: "Observation", + EdgeLabel: "specimen_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen_observation", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|specimen_Specimen|Observation": { + FromType: "Specimen", + EdgeLabel: "specimen_Specimen", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen_observation", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Observation|specimen_Group|Group": { + FromType: "Observation", + EdgeLabel: "specimen_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen_observation", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|specimen_Group|Observation": { + FromType: "Group", + EdgeLabel: "specimen_Group", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen_observation", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Observation|subject_Patient|Patient": { + FromType: "Observation", + EdgeLabel: "subject_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_observation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|subject_Patient|Observation": { + FromType: "Patient", + EdgeLabel: "subject_Patient", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_observation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Observation|subject_Group|Group": { + FromType: "Observation", + EdgeLabel: "subject_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_observation", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|subject_Group|Observation": { + FromType: "Group", + EdgeLabel: "subject_Group", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_observation", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Observation|subject_Organization|Organization": { + FromType: "Observation", + EdgeLabel: "subject_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_observation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|subject_Organization|Observation": { + FromType: "Organization", + EdgeLabel: "subject_Organization", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_observation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Observation|subject_Procedure|Procedure": { + FromType: "Observation", + EdgeLabel: "subject_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_observation", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|subject_Procedure|Observation": { + FromType: "Procedure", + EdgeLabel: "subject_Procedure", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_observation", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Observation|subject_Practitioner|Practitioner": { + FromType: "Observation", + EdgeLabel: "subject_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_observation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|subject_Practitioner|Observation": { + FromType: "Practitioner", + EdgeLabel: "subject_Practitioner", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_observation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Observation|subject_Medication|Medication": { + FromType: "Observation", + EdgeLabel: "subject_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_observation", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|subject_Medication|Observation": { + FromType: "Medication", + EdgeLabel: "subject_Medication", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_observation", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Observation|subject_Substance|Substance": { + FromType: "Observation", + EdgeLabel: "subject_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_observation", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|subject_Substance|Observation": { + FromType: "Substance", + EdgeLabel: "subject_Substance", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_observation", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Observation|note_authorReference_Practitioner|Practitioner": { + FromType: "Observation", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|note_authorReference_Practitioner|Observation": { + FromType: "Practitioner", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Observation|note_authorReference_PractitionerRole|PractitionerRole": { + FromType: "Observation", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|note_authorReference_PractitionerRole|Observation": { + FromType: "PractitionerRole", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Observation|note_authorReference_Patient|Patient": { + FromType: "Observation", + EdgeLabel: "note_authorReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|note_authorReference_Patient|Observation": { + FromType: "Patient", + EdgeLabel: "note_authorReference_Patient", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Observation|note_authorReference_Organization|Organization": { + FromType: "Observation", + EdgeLabel: "note_authorReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|note_authorReference_Organization|Observation": { + FromType: "Organization", + EdgeLabel: "note_authorReference_Organization", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Observation|triggeredBy_observation|Observation": { + FromType: "Observation", + EdgeLabel: "triggeredBy_observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "observation_triggered_by", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "ObservationTriggeredBy|observation|Observation": { + FromType: "ObservationTriggeredBy", + EdgeLabel: "observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "observation_triggered_by", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|observation|ObservationTriggeredBy": { + FromType: "Observation", + EdgeLabel: "observation", + ToType: "ObservationTriggeredBy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "observation_triggered_by", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Organization|partOf|Organization": { + FromType: "Organization", + EdgeLabel: "partOf", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "organization", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|contact_organization|Organization": { + FromType: "Organization", + EdgeLabel: "contact_organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extended_contact_detail", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|qualification_issuer|Organization": { + FromType: "Organization", + EdgeLabel: "qualification_issuer", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "organization_qualification", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "OrganizationQualification|issuer|Organization": { + FromType: "OrganizationQualification", + EdgeLabel: "issuer", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "organization_qualification", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|issuer|OrganizationQualification": { + FromType: "Organization", + EdgeLabel: "issuer", + ToType: "OrganizationQualification", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "organization_qualification", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Patient|generalPractitioner_Organization|Organization": { + FromType: "Patient", + EdgeLabel: "generalPractitioner_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "generalPractitioner_patient", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|generalPractitioner_Organization|Patient": { + FromType: "Organization", + EdgeLabel: "generalPractitioner_Organization", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "generalPractitioner_patient", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Patient|generalPractitioner_Practitioner|Practitioner": { + FromType: "Patient", + EdgeLabel: "generalPractitioner_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "generalPractitioner_patient", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|generalPractitioner_Practitioner|Patient": { + FromType: "Practitioner", + EdgeLabel: "generalPractitioner_Practitioner", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "generalPractitioner_patient", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Patient|generalPractitioner_PractitionerRole|PractitionerRole": { + FromType: "Patient", + EdgeLabel: "generalPractitioner_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "generalPractitioner_patient", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|generalPractitioner_PractitionerRole|Patient": { + FromType: "PractitionerRole", + EdgeLabel: "generalPractitioner_PractitionerRole", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "generalPractitioner_patient", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Patient|managingOrganization|Organization": { + FromType: "Patient", + EdgeLabel: "managingOrganization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "managingOrganization_patient", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|managingOrganization|Patient": { + FromType: "Organization", + EdgeLabel: "managingOrganization", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "managingOrganization_patient", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Patient|contact_organization|Organization": { + FromType: "Patient", + EdgeLabel: "contact_organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "patient_contact", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|contact_organization|Patient": { + FromType: "Organization", + EdgeLabel: "contact_organization", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "patient_contact", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Patient|link_other_Patient|Patient": { + FromType: "Patient", + EdgeLabel: "link_other_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "patient_link", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "PatientContact|organization|Organization": { + FromType: "PatientContact", + EdgeLabel: "organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "patient_contact", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|organization|PatientContact": { + FromType: "Organization", + EdgeLabel: "organization", + ToType: "PatientContact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "patient_contact", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "PatientLink|other_Patient|Patient": { + FromType: "PatientLink", + EdgeLabel: "other_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "patient_link", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|other_Patient|PatientLink": { + FromType: "Patient", + EdgeLabel: "other_Patient", + ToType: "PatientLink", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "patient_link", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Practitioner|qualification_issuer|Organization": { + FromType: "Practitioner", + EdgeLabel: "qualification_issuer", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "practitioner_qualification", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|qualification_issuer|Practitioner": { + FromType: "Organization", + EdgeLabel: "qualification_issuer", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "practitioner_qualification", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "PractitionerQualification|issuer|Organization": { + FromType: "PractitionerQualification", + EdgeLabel: "issuer", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "practitioner_qualification", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|issuer|PractitionerQualification": { + FromType: "Organization", + EdgeLabel: "issuer", + ToType: "PractitionerQualification", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "practitioner_qualification", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "PractitionerRole|organization|Organization": { + FromType: "PractitionerRole", + EdgeLabel: "organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "practitioner_role", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|organization|PractitionerRole": { + FromType: "Organization", + EdgeLabel: "organization", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "practitioner_role", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "PractitionerRole|practitioner|Practitioner": { + FromType: "PractitionerRole", + EdgeLabel: "practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "practitioner_role", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|practitioner|PractitionerRole": { + FromType: "Practitioner", + EdgeLabel: "practitioner", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "practitioner_role", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "PractitionerRole|contact_organization|Organization": { + FromType: "PractitionerRole", + EdgeLabel: "contact_organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extended_contact_detail", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|contact_organization|PractitionerRole": { + FromType: "Organization", + EdgeLabel: "contact_organization", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extended_contact_detail", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Procedure|focus_Patient|Patient": { + FromType: "Procedure", + EdgeLabel: "focus_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_procedure", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|focus_Patient|Procedure": { + FromType: "Patient", + EdgeLabel: "focus_Patient", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_procedure", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Procedure|focus_Group|Group": { + FromType: "Procedure", + EdgeLabel: "focus_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_procedure", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|focus_Group|Procedure": { + FromType: "Group", + EdgeLabel: "focus_Group", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_procedure", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Procedure|focus_Practitioner|Practitioner": { + FromType: "Procedure", + EdgeLabel: "focus_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_procedure", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|focus_Practitioner|Procedure": { + FromType: "Practitioner", + EdgeLabel: "focus_Practitioner", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_procedure", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Procedure|focus_Organization|Organization": { + FromType: "Procedure", + EdgeLabel: "focus_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_procedure", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|focus_Organization|Procedure": { + FromType: "Organization", + EdgeLabel: "focus_Organization", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_procedure", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Procedure|focus_PractitionerRole|PractitionerRole": { + FromType: "Procedure", + EdgeLabel: "focus_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_procedure", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|focus_PractitionerRole|Procedure": { + FromType: "PractitionerRole", + EdgeLabel: "focus_PractitionerRole", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_procedure", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Procedure|focus_Specimen|Specimen": { + FromType: "Procedure", + EdgeLabel: "focus_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_procedure", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|focus_Specimen|Procedure": { + FromType: "Specimen", + EdgeLabel: "focus_Specimen", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_procedure", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Procedure|partOf_Procedure|Procedure": { + FromType: "Procedure", + EdgeLabel: "partOf_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "partOf_procedure", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|partOf_Observation|Observation": { + FromType: "Procedure", + EdgeLabel: "partOf_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "partOf_procedure", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|partOf_Observation|Procedure": { + FromType: "Observation", + EdgeLabel: "partOf_Observation", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "partOf_procedure", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Procedure|partOf_MedicationAdministration|MedicationAdministration": { + FromType: "Procedure", + EdgeLabel: "partOf_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "partOf_procedure", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|partOf_MedicationAdministration|Procedure": { + FromType: "MedicationAdministration", + EdgeLabel: "partOf_MedicationAdministration", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "partOf_procedure", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "Procedure|recorder_Patient|Patient": { + FromType: "Procedure", + EdgeLabel: "recorder_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "recorder_procedure", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|recorder_Patient|Procedure": { + FromType: "Patient", + EdgeLabel: "recorder_Patient", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "recorder_procedure", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Procedure|recorder_Practitioner|Practitioner": { + FromType: "Procedure", + EdgeLabel: "recorder_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "recorder_procedure", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|recorder_Practitioner|Procedure": { + FromType: "Practitioner", + EdgeLabel: "recorder_Practitioner", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "recorder_procedure", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Procedure|recorder_PractitionerRole|PractitionerRole": { + FromType: "Procedure", + EdgeLabel: "recorder_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "recorder_procedure", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|recorder_PractitionerRole|Procedure": { + FromType: "PractitionerRole", + EdgeLabel: "recorder_PractitionerRole", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "recorder_procedure", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Procedure|report_DiagnosticReport|DiagnosticReport": { + FromType: "Procedure", + EdgeLabel: "report_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "report_procedure", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|report_DiagnosticReport|Procedure": { + FromType: "DiagnosticReport", + EdgeLabel: "report_DiagnosticReport", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "report_procedure", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "Procedure|report_DocumentReference|DocumentReference": { + FromType: "Procedure", + EdgeLabel: "report_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "report_procedure", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|report_DocumentReference|Procedure": { + FromType: "DocumentReference", + EdgeLabel: "report_DocumentReference", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "report_procedure", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "Procedure|reportedReference_Patient|Patient": { + FromType: "Procedure", + EdgeLabel: "reportedReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "reportedReference_procedure", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|reportedReference_Patient|Procedure": { + FromType: "Patient", + EdgeLabel: "reportedReference_Patient", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "reportedReference_procedure", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Procedure|reportedReference_Practitioner|Practitioner": { + FromType: "Procedure", + EdgeLabel: "reportedReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "reportedReference_procedure", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|reportedReference_Practitioner|Procedure": { + FromType: "Practitioner", + EdgeLabel: "reportedReference_Practitioner", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "reportedReference_procedure", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Procedure|reportedReference_PractitionerRole|PractitionerRole": { + FromType: "Procedure", + EdgeLabel: "reportedReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "reportedReference_procedure", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|reportedReference_PractitionerRole|Procedure": { + FromType: "PractitionerRole", + EdgeLabel: "reportedReference_PractitionerRole", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "reportedReference_procedure", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Procedure|reportedReference_Organization|Organization": { + FromType: "Procedure", + EdgeLabel: "reportedReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "reportedReference_procedure", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|reportedReference_Organization|Procedure": { + FromType: "Organization", + EdgeLabel: "reportedReference_Organization", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "reportedReference_procedure", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Procedure|subject_Patient|Patient": { + FromType: "Procedure", + EdgeLabel: "subject_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_procedure", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|subject_Patient|Procedure": { + FromType: "Patient", + EdgeLabel: "subject_Patient", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_procedure", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Procedure|subject_Group|Group": { + FromType: "Procedure", + EdgeLabel: "subject_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_procedure", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|subject_Group|Procedure": { + FromType: "Group", + EdgeLabel: "subject_Group", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_procedure", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Procedure|subject_Practitioner|Practitioner": { + FromType: "Procedure", + EdgeLabel: "subject_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_procedure", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|subject_Practitioner|Procedure": { + FromType: "Practitioner", + EdgeLabel: "subject_Practitioner", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_procedure", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Procedure|subject_Organization|Organization": { + FromType: "Procedure", + EdgeLabel: "subject_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_procedure", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|subject_Organization|Procedure": { + FromType: "Organization", + EdgeLabel: "subject_Organization", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "subject_procedure", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Procedure|supportingInfo_Organization|Organization": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|supportingInfo_Organization|Procedure": { + FromType: "Organization", + EdgeLabel: "supportingInfo_Organization", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Procedure|supportingInfo_Group|Group": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|supportingInfo_Group|Procedure": { + FromType: "Group", + EdgeLabel: "supportingInfo_Group", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Procedure|supportingInfo_Practitioner|Practitioner": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|supportingInfo_Practitioner|Procedure": { + FromType: "Practitioner", + EdgeLabel: "supportingInfo_Practitioner", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Procedure|supportingInfo_PractitionerRole|PractitionerRole": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|supportingInfo_PractitionerRole|Procedure": { + FromType: "PractitionerRole", + EdgeLabel: "supportingInfo_PractitionerRole", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Procedure|supportingInfo_ResearchStudy|ResearchStudy": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|supportingInfo_ResearchStudy|Procedure": { + FromType: "ResearchStudy", + EdgeLabel: "supportingInfo_ResearchStudy", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "Procedure|supportingInfo_Patient|Patient": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|supportingInfo_Patient|Procedure": { + FromType: "Patient", + EdgeLabel: "supportingInfo_Patient", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Procedure|supportingInfo_ResearchSubject|ResearchSubject": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|supportingInfo_ResearchSubject|Procedure": { + FromType: "ResearchSubject", + EdgeLabel: "supportingInfo_ResearchSubject", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "Procedure|supportingInfo_Substance|Substance": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|supportingInfo_Substance|Procedure": { + FromType: "Substance", + EdgeLabel: "supportingInfo_Substance", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Procedure|supportingInfo_SubstanceDefinition|SubstanceDefinition": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|supportingInfo_SubstanceDefinition|Procedure": { + FromType: "SubstanceDefinition", + EdgeLabel: "supportingInfo_SubstanceDefinition", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "Procedure|supportingInfo_Specimen|Specimen": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|supportingInfo_Specimen|Procedure": { + FromType: "Specimen", + EdgeLabel: "supportingInfo_Specimen", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Procedure|supportingInfo_Observation|Observation": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|supportingInfo_Observation|Procedure": { + FromType: "Observation", + EdgeLabel: "supportingInfo_Observation", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Procedure|supportingInfo_DiagnosticReport|DiagnosticReport": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|supportingInfo_DiagnosticReport|Procedure": { + FromType: "DiagnosticReport", + EdgeLabel: "supportingInfo_DiagnosticReport", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "Procedure|supportingInfo_Condition|Condition": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|supportingInfo_Condition|Procedure": { + FromType: "Condition", + EdgeLabel: "supportingInfo_Condition", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Procedure|supportingInfo_Medication|Medication": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|supportingInfo_Medication|Procedure": { + FromType: "Medication", + EdgeLabel: "supportingInfo_Medication", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Procedure|supportingInfo_MedicationAdministration|MedicationAdministration": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|supportingInfo_MedicationAdministration|Procedure": { + FromType: "MedicationAdministration", + EdgeLabel: "supportingInfo_MedicationAdministration", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "Procedure|supportingInfo_MedicationStatement|MedicationStatement": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|supportingInfo_MedicationStatement|Procedure": { + FromType: "MedicationStatement", + EdgeLabel: "supportingInfo_MedicationStatement", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "Procedure|supportingInfo_MedicationRequest|MedicationRequest": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|supportingInfo_MedicationRequest|Procedure": { + FromType: "MedicationRequest", + EdgeLabel: "supportingInfo_MedicationRequest", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "Procedure|supportingInfo_Procedure|Procedure": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|supportingInfo_DocumentReference|DocumentReference": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|supportingInfo_DocumentReference|Procedure": { + FromType: "DocumentReference", + EdgeLabel: "supportingInfo_DocumentReference", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "Procedure|supportingInfo_Task|Task": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|supportingInfo_Task|Procedure": { + FromType: "Task", + EdgeLabel: "supportingInfo_Task", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Procedure|supportingInfo_ImagingStudy|ImagingStudy": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|supportingInfo_ImagingStudy|Procedure": { + FromType: "ImagingStudy", + EdgeLabel: "supportingInfo_ImagingStudy", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "Procedure|supportingInfo_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|supportingInfo_FamilyMemberHistory|Procedure": { + FromType: "FamilyMemberHistory", + EdgeLabel: "supportingInfo_FamilyMemberHistory", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "Procedure|supportingInfo_BodyStructure|BodyStructure": { + FromType: "Procedure", + EdgeLabel: "supportingInfo_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|supportingInfo_BodyStructure|Procedure": { + FromType: "BodyStructure", + EdgeLabel: "supportingInfo_BodyStructure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supportingInfo_procedure", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "Procedure|complication_reference_Organization|Organization": { + FromType: "Procedure", + EdgeLabel: "complication_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|complication_reference_Organization|Procedure": { + FromType: "Organization", + EdgeLabel: "complication_reference_Organization", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Procedure|complication_reference_Group|Group": { + FromType: "Procedure", + EdgeLabel: "complication_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|complication_reference_Group|Procedure": { + FromType: "Group", + EdgeLabel: "complication_reference_Group", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Procedure|complication_reference_Practitioner|Practitioner": { + FromType: "Procedure", + EdgeLabel: "complication_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|complication_reference_Practitioner|Procedure": { + FromType: "Practitioner", + EdgeLabel: "complication_reference_Practitioner", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Procedure|complication_reference_PractitionerRole|PractitionerRole": { + FromType: "Procedure", + EdgeLabel: "complication_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|complication_reference_PractitionerRole|Procedure": { + FromType: "PractitionerRole", + EdgeLabel: "complication_reference_PractitionerRole", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Procedure|complication_reference_ResearchStudy|ResearchStudy": { + FromType: "Procedure", + EdgeLabel: "complication_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|complication_reference_ResearchStudy|Procedure": { + FromType: "ResearchStudy", + EdgeLabel: "complication_reference_ResearchStudy", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "Procedure|complication_reference_Patient|Patient": { + FromType: "Procedure", + EdgeLabel: "complication_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|complication_reference_Patient|Procedure": { + FromType: "Patient", + EdgeLabel: "complication_reference_Patient", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Procedure|complication_reference_ResearchSubject|ResearchSubject": { + FromType: "Procedure", + EdgeLabel: "complication_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|complication_reference_ResearchSubject|Procedure": { + FromType: "ResearchSubject", + EdgeLabel: "complication_reference_ResearchSubject", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "Procedure|complication_reference_Substance|Substance": { + FromType: "Procedure", + EdgeLabel: "complication_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|complication_reference_Substance|Procedure": { + FromType: "Substance", + EdgeLabel: "complication_reference_Substance", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Procedure|complication_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "Procedure", + EdgeLabel: "complication_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|complication_reference_SubstanceDefinition|Procedure": { + FromType: "SubstanceDefinition", + EdgeLabel: "complication_reference_SubstanceDefinition", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "Procedure|complication_reference_Specimen|Specimen": { + FromType: "Procedure", + EdgeLabel: "complication_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|complication_reference_Specimen|Procedure": { + FromType: "Specimen", + EdgeLabel: "complication_reference_Specimen", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Procedure|complication_reference_Observation|Observation": { + FromType: "Procedure", + EdgeLabel: "complication_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|complication_reference_Observation|Procedure": { + FromType: "Observation", + EdgeLabel: "complication_reference_Observation", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Procedure|complication_reference_DiagnosticReport|DiagnosticReport": { + FromType: "Procedure", + EdgeLabel: "complication_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|complication_reference_DiagnosticReport|Procedure": { + FromType: "DiagnosticReport", + EdgeLabel: "complication_reference_DiagnosticReport", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "Procedure|complication_reference_Condition|Condition": { + FromType: "Procedure", + EdgeLabel: "complication_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|complication_reference_Condition|Procedure": { + FromType: "Condition", + EdgeLabel: "complication_reference_Condition", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Procedure|complication_reference_Medication|Medication": { + FromType: "Procedure", + EdgeLabel: "complication_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|complication_reference_Medication|Procedure": { + FromType: "Medication", + EdgeLabel: "complication_reference_Medication", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Procedure|complication_reference_MedicationAdministration|MedicationAdministration": { + FromType: "Procedure", + EdgeLabel: "complication_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|complication_reference_MedicationAdministration|Procedure": { + FromType: "MedicationAdministration", + EdgeLabel: "complication_reference_MedicationAdministration", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "Procedure|complication_reference_MedicationStatement|MedicationStatement": { + FromType: "Procedure", + EdgeLabel: "complication_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|complication_reference_MedicationStatement|Procedure": { + FromType: "MedicationStatement", + EdgeLabel: "complication_reference_MedicationStatement", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "Procedure|complication_reference_MedicationRequest|MedicationRequest": { + FromType: "Procedure", + EdgeLabel: "complication_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|complication_reference_MedicationRequest|Procedure": { + FromType: "MedicationRequest", + EdgeLabel: "complication_reference_MedicationRequest", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "Procedure|complication_reference_Procedure|Procedure": { + FromType: "Procedure", + EdgeLabel: "complication_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|complication_reference_DocumentReference|DocumentReference": { + FromType: "Procedure", + EdgeLabel: "complication_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|complication_reference_DocumentReference|Procedure": { + FromType: "DocumentReference", + EdgeLabel: "complication_reference_DocumentReference", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "Procedure|complication_reference_Task|Task": { + FromType: "Procedure", + EdgeLabel: "complication_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|complication_reference_Task|Procedure": { + FromType: "Task", + EdgeLabel: "complication_reference_Task", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Procedure|complication_reference_ImagingStudy|ImagingStudy": { + FromType: "Procedure", + EdgeLabel: "complication_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|complication_reference_ImagingStudy|Procedure": { + FromType: "ImagingStudy", + EdgeLabel: "complication_reference_ImagingStudy", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "Procedure|complication_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "Procedure", + EdgeLabel: "complication_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|complication_reference_FamilyMemberHistory|Procedure": { + FromType: "FamilyMemberHistory", + EdgeLabel: "complication_reference_FamilyMemberHistory", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "Procedure|complication_reference_BodyStructure|BodyStructure": { + FromType: "Procedure", + EdgeLabel: "complication_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|complication_reference_BodyStructure|Procedure": { + FromType: "BodyStructure", + EdgeLabel: "complication_reference_BodyStructure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "Procedure|note_authorReference_Practitioner|Practitioner": { + FromType: "Procedure", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|note_authorReference_Practitioner|Procedure": { + FromType: "Practitioner", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Procedure|note_authorReference_PractitionerRole|PractitionerRole": { + FromType: "Procedure", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|note_authorReference_PractitionerRole|Procedure": { + FromType: "PractitionerRole", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Procedure|note_authorReference_Patient|Patient": { + FromType: "Procedure", + EdgeLabel: "note_authorReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|note_authorReference_Patient|Procedure": { + FromType: "Patient", + EdgeLabel: "note_authorReference_Patient", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Procedure|note_authorReference_Organization|Organization": { + FromType: "Procedure", + EdgeLabel: "note_authorReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|note_authorReference_Organization|Procedure": { + FromType: "Organization", + EdgeLabel: "note_authorReference_Organization", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Procedure|performer_actor_Practitioner|Practitioner": { + FromType: "Procedure", + EdgeLabel: "performer_actor_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "actor_procedure_performer", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|performer_actor_Practitioner|Procedure": { + FromType: "Practitioner", + EdgeLabel: "performer_actor_Practitioner", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "actor_procedure_performer", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Procedure|performer_actor_PractitionerRole|PractitionerRole": { + FromType: "Procedure", + EdgeLabel: "performer_actor_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "actor_procedure_performer", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|performer_actor_PractitionerRole|Procedure": { + FromType: "PractitionerRole", + EdgeLabel: "performer_actor_PractitionerRole", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "actor_procedure_performer", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Procedure|performer_actor_Organization|Organization": { + FromType: "Procedure", + EdgeLabel: "performer_actor_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "actor_procedure_performer", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|performer_actor_Organization|Procedure": { + FromType: "Organization", + EdgeLabel: "performer_actor_Organization", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "actor_procedure_performer", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Procedure|performer_actor_Patient|Patient": { + FromType: "Procedure", + EdgeLabel: "performer_actor_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "actor_procedure_performer", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|performer_actor_Patient|Procedure": { + FromType: "Patient", + EdgeLabel: "performer_actor_Patient", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "actor_procedure_performer", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Procedure|performer_onBehalfOf|Organization": { + FromType: "Procedure", + EdgeLabel: "performer_onBehalfOf", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_procedure_performer", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|performer_onBehalfOf|Procedure": { + FromType: "Organization", + EdgeLabel: "performer_onBehalfOf", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_procedure_performer", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Procedure|reason_reference_Organization|Organization": { + FromType: "Procedure", + EdgeLabel: "reason_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|reason_reference_Organization|Procedure": { + FromType: "Organization", + EdgeLabel: "reason_reference_Organization", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Procedure|reason_reference_Group|Group": { + FromType: "Procedure", + EdgeLabel: "reason_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|reason_reference_Group|Procedure": { + FromType: "Group", + EdgeLabel: "reason_reference_Group", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Procedure|reason_reference_Practitioner|Practitioner": { + FromType: "Procedure", + EdgeLabel: "reason_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|reason_reference_Practitioner|Procedure": { + FromType: "Practitioner", + EdgeLabel: "reason_reference_Practitioner", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Procedure|reason_reference_PractitionerRole|PractitionerRole": { + FromType: "Procedure", + EdgeLabel: "reason_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|reason_reference_PractitionerRole|Procedure": { + FromType: "PractitionerRole", + EdgeLabel: "reason_reference_PractitionerRole", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Procedure|reason_reference_ResearchStudy|ResearchStudy": { + FromType: "Procedure", + EdgeLabel: "reason_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|reason_reference_ResearchStudy|Procedure": { + FromType: "ResearchStudy", + EdgeLabel: "reason_reference_ResearchStudy", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "Procedure|reason_reference_Patient|Patient": { + FromType: "Procedure", + EdgeLabel: "reason_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|reason_reference_Patient|Procedure": { + FromType: "Patient", + EdgeLabel: "reason_reference_Patient", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Procedure|reason_reference_ResearchSubject|ResearchSubject": { + FromType: "Procedure", + EdgeLabel: "reason_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|reason_reference_ResearchSubject|Procedure": { + FromType: "ResearchSubject", + EdgeLabel: "reason_reference_ResearchSubject", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "Procedure|reason_reference_Substance|Substance": { + FromType: "Procedure", + EdgeLabel: "reason_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|reason_reference_Substance|Procedure": { + FromType: "Substance", + EdgeLabel: "reason_reference_Substance", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Procedure|reason_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "Procedure", + EdgeLabel: "reason_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|reason_reference_SubstanceDefinition|Procedure": { + FromType: "SubstanceDefinition", + EdgeLabel: "reason_reference_SubstanceDefinition", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "Procedure|reason_reference_Specimen|Specimen": { + FromType: "Procedure", + EdgeLabel: "reason_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|reason_reference_Specimen|Procedure": { + FromType: "Specimen", + EdgeLabel: "reason_reference_Specimen", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Procedure|reason_reference_Observation|Observation": { + FromType: "Procedure", + EdgeLabel: "reason_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|reason_reference_Observation|Procedure": { + FromType: "Observation", + EdgeLabel: "reason_reference_Observation", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Procedure|reason_reference_DiagnosticReport|DiagnosticReport": { + FromType: "Procedure", + EdgeLabel: "reason_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|reason_reference_DiagnosticReport|Procedure": { + FromType: "DiagnosticReport", + EdgeLabel: "reason_reference_DiagnosticReport", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "Procedure|reason_reference_Condition|Condition": { + FromType: "Procedure", + EdgeLabel: "reason_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|reason_reference_Condition|Procedure": { + FromType: "Condition", + EdgeLabel: "reason_reference_Condition", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Procedure|reason_reference_Medication|Medication": { + FromType: "Procedure", + EdgeLabel: "reason_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|reason_reference_Medication|Procedure": { + FromType: "Medication", + EdgeLabel: "reason_reference_Medication", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Procedure|reason_reference_MedicationAdministration|MedicationAdministration": { + FromType: "Procedure", + EdgeLabel: "reason_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|reason_reference_MedicationAdministration|Procedure": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_MedicationAdministration", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "Procedure|reason_reference_MedicationStatement|MedicationStatement": { + FromType: "Procedure", + EdgeLabel: "reason_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|reason_reference_MedicationStatement|Procedure": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_MedicationStatement", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "Procedure|reason_reference_MedicationRequest|MedicationRequest": { + FromType: "Procedure", + EdgeLabel: "reason_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|reason_reference_MedicationRequest|Procedure": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_MedicationRequest", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "Procedure|reason_reference_Procedure|Procedure": { + FromType: "Procedure", + EdgeLabel: "reason_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|reason_reference_DocumentReference|DocumentReference": { + FromType: "Procedure", + EdgeLabel: "reason_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|reason_reference_DocumentReference|Procedure": { + FromType: "DocumentReference", + EdgeLabel: "reason_reference_DocumentReference", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "Procedure|reason_reference_Task|Task": { + FromType: "Procedure", + EdgeLabel: "reason_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|reason_reference_Task|Procedure": { + FromType: "Task", + EdgeLabel: "reason_reference_Task", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Procedure|reason_reference_ImagingStudy|ImagingStudy": { + FromType: "Procedure", + EdgeLabel: "reason_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|reason_reference_ImagingStudy|Procedure": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_ImagingStudy", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "Procedure|reason_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "Procedure", + EdgeLabel: "reason_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|reason_reference_FamilyMemberHistory|Procedure": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_FamilyMemberHistory", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "Procedure|reason_reference_BodyStructure|BodyStructure": { + FromType: "Procedure", + EdgeLabel: "reason_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|reason_reference_BodyStructure|Procedure": { + FromType: "BodyStructure", + EdgeLabel: "reason_reference_BodyStructure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "Procedure|used_reference_Organization|Organization": { + FromType: "Procedure", + EdgeLabel: "used_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|used_reference_Organization|Procedure": { + FromType: "Organization", + EdgeLabel: "used_reference_Organization", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Procedure|used_reference_Group|Group": { + FromType: "Procedure", + EdgeLabel: "used_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|used_reference_Group|Procedure": { + FromType: "Group", + EdgeLabel: "used_reference_Group", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Procedure|used_reference_Practitioner|Practitioner": { + FromType: "Procedure", + EdgeLabel: "used_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|used_reference_Practitioner|Procedure": { + FromType: "Practitioner", + EdgeLabel: "used_reference_Practitioner", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Procedure|used_reference_PractitionerRole|PractitionerRole": { + FromType: "Procedure", + EdgeLabel: "used_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|used_reference_PractitionerRole|Procedure": { + FromType: "PractitionerRole", + EdgeLabel: "used_reference_PractitionerRole", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Procedure|used_reference_ResearchStudy|ResearchStudy": { + FromType: "Procedure", + EdgeLabel: "used_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|used_reference_ResearchStudy|Procedure": { + FromType: "ResearchStudy", + EdgeLabel: "used_reference_ResearchStudy", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "Procedure|used_reference_Patient|Patient": { + FromType: "Procedure", + EdgeLabel: "used_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|used_reference_Patient|Procedure": { + FromType: "Patient", + EdgeLabel: "used_reference_Patient", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Procedure|used_reference_ResearchSubject|ResearchSubject": { + FromType: "Procedure", + EdgeLabel: "used_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|used_reference_ResearchSubject|Procedure": { + FromType: "ResearchSubject", + EdgeLabel: "used_reference_ResearchSubject", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "Procedure|used_reference_Substance|Substance": { + FromType: "Procedure", + EdgeLabel: "used_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|used_reference_Substance|Procedure": { + FromType: "Substance", + EdgeLabel: "used_reference_Substance", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Procedure|used_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "Procedure", + EdgeLabel: "used_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|used_reference_SubstanceDefinition|Procedure": { + FromType: "SubstanceDefinition", + EdgeLabel: "used_reference_SubstanceDefinition", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "Procedure|used_reference_Specimen|Specimen": { + FromType: "Procedure", + EdgeLabel: "used_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|used_reference_Specimen|Procedure": { + FromType: "Specimen", + EdgeLabel: "used_reference_Specimen", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Procedure|used_reference_Observation|Observation": { + FromType: "Procedure", + EdgeLabel: "used_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|used_reference_Observation|Procedure": { + FromType: "Observation", + EdgeLabel: "used_reference_Observation", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Procedure|used_reference_DiagnosticReport|DiagnosticReport": { + FromType: "Procedure", + EdgeLabel: "used_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|used_reference_DiagnosticReport|Procedure": { + FromType: "DiagnosticReport", + EdgeLabel: "used_reference_DiagnosticReport", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "Procedure|used_reference_Condition|Condition": { + FromType: "Procedure", + EdgeLabel: "used_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|used_reference_Condition|Procedure": { + FromType: "Condition", + EdgeLabel: "used_reference_Condition", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Procedure|used_reference_Medication|Medication": { + FromType: "Procedure", + EdgeLabel: "used_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|used_reference_Medication|Procedure": { + FromType: "Medication", + EdgeLabel: "used_reference_Medication", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Procedure|used_reference_MedicationAdministration|MedicationAdministration": { + FromType: "Procedure", + EdgeLabel: "used_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|used_reference_MedicationAdministration|Procedure": { + FromType: "MedicationAdministration", + EdgeLabel: "used_reference_MedicationAdministration", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "Procedure|used_reference_MedicationStatement|MedicationStatement": { + FromType: "Procedure", + EdgeLabel: "used_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|used_reference_MedicationStatement|Procedure": { + FromType: "MedicationStatement", + EdgeLabel: "used_reference_MedicationStatement", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "Procedure|used_reference_MedicationRequest|MedicationRequest": { + FromType: "Procedure", + EdgeLabel: "used_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|used_reference_MedicationRequest|Procedure": { + FromType: "MedicationRequest", + EdgeLabel: "used_reference_MedicationRequest", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "Procedure|used_reference_Procedure|Procedure": { + FromType: "Procedure", + EdgeLabel: "used_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|used_reference_DocumentReference|DocumentReference": { + FromType: "Procedure", + EdgeLabel: "used_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|used_reference_DocumentReference|Procedure": { + FromType: "DocumentReference", + EdgeLabel: "used_reference_DocumentReference", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "Procedure|used_reference_Task|Task": { + FromType: "Procedure", + EdgeLabel: "used_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|used_reference_Task|Procedure": { + FromType: "Task", + EdgeLabel: "used_reference_Task", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Procedure|used_reference_ImagingStudy|ImagingStudy": { + FromType: "Procedure", + EdgeLabel: "used_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|used_reference_ImagingStudy|Procedure": { + FromType: "ImagingStudy", + EdgeLabel: "used_reference_ImagingStudy", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "Procedure|used_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "Procedure", + EdgeLabel: "used_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|used_reference_FamilyMemberHistory|Procedure": { + FromType: "FamilyMemberHistory", + EdgeLabel: "used_reference_FamilyMemberHistory", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "Procedure|used_reference_BodyStructure|BodyStructure": { + FromType: "Procedure", + EdgeLabel: "used_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|used_reference_BodyStructure|Procedure": { + FromType: "BodyStructure", + EdgeLabel: "used_reference_BodyStructure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "ProcedurePerformer|actor_Practitioner|Practitioner": { + FromType: "ProcedurePerformer", + EdgeLabel: "actor_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "actor_procedure_performer", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|actor_Practitioner|ProcedurePerformer": { + FromType: "Practitioner", + EdgeLabel: "actor_Practitioner", + ToType: "ProcedurePerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "actor_procedure_performer", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "ProcedurePerformer|actor_PractitionerRole|PractitionerRole": { + FromType: "ProcedurePerformer", + EdgeLabel: "actor_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "actor_procedure_performer", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|actor_PractitionerRole|ProcedurePerformer": { + FromType: "PractitionerRole", + EdgeLabel: "actor_PractitionerRole", + ToType: "ProcedurePerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "actor_procedure_performer", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "ProcedurePerformer|actor_Organization|Organization": { + FromType: "ProcedurePerformer", + EdgeLabel: "actor_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "actor_procedure_performer", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|actor_Organization|ProcedurePerformer": { + FromType: "Organization", + EdgeLabel: "actor_Organization", + ToType: "ProcedurePerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "actor_procedure_performer", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "ProcedurePerformer|actor_Patient|Patient": { + FromType: "ProcedurePerformer", + EdgeLabel: "actor_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "actor_procedure_performer", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|actor_Patient|ProcedurePerformer": { + FromType: "Patient", + EdgeLabel: "actor_Patient", + ToType: "ProcedurePerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "actor_procedure_performer", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "ProcedurePerformer|onBehalfOf|Organization": { + FromType: "ProcedurePerformer", + EdgeLabel: "onBehalfOf", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_procedure_performer", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|onBehalfOf|ProcedurePerformer": { + FromType: "Organization", + EdgeLabel: "onBehalfOf", + ToType: "ProcedurePerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_procedure_performer", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "RelatedArtifact|resourceReference_Organization|Organization": { + FromType: "RelatedArtifact", + EdgeLabel: "resourceReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|resourceReference_Organization|RelatedArtifact": { + FromType: "Organization", + EdgeLabel: "resourceReference_Organization", + ToType: "RelatedArtifact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "RelatedArtifact|resourceReference_Group|Group": { + FromType: "RelatedArtifact", + EdgeLabel: "resourceReference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|resourceReference_Group|RelatedArtifact": { + FromType: "Group", + EdgeLabel: "resourceReference_Group", + ToType: "RelatedArtifact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "RelatedArtifact|resourceReference_Practitioner|Practitioner": { + FromType: "RelatedArtifact", + EdgeLabel: "resourceReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|resourceReference_Practitioner|RelatedArtifact": { + FromType: "Practitioner", + EdgeLabel: "resourceReference_Practitioner", + ToType: "RelatedArtifact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "RelatedArtifact|resourceReference_PractitionerRole|PractitionerRole": { + FromType: "RelatedArtifact", + EdgeLabel: "resourceReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|resourceReference_PractitionerRole|RelatedArtifact": { + FromType: "PractitionerRole", + EdgeLabel: "resourceReference_PractitionerRole", + ToType: "RelatedArtifact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "RelatedArtifact|resourceReference_ResearchStudy|ResearchStudy": { + FromType: "RelatedArtifact", + EdgeLabel: "resourceReference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|resourceReference_ResearchStudy|RelatedArtifact": { + FromType: "ResearchStudy", + EdgeLabel: "resourceReference_ResearchStudy", + ToType: "RelatedArtifact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "RelatedArtifact|resourceReference_Patient|Patient": { + FromType: "RelatedArtifact", + EdgeLabel: "resourceReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|resourceReference_Patient|RelatedArtifact": { + FromType: "Patient", + EdgeLabel: "resourceReference_Patient", + ToType: "RelatedArtifact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "RelatedArtifact|resourceReference_ResearchSubject|ResearchSubject": { + FromType: "RelatedArtifact", + EdgeLabel: "resourceReference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|resourceReference_ResearchSubject|RelatedArtifact": { + FromType: "ResearchSubject", + EdgeLabel: "resourceReference_ResearchSubject", + ToType: "RelatedArtifact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "RelatedArtifact|resourceReference_Substance|Substance": { + FromType: "RelatedArtifact", + EdgeLabel: "resourceReference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|resourceReference_Substance|RelatedArtifact": { + FromType: "Substance", + EdgeLabel: "resourceReference_Substance", + ToType: "RelatedArtifact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "RelatedArtifact|resourceReference_SubstanceDefinition|SubstanceDefinition": { + FromType: "RelatedArtifact", + EdgeLabel: "resourceReference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|resourceReference_SubstanceDefinition|RelatedArtifact": { + FromType: "SubstanceDefinition", + EdgeLabel: "resourceReference_SubstanceDefinition", + ToType: "RelatedArtifact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "RelatedArtifact|resourceReference_Specimen|Specimen": { + FromType: "RelatedArtifact", + EdgeLabel: "resourceReference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|resourceReference_Specimen|RelatedArtifact": { + FromType: "Specimen", + EdgeLabel: "resourceReference_Specimen", + ToType: "RelatedArtifact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "RelatedArtifact|resourceReference_Observation|Observation": { + FromType: "RelatedArtifact", + EdgeLabel: "resourceReference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|resourceReference_Observation|RelatedArtifact": { + FromType: "Observation", + EdgeLabel: "resourceReference_Observation", + ToType: "RelatedArtifact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "RelatedArtifact|resourceReference_DiagnosticReport|DiagnosticReport": { + FromType: "RelatedArtifact", + EdgeLabel: "resourceReference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|resourceReference_DiagnosticReport|RelatedArtifact": { + FromType: "DiagnosticReport", + EdgeLabel: "resourceReference_DiagnosticReport", + ToType: "RelatedArtifact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "RelatedArtifact|resourceReference_Condition|Condition": { + FromType: "RelatedArtifact", + EdgeLabel: "resourceReference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|resourceReference_Condition|RelatedArtifact": { + FromType: "Condition", + EdgeLabel: "resourceReference_Condition", + ToType: "RelatedArtifact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "RelatedArtifact|resourceReference_Medication|Medication": { + FromType: "RelatedArtifact", + EdgeLabel: "resourceReference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|resourceReference_Medication|RelatedArtifact": { + FromType: "Medication", + EdgeLabel: "resourceReference_Medication", + ToType: "RelatedArtifact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "RelatedArtifact|resourceReference_MedicationAdministration|MedicationAdministration": { + FromType: "RelatedArtifact", + EdgeLabel: "resourceReference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|resourceReference_MedicationAdministration|RelatedArtifact": { + FromType: "MedicationAdministration", + EdgeLabel: "resourceReference_MedicationAdministration", + ToType: "RelatedArtifact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "RelatedArtifact|resourceReference_MedicationStatement|MedicationStatement": { + FromType: "RelatedArtifact", + EdgeLabel: "resourceReference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|resourceReference_MedicationStatement|RelatedArtifact": { + FromType: "MedicationStatement", + EdgeLabel: "resourceReference_MedicationStatement", + ToType: "RelatedArtifact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "RelatedArtifact|resourceReference_MedicationRequest|MedicationRequest": { + FromType: "RelatedArtifact", + EdgeLabel: "resourceReference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|resourceReference_MedicationRequest|RelatedArtifact": { + FromType: "MedicationRequest", + EdgeLabel: "resourceReference_MedicationRequest", + ToType: "RelatedArtifact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "RelatedArtifact|resourceReference_Procedure|Procedure": { + FromType: "RelatedArtifact", + EdgeLabel: "resourceReference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|resourceReference_Procedure|RelatedArtifact": { + FromType: "Procedure", + EdgeLabel: "resourceReference_Procedure", + ToType: "RelatedArtifact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "RelatedArtifact|resourceReference_DocumentReference|DocumentReference": { + FromType: "RelatedArtifact", + EdgeLabel: "resourceReference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|resourceReference_DocumentReference|RelatedArtifact": { + FromType: "DocumentReference", + EdgeLabel: "resourceReference_DocumentReference", + ToType: "RelatedArtifact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "RelatedArtifact|resourceReference_Task|Task": { + FromType: "RelatedArtifact", + EdgeLabel: "resourceReference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|resourceReference_Task|RelatedArtifact": { + FromType: "Task", + EdgeLabel: "resourceReference_Task", + ToType: "RelatedArtifact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "RelatedArtifact|resourceReference_ImagingStudy|ImagingStudy": { + FromType: "RelatedArtifact", + EdgeLabel: "resourceReference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|resourceReference_ImagingStudy|RelatedArtifact": { + FromType: "ImagingStudy", + EdgeLabel: "resourceReference_ImagingStudy", + ToType: "RelatedArtifact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "RelatedArtifact|resourceReference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "RelatedArtifact", + EdgeLabel: "resourceReference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|resourceReference_FamilyMemberHistory|RelatedArtifact": { + FromType: "FamilyMemberHistory", + EdgeLabel: "resourceReference_FamilyMemberHistory", + ToType: "RelatedArtifact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "RelatedArtifact|resourceReference_BodyStructure|BodyStructure": { + FromType: "RelatedArtifact", + EdgeLabel: "resourceReference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|resourceReference_BodyStructure|RelatedArtifact": { + FromType: "BodyStructure", + EdgeLabel: "resourceReference_BodyStructure", + ToType: "RelatedArtifact", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "ResearchStudy|rootDir_Directory|Directory": { + FromType: "ResearchStudy", + EdgeLabel: "rootDir_Directory", + ToType: "Directory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{}, + RegexMatch: []string{ + "Directory/*", + }, + }, + "Directory|rootDir_Directory|ResearchStudy": { + FromType: "Directory", + EdgeLabel: "rootDir_Directory", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{}, + RegexMatch: []string{ + "Directory/*", + }, + }, + "ResearchStudy|partOf|ResearchStudy": { + FromType: "ResearchStudy", + EdgeLabel: "partOf", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "partOf_research_study", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|result_DiagnosticReport|DiagnosticReport": { + FromType: "ResearchStudy", + EdgeLabel: "result_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "result_research_study", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|result_DiagnosticReport|ResearchStudy": { + FromType: "DiagnosticReport", + EdgeLabel: "result_DiagnosticReport", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "result_research_study", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "ResearchStudy|site_ResearchStudy|ResearchStudy": { + FromType: "ResearchStudy", + EdgeLabel: "site_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "site_research_study", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|site_Organization|Organization": { + FromType: "ResearchStudy", + EdgeLabel: "site_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "site_research_study", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|site_Organization|ResearchStudy": { + FromType: "Organization", + EdgeLabel: "site_Organization", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "site_research_study", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "ResearchStudy|associatedParty_party_Practitioner|Practitioner": { + FromType: "ResearchStudy", + EdgeLabel: "associatedParty_party_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_study_associated_party", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|associatedParty_party_Practitioner|ResearchStudy": { + FromType: "Practitioner", + EdgeLabel: "associatedParty_party_Practitioner", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_study_associated_party", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "ResearchStudy|associatedParty_party_PractitionerRole|PractitionerRole": { + FromType: "ResearchStudy", + EdgeLabel: "associatedParty_party_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_study_associated_party", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|associatedParty_party_PractitionerRole|ResearchStudy": { + FromType: "PractitionerRole", + EdgeLabel: "associatedParty_party_PractitionerRole", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_study_associated_party", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "ResearchStudy|associatedParty_party_Organization|Organization": { + FromType: "ResearchStudy", + EdgeLabel: "associatedParty_party_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_study_associated_party", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|associatedParty_party_Organization|ResearchStudy": { + FromType: "Organization", + EdgeLabel: "associatedParty_party_Organization", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_study_associated_party", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "ResearchStudy|comparisonGroup_observedGroup|Group": { + FromType: "ResearchStudy", + EdgeLabel: "comparisonGroup_observedGroup", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_study_comparison_group", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|comparisonGroup_observedGroup|ResearchStudy": { + FromType: "Group", + EdgeLabel: "comparisonGroup_observedGroup", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_study_comparison_group", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "ResearchStudy|focus_reference_Organization|Organization": { + FromType: "ResearchStudy", + EdgeLabel: "focus_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|focus_reference_Organization|ResearchStudy": { + FromType: "Organization", + EdgeLabel: "focus_reference_Organization", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "ResearchStudy|focus_reference_Group|Group": { + FromType: "ResearchStudy", + EdgeLabel: "focus_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|focus_reference_Group|ResearchStudy": { + FromType: "Group", + EdgeLabel: "focus_reference_Group", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "ResearchStudy|focus_reference_Practitioner|Practitioner": { + FromType: "ResearchStudy", + EdgeLabel: "focus_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|focus_reference_Practitioner|ResearchStudy": { + FromType: "Practitioner", + EdgeLabel: "focus_reference_Practitioner", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "ResearchStudy|focus_reference_PractitionerRole|PractitionerRole": { + FromType: "ResearchStudy", + EdgeLabel: "focus_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|focus_reference_PractitionerRole|ResearchStudy": { + FromType: "PractitionerRole", + EdgeLabel: "focus_reference_PractitionerRole", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "ResearchStudy|focus_reference_ResearchStudy|ResearchStudy": { + FromType: "ResearchStudy", + EdgeLabel: "focus_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|focus_reference_Patient|Patient": { + FromType: "ResearchStudy", + EdgeLabel: "focus_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|focus_reference_Patient|ResearchStudy": { + FromType: "Patient", + EdgeLabel: "focus_reference_Patient", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "ResearchStudy|focus_reference_ResearchSubject|ResearchSubject": { + FromType: "ResearchStudy", + EdgeLabel: "focus_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|focus_reference_ResearchSubject|ResearchStudy": { + FromType: "ResearchSubject", + EdgeLabel: "focus_reference_ResearchSubject", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchStudy|focus_reference_Substance|Substance": { + FromType: "ResearchStudy", + EdgeLabel: "focus_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|focus_reference_Substance|ResearchStudy": { + FromType: "Substance", + EdgeLabel: "focus_reference_Substance", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "ResearchStudy|focus_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "ResearchStudy", + EdgeLabel: "focus_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|focus_reference_SubstanceDefinition|ResearchStudy": { + FromType: "SubstanceDefinition", + EdgeLabel: "focus_reference_SubstanceDefinition", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "ResearchStudy|focus_reference_Specimen|Specimen": { + FromType: "ResearchStudy", + EdgeLabel: "focus_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|focus_reference_Specimen|ResearchStudy": { + FromType: "Specimen", + EdgeLabel: "focus_reference_Specimen", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "ResearchStudy|focus_reference_Observation|Observation": { + FromType: "ResearchStudy", + EdgeLabel: "focus_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|focus_reference_Observation|ResearchStudy": { + FromType: "Observation", + EdgeLabel: "focus_reference_Observation", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "ResearchStudy|focus_reference_DiagnosticReport|DiagnosticReport": { + FromType: "ResearchStudy", + EdgeLabel: "focus_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|focus_reference_DiagnosticReport|ResearchStudy": { + FromType: "DiagnosticReport", + EdgeLabel: "focus_reference_DiagnosticReport", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "ResearchStudy|focus_reference_Condition|Condition": { + FromType: "ResearchStudy", + EdgeLabel: "focus_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|focus_reference_Condition|ResearchStudy": { + FromType: "Condition", + EdgeLabel: "focus_reference_Condition", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "ResearchStudy|focus_reference_Medication|Medication": { + FromType: "ResearchStudy", + EdgeLabel: "focus_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|focus_reference_Medication|ResearchStudy": { + FromType: "Medication", + EdgeLabel: "focus_reference_Medication", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "ResearchStudy|focus_reference_MedicationAdministration|MedicationAdministration": { + FromType: "ResearchStudy", + EdgeLabel: "focus_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|focus_reference_MedicationAdministration|ResearchStudy": { + FromType: "MedicationAdministration", + EdgeLabel: "focus_reference_MedicationAdministration", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "ResearchStudy|focus_reference_MedicationStatement|MedicationStatement": { + FromType: "ResearchStudy", + EdgeLabel: "focus_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|focus_reference_MedicationStatement|ResearchStudy": { + FromType: "MedicationStatement", + EdgeLabel: "focus_reference_MedicationStatement", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "ResearchStudy|focus_reference_MedicationRequest|MedicationRequest": { + FromType: "ResearchStudy", + EdgeLabel: "focus_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|focus_reference_MedicationRequest|ResearchStudy": { + FromType: "MedicationRequest", + EdgeLabel: "focus_reference_MedicationRequest", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "ResearchStudy|focus_reference_Procedure|Procedure": { + FromType: "ResearchStudy", + EdgeLabel: "focus_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|focus_reference_Procedure|ResearchStudy": { + FromType: "Procedure", + EdgeLabel: "focus_reference_Procedure", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "ResearchStudy|focus_reference_DocumentReference|DocumentReference": { + FromType: "ResearchStudy", + EdgeLabel: "focus_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|focus_reference_DocumentReference|ResearchStudy": { + FromType: "DocumentReference", + EdgeLabel: "focus_reference_DocumentReference", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "ResearchStudy|focus_reference_Task|Task": { + FromType: "ResearchStudy", + EdgeLabel: "focus_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|focus_reference_Task|ResearchStudy": { + FromType: "Task", + EdgeLabel: "focus_reference_Task", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "ResearchStudy|focus_reference_ImagingStudy|ImagingStudy": { + FromType: "ResearchStudy", + EdgeLabel: "focus_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|focus_reference_ImagingStudy|ResearchStudy": { + FromType: "ImagingStudy", + EdgeLabel: "focus_reference_ImagingStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ResearchStudy|focus_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "ResearchStudy", + EdgeLabel: "focus_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|focus_reference_FamilyMemberHistory|ResearchStudy": { + FromType: "FamilyMemberHistory", + EdgeLabel: "focus_reference_FamilyMemberHistory", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "ResearchStudy|focus_reference_BodyStructure|BodyStructure": { + FromType: "ResearchStudy", + EdgeLabel: "focus_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|focus_reference_BodyStructure|ResearchStudy": { + FromType: "BodyStructure", + EdgeLabel: "focus_reference_BodyStructure", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "ResearchStudy|note_authorReference_Practitioner|Practitioner": { + FromType: "ResearchStudy", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|note_authorReference_Practitioner|ResearchStudy": { + FromType: "Practitioner", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "ResearchStudy|note_authorReference_PractitionerRole|PractitionerRole": { + FromType: "ResearchStudy", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|note_authorReference_PractitionerRole|ResearchStudy": { + FromType: "PractitionerRole", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "ResearchStudy|note_authorReference_Patient|Patient": { + FromType: "ResearchStudy", + EdgeLabel: "note_authorReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|note_authorReference_Patient|ResearchStudy": { + FromType: "Patient", + EdgeLabel: "note_authorReference_Patient", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "ResearchStudy|note_authorReference_Organization|Organization": { + FromType: "ResearchStudy", + EdgeLabel: "note_authorReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|note_authorReference_Organization|ResearchStudy": { + FromType: "Organization", + EdgeLabel: "note_authorReference_Organization", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "ResearchStudy|recruitment_actualGroup|Group": { + FromType: "ResearchStudy", + EdgeLabel: "recruitment_actualGroup", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "actualGroup_research_study_recruitment", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|recruitment_actualGroup|ResearchStudy": { + FromType: "Group", + EdgeLabel: "recruitment_actualGroup", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "actualGroup_research_study_recruitment", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "ResearchStudy|recruitment_eligibility_Group|Group": { + FromType: "ResearchStudy", + EdgeLabel: "recruitment_eligibility_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "eligibility_research_study_recruitment", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|recruitment_eligibility_Group|ResearchStudy": { + FromType: "Group", + EdgeLabel: "recruitment_eligibility_Group", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "eligibility_research_study_recruitment", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "ResearchStudy|relatedArtifact_resourceReference_Organization|Organization": { + FromType: "ResearchStudy", + EdgeLabel: "relatedArtifact_resourceReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|relatedArtifact_resourceReference_Organization|ResearchStudy": { + FromType: "Organization", + EdgeLabel: "relatedArtifact_resourceReference_Organization", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "ResearchStudy|relatedArtifact_resourceReference_Group|Group": { + FromType: "ResearchStudy", + EdgeLabel: "relatedArtifact_resourceReference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|relatedArtifact_resourceReference_Group|ResearchStudy": { + FromType: "Group", + EdgeLabel: "relatedArtifact_resourceReference_Group", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "ResearchStudy|relatedArtifact_resourceReference_Practitioner|Practitioner": { + FromType: "ResearchStudy", + EdgeLabel: "relatedArtifact_resourceReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|relatedArtifact_resourceReference_Practitioner|ResearchStudy": { + FromType: "Practitioner", + EdgeLabel: "relatedArtifact_resourceReference_Practitioner", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "ResearchStudy|relatedArtifact_resourceReference_PractitionerRole|PractitionerRole": { + FromType: "ResearchStudy", + EdgeLabel: "relatedArtifact_resourceReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|relatedArtifact_resourceReference_PractitionerRole|ResearchStudy": { + FromType: "PractitionerRole", + EdgeLabel: "relatedArtifact_resourceReference_PractitionerRole", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "ResearchStudy|relatedArtifact_resourceReference_ResearchStudy|ResearchStudy": { + FromType: "ResearchStudy", + EdgeLabel: "relatedArtifact_resourceReference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|relatedArtifact_resourceReference_Patient|Patient": { + FromType: "ResearchStudy", + EdgeLabel: "relatedArtifact_resourceReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|relatedArtifact_resourceReference_Patient|ResearchStudy": { + FromType: "Patient", + EdgeLabel: "relatedArtifact_resourceReference_Patient", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "ResearchStudy|relatedArtifact_resourceReference_ResearchSubject|ResearchSubject": { + FromType: "ResearchStudy", + EdgeLabel: "relatedArtifact_resourceReference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|relatedArtifact_resourceReference_ResearchSubject|ResearchStudy": { + FromType: "ResearchSubject", + EdgeLabel: "relatedArtifact_resourceReference_ResearchSubject", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchStudy|relatedArtifact_resourceReference_Substance|Substance": { + FromType: "ResearchStudy", + EdgeLabel: "relatedArtifact_resourceReference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|relatedArtifact_resourceReference_Substance|ResearchStudy": { + FromType: "Substance", + EdgeLabel: "relatedArtifact_resourceReference_Substance", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "ResearchStudy|relatedArtifact_resourceReference_SubstanceDefinition|SubstanceDefinition": { + FromType: "ResearchStudy", + EdgeLabel: "relatedArtifact_resourceReference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|relatedArtifact_resourceReference_SubstanceDefinition|ResearchStudy": { + FromType: "SubstanceDefinition", + EdgeLabel: "relatedArtifact_resourceReference_SubstanceDefinition", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "ResearchStudy|relatedArtifact_resourceReference_Specimen|Specimen": { + FromType: "ResearchStudy", + EdgeLabel: "relatedArtifact_resourceReference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|relatedArtifact_resourceReference_Specimen|ResearchStudy": { + FromType: "Specimen", + EdgeLabel: "relatedArtifact_resourceReference_Specimen", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "ResearchStudy|relatedArtifact_resourceReference_Observation|Observation": { + FromType: "ResearchStudy", + EdgeLabel: "relatedArtifact_resourceReference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|relatedArtifact_resourceReference_Observation|ResearchStudy": { + FromType: "Observation", + EdgeLabel: "relatedArtifact_resourceReference_Observation", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "ResearchStudy|relatedArtifact_resourceReference_DiagnosticReport|DiagnosticReport": { + FromType: "ResearchStudy", + EdgeLabel: "relatedArtifact_resourceReference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|relatedArtifact_resourceReference_DiagnosticReport|ResearchStudy": { + FromType: "DiagnosticReport", + EdgeLabel: "relatedArtifact_resourceReference_DiagnosticReport", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "ResearchStudy|relatedArtifact_resourceReference_Condition|Condition": { + FromType: "ResearchStudy", + EdgeLabel: "relatedArtifact_resourceReference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|relatedArtifact_resourceReference_Condition|ResearchStudy": { + FromType: "Condition", + EdgeLabel: "relatedArtifact_resourceReference_Condition", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "ResearchStudy|relatedArtifact_resourceReference_Medication|Medication": { + FromType: "ResearchStudy", + EdgeLabel: "relatedArtifact_resourceReference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|relatedArtifact_resourceReference_Medication|ResearchStudy": { + FromType: "Medication", + EdgeLabel: "relatedArtifact_resourceReference_Medication", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "ResearchStudy|relatedArtifact_resourceReference_MedicationAdministration|MedicationAdministration": { + FromType: "ResearchStudy", + EdgeLabel: "relatedArtifact_resourceReference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|relatedArtifact_resourceReference_MedicationAdministration|ResearchStudy": { + FromType: "MedicationAdministration", + EdgeLabel: "relatedArtifact_resourceReference_MedicationAdministration", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "ResearchStudy|relatedArtifact_resourceReference_MedicationStatement|MedicationStatement": { + FromType: "ResearchStudy", + EdgeLabel: "relatedArtifact_resourceReference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|relatedArtifact_resourceReference_MedicationStatement|ResearchStudy": { + FromType: "MedicationStatement", + EdgeLabel: "relatedArtifact_resourceReference_MedicationStatement", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "ResearchStudy|relatedArtifact_resourceReference_MedicationRequest|MedicationRequest": { + FromType: "ResearchStudy", + EdgeLabel: "relatedArtifact_resourceReference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|relatedArtifact_resourceReference_MedicationRequest|ResearchStudy": { + FromType: "MedicationRequest", + EdgeLabel: "relatedArtifact_resourceReference_MedicationRequest", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "ResearchStudy|relatedArtifact_resourceReference_Procedure|Procedure": { + FromType: "ResearchStudy", + EdgeLabel: "relatedArtifact_resourceReference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|relatedArtifact_resourceReference_Procedure|ResearchStudy": { + FromType: "Procedure", + EdgeLabel: "relatedArtifact_resourceReference_Procedure", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "ResearchStudy|relatedArtifact_resourceReference_DocumentReference|DocumentReference": { + FromType: "ResearchStudy", + EdgeLabel: "relatedArtifact_resourceReference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|relatedArtifact_resourceReference_DocumentReference|ResearchStudy": { + FromType: "DocumentReference", + EdgeLabel: "relatedArtifact_resourceReference_DocumentReference", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "ResearchStudy|relatedArtifact_resourceReference_Task|Task": { + FromType: "ResearchStudy", + EdgeLabel: "relatedArtifact_resourceReference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|relatedArtifact_resourceReference_Task|ResearchStudy": { + FromType: "Task", + EdgeLabel: "relatedArtifact_resourceReference_Task", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "ResearchStudy|relatedArtifact_resourceReference_ImagingStudy|ImagingStudy": { + FromType: "ResearchStudy", + EdgeLabel: "relatedArtifact_resourceReference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|relatedArtifact_resourceReference_ImagingStudy|ResearchStudy": { + FromType: "ImagingStudy", + EdgeLabel: "relatedArtifact_resourceReference_ImagingStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ResearchStudy|relatedArtifact_resourceReference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "ResearchStudy", + EdgeLabel: "relatedArtifact_resourceReference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|relatedArtifact_resourceReference_FamilyMemberHistory|ResearchStudy": { + FromType: "FamilyMemberHistory", + EdgeLabel: "relatedArtifact_resourceReference_FamilyMemberHistory", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "ResearchStudy|relatedArtifact_resourceReference_BodyStructure|BodyStructure": { + FromType: "ResearchStudy", + EdgeLabel: "relatedArtifact_resourceReference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|relatedArtifact_resourceReference_BodyStructure|ResearchStudy": { + FromType: "BodyStructure", + EdgeLabel: "relatedArtifact_resourceReference_BodyStructure", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "ResearchStudyAssociatedParty|party_Practitioner|Practitioner": { + FromType: "ResearchStudyAssociatedParty", + EdgeLabel: "party_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_study_associated_party", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|party_Practitioner|ResearchStudyAssociatedParty": { + FromType: "Practitioner", + EdgeLabel: "party_Practitioner", + ToType: "ResearchStudyAssociatedParty", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_study_associated_party", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "ResearchStudyAssociatedParty|party_PractitionerRole|PractitionerRole": { + FromType: "ResearchStudyAssociatedParty", + EdgeLabel: "party_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_study_associated_party", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|party_PractitionerRole|ResearchStudyAssociatedParty": { + FromType: "PractitionerRole", + EdgeLabel: "party_PractitionerRole", + ToType: "ResearchStudyAssociatedParty", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_study_associated_party", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "ResearchStudyAssociatedParty|party_Organization|Organization": { + FromType: "ResearchStudyAssociatedParty", + EdgeLabel: "party_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_study_associated_party", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|party_Organization|ResearchStudyAssociatedParty": { + FromType: "Organization", + EdgeLabel: "party_Organization", + ToType: "ResearchStudyAssociatedParty", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_study_associated_party", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "ResearchStudyComparisonGroup|observedGroup|Group": { + FromType: "ResearchStudyComparisonGroup", + EdgeLabel: "observedGroup", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_study_comparison_group", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|observedGroup|ResearchStudyComparisonGroup": { + FromType: "Group", + EdgeLabel: "observedGroup", + ToType: "ResearchStudyComparisonGroup", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_study_comparison_group", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "ResearchStudyRecruitment|actualGroup|Group": { + FromType: "ResearchStudyRecruitment", + EdgeLabel: "actualGroup", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "actualGroup_research_study_recruitment", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|actualGroup|ResearchStudyRecruitment": { + FromType: "Group", + EdgeLabel: "actualGroup", + ToType: "ResearchStudyRecruitment", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "actualGroup_research_study_recruitment", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "ResearchStudyRecruitment|eligibility_Group|Group": { + FromType: "ResearchStudyRecruitment", + EdgeLabel: "eligibility_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "eligibility_research_study_recruitment", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|eligibility_Group|ResearchStudyRecruitment": { + FromType: "Group", + EdgeLabel: "eligibility_Group", + ToType: "ResearchStudyRecruitment", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "eligibility_research_study_recruitment", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "ResearchSubject|study|ResearchStudy": { + FromType: "ResearchSubject", + EdgeLabel: "study", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_subject", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|study|ResearchSubject": { + FromType: "ResearchStudy", + EdgeLabel: "study", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_subject", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchSubject|subject_Patient|Patient": { + FromType: "ResearchSubject", + EdgeLabel: "subject_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_subject", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|subject_Patient|ResearchSubject": { + FromType: "Patient", + EdgeLabel: "subject_Patient", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_subject", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "ResearchSubject|subject_Group|Group": { + FromType: "ResearchSubject", + EdgeLabel: "subject_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_subject", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|subject_Group|ResearchSubject": { + FromType: "Group", + EdgeLabel: "subject_Group", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_subject", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "ResearchSubject|subject_Specimen|Specimen": { + FromType: "ResearchSubject", + EdgeLabel: "subject_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_subject", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|subject_Specimen|ResearchSubject": { + FromType: "Specimen", + EdgeLabel: "subject_Specimen", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_subject", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "ResearchSubject|subject_Medication|Medication": { + FromType: "ResearchSubject", + EdgeLabel: "subject_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_subject", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|subject_Medication|ResearchSubject": { + FromType: "Medication", + EdgeLabel: "subject_Medication", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_subject", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "ResearchSubject|subject_Substance|Substance": { + FromType: "ResearchSubject", + EdgeLabel: "subject_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_subject", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|subject_Substance|ResearchSubject": { + FromType: "Substance", + EdgeLabel: "subject_Substance", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "research_subject", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Signature|onBehalfOf_Practitioner|Practitioner": { + FromType: "Signature", + EdgeLabel: "onBehalfOf_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|onBehalfOf_Practitioner|Signature": { + FromType: "Practitioner", + EdgeLabel: "onBehalfOf_Practitioner", + ToType: "Signature", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Signature|onBehalfOf_PractitionerRole|PractitionerRole": { + FromType: "Signature", + EdgeLabel: "onBehalfOf_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|onBehalfOf_PractitionerRole|Signature": { + FromType: "PractitionerRole", + EdgeLabel: "onBehalfOf_PractitionerRole", + ToType: "Signature", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Signature|onBehalfOf_Patient|Patient": { + FromType: "Signature", + EdgeLabel: "onBehalfOf_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|onBehalfOf_Patient|Signature": { + FromType: "Patient", + EdgeLabel: "onBehalfOf_Patient", + ToType: "Signature", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Signature|onBehalfOf_Organization|Organization": { + FromType: "Signature", + EdgeLabel: "onBehalfOf_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|onBehalfOf_Organization|Signature": { + FromType: "Organization", + EdgeLabel: "onBehalfOf_Organization", + ToType: "Signature", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Signature|who_Practitioner|Practitioner": { + FromType: "Signature", + EdgeLabel: "who_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|who_Practitioner|Signature": { + FromType: "Practitioner", + EdgeLabel: "who_Practitioner", + ToType: "Signature", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Signature|who_PractitionerRole|PractitionerRole": { + FromType: "Signature", + EdgeLabel: "who_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|who_PractitionerRole|Signature": { + FromType: "PractitionerRole", + EdgeLabel: "who_PractitionerRole", + ToType: "Signature", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Signature|who_Patient|Patient": { + FromType: "Signature", + EdgeLabel: "who_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|who_Patient|Signature": { + FromType: "Patient", + EdgeLabel: "who_Patient", + ToType: "Signature", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Signature|who_Organization|Organization": { + FromType: "Signature", + EdgeLabel: "who_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|who_Organization|Signature": { + FromType: "Organization", + EdgeLabel: "who_Organization", + ToType: "Signature", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Specimen|parent|Specimen": { + FromType: "Specimen", + EdgeLabel: "parent", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "parent_specimen", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|subject_Patient|Patient": { + FromType: "Specimen", + EdgeLabel: "subject_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|subject_Patient|Specimen": { + FromType: "Patient", + EdgeLabel: "subject_Patient", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Specimen|subject_Group|Group": { + FromType: "Specimen", + EdgeLabel: "subject_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|subject_Group|Specimen": { + FromType: "Group", + EdgeLabel: "subject_Group", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Specimen|subject_Substance|Substance": { + FromType: "Specimen", + EdgeLabel: "subject_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|subject_Substance|Specimen": { + FromType: "Substance", + EdgeLabel: "subject_Substance", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Specimen|collection_collector_Practitioner|Practitioner": { + FromType: "Specimen", + EdgeLabel: "collection_collector_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen_collection", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|collection_collector_Practitioner|Specimen": { + FromType: "Practitioner", + EdgeLabel: "collection_collector_Practitioner", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen_collection", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Specimen|collection_collector_PractitionerRole|PractitionerRole": { + FromType: "Specimen", + EdgeLabel: "collection_collector_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen_collection", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|collection_collector_PractitionerRole|Specimen": { + FromType: "PractitionerRole", + EdgeLabel: "collection_collector_PractitionerRole", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen_collection", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Specimen|collection_collector_Patient|Patient": { + FromType: "Specimen", + EdgeLabel: "collection_collector_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen_collection", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|collection_collector_Patient|Specimen": { + FromType: "Patient", + EdgeLabel: "collection_collector_Patient", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen_collection", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Specimen|collection_procedure|Procedure": { + FromType: "Specimen", + EdgeLabel: "collection_procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen_collection", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|collection_procedure|Specimen": { + FromType: "Procedure", + EdgeLabel: "collection_procedure", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen_collection", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Specimen|note_authorReference_Practitioner|Practitioner": { + FromType: "Specimen", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|note_authorReference_Practitioner|Specimen": { + FromType: "Practitioner", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Specimen|note_authorReference_PractitionerRole|PractitionerRole": { + FromType: "Specimen", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|note_authorReference_PractitionerRole|Specimen": { + FromType: "PractitionerRole", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Specimen|note_authorReference_Patient|Patient": { + FromType: "Specimen", + EdgeLabel: "note_authorReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|note_authorReference_Patient|Specimen": { + FromType: "Patient", + EdgeLabel: "note_authorReference_Patient", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Specimen|note_authorReference_Organization|Organization": { + FromType: "Specimen", + EdgeLabel: "note_authorReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|note_authorReference_Organization|Specimen": { + FromType: "Organization", + EdgeLabel: "note_authorReference_Organization", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Specimen|processing_additive|Substance": { + FromType: "Specimen", + EdgeLabel: "processing_additive", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "additive_specimen_processing", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|processing_additive|Specimen": { + FromType: "Substance", + EdgeLabel: "processing_additive", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "additive_specimen_processing", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "SpecimenCollection|collector_Practitioner|Practitioner": { + FromType: "SpecimenCollection", + EdgeLabel: "collector_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen_collection", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|collector_Practitioner|SpecimenCollection": { + FromType: "Practitioner", + EdgeLabel: "collector_Practitioner", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen_collection", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "SpecimenCollection|collector_PractitionerRole|PractitionerRole": { + FromType: "SpecimenCollection", + EdgeLabel: "collector_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen_collection", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|collector_PractitionerRole|SpecimenCollection": { + FromType: "PractitionerRole", + EdgeLabel: "collector_PractitionerRole", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen_collection", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "SpecimenCollection|collector_Patient|Patient": { + FromType: "SpecimenCollection", + EdgeLabel: "collector_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen_collection", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|collector_Patient|SpecimenCollection": { + FromType: "Patient", + EdgeLabel: "collector_Patient", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen_collection", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "SpecimenCollection|procedure|Procedure": { + FromType: "SpecimenCollection", + EdgeLabel: "procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen_collection", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|procedure|SpecimenCollection": { + FromType: "Procedure", + EdgeLabel: "procedure", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "specimen_collection", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "SpecimenCollection|bodySite_reference_Organization|Organization": { + FromType: "SpecimenCollection", + EdgeLabel: "bodySite_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|bodySite_reference_Organization|SpecimenCollection": { + FromType: "Organization", + EdgeLabel: "bodySite_reference_Organization", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "SpecimenCollection|bodySite_reference_Group|Group": { + FromType: "SpecimenCollection", + EdgeLabel: "bodySite_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|bodySite_reference_Group|SpecimenCollection": { + FromType: "Group", + EdgeLabel: "bodySite_reference_Group", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "SpecimenCollection|bodySite_reference_Practitioner|Practitioner": { + FromType: "SpecimenCollection", + EdgeLabel: "bodySite_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|bodySite_reference_Practitioner|SpecimenCollection": { + FromType: "Practitioner", + EdgeLabel: "bodySite_reference_Practitioner", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "SpecimenCollection|bodySite_reference_PractitionerRole|PractitionerRole": { + FromType: "SpecimenCollection", + EdgeLabel: "bodySite_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|bodySite_reference_PractitionerRole|SpecimenCollection": { + FromType: "PractitionerRole", + EdgeLabel: "bodySite_reference_PractitionerRole", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "SpecimenCollection|bodySite_reference_ResearchStudy|ResearchStudy": { + FromType: "SpecimenCollection", + EdgeLabel: "bodySite_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|bodySite_reference_ResearchStudy|SpecimenCollection": { + FromType: "ResearchStudy", + EdgeLabel: "bodySite_reference_ResearchStudy", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "SpecimenCollection|bodySite_reference_Patient|Patient": { + FromType: "SpecimenCollection", + EdgeLabel: "bodySite_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|bodySite_reference_Patient|SpecimenCollection": { + FromType: "Patient", + EdgeLabel: "bodySite_reference_Patient", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "SpecimenCollection|bodySite_reference_ResearchSubject|ResearchSubject": { + FromType: "SpecimenCollection", + EdgeLabel: "bodySite_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|bodySite_reference_ResearchSubject|SpecimenCollection": { + FromType: "ResearchSubject", + EdgeLabel: "bodySite_reference_ResearchSubject", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "SpecimenCollection|bodySite_reference_Substance|Substance": { + FromType: "SpecimenCollection", + EdgeLabel: "bodySite_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|bodySite_reference_Substance|SpecimenCollection": { + FromType: "Substance", + EdgeLabel: "bodySite_reference_Substance", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "SpecimenCollection|bodySite_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "SpecimenCollection", + EdgeLabel: "bodySite_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|bodySite_reference_SubstanceDefinition|SpecimenCollection": { + FromType: "SubstanceDefinition", + EdgeLabel: "bodySite_reference_SubstanceDefinition", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SpecimenCollection|bodySite_reference_Specimen|Specimen": { + FromType: "SpecimenCollection", + EdgeLabel: "bodySite_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|bodySite_reference_Specimen|SpecimenCollection": { + FromType: "Specimen", + EdgeLabel: "bodySite_reference_Specimen", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "SpecimenCollection|bodySite_reference_Observation|Observation": { + FromType: "SpecimenCollection", + EdgeLabel: "bodySite_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|bodySite_reference_Observation|SpecimenCollection": { + FromType: "Observation", + EdgeLabel: "bodySite_reference_Observation", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "SpecimenCollection|bodySite_reference_DiagnosticReport|DiagnosticReport": { + FromType: "SpecimenCollection", + EdgeLabel: "bodySite_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|bodySite_reference_DiagnosticReport|SpecimenCollection": { + FromType: "DiagnosticReport", + EdgeLabel: "bodySite_reference_DiagnosticReport", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "SpecimenCollection|bodySite_reference_Condition|Condition": { + FromType: "SpecimenCollection", + EdgeLabel: "bodySite_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|bodySite_reference_Condition|SpecimenCollection": { + FromType: "Condition", + EdgeLabel: "bodySite_reference_Condition", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "SpecimenCollection|bodySite_reference_Medication|Medication": { + FromType: "SpecimenCollection", + EdgeLabel: "bodySite_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|bodySite_reference_Medication|SpecimenCollection": { + FromType: "Medication", + EdgeLabel: "bodySite_reference_Medication", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "SpecimenCollection|bodySite_reference_MedicationAdministration|MedicationAdministration": { + FromType: "SpecimenCollection", + EdgeLabel: "bodySite_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|bodySite_reference_MedicationAdministration|SpecimenCollection": { + FromType: "MedicationAdministration", + EdgeLabel: "bodySite_reference_MedicationAdministration", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "SpecimenCollection|bodySite_reference_MedicationStatement|MedicationStatement": { + FromType: "SpecimenCollection", + EdgeLabel: "bodySite_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|bodySite_reference_MedicationStatement|SpecimenCollection": { + FromType: "MedicationStatement", + EdgeLabel: "bodySite_reference_MedicationStatement", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "SpecimenCollection|bodySite_reference_MedicationRequest|MedicationRequest": { + FromType: "SpecimenCollection", + EdgeLabel: "bodySite_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|bodySite_reference_MedicationRequest|SpecimenCollection": { + FromType: "MedicationRequest", + EdgeLabel: "bodySite_reference_MedicationRequest", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "SpecimenCollection|bodySite_reference_Procedure|Procedure": { + FromType: "SpecimenCollection", + EdgeLabel: "bodySite_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|bodySite_reference_Procedure|SpecimenCollection": { + FromType: "Procedure", + EdgeLabel: "bodySite_reference_Procedure", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "SpecimenCollection|bodySite_reference_DocumentReference|DocumentReference": { + FromType: "SpecimenCollection", + EdgeLabel: "bodySite_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|bodySite_reference_DocumentReference|SpecimenCollection": { + FromType: "DocumentReference", + EdgeLabel: "bodySite_reference_DocumentReference", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "SpecimenCollection|bodySite_reference_Task|Task": { + FromType: "SpecimenCollection", + EdgeLabel: "bodySite_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|bodySite_reference_Task|SpecimenCollection": { + FromType: "Task", + EdgeLabel: "bodySite_reference_Task", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "SpecimenCollection|bodySite_reference_ImagingStudy|ImagingStudy": { + FromType: "SpecimenCollection", + EdgeLabel: "bodySite_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|bodySite_reference_ImagingStudy|SpecimenCollection": { + FromType: "ImagingStudy", + EdgeLabel: "bodySite_reference_ImagingStudy", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "SpecimenCollection|bodySite_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "SpecimenCollection", + EdgeLabel: "bodySite_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|bodySite_reference_FamilyMemberHistory|SpecimenCollection": { + FromType: "FamilyMemberHistory", + EdgeLabel: "bodySite_reference_FamilyMemberHistory", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "SpecimenCollection|bodySite_reference_BodyStructure|BodyStructure": { + FromType: "SpecimenCollection", + EdgeLabel: "bodySite_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|bodySite_reference_BodyStructure|SpecimenCollection": { + FromType: "BodyStructure", + EdgeLabel: "bodySite_reference_BodyStructure", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "SpecimenCollection|device_reference_Organization|Organization": { + FromType: "SpecimenCollection", + EdgeLabel: "device_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|device_reference_Organization|SpecimenCollection": { + FromType: "Organization", + EdgeLabel: "device_reference_Organization", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "SpecimenCollection|device_reference_Group|Group": { + FromType: "SpecimenCollection", + EdgeLabel: "device_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|device_reference_Group|SpecimenCollection": { + FromType: "Group", + EdgeLabel: "device_reference_Group", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "SpecimenCollection|device_reference_Practitioner|Practitioner": { + FromType: "SpecimenCollection", + EdgeLabel: "device_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|device_reference_Practitioner|SpecimenCollection": { + FromType: "Practitioner", + EdgeLabel: "device_reference_Practitioner", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "SpecimenCollection|device_reference_PractitionerRole|PractitionerRole": { + FromType: "SpecimenCollection", + EdgeLabel: "device_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|device_reference_PractitionerRole|SpecimenCollection": { + FromType: "PractitionerRole", + EdgeLabel: "device_reference_PractitionerRole", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "SpecimenCollection|device_reference_ResearchStudy|ResearchStudy": { + FromType: "SpecimenCollection", + EdgeLabel: "device_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|device_reference_ResearchStudy|SpecimenCollection": { + FromType: "ResearchStudy", + EdgeLabel: "device_reference_ResearchStudy", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "SpecimenCollection|device_reference_Patient|Patient": { + FromType: "SpecimenCollection", + EdgeLabel: "device_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|device_reference_Patient|SpecimenCollection": { + FromType: "Patient", + EdgeLabel: "device_reference_Patient", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "SpecimenCollection|device_reference_ResearchSubject|ResearchSubject": { + FromType: "SpecimenCollection", + EdgeLabel: "device_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|device_reference_ResearchSubject|SpecimenCollection": { + FromType: "ResearchSubject", + EdgeLabel: "device_reference_ResearchSubject", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "SpecimenCollection|device_reference_Substance|Substance": { + FromType: "SpecimenCollection", + EdgeLabel: "device_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|device_reference_Substance|SpecimenCollection": { + FromType: "Substance", + EdgeLabel: "device_reference_Substance", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "SpecimenCollection|device_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "SpecimenCollection", + EdgeLabel: "device_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|device_reference_SubstanceDefinition|SpecimenCollection": { + FromType: "SubstanceDefinition", + EdgeLabel: "device_reference_SubstanceDefinition", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SpecimenCollection|device_reference_Specimen|Specimen": { + FromType: "SpecimenCollection", + EdgeLabel: "device_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|device_reference_Specimen|SpecimenCollection": { + FromType: "Specimen", + EdgeLabel: "device_reference_Specimen", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "SpecimenCollection|device_reference_Observation|Observation": { + FromType: "SpecimenCollection", + EdgeLabel: "device_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|device_reference_Observation|SpecimenCollection": { + FromType: "Observation", + EdgeLabel: "device_reference_Observation", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "SpecimenCollection|device_reference_DiagnosticReport|DiagnosticReport": { + FromType: "SpecimenCollection", + EdgeLabel: "device_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|device_reference_DiagnosticReport|SpecimenCollection": { + FromType: "DiagnosticReport", + EdgeLabel: "device_reference_DiagnosticReport", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "SpecimenCollection|device_reference_Condition|Condition": { + FromType: "SpecimenCollection", + EdgeLabel: "device_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|device_reference_Condition|SpecimenCollection": { + FromType: "Condition", + EdgeLabel: "device_reference_Condition", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "SpecimenCollection|device_reference_Medication|Medication": { + FromType: "SpecimenCollection", + EdgeLabel: "device_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|device_reference_Medication|SpecimenCollection": { + FromType: "Medication", + EdgeLabel: "device_reference_Medication", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "SpecimenCollection|device_reference_MedicationAdministration|MedicationAdministration": { + FromType: "SpecimenCollection", + EdgeLabel: "device_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|device_reference_MedicationAdministration|SpecimenCollection": { + FromType: "MedicationAdministration", + EdgeLabel: "device_reference_MedicationAdministration", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "SpecimenCollection|device_reference_MedicationStatement|MedicationStatement": { + FromType: "SpecimenCollection", + EdgeLabel: "device_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|device_reference_MedicationStatement|SpecimenCollection": { + FromType: "MedicationStatement", + EdgeLabel: "device_reference_MedicationStatement", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "SpecimenCollection|device_reference_MedicationRequest|MedicationRequest": { + FromType: "SpecimenCollection", + EdgeLabel: "device_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|device_reference_MedicationRequest|SpecimenCollection": { + FromType: "MedicationRequest", + EdgeLabel: "device_reference_MedicationRequest", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "SpecimenCollection|device_reference_Procedure|Procedure": { + FromType: "SpecimenCollection", + EdgeLabel: "device_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|device_reference_Procedure|SpecimenCollection": { + FromType: "Procedure", + EdgeLabel: "device_reference_Procedure", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "SpecimenCollection|device_reference_DocumentReference|DocumentReference": { + FromType: "SpecimenCollection", + EdgeLabel: "device_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|device_reference_DocumentReference|SpecimenCollection": { + FromType: "DocumentReference", + EdgeLabel: "device_reference_DocumentReference", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "SpecimenCollection|device_reference_Task|Task": { + FromType: "SpecimenCollection", + EdgeLabel: "device_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|device_reference_Task|SpecimenCollection": { + FromType: "Task", + EdgeLabel: "device_reference_Task", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "SpecimenCollection|device_reference_ImagingStudy|ImagingStudy": { + FromType: "SpecimenCollection", + EdgeLabel: "device_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|device_reference_ImagingStudy|SpecimenCollection": { + FromType: "ImagingStudy", + EdgeLabel: "device_reference_ImagingStudy", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "SpecimenCollection|device_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "SpecimenCollection", + EdgeLabel: "device_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|device_reference_FamilyMemberHistory|SpecimenCollection": { + FromType: "FamilyMemberHistory", + EdgeLabel: "device_reference_FamilyMemberHistory", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "SpecimenCollection|device_reference_BodyStructure|BodyStructure": { + FromType: "SpecimenCollection", + EdgeLabel: "device_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|device_reference_BodyStructure|SpecimenCollection": { + FromType: "BodyStructure", + EdgeLabel: "device_reference_BodyStructure", + ToType: "SpecimenCollection", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "SpecimenProcessing|additive|Substance": { + FromType: "SpecimenProcessing", + EdgeLabel: "additive", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "additive_specimen_processing", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|additive|SpecimenProcessing": { + FromType: "Substance", + EdgeLabel: "additive", + ToType: "SpecimenProcessing", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "additive_specimen_processing", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|code_reference_Organization|Organization": { + FromType: "Substance", + EdgeLabel: "code_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|code_reference_Organization|Substance": { + FromType: "Organization", + EdgeLabel: "code_reference_Organization", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Substance|code_reference_Group|Group": { + FromType: "Substance", + EdgeLabel: "code_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|code_reference_Group|Substance": { + FromType: "Group", + EdgeLabel: "code_reference_Group", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Substance|code_reference_Practitioner|Practitioner": { + FromType: "Substance", + EdgeLabel: "code_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|code_reference_Practitioner|Substance": { + FromType: "Practitioner", + EdgeLabel: "code_reference_Practitioner", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Substance|code_reference_PractitionerRole|PractitionerRole": { + FromType: "Substance", + EdgeLabel: "code_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|code_reference_PractitionerRole|Substance": { + FromType: "PractitionerRole", + EdgeLabel: "code_reference_PractitionerRole", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Substance|code_reference_ResearchStudy|ResearchStudy": { + FromType: "Substance", + EdgeLabel: "code_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|code_reference_ResearchStudy|Substance": { + FromType: "ResearchStudy", + EdgeLabel: "code_reference_ResearchStudy", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "Substance|code_reference_Patient|Patient": { + FromType: "Substance", + EdgeLabel: "code_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|code_reference_Patient|Substance": { + FromType: "Patient", + EdgeLabel: "code_reference_Patient", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Substance|code_reference_ResearchSubject|ResearchSubject": { + FromType: "Substance", + EdgeLabel: "code_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|code_reference_ResearchSubject|Substance": { + FromType: "ResearchSubject", + EdgeLabel: "code_reference_ResearchSubject", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "Substance|code_reference_Substance|Substance": { + FromType: "Substance", + EdgeLabel: "code_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|code_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "Substance", + EdgeLabel: "code_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|code_reference_SubstanceDefinition|Substance": { + FromType: "SubstanceDefinition", + EdgeLabel: "code_reference_SubstanceDefinition", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "Substance|code_reference_Specimen|Specimen": { + FromType: "Substance", + EdgeLabel: "code_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|code_reference_Specimen|Substance": { + FromType: "Specimen", + EdgeLabel: "code_reference_Specimen", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Substance|code_reference_Observation|Observation": { + FromType: "Substance", + EdgeLabel: "code_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|code_reference_Observation|Substance": { + FromType: "Observation", + EdgeLabel: "code_reference_Observation", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Substance|code_reference_DiagnosticReport|DiagnosticReport": { + FromType: "Substance", + EdgeLabel: "code_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|code_reference_DiagnosticReport|Substance": { + FromType: "DiagnosticReport", + EdgeLabel: "code_reference_DiagnosticReport", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "Substance|code_reference_Condition|Condition": { + FromType: "Substance", + EdgeLabel: "code_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|code_reference_Condition|Substance": { + FromType: "Condition", + EdgeLabel: "code_reference_Condition", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Substance|code_reference_Medication|Medication": { + FromType: "Substance", + EdgeLabel: "code_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|code_reference_Medication|Substance": { + FromType: "Medication", + EdgeLabel: "code_reference_Medication", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Substance|code_reference_MedicationAdministration|MedicationAdministration": { + FromType: "Substance", + EdgeLabel: "code_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|code_reference_MedicationAdministration|Substance": { + FromType: "MedicationAdministration", + EdgeLabel: "code_reference_MedicationAdministration", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "Substance|code_reference_MedicationStatement|MedicationStatement": { + FromType: "Substance", + EdgeLabel: "code_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|code_reference_MedicationStatement|Substance": { + FromType: "MedicationStatement", + EdgeLabel: "code_reference_MedicationStatement", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "Substance|code_reference_MedicationRequest|MedicationRequest": { + FromType: "Substance", + EdgeLabel: "code_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|code_reference_MedicationRequest|Substance": { + FromType: "MedicationRequest", + EdgeLabel: "code_reference_MedicationRequest", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "Substance|code_reference_Procedure|Procedure": { + FromType: "Substance", + EdgeLabel: "code_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|code_reference_Procedure|Substance": { + FromType: "Procedure", + EdgeLabel: "code_reference_Procedure", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Substance|code_reference_DocumentReference|DocumentReference": { + FromType: "Substance", + EdgeLabel: "code_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|code_reference_DocumentReference|Substance": { + FromType: "DocumentReference", + EdgeLabel: "code_reference_DocumentReference", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "Substance|code_reference_Task|Task": { + FromType: "Substance", + EdgeLabel: "code_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|code_reference_Task|Substance": { + FromType: "Task", + EdgeLabel: "code_reference_Task", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Substance|code_reference_ImagingStudy|ImagingStudy": { + FromType: "Substance", + EdgeLabel: "code_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|code_reference_ImagingStudy|Substance": { + FromType: "ImagingStudy", + EdgeLabel: "code_reference_ImagingStudy", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "Substance|code_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "Substance", + EdgeLabel: "code_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|code_reference_FamilyMemberHistory|Substance": { + FromType: "FamilyMemberHistory", + EdgeLabel: "code_reference_FamilyMemberHistory", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "Substance|code_reference_BodyStructure|BodyStructure": { + FromType: "Substance", + EdgeLabel: "code_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|code_reference_BodyStructure|Substance": { + FromType: "BodyStructure", + EdgeLabel: "code_reference_BodyStructure", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "Substance|ingredient_substanceReference|Substance": { + FromType: "Substance", + EdgeLabel: "ingredient_substanceReference", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "substance_ingredient", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "SubstanceDefinition|manufacturer|Organization": { + FromType: "SubstanceDefinition", + EdgeLabel: "manufacturer", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "manufacturer_substance_definition", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|manufacturer|SubstanceDefinition": { + FromType: "Organization", + EdgeLabel: "manufacturer", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "manufacturer_substance_definition", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "SubstanceDefinition|supplier|Organization": { + FromType: "SubstanceDefinition", + EdgeLabel: "supplier", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supplier_substance_definition", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|supplier|SubstanceDefinition": { + FromType: "Organization", + EdgeLabel: "supplier", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "supplier_substance_definition", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "SubstanceDefinition|code_source|DocumentReference": { + FromType: "SubstanceDefinition", + EdgeLabel: "code_source", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "source_substance_definition_code", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|code_source|SubstanceDefinition": { + FromType: "DocumentReference", + EdgeLabel: "code_source", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "source_substance_definition_code", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "SubstanceDefinition|name_source|DocumentReference": { + FromType: "SubstanceDefinition", + EdgeLabel: "name_source", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "source_substance_definition_name", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|name_source|SubstanceDefinition": { + FromType: "DocumentReference", + EdgeLabel: "name_source", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "source_substance_definition_name", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "SubstanceDefinition|note_authorReference_Practitioner|Practitioner": { + FromType: "SubstanceDefinition", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|note_authorReference_Practitioner|SubstanceDefinition": { + FromType: "Practitioner", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "SubstanceDefinition|note_authorReference_PractitionerRole|PractitionerRole": { + FromType: "SubstanceDefinition", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|note_authorReference_PractitionerRole|SubstanceDefinition": { + FromType: "PractitionerRole", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "SubstanceDefinition|note_authorReference_Patient|Patient": { + FromType: "SubstanceDefinition", + EdgeLabel: "note_authorReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|note_authorReference_Patient|SubstanceDefinition": { + FromType: "Patient", + EdgeLabel: "note_authorReference_Patient", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "SubstanceDefinition|note_authorReference_Organization|Organization": { + FromType: "SubstanceDefinition", + EdgeLabel: "note_authorReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|note_authorReference_Organization|SubstanceDefinition": { + FromType: "Organization", + EdgeLabel: "note_authorReference_Organization", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "SubstanceDefinition|relationship_source|DocumentReference": { + FromType: "SubstanceDefinition", + EdgeLabel: "relationship_source", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "source_substance_definition_relationship", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|relationship_source|SubstanceDefinition": { + FromType: "DocumentReference", + EdgeLabel: "relationship_source", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "source_substance_definition_relationship", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "SubstanceDefinition|relationship_substanceDefinitionReference|SubstanceDefinition": { + FromType: "SubstanceDefinition", + EdgeLabel: "relationship_substanceDefinitionReference", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "substance_definition_relationship", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|structure_sourceDocument|DocumentReference": { + FromType: "SubstanceDefinition", + EdgeLabel: "structure_sourceDocument", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "sourceDocument_substance_definition_structure", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|structure_sourceDocument|SubstanceDefinition": { + FromType: "DocumentReference", + EdgeLabel: "structure_sourceDocument", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "sourceDocument_substance_definition_structure", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "SubstanceDefinitionCode|source|DocumentReference": { + FromType: "SubstanceDefinitionCode", + EdgeLabel: "source", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "source_substance_definition_code", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|source|SubstanceDefinitionCode": { + FromType: "DocumentReference", + EdgeLabel: "source", + ToType: "SubstanceDefinitionCode", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "source_substance_definition_code", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "SubstanceDefinitionCode|note_authorReference_Practitioner|Practitioner": { + FromType: "SubstanceDefinitionCode", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|note_authorReference_Practitioner|SubstanceDefinitionCode": { + FromType: "Practitioner", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "SubstanceDefinitionCode", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "SubstanceDefinitionCode|note_authorReference_PractitionerRole|PractitionerRole": { + FromType: "SubstanceDefinitionCode", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|note_authorReference_PractitionerRole|SubstanceDefinitionCode": { + FromType: "PractitionerRole", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "SubstanceDefinitionCode", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "SubstanceDefinitionCode|note_authorReference_Patient|Patient": { + FromType: "SubstanceDefinitionCode", + EdgeLabel: "note_authorReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|note_authorReference_Patient|SubstanceDefinitionCode": { + FromType: "Patient", + EdgeLabel: "note_authorReference_Patient", + ToType: "SubstanceDefinitionCode", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "SubstanceDefinitionCode|note_authorReference_Organization|Organization": { + FromType: "SubstanceDefinitionCode", + EdgeLabel: "note_authorReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|note_authorReference_Organization|SubstanceDefinitionCode": { + FromType: "Organization", + EdgeLabel: "note_authorReference_Organization", + ToType: "SubstanceDefinitionCode", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "SubstanceDefinitionName|source|DocumentReference": { + FromType: "SubstanceDefinitionName", + EdgeLabel: "source", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "source_substance_definition_name", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|source|SubstanceDefinitionName": { + FromType: "DocumentReference", + EdgeLabel: "source", + ToType: "SubstanceDefinitionName", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "source_substance_definition_name", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "SubstanceDefinitionName|synonym_source|DocumentReference": { + FromType: "SubstanceDefinitionName", + EdgeLabel: "synonym_source", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "source_substance_definition_name", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|synonym_source|SubstanceDefinitionName": { + FromType: "DocumentReference", + EdgeLabel: "synonym_source", + ToType: "SubstanceDefinitionName", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "source_substance_definition_name", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "SubstanceDefinitionName|translation_source|DocumentReference": { + FromType: "SubstanceDefinitionName", + EdgeLabel: "translation_source", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "source_substance_definition_name", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|translation_source|SubstanceDefinitionName": { + FromType: "DocumentReference", + EdgeLabel: "translation_source", + ToType: "SubstanceDefinitionName", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "source_substance_definition_name", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "SubstanceDefinitionRelationship|source|DocumentReference": { + FromType: "SubstanceDefinitionRelationship", + EdgeLabel: "source", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "source_substance_definition_relationship", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|source|SubstanceDefinitionRelationship": { + FromType: "DocumentReference", + EdgeLabel: "source", + ToType: "SubstanceDefinitionRelationship", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "source_substance_definition_relationship", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "SubstanceDefinitionRelationship|substanceDefinitionReference|SubstanceDefinition": { + FromType: "SubstanceDefinitionRelationship", + EdgeLabel: "substanceDefinitionReference", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "substance_definition_relationship", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|substanceDefinitionReference|SubstanceDefinitionRelationship": { + FromType: "SubstanceDefinition", + EdgeLabel: "substanceDefinitionReference", + ToType: "SubstanceDefinitionRelationship", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "substance_definition_relationship", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinitionStructure|sourceDocument|DocumentReference": { + FromType: "SubstanceDefinitionStructure", + EdgeLabel: "sourceDocument", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "sourceDocument_substance_definition_structure", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|sourceDocument|SubstanceDefinitionStructure": { + FromType: "DocumentReference", + EdgeLabel: "sourceDocument", + ToType: "SubstanceDefinitionStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "sourceDocument_substance_definition_structure", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "SubstanceDefinitionStructure|representation_document|DocumentReference": { + FromType: "SubstanceDefinitionStructure", + EdgeLabel: "representation_document", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "substance_definition_structure_representation", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|representation_document|SubstanceDefinitionStructure": { + FromType: "DocumentReference", + EdgeLabel: "representation_document", + ToType: "SubstanceDefinitionStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "substance_definition_structure_representation", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "SubstanceDefinitionStructureRepresentation|document|DocumentReference": { + FromType: "SubstanceDefinitionStructureRepresentation", + EdgeLabel: "document", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "substance_definition_structure_representation", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|document|SubstanceDefinitionStructureRepresentation": { + FromType: "DocumentReference", + EdgeLabel: "document", + ToType: "SubstanceDefinitionStructureRepresentation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "substance_definition_structure_representation", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "SubstanceIngredient|substanceReference|Substance": { + FromType: "SubstanceIngredient", + EdgeLabel: "substanceReference", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "substance_ingredient", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|substanceReference|SubstanceIngredient": { + FromType: "Substance", + EdgeLabel: "substanceReference", + ToType: "SubstanceIngredient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "substance_ingredient", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Task|basedOn_Organization|Organization": { + FromType: "Task", + EdgeLabel: "basedOn_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|basedOn_Organization|Task": { + FromType: "Organization", + EdgeLabel: "basedOn_Organization", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Task|basedOn_Group|Group": { + FromType: "Task", + EdgeLabel: "basedOn_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|basedOn_Group|Task": { + FromType: "Group", + EdgeLabel: "basedOn_Group", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Task|basedOn_Practitioner|Practitioner": { + FromType: "Task", + EdgeLabel: "basedOn_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|basedOn_Practitioner|Task": { + FromType: "Practitioner", + EdgeLabel: "basedOn_Practitioner", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Task|basedOn_PractitionerRole|PractitionerRole": { + FromType: "Task", + EdgeLabel: "basedOn_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|basedOn_PractitionerRole|Task": { + FromType: "PractitionerRole", + EdgeLabel: "basedOn_PractitionerRole", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Task|basedOn_ResearchStudy|ResearchStudy": { + FromType: "Task", + EdgeLabel: "basedOn_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|basedOn_ResearchStudy|Task": { + FromType: "ResearchStudy", + EdgeLabel: "basedOn_ResearchStudy", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "Task|basedOn_Patient|Patient": { + FromType: "Task", + EdgeLabel: "basedOn_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|basedOn_Patient|Task": { + FromType: "Patient", + EdgeLabel: "basedOn_Patient", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Task|basedOn_ResearchSubject|ResearchSubject": { + FromType: "Task", + EdgeLabel: "basedOn_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|basedOn_ResearchSubject|Task": { + FromType: "ResearchSubject", + EdgeLabel: "basedOn_ResearchSubject", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "Task|basedOn_Substance|Substance": { + FromType: "Task", + EdgeLabel: "basedOn_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|basedOn_Substance|Task": { + FromType: "Substance", + EdgeLabel: "basedOn_Substance", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Task|basedOn_SubstanceDefinition|SubstanceDefinition": { + FromType: "Task", + EdgeLabel: "basedOn_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|basedOn_SubstanceDefinition|Task": { + FromType: "SubstanceDefinition", + EdgeLabel: "basedOn_SubstanceDefinition", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "Task|basedOn_Specimen|Specimen": { + FromType: "Task", + EdgeLabel: "basedOn_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|basedOn_Specimen|Task": { + FromType: "Specimen", + EdgeLabel: "basedOn_Specimen", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Task|basedOn_Observation|Observation": { + FromType: "Task", + EdgeLabel: "basedOn_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|basedOn_Observation|Task": { + FromType: "Observation", + EdgeLabel: "basedOn_Observation", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Task|basedOn_DiagnosticReport|DiagnosticReport": { + FromType: "Task", + EdgeLabel: "basedOn_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|basedOn_DiagnosticReport|Task": { + FromType: "DiagnosticReport", + EdgeLabel: "basedOn_DiagnosticReport", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "Task|basedOn_Condition|Condition": { + FromType: "Task", + EdgeLabel: "basedOn_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|basedOn_Condition|Task": { + FromType: "Condition", + EdgeLabel: "basedOn_Condition", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Task|basedOn_Medication|Medication": { + FromType: "Task", + EdgeLabel: "basedOn_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|basedOn_Medication|Task": { + FromType: "Medication", + EdgeLabel: "basedOn_Medication", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Task|basedOn_MedicationAdministration|MedicationAdministration": { + FromType: "Task", + EdgeLabel: "basedOn_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|basedOn_MedicationAdministration|Task": { + FromType: "MedicationAdministration", + EdgeLabel: "basedOn_MedicationAdministration", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "Task|basedOn_MedicationStatement|MedicationStatement": { + FromType: "Task", + EdgeLabel: "basedOn_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|basedOn_MedicationStatement|Task": { + FromType: "MedicationStatement", + EdgeLabel: "basedOn_MedicationStatement", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "Task|basedOn_MedicationRequest|MedicationRequest": { + FromType: "Task", + EdgeLabel: "basedOn_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|basedOn_MedicationRequest|Task": { + FromType: "MedicationRequest", + EdgeLabel: "basedOn_MedicationRequest", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "Task|basedOn_Procedure|Procedure": { + FromType: "Task", + EdgeLabel: "basedOn_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|basedOn_Procedure|Task": { + FromType: "Procedure", + EdgeLabel: "basedOn_Procedure", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Task|basedOn_DocumentReference|DocumentReference": { + FromType: "Task", + EdgeLabel: "basedOn_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|basedOn_DocumentReference|Task": { + FromType: "DocumentReference", + EdgeLabel: "basedOn_DocumentReference", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "Task|basedOn_Task|Task": { + FromType: "Task", + EdgeLabel: "basedOn_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|basedOn_ImagingStudy|ImagingStudy": { + FromType: "Task", + EdgeLabel: "basedOn_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|basedOn_ImagingStudy|Task": { + FromType: "ImagingStudy", + EdgeLabel: "basedOn_ImagingStudy", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "Task|basedOn_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "Task", + EdgeLabel: "basedOn_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|basedOn_FamilyMemberHistory|Task": { + FromType: "FamilyMemberHistory", + EdgeLabel: "basedOn_FamilyMemberHistory", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "Task|basedOn_BodyStructure|BodyStructure": { + FromType: "Task", + EdgeLabel: "basedOn_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|basedOn_BodyStructure|Task": { + FromType: "BodyStructure", + EdgeLabel: "basedOn_BodyStructure", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "basedOn_task", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "Task|focus_Organization|Organization": { + FromType: "Task", + EdgeLabel: "focus_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|focus_Organization|Task": { + FromType: "Organization", + EdgeLabel: "focus_Organization", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Task|focus_Group|Group": { + FromType: "Task", + EdgeLabel: "focus_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|focus_Group|Task": { + FromType: "Group", + EdgeLabel: "focus_Group", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Task|focus_Practitioner|Practitioner": { + FromType: "Task", + EdgeLabel: "focus_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|focus_Practitioner|Task": { + FromType: "Practitioner", + EdgeLabel: "focus_Practitioner", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Task|focus_PractitionerRole|PractitionerRole": { + FromType: "Task", + EdgeLabel: "focus_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|focus_PractitionerRole|Task": { + FromType: "PractitionerRole", + EdgeLabel: "focus_PractitionerRole", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Task|focus_ResearchStudy|ResearchStudy": { + FromType: "Task", + EdgeLabel: "focus_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|focus_ResearchStudy|Task": { + FromType: "ResearchStudy", + EdgeLabel: "focus_ResearchStudy", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "Task|focus_Patient|Patient": { + FromType: "Task", + EdgeLabel: "focus_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|focus_Patient|Task": { + FromType: "Patient", + EdgeLabel: "focus_Patient", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Task|focus_ResearchSubject|ResearchSubject": { + FromType: "Task", + EdgeLabel: "focus_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|focus_ResearchSubject|Task": { + FromType: "ResearchSubject", + EdgeLabel: "focus_ResearchSubject", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "Task|focus_Substance|Substance": { + FromType: "Task", + EdgeLabel: "focus_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|focus_Substance|Task": { + FromType: "Substance", + EdgeLabel: "focus_Substance", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Task|focus_SubstanceDefinition|SubstanceDefinition": { + FromType: "Task", + EdgeLabel: "focus_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|focus_SubstanceDefinition|Task": { + FromType: "SubstanceDefinition", + EdgeLabel: "focus_SubstanceDefinition", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "Task|focus_Specimen|Specimen": { + FromType: "Task", + EdgeLabel: "focus_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|focus_Specimen|Task": { + FromType: "Specimen", + EdgeLabel: "focus_Specimen", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Task|focus_Observation|Observation": { + FromType: "Task", + EdgeLabel: "focus_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|focus_Observation|Task": { + FromType: "Observation", + EdgeLabel: "focus_Observation", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Task|focus_DiagnosticReport|DiagnosticReport": { + FromType: "Task", + EdgeLabel: "focus_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|focus_DiagnosticReport|Task": { + FromType: "DiagnosticReport", + EdgeLabel: "focus_DiagnosticReport", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "Task|focus_Condition|Condition": { + FromType: "Task", + EdgeLabel: "focus_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|focus_Condition|Task": { + FromType: "Condition", + EdgeLabel: "focus_Condition", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Task|focus_Medication|Medication": { + FromType: "Task", + EdgeLabel: "focus_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|focus_Medication|Task": { + FromType: "Medication", + EdgeLabel: "focus_Medication", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Task|focus_MedicationAdministration|MedicationAdministration": { + FromType: "Task", + EdgeLabel: "focus_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|focus_MedicationAdministration|Task": { + FromType: "MedicationAdministration", + EdgeLabel: "focus_MedicationAdministration", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "Task|focus_MedicationStatement|MedicationStatement": { + FromType: "Task", + EdgeLabel: "focus_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|focus_MedicationStatement|Task": { + FromType: "MedicationStatement", + EdgeLabel: "focus_MedicationStatement", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "Task|focus_MedicationRequest|MedicationRequest": { + FromType: "Task", + EdgeLabel: "focus_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|focus_MedicationRequest|Task": { + FromType: "MedicationRequest", + EdgeLabel: "focus_MedicationRequest", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "Task|focus_Procedure|Procedure": { + FromType: "Task", + EdgeLabel: "focus_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|focus_Procedure|Task": { + FromType: "Procedure", + EdgeLabel: "focus_Procedure", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Task|focus_DocumentReference|DocumentReference": { + FromType: "Task", + EdgeLabel: "focus_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|focus_DocumentReference|Task": { + FromType: "DocumentReference", + EdgeLabel: "focus_DocumentReference", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "Task|focus_Task|Task": { + FromType: "Task", + EdgeLabel: "focus_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|focus_ImagingStudy|ImagingStudy": { + FromType: "Task", + EdgeLabel: "focus_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|focus_ImagingStudy|Task": { + FromType: "ImagingStudy", + EdgeLabel: "focus_ImagingStudy", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "Task|focus_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "Task", + EdgeLabel: "focus_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|focus_FamilyMemberHistory|Task": { + FromType: "FamilyMemberHistory", + EdgeLabel: "focus_FamilyMemberHistory", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "Task|focus_BodyStructure|BodyStructure": { + FromType: "Task", + EdgeLabel: "focus_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|focus_BodyStructure|Task": { + FromType: "BodyStructure", + EdgeLabel: "focus_BodyStructure", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "focus_task", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "Task|for_fhir_Organization|Organization": { + FromType: "Task", + EdgeLabel: "for_fhir_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|for_fhir_Organization|Task": { + FromType: "Organization", + EdgeLabel: "for_fhir_Organization", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Task|for_fhir_Group|Group": { + FromType: "Task", + EdgeLabel: "for_fhir_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|for_fhir_Group|Task": { + FromType: "Group", + EdgeLabel: "for_fhir_Group", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Task|for_fhir_Practitioner|Practitioner": { + FromType: "Task", + EdgeLabel: "for_fhir_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|for_fhir_Practitioner|Task": { + FromType: "Practitioner", + EdgeLabel: "for_fhir_Practitioner", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Task|for_fhir_PractitionerRole|PractitionerRole": { + FromType: "Task", + EdgeLabel: "for_fhir_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|for_fhir_PractitionerRole|Task": { + FromType: "PractitionerRole", + EdgeLabel: "for_fhir_PractitionerRole", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Task|for_fhir_ResearchStudy|ResearchStudy": { + FromType: "Task", + EdgeLabel: "for_fhir_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|for_fhir_ResearchStudy|Task": { + FromType: "ResearchStudy", + EdgeLabel: "for_fhir_ResearchStudy", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "Task|for_fhir_Patient|Patient": { + FromType: "Task", + EdgeLabel: "for_fhir_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|for_fhir_Patient|Task": { + FromType: "Patient", + EdgeLabel: "for_fhir_Patient", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Task|for_fhir_ResearchSubject|ResearchSubject": { + FromType: "Task", + EdgeLabel: "for_fhir_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|for_fhir_ResearchSubject|Task": { + FromType: "ResearchSubject", + EdgeLabel: "for_fhir_ResearchSubject", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "Task|for_fhir_Substance|Substance": { + FromType: "Task", + EdgeLabel: "for_fhir_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|for_fhir_Substance|Task": { + FromType: "Substance", + EdgeLabel: "for_fhir_Substance", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Task|for_fhir_SubstanceDefinition|SubstanceDefinition": { + FromType: "Task", + EdgeLabel: "for_fhir_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|for_fhir_SubstanceDefinition|Task": { + FromType: "SubstanceDefinition", + EdgeLabel: "for_fhir_SubstanceDefinition", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "Task|for_fhir_Specimen|Specimen": { + FromType: "Task", + EdgeLabel: "for_fhir_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|for_fhir_Specimen|Task": { + FromType: "Specimen", + EdgeLabel: "for_fhir_Specimen", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Task|for_fhir_Observation|Observation": { + FromType: "Task", + EdgeLabel: "for_fhir_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|for_fhir_Observation|Task": { + FromType: "Observation", + EdgeLabel: "for_fhir_Observation", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Task|for_fhir_DiagnosticReport|DiagnosticReport": { + FromType: "Task", + EdgeLabel: "for_fhir_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|for_fhir_DiagnosticReport|Task": { + FromType: "DiagnosticReport", + EdgeLabel: "for_fhir_DiagnosticReport", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "Task|for_fhir_Condition|Condition": { + FromType: "Task", + EdgeLabel: "for_fhir_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|for_fhir_Condition|Task": { + FromType: "Condition", + EdgeLabel: "for_fhir_Condition", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Task|for_fhir_Medication|Medication": { + FromType: "Task", + EdgeLabel: "for_fhir_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|for_fhir_Medication|Task": { + FromType: "Medication", + EdgeLabel: "for_fhir_Medication", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Task|for_fhir_MedicationAdministration|MedicationAdministration": { + FromType: "Task", + EdgeLabel: "for_fhir_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|for_fhir_MedicationAdministration|Task": { + FromType: "MedicationAdministration", + EdgeLabel: "for_fhir_MedicationAdministration", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "Task|for_fhir_MedicationStatement|MedicationStatement": { + FromType: "Task", + EdgeLabel: "for_fhir_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|for_fhir_MedicationStatement|Task": { + FromType: "MedicationStatement", + EdgeLabel: "for_fhir_MedicationStatement", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "Task|for_fhir_MedicationRequest|MedicationRequest": { + FromType: "Task", + EdgeLabel: "for_fhir_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|for_fhir_MedicationRequest|Task": { + FromType: "MedicationRequest", + EdgeLabel: "for_fhir_MedicationRequest", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "Task|for_fhir_Procedure|Procedure": { + FromType: "Task", + EdgeLabel: "for_fhir_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|for_fhir_Procedure|Task": { + FromType: "Procedure", + EdgeLabel: "for_fhir_Procedure", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Task|for_fhir_DocumentReference|DocumentReference": { + FromType: "Task", + EdgeLabel: "for_fhir_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|for_fhir_DocumentReference|Task": { + FromType: "DocumentReference", + EdgeLabel: "for_fhir_DocumentReference", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "Task|for_fhir_Task|Task": { + FromType: "Task", + EdgeLabel: "for_fhir_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|for_fhir_ImagingStudy|ImagingStudy": { + FromType: "Task", + EdgeLabel: "for_fhir_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|for_fhir_ImagingStudy|Task": { + FromType: "ImagingStudy", + EdgeLabel: "for_fhir_ImagingStudy", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "Task|for_fhir_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "Task", + EdgeLabel: "for_fhir_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|for_fhir_FamilyMemberHistory|Task": { + FromType: "FamilyMemberHistory", + EdgeLabel: "for_fhir_FamilyMemberHistory", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "Task|for_fhir_BodyStructure|BodyStructure": { + FromType: "Task", + EdgeLabel: "for_fhir_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|for_fhir_BodyStructure|Task": { + FromType: "BodyStructure", + EdgeLabel: "for_fhir_BodyStructure", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "for_task", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "Task|owner_Practitioner|Practitioner": { + FromType: "Task", + EdgeLabel: "owner_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "owner_task", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|owner_Practitioner|Task": { + FromType: "Practitioner", + EdgeLabel: "owner_Practitioner", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "owner_task", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Task|owner_PractitionerRole|PractitionerRole": { + FromType: "Task", + EdgeLabel: "owner_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "owner_task", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|owner_PractitionerRole|Task": { + FromType: "PractitionerRole", + EdgeLabel: "owner_PractitionerRole", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "owner_task", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Task|owner_Organization|Organization": { + FromType: "Task", + EdgeLabel: "owner_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "owner_task", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|owner_Organization|Task": { + FromType: "Organization", + EdgeLabel: "owner_Organization", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "owner_task", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Task|owner_Patient|Patient": { + FromType: "Task", + EdgeLabel: "owner_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "owner_task", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|owner_Patient|Task": { + FromType: "Patient", + EdgeLabel: "owner_Patient", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "owner_task", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Task|partOf|Task": { + FromType: "Task", + EdgeLabel: "partOf", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "partOf_task", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|requester_Organization|Organization": { + FromType: "Task", + EdgeLabel: "requester_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "requester_task", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|requester_Organization|Task": { + FromType: "Organization", + EdgeLabel: "requester_Organization", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "requester_task", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Task|requester_Patient|Patient": { + FromType: "Task", + EdgeLabel: "requester_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "requester_task", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|requester_Patient|Task": { + FromType: "Patient", + EdgeLabel: "requester_Patient", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "requester_task", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Task|requester_Practitioner|Practitioner": { + FromType: "Task", + EdgeLabel: "requester_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "requester_task", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|requester_Practitioner|Task": { + FromType: "Practitioner", + EdgeLabel: "requester_Practitioner", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "requester_task", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Task|requester_PractitionerRole|PractitionerRole": { + FromType: "Task", + EdgeLabel: "requester_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "requester_task", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|requester_PractitionerRole|Task": { + FromType: "PractitionerRole", + EdgeLabel: "requester_PractitionerRole", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "requester_task", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Task|input_valueReference_Organization|Organization": { + FromType: "Task", + EdgeLabel: "input_valueReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|input_valueReference_Organization|Task": { + FromType: "Organization", + EdgeLabel: "input_valueReference_Organization", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Task|input_valueReference_Group|Group": { + FromType: "Task", + EdgeLabel: "input_valueReference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|input_valueReference_Group|Task": { + FromType: "Group", + EdgeLabel: "input_valueReference_Group", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Task|input_valueReference_Practitioner|Practitioner": { + FromType: "Task", + EdgeLabel: "input_valueReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|input_valueReference_Practitioner|Task": { + FromType: "Practitioner", + EdgeLabel: "input_valueReference_Practitioner", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Task|input_valueReference_PractitionerRole|PractitionerRole": { + FromType: "Task", + EdgeLabel: "input_valueReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|input_valueReference_PractitionerRole|Task": { + FromType: "PractitionerRole", + EdgeLabel: "input_valueReference_PractitionerRole", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Task|input_valueReference_ResearchStudy|ResearchStudy": { + FromType: "Task", + EdgeLabel: "input_valueReference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|input_valueReference_ResearchStudy|Task": { + FromType: "ResearchStudy", + EdgeLabel: "input_valueReference_ResearchStudy", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "Task|input_valueReference_Patient|Patient": { + FromType: "Task", + EdgeLabel: "input_valueReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|input_valueReference_Patient|Task": { + FromType: "Patient", + EdgeLabel: "input_valueReference_Patient", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Task|input_valueReference_ResearchSubject|ResearchSubject": { + FromType: "Task", + EdgeLabel: "input_valueReference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|input_valueReference_ResearchSubject|Task": { + FromType: "ResearchSubject", + EdgeLabel: "input_valueReference_ResearchSubject", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "Task|input_valueReference_Substance|Substance": { + FromType: "Task", + EdgeLabel: "input_valueReference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|input_valueReference_Substance|Task": { + FromType: "Substance", + EdgeLabel: "input_valueReference_Substance", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Task|input_valueReference_SubstanceDefinition|SubstanceDefinition": { + FromType: "Task", + EdgeLabel: "input_valueReference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|input_valueReference_SubstanceDefinition|Task": { + FromType: "SubstanceDefinition", + EdgeLabel: "input_valueReference_SubstanceDefinition", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "Task|input_valueReference_Specimen|Specimen": { + FromType: "Task", + EdgeLabel: "input_valueReference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|input_valueReference_Specimen|Task": { + FromType: "Specimen", + EdgeLabel: "input_valueReference_Specimen", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Task|input_valueReference_Observation|Observation": { + FromType: "Task", + EdgeLabel: "input_valueReference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|input_valueReference_Observation|Task": { + FromType: "Observation", + EdgeLabel: "input_valueReference_Observation", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Task|input_valueReference_DiagnosticReport|DiagnosticReport": { + FromType: "Task", + EdgeLabel: "input_valueReference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|input_valueReference_DiagnosticReport|Task": { + FromType: "DiagnosticReport", + EdgeLabel: "input_valueReference_DiagnosticReport", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "Task|input_valueReference_Condition|Condition": { + FromType: "Task", + EdgeLabel: "input_valueReference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|input_valueReference_Condition|Task": { + FromType: "Condition", + EdgeLabel: "input_valueReference_Condition", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Task|input_valueReference_Medication|Medication": { + FromType: "Task", + EdgeLabel: "input_valueReference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|input_valueReference_Medication|Task": { + FromType: "Medication", + EdgeLabel: "input_valueReference_Medication", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Task|input_valueReference_MedicationAdministration|MedicationAdministration": { + FromType: "Task", + EdgeLabel: "input_valueReference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|input_valueReference_MedicationAdministration|Task": { + FromType: "MedicationAdministration", + EdgeLabel: "input_valueReference_MedicationAdministration", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "Task|input_valueReference_MedicationStatement|MedicationStatement": { + FromType: "Task", + EdgeLabel: "input_valueReference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|input_valueReference_MedicationStatement|Task": { + FromType: "MedicationStatement", + EdgeLabel: "input_valueReference_MedicationStatement", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "Task|input_valueReference_MedicationRequest|MedicationRequest": { + FromType: "Task", + EdgeLabel: "input_valueReference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|input_valueReference_MedicationRequest|Task": { + FromType: "MedicationRequest", + EdgeLabel: "input_valueReference_MedicationRequest", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "Task|input_valueReference_Procedure|Procedure": { + FromType: "Task", + EdgeLabel: "input_valueReference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|input_valueReference_Procedure|Task": { + FromType: "Procedure", + EdgeLabel: "input_valueReference_Procedure", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Task|input_valueReference_DocumentReference|DocumentReference": { + FromType: "Task", + EdgeLabel: "input_valueReference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|input_valueReference_DocumentReference|Task": { + FromType: "DocumentReference", + EdgeLabel: "input_valueReference_DocumentReference", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "Task|input_valueReference_Task|Task": { + FromType: "Task", + EdgeLabel: "input_valueReference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|input_valueReference_ImagingStudy|ImagingStudy": { + FromType: "Task", + EdgeLabel: "input_valueReference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|input_valueReference_ImagingStudy|Task": { + FromType: "ImagingStudy", + EdgeLabel: "input_valueReference_ImagingStudy", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "Task|input_valueReference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "Task", + EdgeLabel: "input_valueReference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|input_valueReference_FamilyMemberHistory|Task": { + FromType: "FamilyMemberHistory", + EdgeLabel: "input_valueReference_FamilyMemberHistory", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "Task|input_valueReference_BodyStructure|BodyStructure": { + FromType: "Task", + EdgeLabel: "input_valueReference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|input_valueReference_BodyStructure|Task": { + FromType: "BodyStructure", + EdgeLabel: "input_valueReference_BodyStructure", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "Task|note_authorReference_Practitioner|Practitioner": { + FromType: "Task", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|note_authorReference_Practitioner|Task": { + FromType: "Practitioner", + EdgeLabel: "note_authorReference_Practitioner", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Task|note_authorReference_PractitionerRole|PractitionerRole": { + FromType: "Task", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|note_authorReference_PractitionerRole|Task": { + FromType: "PractitionerRole", + EdgeLabel: "note_authorReference_PractitionerRole", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Task|note_authorReference_Patient|Patient": { + FromType: "Task", + EdgeLabel: "note_authorReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|note_authorReference_Patient|Task": { + FromType: "Patient", + EdgeLabel: "note_authorReference_Patient", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Task|note_authorReference_Organization|Organization": { + FromType: "Task", + EdgeLabel: "note_authorReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|note_authorReference_Organization|Task": { + FromType: "Organization", + EdgeLabel: "note_authorReference_Organization", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Task|output_valueReference_Organization|Organization": { + FromType: "Task", + EdgeLabel: "output_valueReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|output_valueReference_Organization|Task": { + FromType: "Organization", + EdgeLabel: "output_valueReference_Organization", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Task|output_valueReference_Group|Group": { + FromType: "Task", + EdgeLabel: "output_valueReference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|output_valueReference_Group|Task": { + FromType: "Group", + EdgeLabel: "output_valueReference_Group", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Task|output_valueReference_Practitioner|Practitioner": { + FromType: "Task", + EdgeLabel: "output_valueReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|output_valueReference_Practitioner|Task": { + FromType: "Practitioner", + EdgeLabel: "output_valueReference_Practitioner", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Task|output_valueReference_PractitionerRole|PractitionerRole": { + FromType: "Task", + EdgeLabel: "output_valueReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|output_valueReference_PractitionerRole|Task": { + FromType: "PractitionerRole", + EdgeLabel: "output_valueReference_PractitionerRole", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Task|output_valueReference_ResearchStudy|ResearchStudy": { + FromType: "Task", + EdgeLabel: "output_valueReference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|output_valueReference_ResearchStudy|Task": { + FromType: "ResearchStudy", + EdgeLabel: "output_valueReference_ResearchStudy", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "Task|output_valueReference_Patient|Patient": { + FromType: "Task", + EdgeLabel: "output_valueReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|output_valueReference_Patient|Task": { + FromType: "Patient", + EdgeLabel: "output_valueReference_Patient", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Task|output_valueReference_ResearchSubject|ResearchSubject": { + FromType: "Task", + EdgeLabel: "output_valueReference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|output_valueReference_ResearchSubject|Task": { + FromType: "ResearchSubject", + EdgeLabel: "output_valueReference_ResearchSubject", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "Task|output_valueReference_Substance|Substance": { + FromType: "Task", + EdgeLabel: "output_valueReference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|output_valueReference_Substance|Task": { + FromType: "Substance", + EdgeLabel: "output_valueReference_Substance", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Task|output_valueReference_SubstanceDefinition|SubstanceDefinition": { + FromType: "Task", + EdgeLabel: "output_valueReference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|output_valueReference_SubstanceDefinition|Task": { + FromType: "SubstanceDefinition", + EdgeLabel: "output_valueReference_SubstanceDefinition", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "Task|output_valueReference_Specimen|Specimen": { + FromType: "Task", + EdgeLabel: "output_valueReference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|output_valueReference_Specimen|Task": { + FromType: "Specimen", + EdgeLabel: "output_valueReference_Specimen", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Task|output_valueReference_Observation|Observation": { + FromType: "Task", + EdgeLabel: "output_valueReference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|output_valueReference_Observation|Task": { + FromType: "Observation", + EdgeLabel: "output_valueReference_Observation", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Task|output_valueReference_DiagnosticReport|DiagnosticReport": { + FromType: "Task", + EdgeLabel: "output_valueReference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|output_valueReference_DiagnosticReport|Task": { + FromType: "DiagnosticReport", + EdgeLabel: "output_valueReference_DiagnosticReport", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "Task|output_valueReference_Condition|Condition": { + FromType: "Task", + EdgeLabel: "output_valueReference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|output_valueReference_Condition|Task": { + FromType: "Condition", + EdgeLabel: "output_valueReference_Condition", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Task|output_valueReference_Medication|Medication": { + FromType: "Task", + EdgeLabel: "output_valueReference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|output_valueReference_Medication|Task": { + FromType: "Medication", + EdgeLabel: "output_valueReference_Medication", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Task|output_valueReference_MedicationAdministration|MedicationAdministration": { + FromType: "Task", + EdgeLabel: "output_valueReference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|output_valueReference_MedicationAdministration|Task": { + FromType: "MedicationAdministration", + EdgeLabel: "output_valueReference_MedicationAdministration", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "Task|output_valueReference_MedicationStatement|MedicationStatement": { + FromType: "Task", + EdgeLabel: "output_valueReference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|output_valueReference_MedicationStatement|Task": { + FromType: "MedicationStatement", + EdgeLabel: "output_valueReference_MedicationStatement", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "Task|output_valueReference_MedicationRequest|MedicationRequest": { + FromType: "Task", + EdgeLabel: "output_valueReference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|output_valueReference_MedicationRequest|Task": { + FromType: "MedicationRequest", + EdgeLabel: "output_valueReference_MedicationRequest", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "Task|output_valueReference_Procedure|Procedure": { + FromType: "Task", + EdgeLabel: "output_valueReference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|output_valueReference_Procedure|Task": { + FromType: "Procedure", + EdgeLabel: "output_valueReference_Procedure", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Task|output_valueReference_DocumentReference|DocumentReference": { + FromType: "Task", + EdgeLabel: "output_valueReference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|output_valueReference_DocumentReference|Task": { + FromType: "DocumentReference", + EdgeLabel: "output_valueReference_DocumentReference", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "Task|output_valueReference_Task|Task": { + FromType: "Task", + EdgeLabel: "output_valueReference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|output_valueReference_ImagingStudy|ImagingStudy": { + FromType: "Task", + EdgeLabel: "output_valueReference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|output_valueReference_ImagingStudy|Task": { + FromType: "ImagingStudy", + EdgeLabel: "output_valueReference_ImagingStudy", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "Task|output_valueReference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "Task", + EdgeLabel: "output_valueReference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|output_valueReference_FamilyMemberHistory|Task": { + FromType: "FamilyMemberHistory", + EdgeLabel: "output_valueReference_FamilyMemberHistory", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "Task|output_valueReference_BodyStructure|BodyStructure": { + FromType: "Task", + EdgeLabel: "output_valueReference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|output_valueReference_BodyStructure|Task": { + FromType: "BodyStructure", + EdgeLabel: "output_valueReference_BodyStructure", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "Task|performer_actor_Practitioner|Practitioner": { + FromType: "Task", + EdgeLabel: "performer_actor_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_performer", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|performer_actor_Practitioner|Task": { + FromType: "Practitioner", + EdgeLabel: "performer_actor_Practitioner", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_performer", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Task|performer_actor_PractitionerRole|PractitionerRole": { + FromType: "Task", + EdgeLabel: "performer_actor_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_performer", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|performer_actor_PractitionerRole|Task": { + FromType: "PractitionerRole", + EdgeLabel: "performer_actor_PractitionerRole", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_performer", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Task|performer_actor_Organization|Organization": { + FromType: "Task", + EdgeLabel: "performer_actor_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_performer", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|performer_actor_Organization|Task": { + FromType: "Organization", + EdgeLabel: "performer_actor_Organization", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_performer", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Task|performer_actor_Patient|Patient": { + FromType: "Task", + EdgeLabel: "performer_actor_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_performer", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|performer_actor_Patient|Task": { + FromType: "Patient", + EdgeLabel: "performer_actor_Patient", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_performer", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Task|reason_reference_Organization|Organization": { + FromType: "Task", + EdgeLabel: "reason_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|reason_reference_Organization|Task": { + FromType: "Organization", + EdgeLabel: "reason_reference_Organization", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Task|reason_reference_Group|Group": { + FromType: "Task", + EdgeLabel: "reason_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|reason_reference_Group|Task": { + FromType: "Group", + EdgeLabel: "reason_reference_Group", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Task|reason_reference_Practitioner|Practitioner": { + FromType: "Task", + EdgeLabel: "reason_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|reason_reference_Practitioner|Task": { + FromType: "Practitioner", + EdgeLabel: "reason_reference_Practitioner", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Task|reason_reference_PractitionerRole|PractitionerRole": { + FromType: "Task", + EdgeLabel: "reason_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|reason_reference_PractitionerRole|Task": { + FromType: "PractitionerRole", + EdgeLabel: "reason_reference_PractitionerRole", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Task|reason_reference_ResearchStudy|ResearchStudy": { + FromType: "Task", + EdgeLabel: "reason_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|reason_reference_ResearchStudy|Task": { + FromType: "ResearchStudy", + EdgeLabel: "reason_reference_ResearchStudy", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "Task|reason_reference_Patient|Patient": { + FromType: "Task", + EdgeLabel: "reason_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|reason_reference_Patient|Task": { + FromType: "Patient", + EdgeLabel: "reason_reference_Patient", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Task|reason_reference_ResearchSubject|ResearchSubject": { + FromType: "Task", + EdgeLabel: "reason_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|reason_reference_ResearchSubject|Task": { + FromType: "ResearchSubject", + EdgeLabel: "reason_reference_ResearchSubject", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "Task|reason_reference_Substance|Substance": { + FromType: "Task", + EdgeLabel: "reason_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|reason_reference_Substance|Task": { + FromType: "Substance", + EdgeLabel: "reason_reference_Substance", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Task|reason_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "Task", + EdgeLabel: "reason_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|reason_reference_SubstanceDefinition|Task": { + FromType: "SubstanceDefinition", + EdgeLabel: "reason_reference_SubstanceDefinition", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "Task|reason_reference_Specimen|Specimen": { + FromType: "Task", + EdgeLabel: "reason_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|reason_reference_Specimen|Task": { + FromType: "Specimen", + EdgeLabel: "reason_reference_Specimen", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Task|reason_reference_Observation|Observation": { + FromType: "Task", + EdgeLabel: "reason_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|reason_reference_Observation|Task": { + FromType: "Observation", + EdgeLabel: "reason_reference_Observation", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Task|reason_reference_DiagnosticReport|DiagnosticReport": { + FromType: "Task", + EdgeLabel: "reason_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|reason_reference_DiagnosticReport|Task": { + FromType: "DiagnosticReport", + EdgeLabel: "reason_reference_DiagnosticReport", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "Task|reason_reference_Condition|Condition": { + FromType: "Task", + EdgeLabel: "reason_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|reason_reference_Condition|Task": { + FromType: "Condition", + EdgeLabel: "reason_reference_Condition", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Task|reason_reference_Medication|Medication": { + FromType: "Task", + EdgeLabel: "reason_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|reason_reference_Medication|Task": { + FromType: "Medication", + EdgeLabel: "reason_reference_Medication", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Task|reason_reference_MedicationAdministration|MedicationAdministration": { + FromType: "Task", + EdgeLabel: "reason_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|reason_reference_MedicationAdministration|Task": { + FromType: "MedicationAdministration", + EdgeLabel: "reason_reference_MedicationAdministration", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "Task|reason_reference_MedicationStatement|MedicationStatement": { + FromType: "Task", + EdgeLabel: "reason_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|reason_reference_MedicationStatement|Task": { + FromType: "MedicationStatement", + EdgeLabel: "reason_reference_MedicationStatement", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "Task|reason_reference_MedicationRequest|MedicationRequest": { + FromType: "Task", + EdgeLabel: "reason_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|reason_reference_MedicationRequest|Task": { + FromType: "MedicationRequest", + EdgeLabel: "reason_reference_MedicationRequest", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "Task|reason_reference_Procedure|Procedure": { + FromType: "Task", + EdgeLabel: "reason_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|reason_reference_Procedure|Task": { + FromType: "Procedure", + EdgeLabel: "reason_reference_Procedure", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Task|reason_reference_DocumentReference|DocumentReference": { + FromType: "Task", + EdgeLabel: "reason_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|reason_reference_DocumentReference|Task": { + FromType: "DocumentReference", + EdgeLabel: "reason_reference_DocumentReference", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "Task|reason_reference_Task|Task": { + FromType: "Task", + EdgeLabel: "reason_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|reason_reference_ImagingStudy|ImagingStudy": { + FromType: "Task", + EdgeLabel: "reason_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|reason_reference_ImagingStudy|Task": { + FromType: "ImagingStudy", + EdgeLabel: "reason_reference_ImagingStudy", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "Task|reason_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "Task", + EdgeLabel: "reason_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|reason_reference_FamilyMemberHistory|Task": { + FromType: "FamilyMemberHistory", + EdgeLabel: "reason_reference_FamilyMemberHistory", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "Task|reason_reference_BodyStructure|BodyStructure": { + FromType: "Task", + EdgeLabel: "reason_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|reason_reference_BodyStructure|Task": { + FromType: "BodyStructure", + EdgeLabel: "reason_reference_BodyStructure", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "Task|requestedPerformer_reference_Organization|Organization": { + FromType: "Task", + EdgeLabel: "requestedPerformer_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|requestedPerformer_reference_Organization|Task": { + FromType: "Organization", + EdgeLabel: "requestedPerformer_reference_Organization", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Task|requestedPerformer_reference_Group|Group": { + FromType: "Task", + EdgeLabel: "requestedPerformer_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|requestedPerformer_reference_Group|Task": { + FromType: "Group", + EdgeLabel: "requestedPerformer_reference_Group", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Task|requestedPerformer_reference_Practitioner|Practitioner": { + FromType: "Task", + EdgeLabel: "requestedPerformer_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|requestedPerformer_reference_Practitioner|Task": { + FromType: "Practitioner", + EdgeLabel: "requestedPerformer_reference_Practitioner", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Task|requestedPerformer_reference_PractitionerRole|PractitionerRole": { + FromType: "Task", + EdgeLabel: "requestedPerformer_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|requestedPerformer_reference_PractitionerRole|Task": { + FromType: "PractitionerRole", + EdgeLabel: "requestedPerformer_reference_PractitionerRole", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Task|requestedPerformer_reference_ResearchStudy|ResearchStudy": { + FromType: "Task", + EdgeLabel: "requestedPerformer_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|requestedPerformer_reference_ResearchStudy|Task": { + FromType: "ResearchStudy", + EdgeLabel: "requestedPerformer_reference_ResearchStudy", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "Task|requestedPerformer_reference_Patient|Patient": { + FromType: "Task", + EdgeLabel: "requestedPerformer_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|requestedPerformer_reference_Patient|Task": { + FromType: "Patient", + EdgeLabel: "requestedPerformer_reference_Patient", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Task|requestedPerformer_reference_ResearchSubject|ResearchSubject": { + FromType: "Task", + EdgeLabel: "requestedPerformer_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|requestedPerformer_reference_ResearchSubject|Task": { + FromType: "ResearchSubject", + EdgeLabel: "requestedPerformer_reference_ResearchSubject", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "Task|requestedPerformer_reference_Substance|Substance": { + FromType: "Task", + EdgeLabel: "requestedPerformer_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|requestedPerformer_reference_Substance|Task": { + FromType: "Substance", + EdgeLabel: "requestedPerformer_reference_Substance", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Task|requestedPerformer_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "Task", + EdgeLabel: "requestedPerformer_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|requestedPerformer_reference_SubstanceDefinition|Task": { + FromType: "SubstanceDefinition", + EdgeLabel: "requestedPerformer_reference_SubstanceDefinition", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "Task|requestedPerformer_reference_Specimen|Specimen": { + FromType: "Task", + EdgeLabel: "requestedPerformer_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|requestedPerformer_reference_Specimen|Task": { + FromType: "Specimen", + EdgeLabel: "requestedPerformer_reference_Specimen", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Task|requestedPerformer_reference_Observation|Observation": { + FromType: "Task", + EdgeLabel: "requestedPerformer_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|requestedPerformer_reference_Observation|Task": { + FromType: "Observation", + EdgeLabel: "requestedPerformer_reference_Observation", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Task|requestedPerformer_reference_DiagnosticReport|DiagnosticReport": { + FromType: "Task", + EdgeLabel: "requestedPerformer_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|requestedPerformer_reference_DiagnosticReport|Task": { + FromType: "DiagnosticReport", + EdgeLabel: "requestedPerformer_reference_DiagnosticReport", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "Task|requestedPerformer_reference_Condition|Condition": { + FromType: "Task", + EdgeLabel: "requestedPerformer_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|requestedPerformer_reference_Condition|Task": { + FromType: "Condition", + EdgeLabel: "requestedPerformer_reference_Condition", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Task|requestedPerformer_reference_Medication|Medication": { + FromType: "Task", + EdgeLabel: "requestedPerformer_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|requestedPerformer_reference_Medication|Task": { + FromType: "Medication", + EdgeLabel: "requestedPerformer_reference_Medication", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Task|requestedPerformer_reference_MedicationAdministration|MedicationAdministration": { + FromType: "Task", + EdgeLabel: "requestedPerformer_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|requestedPerformer_reference_MedicationAdministration|Task": { + FromType: "MedicationAdministration", + EdgeLabel: "requestedPerformer_reference_MedicationAdministration", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "Task|requestedPerformer_reference_MedicationStatement|MedicationStatement": { + FromType: "Task", + EdgeLabel: "requestedPerformer_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|requestedPerformer_reference_MedicationStatement|Task": { + FromType: "MedicationStatement", + EdgeLabel: "requestedPerformer_reference_MedicationStatement", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "Task|requestedPerformer_reference_MedicationRequest|MedicationRequest": { + FromType: "Task", + EdgeLabel: "requestedPerformer_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|requestedPerformer_reference_MedicationRequest|Task": { + FromType: "MedicationRequest", + EdgeLabel: "requestedPerformer_reference_MedicationRequest", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "Task|requestedPerformer_reference_Procedure|Procedure": { + FromType: "Task", + EdgeLabel: "requestedPerformer_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|requestedPerformer_reference_Procedure|Task": { + FromType: "Procedure", + EdgeLabel: "requestedPerformer_reference_Procedure", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Task|requestedPerformer_reference_DocumentReference|DocumentReference": { + FromType: "Task", + EdgeLabel: "requestedPerformer_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|requestedPerformer_reference_DocumentReference|Task": { + FromType: "DocumentReference", + EdgeLabel: "requestedPerformer_reference_DocumentReference", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "Task|requestedPerformer_reference_Task|Task": { + FromType: "Task", + EdgeLabel: "requestedPerformer_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|requestedPerformer_reference_ImagingStudy|ImagingStudy": { + FromType: "Task", + EdgeLabel: "requestedPerformer_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|requestedPerformer_reference_ImagingStudy|Task": { + FromType: "ImagingStudy", + EdgeLabel: "requestedPerformer_reference_ImagingStudy", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "Task|requestedPerformer_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "Task", + EdgeLabel: "requestedPerformer_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|requestedPerformer_reference_FamilyMemberHistory|Task": { + FromType: "FamilyMemberHistory", + EdgeLabel: "requestedPerformer_reference_FamilyMemberHistory", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "Task|requestedPerformer_reference_BodyStructure|BodyStructure": { + FromType: "Task", + EdgeLabel: "requestedPerformer_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|requestedPerformer_reference_BodyStructure|Task": { + FromType: "BodyStructure", + EdgeLabel: "requestedPerformer_reference_BodyStructure", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "Task|restriction_recipient_Patient|Patient": { + FromType: "Task", + EdgeLabel: "restriction_recipient_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "recipient_task_restriction", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|restriction_recipient_Patient|Task": { + FromType: "Patient", + EdgeLabel: "restriction_recipient_Patient", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "recipient_task_restriction", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Task|restriction_recipient_Practitioner|Practitioner": { + FromType: "Task", + EdgeLabel: "restriction_recipient_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "recipient_task_restriction", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|restriction_recipient_Practitioner|Task": { + FromType: "Practitioner", + EdgeLabel: "restriction_recipient_Practitioner", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "recipient_task_restriction", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Task|restriction_recipient_PractitionerRole|PractitionerRole": { + FromType: "Task", + EdgeLabel: "restriction_recipient_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "recipient_task_restriction", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|restriction_recipient_PractitionerRole|Task": { + FromType: "PractitionerRole", + EdgeLabel: "restriction_recipient_PractitionerRole", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "recipient_task_restriction", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Task|restriction_recipient_Group|Group": { + FromType: "Task", + EdgeLabel: "restriction_recipient_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "recipient_task_restriction", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|restriction_recipient_Group|Task": { + FromType: "Group", + EdgeLabel: "restriction_recipient_Group", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "recipient_task_restriction", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Task|restriction_recipient_Organization|Organization": { + FromType: "Task", + EdgeLabel: "restriction_recipient_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "recipient_task_restriction", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|restriction_recipient_Organization|Task": { + FromType: "Organization", + EdgeLabel: "restriction_recipient_Organization", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "recipient_task_restriction", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Task|statusReason_reference_Organization|Organization": { + FromType: "Task", + EdgeLabel: "statusReason_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|statusReason_reference_Organization|Task": { + FromType: "Organization", + EdgeLabel: "statusReason_reference_Organization", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Task|statusReason_reference_Group|Group": { + FromType: "Task", + EdgeLabel: "statusReason_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|statusReason_reference_Group|Task": { + FromType: "Group", + EdgeLabel: "statusReason_reference_Group", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Task|statusReason_reference_Practitioner|Practitioner": { + FromType: "Task", + EdgeLabel: "statusReason_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|statusReason_reference_Practitioner|Task": { + FromType: "Practitioner", + EdgeLabel: "statusReason_reference_Practitioner", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Task|statusReason_reference_PractitionerRole|PractitionerRole": { + FromType: "Task", + EdgeLabel: "statusReason_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|statusReason_reference_PractitionerRole|Task": { + FromType: "PractitionerRole", + EdgeLabel: "statusReason_reference_PractitionerRole", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "Task|statusReason_reference_ResearchStudy|ResearchStudy": { + FromType: "Task", + EdgeLabel: "statusReason_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|statusReason_reference_ResearchStudy|Task": { + FromType: "ResearchStudy", + EdgeLabel: "statusReason_reference_ResearchStudy", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "Task|statusReason_reference_Patient|Patient": { + FromType: "Task", + EdgeLabel: "statusReason_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|statusReason_reference_Patient|Task": { + FromType: "Patient", + EdgeLabel: "statusReason_reference_Patient", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Task|statusReason_reference_ResearchSubject|ResearchSubject": { + FromType: "Task", + EdgeLabel: "statusReason_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|statusReason_reference_ResearchSubject|Task": { + FromType: "ResearchSubject", + EdgeLabel: "statusReason_reference_ResearchSubject", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "Task|statusReason_reference_Substance|Substance": { + FromType: "Task", + EdgeLabel: "statusReason_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|statusReason_reference_Substance|Task": { + FromType: "Substance", + EdgeLabel: "statusReason_reference_Substance", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Task|statusReason_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "Task", + EdgeLabel: "statusReason_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|statusReason_reference_SubstanceDefinition|Task": { + FromType: "SubstanceDefinition", + EdgeLabel: "statusReason_reference_SubstanceDefinition", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "Task|statusReason_reference_Specimen|Specimen": { + FromType: "Task", + EdgeLabel: "statusReason_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|statusReason_reference_Specimen|Task": { + FromType: "Specimen", + EdgeLabel: "statusReason_reference_Specimen", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Task|statusReason_reference_Observation|Observation": { + FromType: "Task", + EdgeLabel: "statusReason_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|statusReason_reference_Observation|Task": { + FromType: "Observation", + EdgeLabel: "statusReason_reference_Observation", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Task|statusReason_reference_DiagnosticReport|DiagnosticReport": { + FromType: "Task", + EdgeLabel: "statusReason_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|statusReason_reference_DiagnosticReport|Task": { + FromType: "DiagnosticReport", + EdgeLabel: "statusReason_reference_DiagnosticReport", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "Task|statusReason_reference_Condition|Condition": { + FromType: "Task", + EdgeLabel: "statusReason_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|statusReason_reference_Condition|Task": { + FromType: "Condition", + EdgeLabel: "statusReason_reference_Condition", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Task|statusReason_reference_Medication|Medication": { + FromType: "Task", + EdgeLabel: "statusReason_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|statusReason_reference_Medication|Task": { + FromType: "Medication", + EdgeLabel: "statusReason_reference_Medication", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Task|statusReason_reference_MedicationAdministration|MedicationAdministration": { + FromType: "Task", + EdgeLabel: "statusReason_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|statusReason_reference_MedicationAdministration|Task": { + FromType: "MedicationAdministration", + EdgeLabel: "statusReason_reference_MedicationAdministration", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "Task|statusReason_reference_MedicationStatement|MedicationStatement": { + FromType: "Task", + EdgeLabel: "statusReason_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|statusReason_reference_MedicationStatement|Task": { + FromType: "MedicationStatement", + EdgeLabel: "statusReason_reference_MedicationStatement", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "Task|statusReason_reference_MedicationRequest|MedicationRequest": { + FromType: "Task", + EdgeLabel: "statusReason_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|statusReason_reference_MedicationRequest|Task": { + FromType: "MedicationRequest", + EdgeLabel: "statusReason_reference_MedicationRequest", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "Task|statusReason_reference_Procedure|Procedure": { + FromType: "Task", + EdgeLabel: "statusReason_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|statusReason_reference_Procedure|Task": { + FromType: "Procedure", + EdgeLabel: "statusReason_reference_Procedure", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Task|statusReason_reference_DocumentReference|DocumentReference": { + FromType: "Task", + EdgeLabel: "statusReason_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|statusReason_reference_DocumentReference|Task": { + FromType: "DocumentReference", + EdgeLabel: "statusReason_reference_DocumentReference", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "Task|statusReason_reference_Task|Task": { + FromType: "Task", + EdgeLabel: "statusReason_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|statusReason_reference_ImagingStudy|ImagingStudy": { + FromType: "Task", + EdgeLabel: "statusReason_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|statusReason_reference_ImagingStudy|Task": { + FromType: "ImagingStudy", + EdgeLabel: "statusReason_reference_ImagingStudy", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "Task|statusReason_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "Task", + EdgeLabel: "statusReason_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|statusReason_reference_FamilyMemberHistory|Task": { + FromType: "FamilyMemberHistory", + EdgeLabel: "statusReason_reference_FamilyMemberHistory", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "Task|statusReason_reference_BodyStructure|BodyStructure": { + FromType: "Task", + EdgeLabel: "statusReason_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|statusReason_reference_BodyStructure|Task": { + FromType: "BodyStructure", + EdgeLabel: "statusReason_reference_BodyStructure", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "TaskInput|valueReference_Organization|Organization": { + FromType: "TaskInput", + EdgeLabel: "valueReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueReference_Organization|TaskInput": { + FromType: "Organization", + EdgeLabel: "valueReference_Organization", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "TaskInput|valueReference_Group|Group": { + FromType: "TaskInput", + EdgeLabel: "valueReference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|valueReference_Group|TaskInput": { + FromType: "Group", + EdgeLabel: "valueReference_Group", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "TaskInput|valueReference_Practitioner|Practitioner": { + FromType: "TaskInput", + EdgeLabel: "valueReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|valueReference_Practitioner|TaskInput": { + FromType: "Practitioner", + EdgeLabel: "valueReference_Practitioner", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "TaskInput|valueReference_PractitionerRole|PractitionerRole": { + FromType: "TaskInput", + EdgeLabel: "valueReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|valueReference_PractitionerRole|TaskInput": { + FromType: "PractitionerRole", + EdgeLabel: "valueReference_PractitionerRole", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "TaskInput|valueReference_ResearchStudy|ResearchStudy": { + FromType: "TaskInput", + EdgeLabel: "valueReference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|valueReference_ResearchStudy|TaskInput": { + FromType: "ResearchStudy", + EdgeLabel: "valueReference_ResearchStudy", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "TaskInput|valueReference_Patient|Patient": { + FromType: "TaskInput", + EdgeLabel: "valueReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|valueReference_Patient|TaskInput": { + FromType: "Patient", + EdgeLabel: "valueReference_Patient", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "TaskInput|valueReference_ResearchSubject|ResearchSubject": { + FromType: "TaskInput", + EdgeLabel: "valueReference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|valueReference_ResearchSubject|TaskInput": { + FromType: "ResearchSubject", + EdgeLabel: "valueReference_ResearchSubject", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "TaskInput|valueReference_Substance|Substance": { + FromType: "TaskInput", + EdgeLabel: "valueReference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|valueReference_Substance|TaskInput": { + FromType: "Substance", + EdgeLabel: "valueReference_Substance", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "TaskInput|valueReference_SubstanceDefinition|SubstanceDefinition": { + FromType: "TaskInput", + EdgeLabel: "valueReference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|valueReference_SubstanceDefinition|TaskInput": { + FromType: "SubstanceDefinition", + EdgeLabel: "valueReference_SubstanceDefinition", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "TaskInput|valueReference_Specimen|Specimen": { + FromType: "TaskInput", + EdgeLabel: "valueReference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|valueReference_Specimen|TaskInput": { + FromType: "Specimen", + EdgeLabel: "valueReference_Specimen", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "TaskInput|valueReference_Observation|Observation": { + FromType: "TaskInput", + EdgeLabel: "valueReference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|valueReference_Observation|TaskInput": { + FromType: "Observation", + EdgeLabel: "valueReference_Observation", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "TaskInput|valueReference_DiagnosticReport|DiagnosticReport": { + FromType: "TaskInput", + EdgeLabel: "valueReference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|valueReference_DiagnosticReport|TaskInput": { + FromType: "DiagnosticReport", + EdgeLabel: "valueReference_DiagnosticReport", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "TaskInput|valueReference_Condition|Condition": { + FromType: "TaskInput", + EdgeLabel: "valueReference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|valueReference_Condition|TaskInput": { + FromType: "Condition", + EdgeLabel: "valueReference_Condition", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "TaskInput|valueReference_Medication|Medication": { + FromType: "TaskInput", + EdgeLabel: "valueReference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|valueReference_Medication|TaskInput": { + FromType: "Medication", + EdgeLabel: "valueReference_Medication", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "TaskInput|valueReference_MedicationAdministration|MedicationAdministration": { + FromType: "TaskInput", + EdgeLabel: "valueReference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|valueReference_MedicationAdministration|TaskInput": { + FromType: "MedicationAdministration", + EdgeLabel: "valueReference_MedicationAdministration", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "TaskInput|valueReference_MedicationStatement|MedicationStatement": { + FromType: "TaskInput", + EdgeLabel: "valueReference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|valueReference_MedicationStatement|TaskInput": { + FromType: "MedicationStatement", + EdgeLabel: "valueReference_MedicationStatement", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "TaskInput|valueReference_MedicationRequest|MedicationRequest": { + FromType: "TaskInput", + EdgeLabel: "valueReference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|valueReference_MedicationRequest|TaskInput": { + FromType: "MedicationRequest", + EdgeLabel: "valueReference_MedicationRequest", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "TaskInput|valueReference_Procedure|Procedure": { + FromType: "TaskInput", + EdgeLabel: "valueReference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|valueReference_Procedure|TaskInput": { + FromType: "Procedure", + EdgeLabel: "valueReference_Procedure", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "TaskInput|valueReference_DocumentReference|DocumentReference": { + FromType: "TaskInput", + EdgeLabel: "valueReference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|valueReference_DocumentReference|TaskInput": { + FromType: "DocumentReference", + EdgeLabel: "valueReference_DocumentReference", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "TaskInput|valueReference_Task|Task": { + FromType: "TaskInput", + EdgeLabel: "valueReference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|valueReference_Task|TaskInput": { + FromType: "Task", + EdgeLabel: "valueReference_Task", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "TaskInput|valueReference_ImagingStudy|ImagingStudy": { + FromType: "TaskInput", + EdgeLabel: "valueReference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|valueReference_ImagingStudy|TaskInput": { + FromType: "ImagingStudy", + EdgeLabel: "valueReference_ImagingStudy", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "TaskInput|valueReference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "TaskInput", + EdgeLabel: "valueReference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|valueReference_FamilyMemberHistory|TaskInput": { + FromType: "FamilyMemberHistory", + EdgeLabel: "valueReference_FamilyMemberHistory", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "TaskInput|valueReference_BodyStructure|BodyStructure": { + FromType: "TaskInput", + EdgeLabel: "valueReference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|valueReference_BodyStructure|TaskInput": { + FromType: "BodyStructure", + EdgeLabel: "valueReference_BodyStructure", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_input", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "TaskInput|valueAnnotation_authorReference_Practitioner|Practitioner": { + FromType: "TaskInput", + EdgeLabel: "valueAnnotation_authorReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|valueAnnotation_authorReference_Practitioner|TaskInput": { + FromType: "Practitioner", + EdgeLabel: "valueAnnotation_authorReference_Practitioner", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "TaskInput|valueAnnotation_authorReference_PractitionerRole|PractitionerRole": { + FromType: "TaskInput", + EdgeLabel: "valueAnnotation_authorReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|valueAnnotation_authorReference_PractitionerRole|TaskInput": { + FromType: "PractitionerRole", + EdgeLabel: "valueAnnotation_authorReference_PractitionerRole", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "TaskInput|valueAnnotation_authorReference_Patient|Patient": { + FromType: "TaskInput", + EdgeLabel: "valueAnnotation_authorReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|valueAnnotation_authorReference_Patient|TaskInput": { + FromType: "Patient", + EdgeLabel: "valueAnnotation_authorReference_Patient", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "TaskInput|valueAnnotation_authorReference_Organization|Organization": { + FromType: "TaskInput", + EdgeLabel: "valueAnnotation_authorReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueAnnotation_authorReference_Organization|TaskInput": { + FromType: "Organization", + EdgeLabel: "valueAnnotation_authorReference_Organization", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "TaskInput|valueCodeableReference_reference_Organization|Organization": { + FromType: "TaskInput", + EdgeLabel: "valueCodeableReference_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueCodeableReference_reference_Organization|TaskInput": { + FromType: "Organization", + EdgeLabel: "valueCodeableReference_reference_Organization", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "TaskInput|valueCodeableReference_reference_Group|Group": { + FromType: "TaskInput", + EdgeLabel: "valueCodeableReference_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|valueCodeableReference_reference_Group|TaskInput": { + FromType: "Group", + EdgeLabel: "valueCodeableReference_reference_Group", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "TaskInput|valueCodeableReference_reference_Practitioner|Practitioner": { + FromType: "TaskInput", + EdgeLabel: "valueCodeableReference_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|valueCodeableReference_reference_Practitioner|TaskInput": { + FromType: "Practitioner", + EdgeLabel: "valueCodeableReference_reference_Practitioner", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "TaskInput|valueCodeableReference_reference_PractitionerRole|PractitionerRole": { + FromType: "TaskInput", + EdgeLabel: "valueCodeableReference_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|valueCodeableReference_reference_PractitionerRole|TaskInput": { + FromType: "PractitionerRole", + EdgeLabel: "valueCodeableReference_reference_PractitionerRole", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "TaskInput|valueCodeableReference_reference_ResearchStudy|ResearchStudy": { + FromType: "TaskInput", + EdgeLabel: "valueCodeableReference_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|valueCodeableReference_reference_ResearchStudy|TaskInput": { + FromType: "ResearchStudy", + EdgeLabel: "valueCodeableReference_reference_ResearchStudy", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "TaskInput|valueCodeableReference_reference_Patient|Patient": { + FromType: "TaskInput", + EdgeLabel: "valueCodeableReference_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|valueCodeableReference_reference_Patient|TaskInput": { + FromType: "Patient", + EdgeLabel: "valueCodeableReference_reference_Patient", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "TaskInput|valueCodeableReference_reference_ResearchSubject|ResearchSubject": { + FromType: "TaskInput", + EdgeLabel: "valueCodeableReference_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|valueCodeableReference_reference_ResearchSubject|TaskInput": { + FromType: "ResearchSubject", + EdgeLabel: "valueCodeableReference_reference_ResearchSubject", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "TaskInput|valueCodeableReference_reference_Substance|Substance": { + FromType: "TaskInput", + EdgeLabel: "valueCodeableReference_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|valueCodeableReference_reference_Substance|TaskInput": { + FromType: "Substance", + EdgeLabel: "valueCodeableReference_reference_Substance", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "TaskInput|valueCodeableReference_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "TaskInput", + EdgeLabel: "valueCodeableReference_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|valueCodeableReference_reference_SubstanceDefinition|TaskInput": { + FromType: "SubstanceDefinition", + EdgeLabel: "valueCodeableReference_reference_SubstanceDefinition", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "TaskInput|valueCodeableReference_reference_Specimen|Specimen": { + FromType: "TaskInput", + EdgeLabel: "valueCodeableReference_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|valueCodeableReference_reference_Specimen|TaskInput": { + FromType: "Specimen", + EdgeLabel: "valueCodeableReference_reference_Specimen", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "TaskInput|valueCodeableReference_reference_Observation|Observation": { + FromType: "TaskInput", + EdgeLabel: "valueCodeableReference_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|valueCodeableReference_reference_Observation|TaskInput": { + FromType: "Observation", + EdgeLabel: "valueCodeableReference_reference_Observation", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "TaskInput|valueCodeableReference_reference_DiagnosticReport|DiagnosticReport": { + FromType: "TaskInput", + EdgeLabel: "valueCodeableReference_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|valueCodeableReference_reference_DiagnosticReport|TaskInput": { + FromType: "DiagnosticReport", + EdgeLabel: "valueCodeableReference_reference_DiagnosticReport", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "TaskInput|valueCodeableReference_reference_Condition|Condition": { + FromType: "TaskInput", + EdgeLabel: "valueCodeableReference_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|valueCodeableReference_reference_Condition|TaskInput": { + FromType: "Condition", + EdgeLabel: "valueCodeableReference_reference_Condition", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "TaskInput|valueCodeableReference_reference_Medication|Medication": { + FromType: "TaskInput", + EdgeLabel: "valueCodeableReference_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|valueCodeableReference_reference_Medication|TaskInput": { + FromType: "Medication", + EdgeLabel: "valueCodeableReference_reference_Medication", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "TaskInput|valueCodeableReference_reference_MedicationAdministration|MedicationAdministration": { + FromType: "TaskInput", + EdgeLabel: "valueCodeableReference_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|valueCodeableReference_reference_MedicationAdministration|TaskInput": { + FromType: "MedicationAdministration", + EdgeLabel: "valueCodeableReference_reference_MedicationAdministration", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "TaskInput|valueCodeableReference_reference_MedicationStatement|MedicationStatement": { + FromType: "TaskInput", + EdgeLabel: "valueCodeableReference_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|valueCodeableReference_reference_MedicationStatement|TaskInput": { + FromType: "MedicationStatement", + EdgeLabel: "valueCodeableReference_reference_MedicationStatement", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "TaskInput|valueCodeableReference_reference_MedicationRequest|MedicationRequest": { + FromType: "TaskInput", + EdgeLabel: "valueCodeableReference_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|valueCodeableReference_reference_MedicationRequest|TaskInput": { + FromType: "MedicationRequest", + EdgeLabel: "valueCodeableReference_reference_MedicationRequest", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "TaskInput|valueCodeableReference_reference_Procedure|Procedure": { + FromType: "TaskInput", + EdgeLabel: "valueCodeableReference_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|valueCodeableReference_reference_Procedure|TaskInput": { + FromType: "Procedure", + EdgeLabel: "valueCodeableReference_reference_Procedure", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "TaskInput|valueCodeableReference_reference_DocumentReference|DocumentReference": { + FromType: "TaskInput", + EdgeLabel: "valueCodeableReference_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|valueCodeableReference_reference_DocumentReference|TaskInput": { + FromType: "DocumentReference", + EdgeLabel: "valueCodeableReference_reference_DocumentReference", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "TaskInput|valueCodeableReference_reference_Task|Task": { + FromType: "TaskInput", + EdgeLabel: "valueCodeableReference_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|valueCodeableReference_reference_Task|TaskInput": { + FromType: "Task", + EdgeLabel: "valueCodeableReference_reference_Task", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "TaskInput|valueCodeableReference_reference_ImagingStudy|ImagingStudy": { + FromType: "TaskInput", + EdgeLabel: "valueCodeableReference_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|valueCodeableReference_reference_ImagingStudy|TaskInput": { + FromType: "ImagingStudy", + EdgeLabel: "valueCodeableReference_reference_ImagingStudy", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "TaskInput|valueCodeableReference_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "TaskInput", + EdgeLabel: "valueCodeableReference_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|valueCodeableReference_reference_FamilyMemberHistory|TaskInput": { + FromType: "FamilyMemberHistory", + EdgeLabel: "valueCodeableReference_reference_FamilyMemberHistory", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "TaskInput|valueCodeableReference_reference_BodyStructure|BodyStructure": { + FromType: "TaskInput", + EdgeLabel: "valueCodeableReference_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|valueCodeableReference_reference_BodyStructure|TaskInput": { + FromType: "BodyStructure", + EdgeLabel: "valueCodeableReference_reference_BodyStructure", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "TaskInput|valueDataRequirement_subjectReference|Group": { + FromType: "TaskInput", + EdgeLabel: "valueDataRequirement_subjectReference", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "data_requirement", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|valueDataRequirement_subjectReference|TaskInput": { + FromType: "Group", + EdgeLabel: "valueDataRequirement_subjectReference", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "data_requirement", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "TaskInput|valueExtendedContactDetail_organization|Organization": { + FromType: "TaskInput", + EdgeLabel: "valueExtendedContactDetail_organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extended_contact_detail", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueExtendedContactDetail_organization|TaskInput": { + FromType: "Organization", + EdgeLabel: "valueExtendedContactDetail_organization", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extended_contact_detail", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "TaskInput|valueRelatedArtifact_resourceReference_Organization|Organization": { + FromType: "TaskInput", + EdgeLabel: "valueRelatedArtifact_resourceReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueRelatedArtifact_resourceReference_Organization|TaskInput": { + FromType: "Organization", + EdgeLabel: "valueRelatedArtifact_resourceReference_Organization", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "TaskInput|valueRelatedArtifact_resourceReference_Group|Group": { + FromType: "TaskInput", + EdgeLabel: "valueRelatedArtifact_resourceReference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|valueRelatedArtifact_resourceReference_Group|TaskInput": { + FromType: "Group", + EdgeLabel: "valueRelatedArtifact_resourceReference_Group", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "TaskInput|valueRelatedArtifact_resourceReference_Practitioner|Practitioner": { + FromType: "TaskInput", + EdgeLabel: "valueRelatedArtifact_resourceReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|valueRelatedArtifact_resourceReference_Practitioner|TaskInput": { + FromType: "Practitioner", + EdgeLabel: "valueRelatedArtifact_resourceReference_Practitioner", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "TaskInput|valueRelatedArtifact_resourceReference_PractitionerRole|PractitionerRole": { + FromType: "TaskInput", + EdgeLabel: "valueRelatedArtifact_resourceReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|valueRelatedArtifact_resourceReference_PractitionerRole|TaskInput": { + FromType: "PractitionerRole", + EdgeLabel: "valueRelatedArtifact_resourceReference_PractitionerRole", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "TaskInput|valueRelatedArtifact_resourceReference_ResearchStudy|ResearchStudy": { + FromType: "TaskInput", + EdgeLabel: "valueRelatedArtifact_resourceReference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|valueRelatedArtifact_resourceReference_ResearchStudy|TaskInput": { + FromType: "ResearchStudy", + EdgeLabel: "valueRelatedArtifact_resourceReference_ResearchStudy", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "TaskInput|valueRelatedArtifact_resourceReference_Patient|Patient": { + FromType: "TaskInput", + EdgeLabel: "valueRelatedArtifact_resourceReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|valueRelatedArtifact_resourceReference_Patient|TaskInput": { + FromType: "Patient", + EdgeLabel: "valueRelatedArtifact_resourceReference_Patient", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "TaskInput|valueRelatedArtifact_resourceReference_ResearchSubject|ResearchSubject": { + FromType: "TaskInput", + EdgeLabel: "valueRelatedArtifact_resourceReference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|valueRelatedArtifact_resourceReference_ResearchSubject|TaskInput": { + FromType: "ResearchSubject", + EdgeLabel: "valueRelatedArtifact_resourceReference_ResearchSubject", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "TaskInput|valueRelatedArtifact_resourceReference_Substance|Substance": { + FromType: "TaskInput", + EdgeLabel: "valueRelatedArtifact_resourceReference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|valueRelatedArtifact_resourceReference_Substance|TaskInput": { + FromType: "Substance", + EdgeLabel: "valueRelatedArtifact_resourceReference_Substance", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "TaskInput|valueRelatedArtifact_resourceReference_SubstanceDefinition|SubstanceDefinition": { + FromType: "TaskInput", + EdgeLabel: "valueRelatedArtifact_resourceReference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|valueRelatedArtifact_resourceReference_SubstanceDefinition|TaskInput": { + FromType: "SubstanceDefinition", + EdgeLabel: "valueRelatedArtifact_resourceReference_SubstanceDefinition", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "TaskInput|valueRelatedArtifact_resourceReference_Specimen|Specimen": { + FromType: "TaskInput", + EdgeLabel: "valueRelatedArtifact_resourceReference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|valueRelatedArtifact_resourceReference_Specimen|TaskInput": { + FromType: "Specimen", + EdgeLabel: "valueRelatedArtifact_resourceReference_Specimen", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "TaskInput|valueRelatedArtifact_resourceReference_Observation|Observation": { + FromType: "TaskInput", + EdgeLabel: "valueRelatedArtifact_resourceReference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|valueRelatedArtifact_resourceReference_Observation|TaskInput": { + FromType: "Observation", + EdgeLabel: "valueRelatedArtifact_resourceReference_Observation", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "TaskInput|valueRelatedArtifact_resourceReference_DiagnosticReport|DiagnosticReport": { + FromType: "TaskInput", + EdgeLabel: "valueRelatedArtifact_resourceReference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|valueRelatedArtifact_resourceReference_DiagnosticReport|TaskInput": { + FromType: "DiagnosticReport", + EdgeLabel: "valueRelatedArtifact_resourceReference_DiagnosticReport", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "TaskInput|valueRelatedArtifact_resourceReference_Condition|Condition": { + FromType: "TaskInput", + EdgeLabel: "valueRelatedArtifact_resourceReference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|valueRelatedArtifact_resourceReference_Condition|TaskInput": { + FromType: "Condition", + EdgeLabel: "valueRelatedArtifact_resourceReference_Condition", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "TaskInput|valueRelatedArtifact_resourceReference_Medication|Medication": { + FromType: "TaskInput", + EdgeLabel: "valueRelatedArtifact_resourceReference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|valueRelatedArtifact_resourceReference_Medication|TaskInput": { + FromType: "Medication", + EdgeLabel: "valueRelatedArtifact_resourceReference_Medication", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "TaskInput|valueRelatedArtifact_resourceReference_MedicationAdministration|MedicationAdministration": { + FromType: "TaskInput", + EdgeLabel: "valueRelatedArtifact_resourceReference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|valueRelatedArtifact_resourceReference_MedicationAdministration|TaskInput": { + FromType: "MedicationAdministration", + EdgeLabel: "valueRelatedArtifact_resourceReference_MedicationAdministration", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "TaskInput|valueRelatedArtifact_resourceReference_MedicationStatement|MedicationStatement": { + FromType: "TaskInput", + EdgeLabel: "valueRelatedArtifact_resourceReference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|valueRelatedArtifact_resourceReference_MedicationStatement|TaskInput": { + FromType: "MedicationStatement", + EdgeLabel: "valueRelatedArtifact_resourceReference_MedicationStatement", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "TaskInput|valueRelatedArtifact_resourceReference_MedicationRequest|MedicationRequest": { + FromType: "TaskInput", + EdgeLabel: "valueRelatedArtifact_resourceReference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|valueRelatedArtifact_resourceReference_MedicationRequest|TaskInput": { + FromType: "MedicationRequest", + EdgeLabel: "valueRelatedArtifact_resourceReference_MedicationRequest", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "TaskInput|valueRelatedArtifact_resourceReference_Procedure|Procedure": { + FromType: "TaskInput", + EdgeLabel: "valueRelatedArtifact_resourceReference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|valueRelatedArtifact_resourceReference_Procedure|TaskInput": { + FromType: "Procedure", + EdgeLabel: "valueRelatedArtifact_resourceReference_Procedure", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "TaskInput|valueRelatedArtifact_resourceReference_DocumentReference|DocumentReference": { + FromType: "TaskInput", + EdgeLabel: "valueRelatedArtifact_resourceReference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|valueRelatedArtifact_resourceReference_DocumentReference|TaskInput": { + FromType: "DocumentReference", + EdgeLabel: "valueRelatedArtifact_resourceReference_DocumentReference", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "TaskInput|valueRelatedArtifact_resourceReference_Task|Task": { + FromType: "TaskInput", + EdgeLabel: "valueRelatedArtifact_resourceReference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|valueRelatedArtifact_resourceReference_Task|TaskInput": { + FromType: "Task", + EdgeLabel: "valueRelatedArtifact_resourceReference_Task", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "TaskInput|valueRelatedArtifact_resourceReference_ImagingStudy|ImagingStudy": { + FromType: "TaskInput", + EdgeLabel: "valueRelatedArtifact_resourceReference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|valueRelatedArtifact_resourceReference_ImagingStudy|TaskInput": { + FromType: "ImagingStudy", + EdgeLabel: "valueRelatedArtifact_resourceReference_ImagingStudy", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "TaskInput|valueRelatedArtifact_resourceReference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "TaskInput", + EdgeLabel: "valueRelatedArtifact_resourceReference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|valueRelatedArtifact_resourceReference_FamilyMemberHistory|TaskInput": { + FromType: "FamilyMemberHistory", + EdgeLabel: "valueRelatedArtifact_resourceReference_FamilyMemberHistory", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "TaskInput|valueRelatedArtifact_resourceReference_BodyStructure|BodyStructure": { + FromType: "TaskInput", + EdgeLabel: "valueRelatedArtifact_resourceReference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|valueRelatedArtifact_resourceReference_BodyStructure|TaskInput": { + FromType: "BodyStructure", + EdgeLabel: "valueRelatedArtifact_resourceReference_BodyStructure", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "TaskInput|valueSignature_onBehalfOf_Practitioner|Practitioner": { + FromType: "TaskInput", + EdgeLabel: "valueSignature_onBehalfOf_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|valueSignature_onBehalfOf_Practitioner|TaskInput": { + FromType: "Practitioner", + EdgeLabel: "valueSignature_onBehalfOf_Practitioner", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "TaskInput|valueSignature_onBehalfOf_PractitionerRole|PractitionerRole": { + FromType: "TaskInput", + EdgeLabel: "valueSignature_onBehalfOf_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|valueSignature_onBehalfOf_PractitionerRole|TaskInput": { + FromType: "PractitionerRole", + EdgeLabel: "valueSignature_onBehalfOf_PractitionerRole", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "TaskInput|valueSignature_onBehalfOf_Patient|Patient": { + FromType: "TaskInput", + EdgeLabel: "valueSignature_onBehalfOf_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|valueSignature_onBehalfOf_Patient|TaskInput": { + FromType: "Patient", + EdgeLabel: "valueSignature_onBehalfOf_Patient", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "TaskInput|valueSignature_onBehalfOf_Organization|Organization": { + FromType: "TaskInput", + EdgeLabel: "valueSignature_onBehalfOf_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueSignature_onBehalfOf_Organization|TaskInput": { + FromType: "Organization", + EdgeLabel: "valueSignature_onBehalfOf_Organization", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "TaskInput|valueSignature_who_Practitioner|Practitioner": { + FromType: "TaskInput", + EdgeLabel: "valueSignature_who_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|valueSignature_who_Practitioner|TaskInput": { + FromType: "Practitioner", + EdgeLabel: "valueSignature_who_Practitioner", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "TaskInput|valueSignature_who_PractitionerRole|PractitionerRole": { + FromType: "TaskInput", + EdgeLabel: "valueSignature_who_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|valueSignature_who_PractitionerRole|TaskInput": { + FromType: "PractitionerRole", + EdgeLabel: "valueSignature_who_PractitionerRole", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "TaskInput|valueSignature_who_Patient|Patient": { + FromType: "TaskInput", + EdgeLabel: "valueSignature_who_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|valueSignature_who_Patient|TaskInput": { + FromType: "Patient", + EdgeLabel: "valueSignature_who_Patient", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "TaskInput|valueSignature_who_Organization|Organization": { + FromType: "TaskInput", + EdgeLabel: "valueSignature_who_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueSignature_who_Organization|TaskInput": { + FromType: "Organization", + EdgeLabel: "valueSignature_who_Organization", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "TaskInput|valueUsageContext_valueReference_ResearchStudy|ResearchStudy": { + FromType: "TaskInput", + EdgeLabel: "valueUsageContext_valueReference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|valueUsageContext_valueReference_ResearchStudy|TaskInput": { + FromType: "ResearchStudy", + EdgeLabel: "valueUsageContext_valueReference_ResearchStudy", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "TaskInput|valueUsageContext_valueReference_Group|Group": { + FromType: "TaskInput", + EdgeLabel: "valueUsageContext_valueReference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|valueUsageContext_valueReference_Group|TaskInput": { + FromType: "Group", + EdgeLabel: "valueUsageContext_valueReference_Group", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "TaskInput|valueUsageContext_valueReference_Organization|Organization": { + FromType: "TaskInput", + EdgeLabel: "valueUsageContext_valueReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueUsageContext_valueReference_Organization|TaskInput": { + FromType: "Organization", + EdgeLabel: "valueUsageContext_valueReference_Organization", + ToType: "TaskInput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "TaskOutput|valueReference_Organization|Organization": { + FromType: "TaskOutput", + EdgeLabel: "valueReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueReference_Organization|TaskOutput": { + FromType: "Organization", + EdgeLabel: "valueReference_Organization", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "TaskOutput|valueReference_Group|Group": { + FromType: "TaskOutput", + EdgeLabel: "valueReference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|valueReference_Group|TaskOutput": { + FromType: "Group", + EdgeLabel: "valueReference_Group", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "TaskOutput|valueReference_Practitioner|Practitioner": { + FromType: "TaskOutput", + EdgeLabel: "valueReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|valueReference_Practitioner|TaskOutput": { + FromType: "Practitioner", + EdgeLabel: "valueReference_Practitioner", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "TaskOutput|valueReference_PractitionerRole|PractitionerRole": { + FromType: "TaskOutput", + EdgeLabel: "valueReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|valueReference_PractitionerRole|TaskOutput": { + FromType: "PractitionerRole", + EdgeLabel: "valueReference_PractitionerRole", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "TaskOutput|valueReference_ResearchStudy|ResearchStudy": { + FromType: "TaskOutput", + EdgeLabel: "valueReference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|valueReference_ResearchStudy|TaskOutput": { + FromType: "ResearchStudy", + EdgeLabel: "valueReference_ResearchStudy", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "TaskOutput|valueReference_Patient|Patient": { + FromType: "TaskOutput", + EdgeLabel: "valueReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|valueReference_Patient|TaskOutput": { + FromType: "Patient", + EdgeLabel: "valueReference_Patient", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "TaskOutput|valueReference_ResearchSubject|ResearchSubject": { + FromType: "TaskOutput", + EdgeLabel: "valueReference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|valueReference_ResearchSubject|TaskOutput": { + FromType: "ResearchSubject", + EdgeLabel: "valueReference_ResearchSubject", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "TaskOutput|valueReference_Substance|Substance": { + FromType: "TaskOutput", + EdgeLabel: "valueReference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|valueReference_Substance|TaskOutput": { + FromType: "Substance", + EdgeLabel: "valueReference_Substance", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "TaskOutput|valueReference_SubstanceDefinition|SubstanceDefinition": { + FromType: "TaskOutput", + EdgeLabel: "valueReference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|valueReference_SubstanceDefinition|TaskOutput": { + FromType: "SubstanceDefinition", + EdgeLabel: "valueReference_SubstanceDefinition", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "TaskOutput|valueReference_Specimen|Specimen": { + FromType: "TaskOutput", + EdgeLabel: "valueReference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|valueReference_Specimen|TaskOutput": { + FromType: "Specimen", + EdgeLabel: "valueReference_Specimen", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "TaskOutput|valueReference_Observation|Observation": { + FromType: "TaskOutput", + EdgeLabel: "valueReference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|valueReference_Observation|TaskOutput": { + FromType: "Observation", + EdgeLabel: "valueReference_Observation", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "TaskOutput|valueReference_DiagnosticReport|DiagnosticReport": { + FromType: "TaskOutput", + EdgeLabel: "valueReference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|valueReference_DiagnosticReport|TaskOutput": { + FromType: "DiagnosticReport", + EdgeLabel: "valueReference_DiagnosticReport", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "TaskOutput|valueReference_Condition|Condition": { + FromType: "TaskOutput", + EdgeLabel: "valueReference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|valueReference_Condition|TaskOutput": { + FromType: "Condition", + EdgeLabel: "valueReference_Condition", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "TaskOutput|valueReference_Medication|Medication": { + FromType: "TaskOutput", + EdgeLabel: "valueReference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|valueReference_Medication|TaskOutput": { + FromType: "Medication", + EdgeLabel: "valueReference_Medication", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "TaskOutput|valueReference_MedicationAdministration|MedicationAdministration": { + FromType: "TaskOutput", + EdgeLabel: "valueReference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|valueReference_MedicationAdministration|TaskOutput": { + FromType: "MedicationAdministration", + EdgeLabel: "valueReference_MedicationAdministration", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "TaskOutput|valueReference_MedicationStatement|MedicationStatement": { + FromType: "TaskOutput", + EdgeLabel: "valueReference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|valueReference_MedicationStatement|TaskOutput": { + FromType: "MedicationStatement", + EdgeLabel: "valueReference_MedicationStatement", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "TaskOutput|valueReference_MedicationRequest|MedicationRequest": { + FromType: "TaskOutput", + EdgeLabel: "valueReference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|valueReference_MedicationRequest|TaskOutput": { + FromType: "MedicationRequest", + EdgeLabel: "valueReference_MedicationRequest", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "TaskOutput|valueReference_Procedure|Procedure": { + FromType: "TaskOutput", + EdgeLabel: "valueReference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|valueReference_Procedure|TaskOutput": { + FromType: "Procedure", + EdgeLabel: "valueReference_Procedure", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "TaskOutput|valueReference_DocumentReference|DocumentReference": { + FromType: "TaskOutput", + EdgeLabel: "valueReference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|valueReference_DocumentReference|TaskOutput": { + FromType: "DocumentReference", + EdgeLabel: "valueReference_DocumentReference", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "TaskOutput|valueReference_Task|Task": { + FromType: "TaskOutput", + EdgeLabel: "valueReference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|valueReference_Task|TaskOutput": { + FromType: "Task", + EdgeLabel: "valueReference_Task", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "TaskOutput|valueReference_ImagingStudy|ImagingStudy": { + FromType: "TaskOutput", + EdgeLabel: "valueReference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|valueReference_ImagingStudy|TaskOutput": { + FromType: "ImagingStudy", + EdgeLabel: "valueReference_ImagingStudy", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "TaskOutput|valueReference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "TaskOutput", + EdgeLabel: "valueReference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|valueReference_FamilyMemberHistory|TaskOutput": { + FromType: "FamilyMemberHistory", + EdgeLabel: "valueReference_FamilyMemberHistory", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "TaskOutput|valueReference_BodyStructure|BodyStructure": { + FromType: "TaskOutput", + EdgeLabel: "valueReference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|valueReference_BodyStructure|TaskOutput": { + FromType: "BodyStructure", + EdgeLabel: "valueReference_BodyStructure", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_output", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "TaskOutput|valueAnnotation_authorReference_Practitioner|Practitioner": { + FromType: "TaskOutput", + EdgeLabel: "valueAnnotation_authorReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|valueAnnotation_authorReference_Practitioner|TaskOutput": { + FromType: "Practitioner", + EdgeLabel: "valueAnnotation_authorReference_Practitioner", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "TaskOutput|valueAnnotation_authorReference_PractitionerRole|PractitionerRole": { + FromType: "TaskOutput", + EdgeLabel: "valueAnnotation_authorReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|valueAnnotation_authorReference_PractitionerRole|TaskOutput": { + FromType: "PractitionerRole", + EdgeLabel: "valueAnnotation_authorReference_PractitionerRole", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "TaskOutput|valueAnnotation_authorReference_Patient|Patient": { + FromType: "TaskOutput", + EdgeLabel: "valueAnnotation_authorReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|valueAnnotation_authorReference_Patient|TaskOutput": { + FromType: "Patient", + EdgeLabel: "valueAnnotation_authorReference_Patient", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "TaskOutput|valueAnnotation_authorReference_Organization|Organization": { + FromType: "TaskOutput", + EdgeLabel: "valueAnnotation_authorReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueAnnotation_authorReference_Organization|TaskOutput": { + FromType: "Organization", + EdgeLabel: "valueAnnotation_authorReference_Organization", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "annotation", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "TaskOutput|valueCodeableReference_reference_Organization|Organization": { + FromType: "TaskOutput", + EdgeLabel: "valueCodeableReference_reference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueCodeableReference_reference_Organization|TaskOutput": { + FromType: "Organization", + EdgeLabel: "valueCodeableReference_reference_Organization", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "TaskOutput|valueCodeableReference_reference_Group|Group": { + FromType: "TaskOutput", + EdgeLabel: "valueCodeableReference_reference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|valueCodeableReference_reference_Group|TaskOutput": { + FromType: "Group", + EdgeLabel: "valueCodeableReference_reference_Group", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "TaskOutput|valueCodeableReference_reference_Practitioner|Practitioner": { + FromType: "TaskOutput", + EdgeLabel: "valueCodeableReference_reference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|valueCodeableReference_reference_Practitioner|TaskOutput": { + FromType: "Practitioner", + EdgeLabel: "valueCodeableReference_reference_Practitioner", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "TaskOutput|valueCodeableReference_reference_PractitionerRole|PractitionerRole": { + FromType: "TaskOutput", + EdgeLabel: "valueCodeableReference_reference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|valueCodeableReference_reference_PractitionerRole|TaskOutput": { + FromType: "PractitionerRole", + EdgeLabel: "valueCodeableReference_reference_PractitionerRole", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "TaskOutput|valueCodeableReference_reference_ResearchStudy|ResearchStudy": { + FromType: "TaskOutput", + EdgeLabel: "valueCodeableReference_reference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|valueCodeableReference_reference_ResearchStudy|TaskOutput": { + FromType: "ResearchStudy", + EdgeLabel: "valueCodeableReference_reference_ResearchStudy", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "TaskOutput|valueCodeableReference_reference_Patient|Patient": { + FromType: "TaskOutput", + EdgeLabel: "valueCodeableReference_reference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|valueCodeableReference_reference_Patient|TaskOutput": { + FromType: "Patient", + EdgeLabel: "valueCodeableReference_reference_Patient", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "TaskOutput|valueCodeableReference_reference_ResearchSubject|ResearchSubject": { + FromType: "TaskOutput", + EdgeLabel: "valueCodeableReference_reference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|valueCodeableReference_reference_ResearchSubject|TaskOutput": { + FromType: "ResearchSubject", + EdgeLabel: "valueCodeableReference_reference_ResearchSubject", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "TaskOutput|valueCodeableReference_reference_Substance|Substance": { + FromType: "TaskOutput", + EdgeLabel: "valueCodeableReference_reference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|valueCodeableReference_reference_Substance|TaskOutput": { + FromType: "Substance", + EdgeLabel: "valueCodeableReference_reference_Substance", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "TaskOutput|valueCodeableReference_reference_SubstanceDefinition|SubstanceDefinition": { + FromType: "TaskOutput", + EdgeLabel: "valueCodeableReference_reference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|valueCodeableReference_reference_SubstanceDefinition|TaskOutput": { + FromType: "SubstanceDefinition", + EdgeLabel: "valueCodeableReference_reference_SubstanceDefinition", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "TaskOutput|valueCodeableReference_reference_Specimen|Specimen": { + FromType: "TaskOutput", + EdgeLabel: "valueCodeableReference_reference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|valueCodeableReference_reference_Specimen|TaskOutput": { + FromType: "Specimen", + EdgeLabel: "valueCodeableReference_reference_Specimen", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "TaskOutput|valueCodeableReference_reference_Observation|Observation": { + FromType: "TaskOutput", + EdgeLabel: "valueCodeableReference_reference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|valueCodeableReference_reference_Observation|TaskOutput": { + FromType: "Observation", + EdgeLabel: "valueCodeableReference_reference_Observation", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "TaskOutput|valueCodeableReference_reference_DiagnosticReport|DiagnosticReport": { + FromType: "TaskOutput", + EdgeLabel: "valueCodeableReference_reference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|valueCodeableReference_reference_DiagnosticReport|TaskOutput": { + FromType: "DiagnosticReport", + EdgeLabel: "valueCodeableReference_reference_DiagnosticReport", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "TaskOutput|valueCodeableReference_reference_Condition|Condition": { + FromType: "TaskOutput", + EdgeLabel: "valueCodeableReference_reference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|valueCodeableReference_reference_Condition|TaskOutput": { + FromType: "Condition", + EdgeLabel: "valueCodeableReference_reference_Condition", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "TaskOutput|valueCodeableReference_reference_Medication|Medication": { + FromType: "TaskOutput", + EdgeLabel: "valueCodeableReference_reference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|valueCodeableReference_reference_Medication|TaskOutput": { + FromType: "Medication", + EdgeLabel: "valueCodeableReference_reference_Medication", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "TaskOutput|valueCodeableReference_reference_MedicationAdministration|MedicationAdministration": { + FromType: "TaskOutput", + EdgeLabel: "valueCodeableReference_reference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|valueCodeableReference_reference_MedicationAdministration|TaskOutput": { + FromType: "MedicationAdministration", + EdgeLabel: "valueCodeableReference_reference_MedicationAdministration", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "TaskOutput|valueCodeableReference_reference_MedicationStatement|MedicationStatement": { + FromType: "TaskOutput", + EdgeLabel: "valueCodeableReference_reference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|valueCodeableReference_reference_MedicationStatement|TaskOutput": { + FromType: "MedicationStatement", + EdgeLabel: "valueCodeableReference_reference_MedicationStatement", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "TaskOutput|valueCodeableReference_reference_MedicationRequest|MedicationRequest": { + FromType: "TaskOutput", + EdgeLabel: "valueCodeableReference_reference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|valueCodeableReference_reference_MedicationRequest|TaskOutput": { + FromType: "MedicationRequest", + EdgeLabel: "valueCodeableReference_reference_MedicationRequest", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "TaskOutput|valueCodeableReference_reference_Procedure|Procedure": { + FromType: "TaskOutput", + EdgeLabel: "valueCodeableReference_reference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|valueCodeableReference_reference_Procedure|TaskOutput": { + FromType: "Procedure", + EdgeLabel: "valueCodeableReference_reference_Procedure", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "TaskOutput|valueCodeableReference_reference_DocumentReference|DocumentReference": { + FromType: "TaskOutput", + EdgeLabel: "valueCodeableReference_reference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|valueCodeableReference_reference_DocumentReference|TaskOutput": { + FromType: "DocumentReference", + EdgeLabel: "valueCodeableReference_reference_DocumentReference", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "TaskOutput|valueCodeableReference_reference_Task|Task": { + FromType: "TaskOutput", + EdgeLabel: "valueCodeableReference_reference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|valueCodeableReference_reference_Task|TaskOutput": { + FromType: "Task", + EdgeLabel: "valueCodeableReference_reference_Task", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "TaskOutput|valueCodeableReference_reference_ImagingStudy|ImagingStudy": { + FromType: "TaskOutput", + EdgeLabel: "valueCodeableReference_reference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|valueCodeableReference_reference_ImagingStudy|TaskOutput": { + FromType: "ImagingStudy", + EdgeLabel: "valueCodeableReference_reference_ImagingStudy", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "TaskOutput|valueCodeableReference_reference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "TaskOutput", + EdgeLabel: "valueCodeableReference_reference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|valueCodeableReference_reference_FamilyMemberHistory|TaskOutput": { + FromType: "FamilyMemberHistory", + EdgeLabel: "valueCodeableReference_reference_FamilyMemberHistory", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "TaskOutput|valueCodeableReference_reference_BodyStructure|BodyStructure": { + FromType: "TaskOutput", + EdgeLabel: "valueCodeableReference_reference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|valueCodeableReference_reference_BodyStructure|TaskOutput": { + FromType: "BodyStructure", + EdgeLabel: "valueCodeableReference_reference_BodyStructure", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "codeable_reference", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "TaskOutput|valueDataRequirement_subjectReference|Group": { + FromType: "TaskOutput", + EdgeLabel: "valueDataRequirement_subjectReference", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "data_requirement", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|valueDataRequirement_subjectReference|TaskOutput": { + FromType: "Group", + EdgeLabel: "valueDataRequirement_subjectReference", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "data_requirement", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "TaskOutput|valueExtendedContactDetail_organization|Organization": { + FromType: "TaskOutput", + EdgeLabel: "valueExtendedContactDetail_organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extended_contact_detail", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueExtendedContactDetail_organization|TaskOutput": { + FromType: "Organization", + EdgeLabel: "valueExtendedContactDetail_organization", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "extended_contact_detail", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "TaskOutput|valueRelatedArtifact_resourceReference_Organization|Organization": { + FromType: "TaskOutput", + EdgeLabel: "valueRelatedArtifact_resourceReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueRelatedArtifact_resourceReference_Organization|TaskOutput": { + FromType: "Organization", + EdgeLabel: "valueRelatedArtifact_resourceReference_Organization", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "TaskOutput|valueRelatedArtifact_resourceReference_Group|Group": { + FromType: "TaskOutput", + EdgeLabel: "valueRelatedArtifact_resourceReference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|valueRelatedArtifact_resourceReference_Group|TaskOutput": { + FromType: "Group", + EdgeLabel: "valueRelatedArtifact_resourceReference_Group", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "TaskOutput|valueRelatedArtifact_resourceReference_Practitioner|Practitioner": { + FromType: "TaskOutput", + EdgeLabel: "valueRelatedArtifact_resourceReference_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|valueRelatedArtifact_resourceReference_Practitioner|TaskOutput": { + FromType: "Practitioner", + EdgeLabel: "valueRelatedArtifact_resourceReference_Practitioner", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "TaskOutput|valueRelatedArtifact_resourceReference_PractitionerRole|PractitionerRole": { + FromType: "TaskOutput", + EdgeLabel: "valueRelatedArtifact_resourceReference_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|valueRelatedArtifact_resourceReference_PractitionerRole|TaskOutput": { + FromType: "PractitionerRole", + EdgeLabel: "valueRelatedArtifact_resourceReference_PractitionerRole", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "TaskOutput|valueRelatedArtifact_resourceReference_ResearchStudy|ResearchStudy": { + FromType: "TaskOutput", + EdgeLabel: "valueRelatedArtifact_resourceReference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|valueRelatedArtifact_resourceReference_ResearchStudy|TaskOutput": { + FromType: "ResearchStudy", + EdgeLabel: "valueRelatedArtifact_resourceReference_ResearchStudy", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "TaskOutput|valueRelatedArtifact_resourceReference_Patient|Patient": { + FromType: "TaskOutput", + EdgeLabel: "valueRelatedArtifact_resourceReference_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|valueRelatedArtifact_resourceReference_Patient|TaskOutput": { + FromType: "Patient", + EdgeLabel: "valueRelatedArtifact_resourceReference_Patient", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "TaskOutput|valueRelatedArtifact_resourceReference_ResearchSubject|ResearchSubject": { + FromType: "TaskOutput", + EdgeLabel: "valueRelatedArtifact_resourceReference_ResearchSubject", + ToType: "ResearchSubject", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "ResearchSubject|valueRelatedArtifact_resourceReference_ResearchSubject|TaskOutput": { + FromType: "ResearchSubject", + EdgeLabel: "valueRelatedArtifact_resourceReference_ResearchSubject", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ResearchSubject/*", + }, + }, + "TaskOutput|valueRelatedArtifact_resourceReference_Substance|Substance": { + FromType: "TaskOutput", + EdgeLabel: "valueRelatedArtifact_resourceReference_Substance", + ToType: "Substance", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "Substance|valueRelatedArtifact_resourceReference_Substance|TaskOutput": { + FromType: "Substance", + EdgeLabel: "valueRelatedArtifact_resourceReference_Substance", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Substance/*", + }, + }, + "TaskOutput|valueRelatedArtifact_resourceReference_SubstanceDefinition|SubstanceDefinition": { + FromType: "TaskOutput", + EdgeLabel: "valueRelatedArtifact_resourceReference_SubstanceDefinition", + ToType: "SubstanceDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "SubstanceDefinition|valueRelatedArtifact_resourceReference_SubstanceDefinition|TaskOutput": { + FromType: "SubstanceDefinition", + EdgeLabel: "valueRelatedArtifact_resourceReference_SubstanceDefinition", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "SubstanceDefinition/*", + }, + }, + "TaskOutput|valueRelatedArtifact_resourceReference_Specimen|Specimen": { + FromType: "TaskOutput", + EdgeLabel: "valueRelatedArtifact_resourceReference_Specimen", + ToType: "Specimen", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "Specimen|valueRelatedArtifact_resourceReference_Specimen|TaskOutput": { + FromType: "Specimen", + EdgeLabel: "valueRelatedArtifact_resourceReference_Specimen", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Specimen/*", + }, + }, + "TaskOutput|valueRelatedArtifact_resourceReference_Observation|Observation": { + FromType: "TaskOutput", + EdgeLabel: "valueRelatedArtifact_resourceReference_Observation", + ToType: "Observation", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "Observation|valueRelatedArtifact_resourceReference_Observation|TaskOutput": { + FromType: "Observation", + EdgeLabel: "valueRelatedArtifact_resourceReference_Observation", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Observation/*", + }, + }, + "TaskOutput|valueRelatedArtifact_resourceReference_DiagnosticReport|DiagnosticReport": { + FromType: "TaskOutput", + EdgeLabel: "valueRelatedArtifact_resourceReference_DiagnosticReport", + ToType: "DiagnosticReport", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "DiagnosticReport|valueRelatedArtifact_resourceReference_DiagnosticReport|TaskOutput": { + FromType: "DiagnosticReport", + EdgeLabel: "valueRelatedArtifact_resourceReference_DiagnosticReport", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "DiagnosticReport/*", + }, + }, + "TaskOutput|valueRelatedArtifact_resourceReference_Condition|Condition": { + FromType: "TaskOutput", + EdgeLabel: "valueRelatedArtifact_resourceReference_Condition", + ToType: "Condition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "Condition|valueRelatedArtifact_resourceReference_Condition|TaskOutput": { + FromType: "Condition", + EdgeLabel: "valueRelatedArtifact_resourceReference_Condition", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Condition/*", + }, + }, + "TaskOutput|valueRelatedArtifact_resourceReference_Medication|Medication": { + FromType: "TaskOutput", + EdgeLabel: "valueRelatedArtifact_resourceReference_Medication", + ToType: "Medication", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "Medication|valueRelatedArtifact_resourceReference_Medication|TaskOutput": { + FromType: "Medication", + EdgeLabel: "valueRelatedArtifact_resourceReference_Medication", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Medication/*", + }, + }, + "TaskOutput|valueRelatedArtifact_resourceReference_MedicationAdministration|MedicationAdministration": { + FromType: "TaskOutput", + EdgeLabel: "valueRelatedArtifact_resourceReference_MedicationAdministration", + ToType: "MedicationAdministration", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "MedicationAdministration|valueRelatedArtifact_resourceReference_MedicationAdministration|TaskOutput": { + FromType: "MedicationAdministration", + EdgeLabel: "valueRelatedArtifact_resourceReference_MedicationAdministration", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationAdministration/*", + }, + }, + "TaskOutput|valueRelatedArtifact_resourceReference_MedicationStatement|MedicationStatement": { + FromType: "TaskOutput", + EdgeLabel: "valueRelatedArtifact_resourceReference_MedicationStatement", + ToType: "MedicationStatement", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "MedicationStatement|valueRelatedArtifact_resourceReference_MedicationStatement|TaskOutput": { + FromType: "MedicationStatement", + EdgeLabel: "valueRelatedArtifact_resourceReference_MedicationStatement", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationStatement/*", + }, + }, + "TaskOutput|valueRelatedArtifact_resourceReference_MedicationRequest|MedicationRequest": { + FromType: "TaskOutput", + EdgeLabel: "valueRelatedArtifact_resourceReference_MedicationRequest", + ToType: "MedicationRequest", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "MedicationRequest|valueRelatedArtifact_resourceReference_MedicationRequest|TaskOutput": { + FromType: "MedicationRequest", + EdgeLabel: "valueRelatedArtifact_resourceReference_MedicationRequest", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "MedicationRequest/*", + }, + }, + "TaskOutput|valueRelatedArtifact_resourceReference_Procedure|Procedure": { + FromType: "TaskOutput", + EdgeLabel: "valueRelatedArtifact_resourceReference_Procedure", + ToType: "Procedure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "Procedure|valueRelatedArtifact_resourceReference_Procedure|TaskOutput": { + FromType: "Procedure", + EdgeLabel: "valueRelatedArtifact_resourceReference_Procedure", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Procedure/*", + }, + }, + "TaskOutput|valueRelatedArtifact_resourceReference_DocumentReference|DocumentReference": { + FromType: "TaskOutput", + EdgeLabel: "valueRelatedArtifact_resourceReference_DocumentReference", + ToType: "DocumentReference", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "DocumentReference|valueRelatedArtifact_resourceReference_DocumentReference|TaskOutput": { + FromType: "DocumentReference", + EdgeLabel: "valueRelatedArtifact_resourceReference_DocumentReference", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "DocumentReference/*", + }, + }, + "TaskOutput|valueRelatedArtifact_resourceReference_Task|Task": { + FromType: "TaskOutput", + EdgeLabel: "valueRelatedArtifact_resourceReference_Task", + ToType: "Task", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "Task|valueRelatedArtifact_resourceReference_Task|TaskOutput": { + FromType: "Task", + EdgeLabel: "valueRelatedArtifact_resourceReference_Task", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "Task/*", + }, + }, + "TaskOutput|valueRelatedArtifact_resourceReference_ImagingStudy|ImagingStudy": { + FromType: "TaskOutput", + EdgeLabel: "valueRelatedArtifact_resourceReference_ImagingStudy", + ToType: "ImagingStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "ImagingStudy|valueRelatedArtifact_resourceReference_ImagingStudy|TaskOutput": { + FromType: "ImagingStudy", + EdgeLabel: "valueRelatedArtifact_resourceReference_ImagingStudy", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "ImagingStudy/*", + }, + }, + "TaskOutput|valueRelatedArtifact_resourceReference_FamilyMemberHistory|FamilyMemberHistory": { + FromType: "TaskOutput", + EdgeLabel: "valueRelatedArtifact_resourceReference_FamilyMemberHistory", + ToType: "FamilyMemberHistory", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "FamilyMemberHistory|valueRelatedArtifact_resourceReference_FamilyMemberHistory|TaskOutput": { + FromType: "FamilyMemberHistory", + EdgeLabel: "valueRelatedArtifact_resourceReference_FamilyMemberHistory", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "FamilyMemberHistory/*", + }, + }, + "TaskOutput|valueRelatedArtifact_resourceReference_BodyStructure|BodyStructure": { + FromType: "TaskOutput", + EdgeLabel: "valueRelatedArtifact_resourceReference_BodyStructure", + ToType: "BodyStructure", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "BodyStructure|valueRelatedArtifact_resourceReference_BodyStructure|TaskOutput": { + FromType: "BodyStructure", + EdgeLabel: "valueRelatedArtifact_resourceReference_BodyStructure", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "related_artifact", + }, + RegexMatch: []string{ + "BodyStructure/*", + }, + }, + "TaskOutput|valueSignature_onBehalfOf_Practitioner|Practitioner": { + FromType: "TaskOutput", + EdgeLabel: "valueSignature_onBehalfOf_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|valueSignature_onBehalfOf_Practitioner|TaskOutput": { + FromType: "Practitioner", + EdgeLabel: "valueSignature_onBehalfOf_Practitioner", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "TaskOutput|valueSignature_onBehalfOf_PractitionerRole|PractitionerRole": { + FromType: "TaskOutput", + EdgeLabel: "valueSignature_onBehalfOf_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|valueSignature_onBehalfOf_PractitionerRole|TaskOutput": { + FromType: "PractitionerRole", + EdgeLabel: "valueSignature_onBehalfOf_PractitionerRole", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "TaskOutput|valueSignature_onBehalfOf_Patient|Patient": { + FromType: "TaskOutput", + EdgeLabel: "valueSignature_onBehalfOf_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|valueSignature_onBehalfOf_Patient|TaskOutput": { + FromType: "Patient", + EdgeLabel: "valueSignature_onBehalfOf_Patient", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "TaskOutput|valueSignature_onBehalfOf_Organization|Organization": { + FromType: "TaskOutput", + EdgeLabel: "valueSignature_onBehalfOf_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueSignature_onBehalfOf_Organization|TaskOutput": { + FromType: "Organization", + EdgeLabel: "valueSignature_onBehalfOf_Organization", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "onBehalfOf_signature", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "TaskOutput|valueSignature_who_Practitioner|Practitioner": { + FromType: "TaskOutput", + EdgeLabel: "valueSignature_who_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|valueSignature_who_Practitioner|TaskOutput": { + FromType: "Practitioner", + EdgeLabel: "valueSignature_who_Practitioner", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "TaskOutput|valueSignature_who_PractitionerRole|PractitionerRole": { + FromType: "TaskOutput", + EdgeLabel: "valueSignature_who_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|valueSignature_who_PractitionerRole|TaskOutput": { + FromType: "PractitionerRole", + EdgeLabel: "valueSignature_who_PractitionerRole", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "TaskOutput|valueSignature_who_Patient|Patient": { + FromType: "TaskOutput", + EdgeLabel: "valueSignature_who_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|valueSignature_who_Patient|TaskOutput": { + FromType: "Patient", + EdgeLabel: "valueSignature_who_Patient", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "TaskOutput|valueSignature_who_Organization|Organization": { + FromType: "TaskOutput", + EdgeLabel: "valueSignature_who_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueSignature_who_Organization|TaskOutput": { + FromType: "Organization", + EdgeLabel: "valueSignature_who_Organization", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "who_signature", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "TaskOutput|valueUsageContext_valueReference_ResearchStudy|ResearchStudy": { + FromType: "TaskOutput", + EdgeLabel: "valueUsageContext_valueReference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|valueUsageContext_valueReference_ResearchStudy|TaskOutput": { + FromType: "ResearchStudy", + EdgeLabel: "valueUsageContext_valueReference_ResearchStudy", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "TaskOutput|valueUsageContext_valueReference_Group|Group": { + FromType: "TaskOutput", + EdgeLabel: "valueUsageContext_valueReference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|valueUsageContext_valueReference_Group|TaskOutput": { + FromType: "Group", + EdgeLabel: "valueUsageContext_valueReference_Group", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "TaskOutput|valueUsageContext_valueReference_Organization|Organization": { + FromType: "TaskOutput", + EdgeLabel: "valueUsageContext_valueReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueUsageContext_valueReference_Organization|TaskOutput": { + FromType: "Organization", + EdgeLabel: "valueUsageContext_valueReference_Organization", + ToType: "TaskOutput", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "TaskPerformer|actor_Practitioner|Practitioner": { + FromType: "TaskPerformer", + EdgeLabel: "actor_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_performer", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|actor_Practitioner|TaskPerformer": { + FromType: "Practitioner", + EdgeLabel: "actor_Practitioner", + ToType: "TaskPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_performer", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "TaskPerformer|actor_PractitionerRole|PractitionerRole": { + FromType: "TaskPerformer", + EdgeLabel: "actor_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_performer", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|actor_PractitionerRole|TaskPerformer": { + FromType: "PractitionerRole", + EdgeLabel: "actor_PractitionerRole", + ToType: "TaskPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_performer", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "TaskPerformer|actor_Organization|Organization": { + FromType: "TaskPerformer", + EdgeLabel: "actor_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_performer", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|actor_Organization|TaskPerformer": { + FromType: "Organization", + EdgeLabel: "actor_Organization", + ToType: "TaskPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_performer", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "TaskPerformer|actor_Patient|Patient": { + FromType: "TaskPerformer", + EdgeLabel: "actor_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_performer", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|actor_Patient|TaskPerformer": { + FromType: "Patient", + EdgeLabel: "actor_Patient", + ToType: "TaskPerformer", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "task_performer", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "TaskRestriction|recipient_Patient|Patient": { + FromType: "TaskRestriction", + EdgeLabel: "recipient_Patient", + ToType: "Patient", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "recipient_task_restriction", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "Patient|recipient_Patient|TaskRestriction": { + FromType: "Patient", + EdgeLabel: "recipient_Patient", + ToType: "TaskRestriction", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "recipient_task_restriction", + }, + RegexMatch: []string{ + "Patient/*", + }, + }, + "TaskRestriction|recipient_Practitioner|Practitioner": { + FromType: "TaskRestriction", + EdgeLabel: "recipient_Practitioner", + ToType: "Practitioner", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "recipient_task_restriction", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "Practitioner|recipient_Practitioner|TaskRestriction": { + FromType: "Practitioner", + EdgeLabel: "recipient_Practitioner", + ToType: "TaskRestriction", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "recipient_task_restriction", + }, + RegexMatch: []string{ + "Practitioner/*", + }, + }, + "TaskRestriction|recipient_PractitionerRole|PractitionerRole": { + FromType: "TaskRestriction", + EdgeLabel: "recipient_PractitionerRole", + ToType: "PractitionerRole", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "recipient_task_restriction", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "PractitionerRole|recipient_PractitionerRole|TaskRestriction": { + FromType: "PractitionerRole", + EdgeLabel: "recipient_PractitionerRole", + ToType: "TaskRestriction", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "recipient_task_restriction", + }, + RegexMatch: []string{ + "PractitionerRole/*", + }, + }, + "TaskRestriction|recipient_Group|Group": { + FromType: "TaskRestriction", + EdgeLabel: "recipient_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "recipient_task_restriction", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|recipient_Group|TaskRestriction": { + FromType: "Group", + EdgeLabel: "recipient_Group", + ToType: "TaskRestriction", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "recipient_task_restriction", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "TaskRestriction|recipient_Organization|Organization": { + FromType: "TaskRestriction", + EdgeLabel: "recipient_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "recipient_task_restriction", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|recipient_Organization|TaskRestriction": { + FromType: "Organization", + EdgeLabel: "recipient_Organization", + ToType: "TaskRestriction", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_many", + }, + Backref: []string{ + "recipient_task_restriction", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "TriggerDefinition|data_subjectReference|Group": { + FromType: "TriggerDefinition", + EdgeLabel: "data_subjectReference", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "data_requirement", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|data_subjectReference|TriggerDefinition": { + FromType: "Group", + EdgeLabel: "data_subjectReference", + ToType: "TriggerDefinition", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "data_requirement", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "UsageContext|valueReference_ResearchStudy|ResearchStudy": { + FromType: "UsageContext", + EdgeLabel: "valueReference_ResearchStudy", + ToType: "ResearchStudy", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "ResearchStudy|valueReference_ResearchStudy|UsageContext": { + FromType: "ResearchStudy", + EdgeLabel: "valueReference_ResearchStudy", + ToType: "UsageContext", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "ResearchStudy/*", + }, + }, + "UsageContext|valueReference_Group|Group": { + FromType: "UsageContext", + EdgeLabel: "valueReference_Group", + ToType: "Group", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "Group|valueReference_Group|UsageContext": { + FromType: "Group", + EdgeLabel: "valueReference_Group", + ToType: "UsageContext", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "Group/*", + }, + }, + "UsageContext|valueReference_Organization|Organization": { + FromType: "UsageContext", + EdgeLabel: "valueReference_Organization", + ToType: "Organization", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, + "Organization|valueReference_Organization|UsageContext": { + FromType: "Organization", + EdgeLabel: "valueReference_Organization", + ToType: "UsageContext", + Direction: []string{ + "outbound", + }, + Multiplicity: []string{ + "has_one", + }, + Backref: []string{ + "usage_context", + }, + RegexMatch: []string{ + "Organization/*", + }, + }, +} diff --git a/internal/fhirschema/schema.go b/internal/fhirschema/schema.go index 0a27e4e..aaffde5 100644 --- a/internal/fhirschema/schema.go +++ b/internal/fhirschema/schema.go @@ -57,9 +57,20 @@ type ResolvedPath struct { } type PivotSpec struct { - Family string - ColumnSelector FieldSelectorSpec - ValueSelector FieldSelectorSpec + Family string + CatalogRootPath string + ColumnSelector FieldSelectorSpec + ValueSelector FieldSelectorSpec +} + +type TraversalSpec struct { + FromType string + EdgeLabel string + ToType string + Direction []string + Multiplicity []string + Backref []string + RegexMatch []string } type generatedDefinition struct { @@ -77,8 +88,8 @@ type generatedProperty struct { } const ( - PredicateContains = "CONTAINS" - maxSelectorFieldDepth = 6 + PredicateContains = "CONTAINS" + maxSelectorFieldDepth = 6 PivotFamilyCodeableConcept = "CODEABLE_CONCEPT" PivotFamilyObservationCodeValue = "OBSERVATION_CODE_VALUE" ) @@ -88,25 +99,6 @@ var ( resourceCache sync.Map ) -func Resources() []ResourceSpec { - out := make([]ResourceSpec, 0, len(generatedResourceTypes)) - for _, resourceType := range generatedResourceTypes { - out = append(out, ResourceSpec{ - ResourceType: resourceType, - Fields: FieldsForResource(resourceType), - }) - } - return out -} - -func Resource(resourceType string) (ResourceSpec, bool) { - fields := FieldsForResource(resourceType) - if len(fields) == 0 { - return ResourceSpec{}, false - } - return ResourceSpec{ResourceType: resourceType, Fields: fields}, true -} - func FieldsForResource(resourceType string) []FieldSpec { if cached, ok := resourceCache.Load(resourceType); ok { return cloneFields(cached.([]FieldSpec)) @@ -128,6 +120,14 @@ func LookupField(resourceType, canonicalPath string) (FieldSpec, bool) { return FieldSpec{}, false } +func LookupTraversal(fromType, edgeLabel, toType string) (TraversalSpec, bool) { + spec, ok := generatedTraversals[traversalKey(fromType, edgeLabel, toType)] + if !ok { + return TraversalSpec{}, false + } + return cloneTraversalSpec(spec), true +} + func ResolvePath(resourceType, canonicalPath string) (ResolvedPath, bool) { parts := strings.Split(strings.TrimSpace(canonicalPath), ".") if len(parts) == 0 || parts[0] == "" { @@ -167,11 +167,6 @@ func ResolvesToCodeableConcept(resourceType, canonicalPath string) bool { return ok && resolved.PropertyRef == "CodeableConcept" } -func ResolvesToCoding(resourceType, canonicalPath string) bool { - resolved, ok := ResolvePath(resourceType, canonicalPath) - return ok && resolved.PropertyRef == "Coding" -} - func ObservationValueSelectorOptions(resourceType string) []FieldSelectorSpec { if resourceType != "Observation" { return []FieldSelectorSpec{} @@ -224,29 +219,15 @@ func ValidatePivotSelectors(resourceType string, column FieldSelectorSpec, value return PivotSpec{}, fmt.Errorf("pivot value selector is required") } - if resourceType == "Observation" && isObservationCodeSelector(columnCanonical) && isObservationValueSelector(valueCanonical) { + if match, ok := resolvePivotFamily(resourceType, columnCanonical, valueCanonical); ok { return PivotSpec{ - Family: PivotFamilyObservationCodeValue, - ColumnSelector: normalizeSelectorSpec(column, columnExpr), - ValueSelector: normalizeSelectorSpec(value, valueExpr), + Family: match.family, + CatalogRootPath: match.catalogRootPath, + ColumnSelector: normalizeSelectorSpec(column, columnExpr), + ValueSelector: normalizeSelectorSpec(value, valueExpr), }, nil } - if roots, ok := codeableConceptRoots(resourceType, columnCanonical); ok { - valueRoots, valueOK := codeableConceptRoots(resourceType, valueCanonical) - if valueOK { - for _, root := range roots { - if slicesContains(valueRoots, root) { - return PivotSpec{ - Family: PivotFamilyCodeableConcept, - ColumnSelector: normalizeSelectorSpec(column, columnExpr), - ValueSelector: normalizeSelectorSpec(value, valueExpr), - }, nil - } - } - } - } - return PivotSpec{}, fmt.Errorf("unsupported pivot selector pair %q / %q for resourceType %q", columnExpr, valueExpr, resourceType) } @@ -301,6 +282,18 @@ func CanonicalPath(spec FieldSelectorSpec) string { })) } +func traversalKey(fromType, edgeLabel, toType string) string { + return fromType + "|" + edgeLabel + "|" + toType +} + +func cloneTraversalSpec(spec TraversalSpec) TraversalSpec { + spec.Direction = cloneStrings(spec.Direction) + spec.Multiplicity = cloneStrings(spec.Multiplicity) + spec.Backref = cloneStrings(spec.Backref) + spec.RegexMatch = cloneStrings(spec.RegexMatch) + return spec +} + func CanonicalizePath(path string) string { parts := strings.Split(strings.TrimSpace(path), ".") out := make([]string, 0, len(parts)) @@ -540,6 +533,54 @@ func codeableConceptRoots(resourceType, canonicalPath string) ([]string, bool) { return nil, false } +type pivotFamilyMatch struct { + family string + catalogRootPath string +} + +func resolvePivotFamily(resourceType, columnCanonical, valueCanonical string) (pivotFamilyMatch, bool) { + resolvers := []func(string, string, string) (pivotFamilyMatch, bool){ + matchObservationCodeValuePivot, + matchSharedCodeableConceptPivot, + } + for _, resolver := range resolvers { + if match, ok := resolver(resourceType, columnCanonical, valueCanonical); ok { + return match, true + } + } + return pivotFamilyMatch{}, false +} + +func matchObservationCodeValuePivot(resourceType, columnCanonical, valueCanonical string) (pivotFamilyMatch, bool) { + if resourceType == "Observation" && isObservationCodeSelector(columnCanonical) && isObservationValueSelector(valueCanonical) { + return pivotFamilyMatch{ + family: PivotFamilyObservationCodeValue, + catalogRootPath: "code", + }, true + } + return pivotFamilyMatch{}, false +} + +func matchSharedCodeableConceptPivot(resourceType, columnCanonical, valueCanonical string) (pivotFamilyMatch, bool) { + roots, ok := codeableConceptRoots(resourceType, columnCanonical) + if !ok { + return pivotFamilyMatch{}, false + } + valueRoots, valueOK := codeableConceptRoots(resourceType, valueCanonical) + if !valueOK { + return pivotFamilyMatch{}, false + } + for _, root := range roots { + if slicesContains(valueRoots, root) { + return pivotFamilyMatch{ + family: PivotFamilyCodeableConcept, + catalogRootPath: root, + }, true + } + } + return pivotFamilyMatch{}, false +} + func isObservationCodeSelector(canonicalPath string) bool { if canonicalPath == "code" { return true diff --git a/internal/fhirschema/schema_test.go b/internal/fhirschema/schema_test.go index 5ee7c09..67c425c 100644 --- a/internal/fhirschema/schema_test.go +++ b/internal/fhirschema/schema_test.go @@ -56,15 +56,6 @@ func TestParseSelectorCanonicalizesIndexedPaths(t *testing.T) { } } -func TestResolvePathRecognizesFHIRRefs(t *testing.T) { - if !ResolvesToCodeableConcept("Observation", "code") { - t.Fatal("expected Observation.code to resolve to CodeableConcept") - } - if !ResolvesToCoding("Observation", "code.coding[]") { - t.Fatal("expected Observation.code.coding[] to resolve to Coding") - } -} - func TestObservationValueSelectorOptions(t *testing.T) { options := ObservationValueSelectorOptions("Observation") if len(options) == 0 { @@ -90,6 +81,9 @@ func TestValidatePivotSelectors(t *testing.T) { if cc.Family != PivotFamilyCodeableConcept { t.Fatalf("unexpected family: %q", cc.Family) } + if cc.CatalogRootPath != "code" { + t.Fatalf("unexpected codeable concept catalog root: %q", cc.CatalogRootPath) + } obs, err := ValidatePivotSelectors("Observation", FieldSelectorSpecFromPath("code.coding[].display"), FieldSelectorSpecFromPath("valueQuantity.value")) if err != nil { @@ -98,4 +92,36 @@ func TestValidatePivotSelectors(t *testing.T) { if obs.Family != PivotFamilyObservationCodeValue { t.Fatalf("unexpected observation family: %q", obs.Family) } + if obs.CatalogRootPath != "code" { + t.Fatalf("unexpected observation catalog root: %q", obs.CatalogRootPath) + } +} + +func TestLookupTraversal(t *testing.T) { + cases := []struct { + fromType string + edgeLabel string + toType string + }{ + {"Patient", "subject_Patient", "Condition"}, + {"Patient", "subject_Patient", "Specimen"}, + {"Patient", "focus_Patient", "Observation"}, + {"Specimen", "subject_Specimen", "DocumentReference"}, + {"Group", "subject_Group", "DocumentReference"}, + } + for _, tc := range cases { + spec, ok := LookupTraversal(tc.fromType, tc.edgeLabel, tc.toType) + if !ok { + t.Fatalf("expected traversal %s %s %s", tc.fromType, tc.edgeLabel, tc.toType) + } + if spec.FromType != tc.fromType || spec.EdgeLabel != tc.edgeLabel || spec.ToType != tc.toType { + t.Fatalf("unexpected traversal spec: %#v", spec) + } + } +} + +func TestLookupTraversalRejectsUnknownTuple(t *testing.T) { + if _, ok := LookupTraversal("Patient", "subject_Patient", "Medication"); ok { + t.Fatal("expected unsupported tuple to miss") + } } diff --git a/internal/fhirsemantics/registry.go b/internal/fhirsemantics/registry.go deleted file mode 100644 index 5885932..0000000 --- a/internal/fhirsemantics/registry.go +++ /dev/null @@ -1,233 +0,0 @@ -package fhirsemantics - -import ( - "strings" - - "arangodb-proto/internal/fhirschema" -) - -const ( - NormalizationNone = "" - NormalizationDocumentReferenceSummary = "DOCUMENT_REFERENCE_SUMMARY" - - TraversalRolePatientNeighborChild = "PATIENT_NEIGHBOR_CHILD" - TraversalRolePatientDirectChild = "PATIENT_DIRECT_CHILD" - TraversalRolePatientDocumentReference = "PATIENT_DOCUMENT_REFERENCE" - TraversalRoleSpecimenGroup = "SPECIMEN_GROUP" - TraversalRoleSpecimenDocumentReference = "SPECIMEN_DOCUMENT_REFERENCE" - TraversalRoleGroupDocumentReference = "GROUP_DOCUMENT_REFERENCE" -) - -type TraversalSpec struct { - FromType string - EdgeLabel string - ToType string - Role string - SetName string - SharedRootNeighborEligible bool -} - -type FieldSpec struct { - ResourceType string - FieldRef string - Label string - Selector fhirschema.FieldSelectorSpec - Normalization string - NormalizedName string -} - -type AliasSpec = FieldSpec - -var aliases = map[string][]FieldSpec{ - "Patient": { - field("Patient", "Patient.case_id", "Case ID", selector("identifier[]", whereContains("system", "case_id"), "value")), - field("Patient", "Patient.case_submitter_id", "Case Submitter ID", selector("identifier[]", whereContains("system", "case_submitter_id"), "value")), - field("Patient", "Patient.gender", "Gender", selector("", nil, "gender")), - field("Patient", "Patient.deceased", "Deceased", selector("", nil, "deceasedBoolean")), - field("Patient", "Patient.race", "Race", selector("extension[]", whereContains("url", "us-core-race"), "valueString")), - field("Patient", "Patient.ethnicity", "Ethnicity", selector("extension[]", whereContains("url", "us-core-ethnicity"), "valueString")), - field("Patient", "Patient.birth_sex", "Birth Sex", selector("extension[]", whereContains("url", "us-core-birthsex"), "valueCode")), - field("Patient", "Patient.patient_age", "Patient Age", selector("extension[]", whereContains("url", "Patient-age"), "valueQuantity.value")), - field("Patient", "Patient.part_of_study", "Part Of Study", selector("extension[]", whereContains("url", "part-of-study"), "valueReference.reference")), - }, - "Condition": { - field("Condition", "Condition.id", "Condition ID", selector("", nil, "id")), - field("Condition", "Condition.diagnosis", "Diagnosis", selector("code.coding[]", nil, "display")), - field("Condition", "Condition.body_site", "Body Site", selector("bodySite[].coding[]", nil, "display")), - }, - "Specimen": { - field("Specimen", "Specimen.id", "Specimen ID", selector("", nil, "id")), - field("Specimen", "Specimen.type_display", "Specimen Type", selector("type.coding[]", nil, "display")), - field("Specimen", "Specimen.preservation_method", "Preservation Method", selector("processing[].method.coding[]", whereContains("system", "preservation_method"), "display")), - }, - "ResearchSubject": { - field("ResearchSubject", "ResearchSubject.id", "Research Subject ID", selector("", nil, "id")), - field("ResearchSubject", "ResearchSubject.status", "Status", selector("", nil, "status")), - field("ResearchSubject", "ResearchSubject.study_ref", "Study Reference", selector("study", nil, "reference")), - }, - "DocumentReference": { - normalizedField("DocumentReference", "DocumentReference.file_id", "File ID", selector("identifier[]", whereContains("system", "file_id"), "value"), "file_id"), - normalizedField("DocumentReference", "DocumentReference.file_name", "File Name", selector("content[].attachment", nil, "title"), "file_name"), - normalizedField("DocumentReference", "DocumentReference.file_url", "File URL", selector("content[].attachment", nil, "url"), "file_url"), - normalizedField("DocumentReference", "DocumentReference.file_size", "File Size", selector("content[].attachment", nil, "size"), "file_size"), - normalizedField("DocumentReference", "DocumentReference.data_category", "Data Category", selector("category[].coding[]", whereContains("system", "data_category"), "display"), "data_category"), - normalizedField("DocumentReference", "DocumentReference.data_type", "Data Type", selector("category[].coding[]", whereContains("system", "data_type"), "display"), "data_type"), - normalizedField("DocumentReference", "DocumentReference.experimental_strategy", "Experimental Strategy", selector("category[].coding[]", whereContains("system", "experimental_strategy"), "display"), "experimental_strategy"), - normalizedField("DocumentReference", "DocumentReference.workflow_type", "Workflow Type", selector("category[].coding[]", whereContains("system", "workflow_type"), "display"), "workflow_type"), - normalizedField("DocumentReference", "DocumentReference.platform", "Platform", selector("category[].coding[]", whereContains("system", "platform"), "display"), "platform"), - normalizedField("DocumentReference", "DocumentReference.access", "Access", selector("category[].coding[]", whereContains("system", "access"), "display"), "access"), - normalizedField("DocumentReference", "DocumentReference.data_format", "Data Format", selector("type.coding[]", nil, "display"), "data_format"), - }, -} - -var traversals = map[string]TraversalSpec{ - traversalKey("Patient", "subject_Patient", "Condition"): { - FromType: "Patient", EdgeLabel: "subject_Patient", ToType: "Condition", - Role: TraversalRolePatientNeighborChild, SetName: "patient_condition_set", SharedRootNeighborEligible: true, - }, - traversalKey("Patient", "subject_Patient", "ResearchSubject"): { - FromType: "Patient", EdgeLabel: "subject_Patient", ToType: "ResearchSubject", - Role: TraversalRolePatientNeighborChild, SetName: "patient_research_subject_set", SharedRootNeighborEligible: true, - }, - traversalKey("Patient", "subject_Patient", "Specimen"): { - FromType: "Patient", EdgeLabel: "subject_Patient", ToType: "Specimen", - Role: TraversalRolePatientNeighborChild, SetName: "patient_specimen_set", SharedRootNeighborEligible: true, - }, - traversalKey("Patient", "subject_Patient", "MedicationAdministration"): { - FromType: "Patient", EdgeLabel: "subject_Patient", ToType: "MedicationAdministration", - Role: TraversalRolePatientNeighborChild, SetName: "patient_medication_administration_set", SharedRootNeighborEligible: true, - }, - traversalKey("Patient", "subject_Patient", "Observation"): { - FromType: "Patient", EdgeLabel: "subject_Patient", ToType: "Observation", - Role: TraversalRolePatientNeighborChild, SetName: "patient_subject_observation_set", SharedRootNeighborEligible: true, - }, - traversalKey("Patient", "subject_Patient", "ImagingStudy"): { - FromType: "Patient", EdgeLabel: "subject_Patient", ToType: "ImagingStudy", - Role: TraversalRolePatientNeighborChild, SetName: "patient_imaging_study_set", SharedRootNeighborEligible: true, - }, - traversalKey("Patient", "subject_Patient", "DocumentReference"): { - FromType: "Patient", EdgeLabel: "subject_Patient", ToType: "DocumentReference", - Role: TraversalRolePatientDocumentReference, SetName: "patient_document_reference_set", SharedRootNeighborEligible: true, - }, - traversalKey("Patient", "focus_Patient", "Observation"): { - FromType: "Patient", EdgeLabel: "focus_Patient", ToType: "Observation", - Role: TraversalRolePatientDirectChild, SetName: "patient_focus_observation_set", - }, - traversalKey("Patient", "member_entity_Patient", "Group"): { - FromType: "Patient", EdgeLabel: "member_entity_Patient", ToType: "Group", - Role: TraversalRolePatientDirectChild, SetName: "patient_group_set", - }, - traversalKey("Specimen", "member_entity_Specimen", "Group"): { - FromType: "Specimen", EdgeLabel: "member_entity_Specimen", ToType: "Group", - Role: TraversalRoleSpecimenGroup, SetName: "specimen_group_set", - }, - traversalKey("Specimen", "subject_Specimen", "DocumentReference"): { - FromType: "Specimen", EdgeLabel: "subject_Specimen", ToType: "DocumentReference", - Role: TraversalRoleSpecimenDocumentReference, SetName: "specimen_document_reference_set", - }, - traversalKey("Group", "subject_Group", "DocumentReference"): { - FromType: "Group", EdgeLabel: "subject_Group", ToType: "DocumentReference", - Role: TraversalRoleGroupDocumentReference, SetName: "group_document_reference_set", - }, -} - -func field(resourceType, fieldRef, label string, sel fhirschema.FieldSelectorSpec) FieldSpec { - return FieldSpec{ - ResourceType: resourceType, - FieldRef: fieldRef, - Label: label, - Selector: sel, - } -} - -func normalizedField(resourceType, fieldRef, label string, sel fhirschema.FieldSelectorSpec, normalized string) FieldSpec { - spec := field(resourceType, fieldRef, label, sel) - spec.Normalization = NormalizationDocumentReferenceSummary - spec.NormalizedName = normalized - return spec -} - -func selector(sourcePath string, predicate *fhirschema.FieldPredicateSpec, valuePath string) fhirschema.FieldSelectorSpec { - return fhirschema.FieldSelectorSpec{ - SourcePath: strings.TrimSpace(sourcePath), - Where: predicate, - ValuePath: strings.TrimSpace(valuePath), - } -} - -func whereContains(path, value string) *fhirschema.FieldPredicateSpec { - return &fhirschema.FieldPredicateSpec{Path: path, Op: fhirschema.PredicateContains, Value: value} -} - -func traversalKey(fromType, edgeLabel, toType string) string { - return fromType + "|" + edgeLabel + "|" + toType -} - -func AliasesForResource(resourceType string) []AliasSpec { - specs := aliases[resourceType] - out := make([]AliasSpec, len(specs)) - copy(out, specs) - return out -} - -func ResolveFieldRef(resourceType, fieldRef string) (FieldSpec, bool) { - for _, spec := range aliases[resourceType] { - if spec.FieldRef == fieldRef { - return spec, true - } - } - return FieldSpec{}, false -} - -func ResolveTraversal(fromType, edgeLabel, toType string) (TraversalSpec, bool) { - spec, ok := traversals[traversalKey(fromType, edgeLabel, toType)] - return spec, ok -} - -func DocumentReferenceSummaryField(selectorExpr string) (string, bool) { - parsed, err := fhirschema.ParseSelector(selectorExpr) - if err != nil { - return "", false - } - for _, spec := range aliases["DocumentReference"] { - if spec.Normalization != NormalizationDocumentReferenceSummary || spec.NormalizedName == "" { - continue - } - if fhirschema.CanonicalPath(spec.Selector) != parsed.CanonicalPath() { - continue - } - if !samePredicate(spec.Selector.Where, parsed.Filter) { - continue - } - return spec.NormalizedName, true - } - return "", false -} - -func SelectorNeedsDocumentReferenceSummary(selectorExpr string) bool { - _, ok := DocumentReferenceSummaryField(selectorExpr) - return ok -} - -func RequiresResearchStudyHydration(selectorExpr string, fieldRef string) bool { - if strings.TrimSpace(fieldRef) == "ResearchSubject.study_ref" { - return false - } - parsed, err := fhirschema.ParseSelector(selectorExpr) - if err != nil { - return false - } - return strings.HasPrefix(parsed.CanonicalPath(), "study.") -} - -func samePredicate(a *fhirschema.FieldPredicateSpec, b *fhirschema.ContainsFilter) bool { - if a == nil && b == nil { - return true - } - if a == nil || b == nil { - return false - } - return strings.EqualFold(strings.TrimSpace(a.Path), strings.TrimSpace(b.Field)) && - strings.EqualFold(strings.TrimSpace(a.Op), fhirschema.PredicateContains) && - strings.TrimSpace(a.Value) == strings.TrimSpace(b.Needle) -} diff --git a/internal/fhirsemantics/registry_test.go b/internal/fhirsemantics/registry_test.go deleted file mode 100644 index ee247e7..0000000 --- a/internal/fhirsemantics/registry_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package fhirsemantics - -import ( - "testing" - - "arangodb-proto/internal/fhirschema" -) - -func TestResolveFieldRef(t *testing.T) { - spec, ok := ResolveFieldRef("Patient", "Patient.birth_sex") - if !ok { - t.Fatal("expected fieldRef to resolve") - } - if got := fhirschema.SelectorExpression(spec.Selector); got != `extension[].valueCode where url contains "us-core-birthsex"` { - t.Fatalf("unexpected selector expression: %q", got) - } - if got := fhirschema.CanonicalPath(spec.Selector); got != "extension[].valueCode" { - t.Fatalf("unexpected canonical path: %q", got) - } -} - -func TestDocumentReferenceSummaryField(t *testing.T) { - got, ok := DocumentReferenceSummaryField(`category[].coding[].display where system contains "workflow_type"`) - if !ok { - t.Fatal("expected selector to map to summary field") - } - if got != "workflow_type" { - t.Fatalf("unexpected summary field: %q", got) - } -} - -func TestResolveTraversal(t *testing.T) { - spec, ok := ResolveTraversal("Patient", "focus_Patient", "Observation") - if !ok { - t.Fatal("expected traversal to resolve") - } - if spec.Role != TraversalRolePatientDirectChild { - t.Fatalf("unexpected traversal role: %q", spec.Role) - } - if spec.SetName != "patient_focus_observation_set" { - t.Fatalf("unexpected set name: %q", spec.SetName) - } -} diff --git a/internal/graphqlapi/generated.go b/internal/graphqlapi/generated.go index b70652f..62d8281 100644 --- a/internal/graphqlapi/generated.go +++ b/internal/graphqlapi/generated.go @@ -3,13 +3,13 @@ package graphqlapi import ( - "arangodb-proto/internal/graphqlapi/model" "bytes" "context" "embed" "encoding/json" "errors" "fmt" + "github.com/calypr/loom/internal/graphqlapi/model" "strconv" "sync" "sync/atomic" diff --git a/internal/graphqlapi/handler.go b/internal/graphqlapi/handler.go index 3e980cc..1b7f102 100644 --- a/internal/graphqlapi/handler.go +++ b/internal/graphqlapi/handler.go @@ -2,7 +2,6 @@ package graphqlapi import ( "encoding/json" - "fmt" "html/template" "net/http" @@ -76,11 +75,3 @@ func NewApolloSandboxHandler(endpoint string) http.Handler { }) }) } - -func GraphQLEndpointForRequest(r *http.Request, path string) string { - scheme := "http" - if r.TLS != nil { - scheme = "https" - } - return fmt.Sprintf("%s://%s%s", scheme, r.Host, path) -} diff --git a/internal/graphqlapi/http_integration_test.go b/internal/graphqlapi/http_integration_test.go index 3a25084..c387b11 100644 --- a/internal/graphqlapi/http_integration_test.go +++ b/internal/graphqlapi/http_integration_test.go @@ -8,23 +8,26 @@ import ( "strings" "testing" - "arangodb-proto/internal/dataframe" - "arangodb-proto/internal/graphqlapi" - "arangodb-proto/internal/proto" - "arangodb-proto/internal/writeapi" + "github.com/calypr/loom/internal/api" + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/dataframe" + "github.com/calypr/loom/internal/graphqlapi" + "github.com/calypr/loom/internal/ingest" + arangostore "github.com/calypr/loom/internal/store/arango" ) func TestGraphQLIntrospectionEndpoint(t *testing.T) { - graphService := graphqlapi.NewService(graphqlapi.ServiceConfig{ - ConnectionOptions: proto.ConnectionOptions{Backend: "arango"}, - DiscoverReferences: func(ctx context.Context, opts proto.PopulatedReferenceOptions) ([]proto.PopulatedReference, error) { - return []proto.PopulatedReference{ + graphResolver := graphqlapi.NewResolver(graphqlapi.ResolverConfig{ + ConnectionOptions: arangostore.ConnectionOptions{}, + DiscoverReferences: func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + return []catalog.PopulatedReference{ {FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 10}, }, nil }, - DiscoverFields: func(ctx context.Context, opts proto.PopulatedFieldOptions) ([]proto.PopulatedField, error) { + DiscoverFields: func(ctx context.Context, opts catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { if opts.PivotOnly { - return []proto.PopulatedField{ + return []catalog.PopulatedField{ { ResourceType: "Patient", Path: "valueCodeableConcept", @@ -39,7 +42,7 @@ func TestGraphQLIntrospectionEndpoint(t *testing.T) { }, }, nil } - return []proto.PopulatedField{ + return []catalog.PopulatedField{ { ResourceType: "Patient", Path: "identifier[].value", @@ -54,16 +57,16 @@ func TestGraphQLIntrospectionEndpoint(t *testing.T) { }, nil }, }) - svc, err := writeapi.NewService(writeapi.ServiceConfig{ + svc, err := api.NewService(api.ServiceConfig{ Runner: fakeRunner{}, }) if err != nil { t.Fatal(err) } - server, err := writeapi.NewHTTPServer(writeapi.HTTPConfig{ + server, err := api.NewHTTPServer(api.HTTPConfig{ Service: svc, - Authenticator: writeapi.StaticAuthenticator{Principal: writeapi.Principal{Subject: "u1", Projects: []string{"P1"}, AuthResourcePaths: []string{"pathA"}}}, - GraphQLHandler: graphqlapi.NewHandler(graphqlapi.NewResolver(graphService)), + Authenticator: authscope.StaticAuthenticator{Principal: authscope.Principal{Subject: "u1", Projects: []string{"P1"}, AuthResourcePaths: []string{"pathA"}}}, + GraphQLHandler: graphqlapi.NewHandler(graphResolver), GraphQLPlaygroundHandler: graphqlapi.NewPlaygroundHandler("/graphql"), ApolloSandboxHandler: graphqlapi.NewApolloSandboxHandler("/graphql"), }) @@ -124,17 +127,17 @@ func TestGraphQLIntrospectionEndpoint(t *testing.T) { } func TestGraphQLSchemaIntrospectionEndpoint(t *testing.T) { - graphService := graphqlapi.NewService(graphqlapi.ServiceConfig{}) - svc, err := writeapi.NewService(writeapi.ServiceConfig{ + graphResolver := graphqlapi.NewResolver(graphqlapi.ResolverConfig{}) + svc, err := api.NewService(api.ServiceConfig{ Runner: fakeRunner{}, }) if err != nil { t.Fatal(err) } - server, err := writeapi.NewHTTPServer(writeapi.HTTPConfig{ + server, err := api.NewHTTPServer(api.HTTPConfig{ Service: svc, - Authenticator: writeapi.StaticAuthenticator{Principal: writeapi.Principal{Subject: "u1"}}, - GraphQLHandler: graphqlapi.NewHandler(graphqlapi.NewResolver(graphService)), + Authenticator: authscope.StaticAuthenticator{Principal: authscope.Principal{Subject: "u1"}}, + GraphQLHandler: graphqlapi.NewHandler(graphResolver), GraphQLPlaygroundHandler: graphqlapi.NewPlaygroundHandler("/graphql"), ApolloSandboxHandler: graphqlapi.NewApolloSandboxHandler("/graphql"), }) @@ -181,84 +184,84 @@ func TestGraphQLSchemaIntrospectionEndpoint(t *testing.T) { func TestGraphQLRunDataframeMutation(t *testing.T) { dfService := dataframe.NewService(dataframe.ServiceConfig{ - ConnectionOptions: proto.ConnectionOptions{Backend: "arango"}, - DiscoverFields: func(ctx context.Context, opts proto.PopulatedFieldOptions) ([]proto.PopulatedField, error) { + ConnectionOptions: arangostore.ConnectionOptions{}, + DiscoverFields: func(ctx context.Context, opts catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { switch opts.ResourceType { case "Patient": - return []proto.PopulatedField{ + return []catalog.PopulatedField{ {ResourceType: "Patient", Path: "gender", Kind: "scalar"}, {ResourceType: "Patient", Path: "id", Kind: "scalar"}, }, nil case "Condition": - return []proto.PopulatedField{ + return []catalog.PopulatedField{ {ResourceType: "Condition", Path: "id", Kind: "scalar"}, }, nil case "Specimen": - return []proto.PopulatedField{ + return []catalog.PopulatedField{ {ResourceType: "Specimen", Path: "type[].coding[].display", Kind: "scalar"}, }, nil default: - return []proto.PopulatedField{}, nil + return []catalog.PopulatedField{}, nil } }, - DiscoverReferences: func(ctx context.Context, opts proto.PopulatedReferenceOptions) ([]proto.PopulatedReference, error) { + DiscoverReferences: func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { if opts.NodeType == "Patient" { - return []proto.PopulatedReference{ + return []catalog.PopulatedReference{ {FromType: "Patient", Label: "subject_Patient", ToType: "Condition", EdgeCount: 1}, {FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 1}, }, nil } - return []proto.PopulatedReference{}, nil + return []catalog.PopulatedReference{}, nil }, - ExecuteRows: func(ctx context.Context, opts proto.ExecuteQueryOptions, query string, bindVars map[string]any, visit func(map[string]any) error) error { + ExecuteRows: func(ctx context.Context, opts dataframe.ExecuteQueryOptions, query string, bindVars map[string]any, visit func(map[string]any) error) error { if !strings.Contains(query, "LET root_patient_neighbor_set") || !strings.Contains(query, "LET patient_condition_set") { t.Fatalf("expected advanced lowered query, got:\n%s", query) } return visit(map[string]any{"_key": "p1", "gender": "female", "condition__condition_count": 1}) }, }) - graphService := graphqlapi.NewService(graphqlapi.ServiceConfig{ - ConnectionOptions: proto.ConnectionOptions{Backend: "arango"}, - DiscoverFields: func(ctx context.Context, opts proto.PopulatedFieldOptions) ([]proto.PopulatedField, error) { + graphResolver := graphqlapi.NewResolver(graphqlapi.ResolverConfig{ + ConnectionOptions: arangostore.ConnectionOptions{}, + DiscoverFields: func(ctx context.Context, opts catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { switch opts.ResourceType { case "Patient": - return []proto.PopulatedField{ + return []catalog.PopulatedField{ {ResourceType: "Patient", Path: "gender", Kind: "scalar"}, {ResourceType: "Patient", Path: "id", Kind: "scalar"}, }, nil case "Condition": - return []proto.PopulatedField{ + return []catalog.PopulatedField{ {ResourceType: "Condition", Path: "id", Kind: "scalar"}, }, nil case "Specimen": - return []proto.PopulatedField{ + return []catalog.PopulatedField{ {ResourceType: "Specimen", Path: "type[].coding[].display", Kind: "scalar"}, }, nil default: - return []proto.PopulatedField{}, nil + return []catalog.PopulatedField{}, nil } }, - DiscoverReferences: func(ctx context.Context, opts proto.PopulatedReferenceOptions) ([]proto.PopulatedReference, error) { + DiscoverReferences: func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { if opts.NodeType == "Patient" { - return []proto.PopulatedReference{ + return []catalog.PopulatedReference{ {FromType: "Patient", Label: "subject_Patient", ToType: "Condition", EdgeCount: 1}, {FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 1}, }, nil } - return []proto.PopulatedReference{}, nil + return []catalog.PopulatedReference{}, nil }, Dataframes: dfService, }) - svc, err := writeapi.NewService(writeapi.ServiceConfig{ + svc, err := api.NewService(api.ServiceConfig{ Runner: fakeRunner{}, }) if err != nil { t.Fatal(err) } - server, err := writeapi.NewHTTPServer(writeapi.HTTPConfig{ + server, err := api.NewHTTPServer(api.HTTPConfig{ Service: svc, - Authenticator: writeapi.StaticAuthenticator{Principal: writeapi.Principal{Subject: "u1", Projects: []string{"P1"}, AuthResourcePaths: []string{"pathA"}}}, - GraphQLHandler: graphqlapi.NewHandler(graphqlapi.NewResolver(graphService)), + Authenticator: authscope.StaticAuthenticator{Principal: authscope.Principal{Subject: "u1", Projects: []string{"P1"}, AuthResourcePaths: []string{"pathA"}}}, + GraphQLHandler: graphqlapi.NewHandler(graphResolver), GraphQLPlaygroundHandler: graphqlapi.NewPlaygroundHandler("/graphql"), ApolloSandboxHandler: graphqlapi.NewApolloSandboxHandler("/graphql"), }) @@ -282,9 +285,9 @@ func TestGraphQLRunDataframeMutation(t *testing.T) { var payload struct { Data struct { Run struct { - Columns []string `json:"columns"` - Rows []map[string]any `json:"rows"` - RowCount int `json:"rowCount"` + Columns []string `json:"columns"` + Rows []map[string]any `json:"rows"` + RowCount int `json:"rowCount"` } `json:"runFhirDataframe"` } `json:"data"` Errors []map[string]any `json:"errors"` @@ -302,20 +305,20 @@ func TestGraphQLRunDataframeMutation(t *testing.T) { func TestGraphQLRunDataframeTraversalBuilder(t *testing.T) { dfService := dataframe.NewService(dataframe.ServiceConfig{ - ConnectionOptions: proto.ConnectionOptions{Backend: "arango"}, - DiscoverFields: func(ctx context.Context, opts proto.PopulatedFieldOptions) ([]proto.PopulatedField, error) { + ConnectionOptions: arangostore.ConnectionOptions{}, + DiscoverFields: func(ctx context.Context, opts catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { switch opts.ResourceType { case "Patient": - return []proto.PopulatedField{{ResourceType: "Patient", Path: "gender", Kind: "scalar"}}, nil + return []catalog.PopulatedField{{ResourceType: "Patient", Path: "gender", Kind: "scalar"}}, nil case "Specimen": - return []proto.PopulatedField{{ResourceType: "Specimen", Path: "type[].coding[].display", Kind: "scalar"}}, nil + return []catalog.PopulatedField{{ResourceType: "Specimen", Path: "type[].coding[].display", Kind: "scalar"}}, nil default: - return []proto.PopulatedField{}, nil + return []catalog.PopulatedField{}, nil } }, - DiscoverReferences: func(ctx context.Context, opts proto.PopulatedReferenceOptions) ([]proto.PopulatedReference, error) { + DiscoverReferences: func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { if opts.NodeType == "Patient" { - return []proto.PopulatedReference{ + return []catalog.PopulatedReference{ { FromType: "Patient", Label: "subject_Patient", @@ -330,9 +333,9 @@ func TestGraphQLRunDataframeTraversalBuilder(t *testing.T) { }, }, nil } - return []proto.PopulatedReference{}, nil + return []catalog.PopulatedReference{}, nil }, - ExecuteRows: func(ctx context.Context, opts proto.ExecuteQueryOptions, query string, bindVars map[string]any, visit func(map[string]any) error) error { + ExecuteRows: func(ctx context.Context, opts dataframe.ExecuteQueryOptions, query string, bindVars map[string]any, visit func(map[string]any) error) error { if !strings.Contains(query, "LET root_patient_neighbor_set") || !strings.Contains(query, "LET patient_specimen_set") { t.Fatalf("expected advanced lowered query, got:\n%s", query) } @@ -344,23 +347,23 @@ func TestGraphQLRunDataframeTraversalBuilder(t *testing.T) { }) }, }) - graphService := graphqlapi.NewService(graphqlapi.ServiceConfig{ - ConnectionOptions: proto.ConnectionOptions{Backend: "arango"}, - DiscoverFields: func(ctx context.Context, opts proto.PopulatedFieldOptions) ([]proto.PopulatedField, error) { + graphResolver := graphqlapi.NewResolver(graphqlapi.ResolverConfig{ + ConnectionOptions: arangostore.ConnectionOptions{}, + DiscoverFields: func(ctx context.Context, opts catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { switch opts.ResourceType { case "Patient": - return []proto.PopulatedField{{ResourceType: "Patient", Path: "gender", Kind: "scalar"}}, nil + return []catalog.PopulatedField{{ResourceType: "Patient", Path: "gender", Kind: "scalar"}}, nil case "Specimen": - return []proto.PopulatedField{{ResourceType: "Specimen", Path: "type[].coding[].display", Kind: "scalar"}}, nil + return []catalog.PopulatedField{{ResourceType: "Specimen", Path: "type[].coding[].display", Kind: "scalar"}}, nil case "Condition": - return []proto.PopulatedField{{ResourceType: "Condition", Path: "id", Kind: "scalar"}}, nil + return []catalog.PopulatedField{{ResourceType: "Condition", Path: "id", Kind: "scalar"}}, nil default: - return []proto.PopulatedField{}, nil + return []catalog.PopulatedField{}, nil } }, - DiscoverReferences: func(ctx context.Context, opts proto.PopulatedReferenceOptions) ([]proto.PopulatedReference, error) { + DiscoverReferences: func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { if opts.NodeType == "Patient" { - return []proto.PopulatedReference{ + return []catalog.PopulatedReference{ { FromType: "Patient", Label: "subject_Patient", @@ -375,20 +378,20 @@ func TestGraphQLRunDataframeTraversalBuilder(t *testing.T) { }, }, nil } - return []proto.PopulatedReference{}, nil + return []catalog.PopulatedReference{}, nil }, Dataframes: dfService, }) - svc, err := writeapi.NewService(writeapi.ServiceConfig{ + svc, err := api.NewService(api.ServiceConfig{ Runner: fakeRunner{}, }) if err != nil { t.Fatal(err) } - server, err := writeapi.NewHTTPServer(writeapi.HTTPConfig{ + server, err := api.NewHTTPServer(api.HTTPConfig{ Service: svc, - Authenticator: writeapi.StaticAuthenticator{Principal: writeapi.Principal{Subject: "u1", Projects: []string{"P1"}, AuthResourcePaths: []string{"pathA"}}}, - GraphQLHandler: graphqlapi.NewHandler(graphqlapi.NewResolver(graphService)), + Authenticator: authscope.StaticAuthenticator{Principal: authscope.Principal{Subject: "u1", Projects: []string{"P1"}, AuthResourcePaths: []string{"pathA"}}}, + GraphQLHandler: graphqlapi.NewHandler(graphResolver), GraphQLPlaygroundHandler: graphqlapi.NewPlaygroundHandler("/graphql"), ApolloSandboxHandler: graphqlapi.NewApolloSandboxHandler("/graphql"), }) @@ -412,9 +415,9 @@ func TestGraphQLRunDataframeTraversalBuilder(t *testing.T) { var payload struct { Data struct { Run struct { - Columns []string `json:"columns"` - Rows []map[string]any `json:"rows"` - RowCount int `json:"rowCount"` + Columns []string `json:"columns"` + Rows []map[string]any `json:"rows"` + RowCount int `json:"rowCount"` } `json:"runFhirDataframe"` } `json:"data"` Errors []map[string]any `json:"errors"` @@ -432,6 +435,6 @@ func TestGraphQLRunDataframeTraversalBuilder(t *testing.T) { type fakeRunner struct{} -func (fakeRunner) Run(ctx context.Context, req writeapi.ImportRequest, sink proto.EventSink) (proto.LoadSummary, error) { - return proto.LoadSummary{}, nil +func (fakeRunner) Run(ctx context.Context, req api.ImportRequest, sink ingest.EventSink) (ingest.LoadSummary, error) { + return ingest.LoadSummary{}, nil } diff --git a/internal/graphqlapi/mappers.go b/internal/graphqlapi/mappers.go deleted file mode 100644 index 2a6cfb6..0000000 --- a/internal/graphqlapi/mappers.go +++ /dev/null @@ -1,355 +0,0 @@ -package graphqlapi - -import ( - "arangodb-proto/internal/dataframe" - "arangodb-proto/internal/graphqlapi/model" - "arangodb-proto/internal/proto" - "encoding/json" - "strings" -) - -func traversalHints(in []proto.PopulatedReference) []*model.DataframeTraversalHint { - if len(in) == 0 { - return []*model.DataframeTraversalHint{} - } - out := make([]*model.DataframeTraversalHint, 0, len(in)) - for _, item := range in { - out = append(out, &model.DataframeTraversalHint{ - FromType: item.FromType, - Label: item.Label, - ToType: item.ToType, - EdgeCount: int(item.EdgeCount), - }) - } - return out -} - -func fieldHints(in []FieldHintResponse) []*model.DataframeFieldHint { - if len(in) == 0 { - return []*model.DataframeFieldHint{} - } - out := make([]*model.DataframeFieldHint, 0, len(in)) - for _, item := range in { - pivotKind := item.PivotKind - var pivotKindPtr *string - if pivotKind != "" { - pivotKindPtr = &pivotKind - } - var pivotFamily *model.FhirPivotFamily - if item.PivotFamily != "" { - pf := model.FhirPivotFamily(item.PivotFamily) - pivotFamily = &pf - } - var predicate *model.DataframeFieldPredicate - if item.Selector.Where != nil { - predicate = &model.DataframeFieldPredicate{ - Path: item.Selector.Where.Path, - Op: model.FhirFieldPredicateOperation(item.Selector.Where.Op), - Value: item.Selector.Where.Value, - } - } - out = append(out, &model.DataframeFieldHint{ - ResourceType: item.ResourceType, - FieldRef: item.FieldRef, - Label: item.Label, - Path: item.Path, - Selector: &model.DataframeFieldSelector{ - SourcePath: optionalString(item.Selector.SourcePath), - Where: predicate, - ValuePath: item.Selector.ValuePath, - }, - Kind: item.Kind, - DocCount: int(item.DocCount), - SampleCount: item.SampleCount, - DistinctValues: cloneStrings(item.DistinctValues), - DistinctTruncated: item.DistinctTruncated, - PivotCandidate: item.PivotCandidate, - PivotKind: pivotKindPtr, - PivotColumns: cloneStrings(item.PivotColumns), - PivotFamily: pivotFamily, - DefaultPivotColumnSelector: selectorModelFromExpression(item.PivotColumnSelect), - DefaultPivotValueSelector: selectorModelFromExpression(item.PivotValueSelect), - }) - } - return out -} - -func resourceHints(in ResourceHintsResponse) *model.DataframeResourceHints { - return &model.DataframeResourceHints{ - ResourceType: in.ResourceType, - Fields: fieldHints(in.Fields), - PivotFields: fieldHints(in.PivotFields), - Traversals: traversalHints(in.Traversals), - } -} - -func relatedResourceHints(in []RelatedResourceHintsResponse) []*model.DataframeRelatedResourceHints { - if len(in) == 0 { - return []*model.DataframeRelatedResourceHints{} - } - out := make([]*model.DataframeRelatedResourceHints, 0, len(in)) - for _, item := range in { - out = append(out, &model.DataframeRelatedResourceHints{ - ViaLabel: item.ViaLabel, - EdgeCount: int(item.EdgeCount), - Target: resourceHints(item.Target), - }) - } - return out -} - -func cloneStrings(in []string) []string { - if len(in) == 0 { - return []string{} - } - return append([]string(nil), in...) -} - -func cloneRows(in []map[string]any) []map[string]any { - if len(in) == 0 { - return []map[string]any{} - } - out := make([]map[string]any, 0, len(in)) - for _, row := range in { - cloned := make(map[string]any, len(row)) - for k, v := range row { - cloned[k] = v - } - out = append(out, cloned) - } - return out -} - -func graphqlRows(in []map[string]any) json.RawMessage { - rows := cloneRows(in) - if len(rows) == 0 { - return json.RawMessage("[]") - } - encoded, err := json.Marshal(rows) - if err != nil { - return json.RawMessage("[]") - } - return json.RawMessage(encoded) -} - -func builderFromInput(in model.FhirDataframeInput) dataframe.Builder { - authResourcePaths := cloneStrings(in.AuthResourcePaths) - if len(authResourcePaths) == 0 && strings.TrimSpace(derefString(in.AuthResourcePath)) != "" { - authResourcePaths = []string{strings.TrimSpace(derefString(in.AuthResourcePath))} - } - return dataframe.Builder{ - Project: in.Project, - AuthResourcePaths: authResourcePaths, - RootResourceType: in.RootResourceType, - Fields: fieldSelectsFromModel(in.RootFields), - Pivots: pivotSelectsFromModel(in.RootPivots), - Aggregates: aggregateSelectsFromModel(in.RootAggregates), - Slices: sliceSelectsFromModel(in.RootSlices), - Traversals: traversalStepsFromModel(in.Traverse), - } -} - -func fieldSelectsFromModel(in []*model.FhirFieldSelectInput) []dataframe.FieldSelect { - if len(in) == 0 { - return []dataframe.FieldSelect{} - } - out := make([]dataframe.FieldSelect, 0, len(in)) - for _, item := range in { - if item == nil { - continue - } - selectText := "" - if item.Selector != nil { - selectText = composeSelector( - derefString(item.Selector.SourcePath), - predicatePathFromInput(item.Selector.Where), - predicateOpFromInput(item.Selector.Where), - predicateValueFromInput(item.Selector.Where), - item.Selector.ValuePath, - ) - } - fallbackSelectors := make([]string, 0, len(item.FallbackSelectors)) - for _, fallback := range item.FallbackSelectors { - if fallback == nil { - continue - } - fallbackSelectors = append(fallbackSelectors, composeSelector( - derefString(fallback.SourcePath), - predicatePathFromInput(fallback.Where), - predicateOpFromInput(fallback.Where), - predicateValueFromInput(fallback.Where), - fallback.ValuePath, - )) - } - out = append(out, dataframe.FieldSelect{ - Name: item.Name, - FieldRef: derefString(item.FieldRef), - Select: selectText, - FallbackFieldRefs: cloneStrings(item.FallbackFieldRefs), - FallbackSelects: fallbackSelectors, - ValueMode: item.ValueMode.String(), - }) - } - return out -} - -func pivotSelectsFromModel(in []*model.FhirPivotInput) []dataframe.PivotSelect { - if len(in) == 0 { - return []dataframe.PivotSelect{} - } - out := make([]dataframe.PivotSelect, 0, len(in)) - for _, item := range in { - if item == nil { - continue - } - out = append(out, dataframe.PivotSelect{ - Name: item.Name, - FieldRef: derefString(item.FieldRef), - ColumnSelect: composeSelectorFromInput(item.ColumnSelector), - ValueSelect: composeSelectorFromInput(item.ValueSelector), - Columns: cloneStrings(item.Columns), - }) - } - return out -} - -func selectorModelFromExpression(expression string) *model.DataframeFieldSelector { - if strings.TrimSpace(expression) == "" { - return nil - } - parts := decomposeSelector(expression) - var predicate *model.DataframeFieldPredicate - if parts.Where != nil { - predicate = &model.DataframeFieldPredicate{ - Path: parts.Where.Path, - Op: model.FhirFieldPredicateOperation(parts.Where.Op), - Value: parts.Where.Value, - } - } - return &model.DataframeFieldSelector{ - SourcePath: optionalString(parts.SourcePath), - Where: predicate, - ValuePath: parts.ValuePath, - } -} - -func composeSelectorFromInput(in *model.FhirFieldSelectorInput) string { - if in == nil { - return "" - } - return composeSelector( - derefString(in.SourcePath), - predicatePathFromInput(in.Where), - predicateOpFromInput(in.Where), - predicateValueFromInput(in.Where), - in.ValuePath, - ) -} - -func aggregateSelectsFromModel(in []*model.FhirAggregateInput) []dataframe.AggregateSelect { - if len(in) == 0 { - return []dataframe.AggregateSelect{} - } - out := make([]dataframe.AggregateSelect, 0, len(in)) - for _, item := range in { - if item == nil { - continue - } - operation := item.Operation.String() - out = append(out, dataframe.AggregateSelect{ - Name: item.Name, - Operation: operation, - FieldRef: strings.TrimSpace(derefString(item.FieldRef)), - Select: strings.TrimSpace(derefString(item.FhirPath)), - PredicateFieldRef: strings.TrimSpace(derefString(item.PredicateFieldRef)), - PredicatePath: strings.TrimSpace(derefString(item.PredicatePath)), - PredicateEquals: derefString(item.PredicateEquals), - ValueMode: item.ValueMode.String(), - }) - } - return out -} - -func sliceSelectsFromModel(in []*model.FhirRepresentativeSliceInput) []dataframe.RepresentativeSlice { - if len(in) == 0 { - return []dataframe.RepresentativeSlice{} - } - out := make([]dataframe.RepresentativeSlice, 0, len(in)) - for _, item := range in { - if item == nil { - continue - } - out = append(out, dataframe.RepresentativeSlice{ - Name: item.Name, - Limit: item.Limit, - PredicateFieldRef: strings.TrimSpace(derefString(item.WhereFieldRef)), - PredicatePath: strings.TrimSpace(derefString(item.WherePath)), - PredicateEquals: derefString(item.WhereEquals), - Fields: fieldSelectsFromModel(item.Fields), - }) - } - return out -} - -func traversalStepsFromModel(in []*model.FhirTraversalStepInput) []dataframe.TraversalStep { - if len(in) == 0 { - return []dataframe.TraversalStep{} - } - out := make([]dataframe.TraversalStep, 0, len(in)) - for _, item := range in { - if item == nil { - continue - } - out = append(out, dataframe.TraversalStep{ - Label: item.EdgeLabel, - ToResourceType: item.ToResourceType, - Alias: item.Alias, - Fields: fieldSelectsFromModel(item.Fields), - Pivots: pivotSelectsFromModel(item.Pivots), - Aggregates: aggregateSelectsFromModel(item.Aggregates), - Slices: sliceSelectsFromModel(item.Slices), - Traversals: traversalStepsFromModel(item.Traverse), - }) - } - return out -} - -func derefString(in *string) string { - if in == nil { - return "" - } - return *in -} - -func derefBool(in *bool) bool { - return in != nil && *in -} - -func optionalString(in string) *string { - in = strings.TrimSpace(in) - if in == "" { - return nil - } - return &in -} - -func predicatePathFromInput(in *model.FhirFieldPredicateInput) string { - if in == nil { - return "" - } - return in.Path -} - -func predicateOpFromInput(in *model.FhirFieldPredicateInput) string { - if in == nil { - return "" - } - return in.Op.String() -} - -func predicateValueFromInput(in *model.FhirFieldPredicateInput) string { - if in == nil { - return "" - } - return in.Value -} diff --git a/internal/graphqlapi/output_mapping.go b/internal/graphqlapi/output_mapping.go new file mode 100644 index 0000000..8637f48 --- /dev/null +++ b/internal/graphqlapi/output_mapping.go @@ -0,0 +1,166 @@ +package graphqlapi + +import ( + "encoding/json" + "strings" + + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/dataframebuilder" + "github.com/calypr/loom/internal/graphqlapi/model" +) + +func traversalHints(in []catalog.PopulatedReference) []*model.DataframeTraversalHint { + if len(in) == 0 { + return []*model.DataframeTraversalHint{} + } + out := make([]*model.DataframeTraversalHint, 0, len(in)) + for _, item := range in { + out = append(out, &model.DataframeTraversalHint{ + FromType: item.FromType, + Label: item.Label, + ToType: item.ToType, + EdgeCount: int(item.EdgeCount), + }) + } + return out +} + +func fieldHints(in []dataframebuilder.FieldHint) []*model.DataframeFieldHint { + if len(in) == 0 { + return []*model.DataframeFieldHint{} + } + out := make([]*model.DataframeFieldHint, 0, len(in)) + for _, item := range in { + pivotKind := item.PivotKind + var pivotKindPtr *string + if pivotKind != "" { + pivotKindPtr = &pivotKind + } + + var pivotFamily *model.FhirPivotFamily + if item.PivotFamily != "" { + family := model.FhirPivotFamily(item.PivotFamily) + pivotFamily = &family + } + + var predicate *model.DataframeFieldPredicate + if item.Selector.Where != nil { + predicate = &model.DataframeFieldPredicate{ + Path: item.Selector.Where.Path, + Op: model.FhirFieldPredicateOperation(item.Selector.Where.Op), + Value: item.Selector.Where.Value, + } + } + + out = append(out, &model.DataframeFieldHint{ + ResourceType: item.ResourceType, + FieldRef: item.FieldRef, + Label: item.Label, + Path: item.Path, + Selector: &model.DataframeFieldSelector{ + SourcePath: optionalString(item.Selector.SourcePath), + Where: predicate, + ValuePath: item.Selector.ValuePath, + }, + Kind: item.Kind, + DocCount: int(item.DocCount), + SampleCount: item.SampleCount, + DistinctValues: cloneStrings(item.DistinctValues), + DistinctTruncated: item.DistinctTruncated, + PivotCandidate: item.PivotCandidate, + PivotKind: pivotKindPtr, + PivotColumns: cloneStrings(item.PivotColumns), + PivotFamily: pivotFamily, + DefaultPivotColumnSelector: selectorModelFromExpression(item.PivotColumnSelect), + DefaultPivotValueSelector: selectorModelFromExpression(item.PivotValueSelect), + }) + } + return out +} + +func resourceHints(in dataframebuilder.ResourceHints) *model.DataframeResourceHints { + return &model.DataframeResourceHints{ + ResourceType: in.ResourceType, + Fields: fieldHints(in.Fields), + PivotFields: fieldHints(in.PivotFields), + Traversals: traversalHints(in.Traversals), + } +} + +func relatedResourceHints(in []dataframebuilder.RelatedResourceHints) []*model.DataframeRelatedResourceHints { + if len(in) == 0 { + return []*model.DataframeRelatedResourceHints{} + } + out := make([]*model.DataframeRelatedResourceHints, 0, len(in)) + for _, item := range in { + out = append(out, &model.DataframeRelatedResourceHints{ + ViaLabel: item.ViaLabel, + EdgeCount: int(item.EdgeCount), + Target: resourceHints(item.Target), + }) + } + return out +} + +func selectorModelFromExpression(expression string) *model.DataframeFieldSelector { + if strings.TrimSpace(expression) == "" { + return nil + } + parts := dataframebuilder.DecomposeSelector(expression) + + var predicate *model.DataframeFieldPredicate + if parts.Where != nil { + predicate = &model.DataframeFieldPredicate{ + Path: parts.Where.Path, + Op: model.FhirFieldPredicateOperation(parts.Where.Op), + Value: parts.Where.Value, + } + } + + return &model.DataframeFieldSelector{ + SourcePath: optionalString(parts.SourcePath), + Where: predicate, + ValuePath: parts.ValuePath, + } +} + +func graphqlRows(in []map[string]any) json.RawMessage { + if len(in) == 0 { + return json.RawMessage("[]") + } + rows := make([]map[string]any, 0, len(in)) + for _, row := range in { + cloned := make(map[string]any, len(row)) + for k, v := range row { + cloned[k] = v + } + rows = append(rows, cloned) + } + encoded, err := json.Marshal(rows) + if err != nil { + return json.RawMessage("[]") + } + return json.RawMessage(encoded) +} + +func cloneStrings(in []string) []string { + if len(in) == 0 { + return []string{} + } + return append([]string(nil), in...) +} + +func cloneTraversals(in []catalog.PopulatedReference) []catalog.PopulatedReference { + if len(in) == 0 { + return []catalog.PopulatedReference{} + } + return append([]catalog.PopulatedReference(nil), in...) +} + +func optionalString(in string) *string { + in = strings.TrimSpace(in) + if in == "" { + return nil + } + return &in +} diff --git a/internal/graphqlapi/resolver.go b/internal/graphqlapi/resolver.go index 4d4d961..b03c807 100644 --- a/internal/graphqlapi/resolver.go +++ b/internal/graphqlapi/resolver.go @@ -1,10 +1,13 @@ package graphqlapi -// Resolver wires gqlgen resolvers onto the dataframe builder service layer. +import "github.com/calypr/loom/internal/dataframebuilder" + type Resolver struct { - Service *Service + service *dataframebuilder.Service } -func NewResolver(service *Service) *Resolver { - return &Resolver{Service: service} +type ResolverConfig = dataframebuilder.Config + +func NewResolver(cfg ResolverConfig) *Resolver { + return &Resolver{service: dataframebuilder.NewService(cfg)} } diff --git a/internal/graphqlapi/schema.resolvers.go b/internal/graphqlapi/schema.resolvers.go index de7ff42..6fe92bb 100644 --- a/internal/graphqlapi/schema.resolvers.go +++ b/internal/graphqlapi/schema.resolvers.go @@ -5,27 +5,14 @@ package graphqlapi // Code generated by github.com/99designs/gqlgen version v0.17.66 import ( - "arangodb-proto/internal/dataframe" - "arangodb-proto/internal/graphqlapi/model" "context" + "github.com/calypr/loom/internal/dataframebuilder" + "github.com/calypr/loom/internal/graphqlapi/model" ) // RunFhirDataframe is the resolver for the runFhirDataframe field. func (r *mutationResolver) RunFhirDataframe(ctx context.Context, input model.FhirDataframeInput, limit *int) (*model.FhirDataframeResult, error) { - normalizedInput, err := r.Service.PrepareRunInput(ctx, input) - if err != nil { - return nil, err - } - rowLimit := 0 - if limit != nil { - rowLimit = *limit - } else if normalizedInput.Limit != nil { - rowLimit = *normalizedInput.Limit - } - result, err := r.Service.RunDataframe(ctx, dataframe.RunRequest{ - Builder: builderFromInput(normalizedInput), - Limit: rowLimit, - }) + result, err := r.service.Run(ctx, input, limit) if err != nil { return nil, err } @@ -42,7 +29,7 @@ func (r *queryResolver) DataframeBuilderIntrospection(ctx context.Context, input if input.IncludePivotOnlyFields != nil { includePivotOnlyFields = *input.IncludePivotOnlyFields } - resp, err := r.Service.Introspect(ctx, IntrospectionRequest{ + resp, err := r.service.Introspect(ctx, dataframebuilder.IntrospectionRequest{ Project: input.Project, RootResourceType: input.RootResourceType, AuthResourcePaths: input.AuthResourcePaths, diff --git a/internal/graphqlapi/service.go b/internal/graphqlapi/service.go deleted file mode 100644 index e070d40..0000000 --- a/internal/graphqlapi/service.go +++ /dev/null @@ -1,456 +0,0 @@ -package graphqlapi - -import ( - "context" - "fmt" - "strings" - - "arangodb-proto/internal/dataframe" - "arangodb-proto/internal/fhirschema" - "arangodb-proto/internal/fhirsemantics" - "arangodb-proto/internal/graphqlapi/model" - "arangodb-proto/internal/proto" - "arangodb-proto/internal/writeapi" -) - -type ServiceConfig struct { - ConnectionOptions proto.ConnectionOptions - DiscoverReferences func(context.Context, proto.PopulatedReferenceOptions) ([]proto.PopulatedReference, error) - DiscoverFields func(context.Context, proto.PopulatedFieldOptions) ([]proto.PopulatedField, error) - Dataframes *dataframe.Service - ScopeResolver *writeapi.ScopeResolver -} - -type Service struct { - connOpts proto.ConnectionOptions - discoverReferences func(context.Context, proto.PopulatedReferenceOptions) ([]proto.PopulatedReference, error) - discoverFields func(context.Context, proto.PopulatedFieldOptions) ([]proto.PopulatedField, error) - dataframes *dataframe.Service - scopeResolver *writeapi.ScopeResolver -} - -type IntrospectionRequest struct { - Project string - RootResourceType string - AuthResourcePaths []string - IncludePivotOnlyFields bool -} - -type IntrospectionResponse struct { - Project string - RootResourceType string - AuthResourcePaths []string - Root ResourceHintsResponse - RelatedResources []RelatedResourceHintsResponse - Traversals []proto.PopulatedReference - Fields []FieldHintResponse - PivotFields []FieldHintResponse -} - -type ResourceHintsResponse struct { - ResourceType string - Fields []FieldHintResponse - PivotFields []FieldHintResponse - Traversals []proto.PopulatedReference -} - -type RelatedResourceHintsResponse struct { - ViaLabel string - EdgeCount int64 - Target ResourceHintsResponse -} - -func NewService(cfg ServiceConfig) *Service { - svc := &Service{ - connOpts: cfg.ConnectionOptions, - scopeResolver: cfg.ScopeResolver, - } - if cfg.DiscoverReferences != nil { - svc.discoverReferences = cfg.DiscoverReferences - } else { - svc.discoverReferences = proto.DiscoverPopulatedReferences - } - if cfg.DiscoverFields != nil { - svc.discoverFields = cfg.DiscoverFields - } else { - svc.discoverFields = proto.DiscoverPopulatedFields - } - if cfg.Dataframes != nil { - svc.dataframes = cfg.Dataframes - } else { - svc.dataframes = dataframe.NewService(dataframe.ServiceConfig{ - ConnectionOptions: cfg.ConnectionOptions, - DiscoverReferences: svc.discoverReferences, - DiscoverFields: svc.discoverFields, - ScopeResolver: cfg.ScopeResolver, - }) - } - return svc -} - -func (s *Service) Introspect(ctx context.Context, req IntrospectionRequest) (*IntrospectionResponse, error) { - if req.Project == "" { - return nil, fmt.Errorf("project is required") - } - if req.RootResourceType == "" { - return nil, fmt.Errorf("rootResourceType is required") - } - - principal, _ := writeapi.PrincipalFromContext(ctx) - resolvedPaths, err := s.resolveAuthResourcePaths(ctx, principal, req.Project, req.AuthResourcePaths) - if err != nil { - return nil, err - } - if err := authorizeProject(principal, req.Project, s.scopeResolver != nil); err != nil { - return nil, err - } - - traversals, err := s.discoverReferences(ctx, proto.PopulatedReferenceOptions{ - ConnectionOptions: s.connOpts, - Project: req.Project, - AuthResourcePaths: resolvedPaths, - NodeType: req.RootResourceType, - Mode: proto.TraversalModeBuilder, - }) - if err != nil { - return nil, err - } - - rootHints, err := s.buildResourceHints(ctx, req.Project, resolvedPaths, req.RootResourceType, traversals, req.IncludePivotOnlyFields) - if err != nil { - return nil, err - } - relatedHints, err := s.buildRelatedResourceHints(ctx, req.Project, resolvedPaths, traversals, req.IncludePivotOnlyFields) - if err != nil { - return nil, err - } - - return &IntrospectionResponse{ - Project: req.Project, - RootResourceType: req.RootResourceType, - AuthResourcePaths: resolvedPaths, - Root: rootHints, - RelatedResources: relatedHints, - Traversals: normalizeTraversalSlice(rootHints.Traversals), - Fields: rootHints.Fields, - PivotFields: rootHints.PivotFields, - }, nil -} - -func (s *Service) buildResourceHints(ctx context.Context, project string, authResourcePaths []string, resourceType string, traversals []proto.PopulatedReference, includePivotOnlyFields bool) (ResourceHintsResponse, error) { - fields, err := s.discoverFields(ctx, proto.PopulatedFieldOptions{ - ConnectionOptions: s.connOpts, - Project: project, - AuthResourcePaths: authResourcePaths, - ResourceType: resourceType, - PivotOnly: false, - }) - if err != nil { - return ResourceHintsResponse{}, err - } - pivotFields := []proto.PopulatedField{} - if includePivotOnlyFields { - pivotFields, err = s.discoverFields(ctx, proto.PopulatedFieldOptions{ - ConnectionOptions: s.connOpts, - Project: project, - AuthResourcePaths: authResourcePaths, - ResourceType: resourceType, - PivotOnly: true, - }) - if err != nil { - return ResourceHintsResponse{}, err - } - } - return ResourceHintsResponse{ - ResourceType: resourceType, - Fields: discoveredFieldHints(resourceType, normalizeFieldSlice(fields)), - PivotFields: discoveredFieldHints(resourceType, normalizeFieldSlice(pivotFields)), - Traversals: normalizeTraversalSlice(traversals), - }, nil -} - -func (s *Service) buildRelatedResourceHints(ctx context.Context, project string, authResourcePaths []string, traversals []proto.PopulatedReference, includePivotOnlyFields bool) ([]RelatedResourceHintsResponse, error) { - if len(traversals) == 0 { - return []RelatedResourceHintsResponse{}, nil - } - typeCache := map[string]ResourceHintsResponse{} - out := make([]RelatedResourceHintsResponse, 0, len(traversals)) - for _, ref := range traversals { - target, ok := typeCache[ref.ToType] - if !ok { - hints, err := s.buildResourceHints(ctx, project, authResourcePaths, ref.ToType, nil, includePivotOnlyFields) - if err != nil { - return nil, err - } - typeCache[ref.ToType] = hints - target = hints - } - out = append(out, RelatedResourceHintsResponse{ - ViaLabel: ref.Label, - EdgeCount: ref.EdgeCount, - Target: target, - }) - } - return out, nil -} - -func normalizeTraversalSlice(in []proto.PopulatedReference) []proto.PopulatedReference { - if len(in) == 0 { - return []proto.PopulatedReference{} - } - return in -} - -func normalizeFieldSlice(in []proto.PopulatedField) []proto.PopulatedField { - if len(in) == 0 { - return []proto.PopulatedField{} - } - for i := range in { - if in[i].DistinctValues == nil { - in[i].DistinctValues = []string{} - } - if in[i].PivotColumns == nil { - in[i].PivotColumns = []string{} - } - } - return in -} - -func (s *Service) RunDataframe(ctx context.Context, req dataframe.RunRequest) (*dataframe.Result, error) { - return s.dataframes.Run(ctx, req) -} - -func (s *Service) PrepareRunInput(ctx context.Context, input model.FhirDataframeInput) (model.FhirDataframeInput, error) { - if input.Project == "" { - return input, fmt.Errorf("project is required") - } - if input.RootResourceType == "" { - return input, fmt.Errorf("rootResourceType is required") - } - principal, _ := writeapi.PrincipalFromContext(ctx) - resolvedPaths, err := s.resolveAuthResourcePaths(ctx, principal, input.Project, input.AuthResourcePaths) - if err != nil { - return input, err - } - if err := authorizeProject(principal, input.Project, s.scopeResolver != nil); err != nil { - return input, err - } - input.AuthResourcePaths = resolvedPaths - if len(input.AuthResourcePaths) == 0 { - input.AuthResourcePaths = nil - } - if err := s.resolveNodeInputRefs(ctx, input.Project, input.AuthResourcePaths, input.RootResourceType, input.RootFields, input.RootPivots, input.RootAggregates, input.RootSlices); err != nil { - return input, err - } - for _, step := range input.Traverse { - if err := s.resolveTraversalInputRefs(ctx, input.Project, input.AuthResourcePaths, step); err != nil { - return input, err - } - } - return input, nil -} - -func (s *Service) resolveTraversalInputRefs(ctx context.Context, project string, authResourcePaths []string, step *model.FhirTraversalStepInput) error { - if step == nil { - return nil - } - if err := s.resolveNodeInputRefs(ctx, project, authResourcePaths, step.ToResourceType, step.Fields, step.Pivots, step.Aggregates, step.Slices); err != nil { - return err - } - for _, child := range step.Traverse { - if err := s.resolveTraversalInputRefs(ctx, project, authResourcePaths, child); err != nil { - return err - } - } - return nil -} - -func (s *Service) resolveNodeInputRefs(ctx context.Context, project string, authResourcePaths []string, resourceType string, fields []*model.FhirFieldSelectInput, pivots []*model.FhirPivotInput, aggregates []*model.FhirAggregateInput, slices []*model.FhirRepresentativeSliceInput) error { - discovered, err := s.discoverFields(ctx, proto.PopulatedFieldOptions{ - ConnectionOptions: s.connOpts, - Project: project, - AuthResourcePaths: authResourcePaths, - ResourceType: resourceType, - }) - if err != nil { - return err - } - for _, field := range fields { - if field == nil { - continue - } - if strings.TrimSpace(derefString(field.FieldRef)) != "" { - selectorText, err := resolveFieldRef(resourceType, discovered, derefString(field.FieldRef)) - if err != nil { - return err - } - field.Selector = selectorInputFromExpression(selectorText) - } - if len(field.FallbackFieldRefs) > 0 { - fallbacks := make([]*model.FhirFieldSelectorInput, 0, len(field.FallbackFieldRefs)) - for _, ref := range field.FallbackFieldRefs { - selectorText, err := resolveFieldRef(resourceType, discovered, ref) - if err != nil { - return err - } - fallbacks = append(fallbacks, selectorInputFromExpression(selectorText)) - } - field.FallbackSelectors = fallbacks - } - } - for _, pivot := range pivots { - if pivot == nil { - continue - } - if strings.TrimSpace(derefString(pivot.FieldRef)) != "" { - hint, err := resolvePivotFieldRef(resourceType, discovered, derefString(pivot.FieldRef)) - if err != nil { - return err - } - if pivot.ColumnSelector == nil { - pivot.ColumnSelector = selectorInputFromExpression(hint.PivotColumnSelect) - } - if pivot.ValueSelector == nil { - pivot.ValueSelector = selectorInputFromExpression(hint.PivotValueSelect) - } - } - } - for _, aggregate := range aggregates { - if aggregate == nil { - continue - } - if strings.TrimSpace(derefString(aggregate.FieldRef)) != "" { - selector, err := resolveFieldRef(resourceType, discovered, derefString(aggregate.FieldRef)) - if err != nil { - return err - } - aggregate.FhirPath = &selector - } - if strings.TrimSpace(derefString(aggregate.PredicateFieldRef)) != "" { - selector, err := resolveFieldRef(resourceType, discovered, derefString(aggregate.PredicateFieldRef)) - if err != nil { - return err - } - aggregate.PredicatePath = &selector - } - } - for _, slice := range slices { - if slice == nil { - continue - } - if strings.TrimSpace(derefString(slice.WhereFieldRef)) != "" { - selector, err := resolveFieldRef(resourceType, discovered, derefString(slice.WhereFieldRef)) - if err != nil { - return err - } - slice.WherePath = &selector - } - for _, field := range slice.Fields { - if field == nil { - continue - } - if strings.TrimSpace(derefString(field.FieldRef)) != "" { - selectorText, err := resolveFieldRef(resourceType, discovered, derefString(field.FieldRef)) - if err != nil { - return err - } - field.Selector = selectorInputFromExpression(selectorText) - } - if len(field.FallbackFieldRefs) > 0 { - fallbacks := make([]*model.FhirFieldSelectorInput, 0, len(field.FallbackFieldRefs)) - for _, ref := range field.FallbackFieldRefs { - selectorText, err := resolveFieldRef(resourceType, discovered, ref) - if err != nil { - return err - } - fallbacks = append(fallbacks, selectorInputFromExpression(selectorText)) - } - field.FallbackSelectors = fallbacks - } - } - } - return nil -} - -func resolvePivotFieldRef(resourceType string, discovered []proto.PopulatedField, fieldRef string) (proto.PopulatedField, error) { - fieldRef = strings.TrimSpace(fieldRef) - if fieldRef == "" { - return proto.PopulatedField{}, fmt.Errorf("fieldRef is required") - } - if spec, ok := fhirsemantics.ResolveFieldRef(resourceType, fieldRef); ok { - base := findFieldByPath(discovered, fhirschema.CanonicalPath(spec.Selector)) - if base != nil { - return *base, nil - } - } - for _, field := range discovered { - if defaultFieldRef(resourceType, field.Path) == fieldRef { - return field, nil - } - } - return proto.PopulatedField{}, fmt.Errorf("unknown pivot fieldRef %q for resourceType %q", fieldRef, resourceType) -} - -func authorizeProject(principal *writeapi.Principal, project string, ignorePrincipalProjects bool) error { - if ignorePrincipalProjects { - return nil - } - if principal == nil || len(principal.Projects) == 0 { - return nil - } - for _, candidate := range principal.Projects { - if candidate == project { - return nil - } - } - return fmt.Errorf("principal is not authorized for project %q", project) -} - -func (s *Service) resolveAuthResourcePaths(ctx context.Context, principal *writeapi.Principal, project string, requested []string) ([]string, error) { - if s.scopeResolver != nil { - return s.scopeResolver.ResolveReadAuthResourcePaths(ctx, principal, project, requested) - } - if len(requested) == 0 { - if principal == nil || len(principal.AuthResourcePaths) == 0 { - return nil, nil - } - return append([]string(nil), principal.AuthResourcePaths...), nil - } - if principal == nil || len(principal.AuthResourcePaths) == 0 { - return append([]string(nil), requested...), nil - } - for _, path := range requested { - found := false - for _, candidate := range principal.AuthResourcePaths { - if candidate == path { - found = true - break - } - } - if !found { - return nil, fmt.Errorf("authResourcePath %q is outside caller scope", path) - } - } - return append([]string(nil), requested...), nil -} - -func selectorInputFromExpression(expression string) *model.FhirFieldSelectorInput { - parts := decomposeSelector(expression) - var where *model.FhirFieldPredicateInput - if parts.Where != nil { - where = &model.FhirFieldPredicateInput{ - Path: parts.Where.Path, - Op: model.FhirFieldPredicateOperation(parts.Where.Op), - Value: parts.Where.Value, - } - } - var sourcePath *string - if trimmed := strings.TrimSpace(parts.SourcePath); trimmed != "" { - sourcePath = &trimmed - } - return &model.FhirFieldSelectorInput{ - SourcePath: sourcePath, - Where: where, - ValuePath: parts.ValuePath, - } -} diff --git a/internal/proto/backend.go b/internal/ingest/backend.go similarity index 50% rename from internal/proto/backend.go rename to internal/ingest/backend.go index 9b7fd22..25f5ba7 100644 --- a/internal/proto/backend.go +++ b/internal/ingest/backend.go @@ -1,38 +1,22 @@ -package proto +package ingest import ( "context" "encoding/json" - "arangodb-proto/internal/catalog" - "arangodb-proto/internal/dbio" - "arangodb-proto/internal/store" + arangostore "github.com/calypr/loom/internal/store/arango" ) const EdgeCollection = "fhir_edge" const PatientFileRollupCollection = "patient_file_rollup" const ScalarIndexCollection = "fhir_scalar_index" -type ConnectionOptions = dbio.ConnectionOptions - -const ( - backendArango = dbio.BackendArango - backendPostgres = dbio.BackendPostgres - backendSurreal = dbio.BackendSurreal -) - -func backendName(name string) string { return dbio.BackendName(name) } - -func openBackend(ctx context.Context, opts ConnectionOptions) (store.Backend, error) { - return dbio.OpenBackend(ctx, opts) +func openBackend(ctx context.Context, opts arangostore.ConnectionOptions) (*arangostore.Client, error) { + return arangostore.Open(ctx, opts.URL, opts.Database) } -func bootstrapSpec(resourceTypes []string, truncate bool) store.BootstrapSpec { - return bootstrapSpecWithReporter(resourceTypes, truncate, nil) -} - -func bootstrapSpecWithReporter(resourceTypes []string, truncate bool, reporter EventSink) store.BootstrapSpec { - collections := make([]store.CollectionSpec, 0, len(resourceTypes)+3) +func bootstrapSpecWithReporter(resourceTypes []string, truncate bool, reporter EventSink) arangostore.BootstrapSpec { + collections := make([]arangostore.CollectionSpec, 0, len(resourceTypes)+3) for _, name := range resourceTypes { indexes := [][]string{{"project"}, {"id"}, {"project", "id"}, {"project", "auth_resource_path"}} if name == "Patient" { @@ -41,14 +25,14 @@ func bootstrapSpecWithReporter(resourceTypes []string, truncate bool, reporter E if name == "DocumentReference" { indexes = append(indexes, []string{"project", "auth_resource_path", "_key"}) } - collections = append(collections, store.CollectionSpec{ + collections = append(collections, arangostore.CollectionSpec{ Name: name, Truncate: truncate, Indexes: indexes, }) } collections = append(collections, - store.CollectionSpec{ + arangostore.CollectionSpec{ Name: EdgeCollection, Edge: true, Truncate: truncate, @@ -58,8 +42,8 @@ func bootstrapSpecWithReporter(resourceTypes []string, truncate bool, reporter E {"project", "to_type", "label"}, }, }, - store.CollectionSpec{ - Name: catalog.FieldCatalogCollection, + arangostore.CollectionSpec{ + Name: "fhir_field_catalog", Truncate: truncate, Indexes: [][]string{ {"project", "resource_type"}, @@ -69,7 +53,7 @@ func bootstrapSpecWithReporter(resourceTypes []string, truncate bool, reporter E {"project", "resource_type", "pivot_candidate"}, }, }, - store.CollectionSpec{ + arangostore.CollectionSpec{ Name: PatientFileRollupCollection, Truncate: truncate, Indexes: [][]string{ @@ -78,23 +62,7 @@ func bootstrapSpecWithReporter(resourceTypes []string, truncate bool, reporter E }, }, ) - return store.BootstrapSpec{ - Collections: collections, - Reporter: func(event string, fields map[string]any) { - emitEvent(reporter, event, fields) - }, - } -} - -func helperBootstrapSpec(collections []store.CollectionSpec, truncate bool) store.BootstrapSpec { - return helperBootstrapSpecWithReporter(collections, truncate, nil) -} - -func helperBootstrapSpecWithReporter(collections []store.CollectionSpec, truncate bool, reporter EventSink) store.BootstrapSpec { - for i := range collections { - collections[i].Truncate = truncate - } - return store.BootstrapSpec{ + return arangostore.BootstrapSpec{ Collections: collections, Reporter: func(event string, fields map[string]any) { emitEvent(reporter, event, fields) @@ -102,6 +70,6 @@ func helperBootstrapSpecWithReporter(collections []store.CollectionSpec, truncat } } -func insertRawDocuments(ctx context.Context, backend store.Backend, collection string, docs []json.RawMessage, overwrite bool, writeAPI string) error { +func insertRawDocuments(ctx context.Context, backend *arangostore.Client, collection string, docs []json.RawMessage, overwrite bool, writeAPI string) error { return backend.InsertBatchRaw(ctx, collection, docs, overwrite, writeAPI) } diff --git a/internal/proto/bench_test.go b/internal/ingest/bench_test.go similarity index 98% rename from internal/proto/bench_test.go rename to internal/ingest/bench_test.go index f9d23ff..8ad4580 100644 --- a/internal/proto/bench_test.go +++ b/internal/ingest/bench_test.go @@ -1,4 +1,4 @@ -package proto +package ingest import ( "bufio" @@ -8,8 +8,8 @@ import ( "strings" "testing" - "arangodb-proto/internal/catalog" - "arangodb-proto/internal/fhir" + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/fhir" jsgarango "github.com/bmeg/jsonschemagraph/arango" "github.com/bmeg/jsonschemagraph/graph" diff --git a/internal/ingest/doc.go b/internal/ingest/doc.go new file mode 100644 index 0000000..57e0f02 --- /dev/null +++ b/internal/ingest/doc.go @@ -0,0 +1,3 @@ +// Package ingest implements the FHIR NDJSON ingest runtime, including file +// discovery, row building, Arango bootstrap, and load progress reporting. +package ingest diff --git a/internal/proto/files.go b/internal/ingest/files.go similarity index 98% rename from internal/proto/files.go rename to internal/ingest/files.go index fb11de8..ae8eb5b 100644 --- a/internal/proto/files.go +++ b/internal/ingest/files.go @@ -1,4 +1,4 @@ -package proto +package ingest import ( "bufio" diff --git a/internal/proto/files_test.go b/internal/ingest/files_test.go similarity index 96% rename from internal/proto/files_test.go rename to internal/ingest/files_test.go index 2870715..f12096e 100644 --- a/internal/proto/files_test.go +++ b/internal/ingest/files_test.go @@ -1,4 +1,4 @@ -package proto +package ingest import "testing" diff --git a/internal/proto/generated_load.go b/internal/ingest/generated_load.go similarity index 99% rename from internal/proto/generated_load.go rename to internal/ingest/generated_load.go index 77870a0..212d606 100644 --- a/internal/proto/generated_load.go +++ b/internal/ingest/generated_load.go @@ -1,11 +1,11 @@ -package proto +package ingest import ( "encoding/json" "fmt" "time" - "arangodb-proto/internal/fhir" + "github.com/calypr/loom/internal/fhir" jsgarango "github.com/bmeg/jsonschemagraph/arango" "github.com/bytedance/sonic" diff --git a/internal/proto/integration_test.go b/internal/ingest/integration_test.go similarity index 72% rename from internal/proto/integration_test.go rename to internal/ingest/integration_test.go index 15663d2..18bff1f 100644 --- a/internal/proto/integration_test.go +++ b/internal/ingest/integration_test.go @@ -1,4 +1,4 @@ -package proto +package ingest import ( "bufio" @@ -10,6 +10,9 @@ import ( "testing" "time" + "github.com/calypr/loom/internal/catalog" + arangostore "github.com/calypr/loom/internal/store/arango" + "github.com/bmeg/jsonschemagraph/graph" "github.com/bmeg/jsonschemagraph/util" "github.com/bytedance/sonic" @@ -59,7 +62,7 @@ func TestLoadAndQueryFixture(t *testing.T) { t.Run(name, func(t *testing.T) { database := "fhir_proto_int_" + strings.ToLower(name) + "_" + time.Now().Format("20060102150405") loadSummary, err := Load(ctx, LoadOptions{ - ConnectionOptions: ConnectionOptions{ + ConnectionOptions: arangostore.ConnectionOptions{ URL: "http://127.0.0.1:8529", Database: database, }, @@ -87,17 +90,10 @@ func TestLoadAndQueryFixture(t *testing.T) { } outputPath := filepath.Join(t.TempDir(), "query.ndjson") - rows, err := Query(ctx, QueryOptions{ - ConnectionOptions: ConnectionOptions{ - URL: "http://127.0.0.1:8529", - Database: database, - }, - QueryFile: repoPath(t, "queries", "gdc_case_assay_matrix_arango_rows.aql"), - Output: outputPath, - Project: "ARANGO_PROTO_TEST", - BatchSize: 100, - ProgressEvery: 1000, - }) + rows, err := runFixtureQuery(ctx, arangostore.ConnectionOptions{ + URL: "http://127.0.0.1:8529", + Database: database, + }, repoPath(t, "queries", "gdc_case_assay_matrix_arango_rows.aql"), outputPath, "ARANGO_PROTO_TEST") if err != nil { t.Fatalf("query fixture: %v", err) } @@ -105,8 +101,8 @@ func TestLoadAndQueryFixture(t *testing.T) { t.Fatalf("query rows = %d, want 1", rows) } - fields, err := DiscoverPopulatedFields(ctx, PopulatedFieldOptions{ - ConnectionOptions: ConnectionOptions{ + fields, err := catalog.DiscoverPopulatedFields(ctx, catalog.PopulatedFieldOptions{ + ConnectionOptions: arangostore.ConnectionOptions{ URL: "http://127.0.0.1:8529", Database: database, }, @@ -155,3 +151,42 @@ func repoPath(t *testing.T, elems ...string) string { base := filepath.Clean(filepath.Join(filepath.Dir(file), "..", "..")) return filepath.Join(append([]string{base}, elems...)...) } + +func runFixtureQuery(ctx context.Context, connOpts arangostore.ConnectionOptions, queryPath, outputPath, project string) (int, error) { + queryBytes, err := os.ReadFile(queryPath) + if err != nil { + return 0, err + } + out, err := os.Create(outputPath) + if err != nil { + return 0, err + } + defer out.Close() + writer := bufio.NewWriter(out) + defer writer.Flush() + + client, err := arangostore.Open(ctx, connOpts.URL, connOpts.Database) + if err != nil { + return 0, err + } + defer client.Close(ctx) + + rows := 0 + err = client.QueryRows(ctx, string(queryBytes), 100, map[string]any{ + "project": project, + "auth_resource_paths": []string(nil), + "auth_resource_paths_unrestricted": true, + "auth_resource_path": nil, + }, func(row map[string]any) error { + rows++ + data, err := sonic.ConfigFastest.Marshal(row) + if err != nil { + return err + } + if _, err := writer.Write(data); err != nil { + return err + } + return writer.WriteByte('\n') + }) + return rows, err +} diff --git a/internal/proto/load.go b/internal/ingest/load.go similarity index 93% rename from internal/proto/load.go rename to internal/ingest/load.go index 0eb5205..ffa988d 100644 --- a/internal/proto/load.go +++ b/internal/ingest/load.go @@ -1,4 +1,4 @@ -package proto +package ingest import ( "context" @@ -12,7 +12,8 @@ import ( "sync/atomic" "time" - "arangodb-proto/internal/catalog" + "github.com/calypr/loom/internal/catalog" + arangostore "github.com/calypr/loom/internal/store/arango" "github.com/bmeg/jsonschema/v6" "github.com/bmeg/jsonschemagraph/graph" @@ -20,7 +21,7 @@ import ( ) type LoadOptions struct { - ConnectionOptions + arangostore.ConnectionOptions Schema string MetaDir string Project string @@ -70,10 +71,9 @@ func Load(ctx context.Context, opts LoadOptions) (LoadSummary, error) { resourceTypes = append(resourceTypes, ResourceTypeFromPath(file)) } emitEvent(opts.EventSink, "go_backend_connect_start", map[string]any{ - "backend": backendName(opts.Backend), - "url": opts.URL, - "database": opts.Database, - "namespace": opts.Namespace, + "backend": "arango", + "url": opts.URL, + "database": opts.Database, }) connectStart := time.Now() client, err := openBackend(ctx, opts.ConnectionOptions) @@ -82,11 +82,10 @@ func Load(ctx context.Context, opts LoadOptions) (LoadSummary, error) { } defer client.Close(ctx) emitEvent(opts.EventSink, "go_backend_connect_complete", map[string]any{ - "backend": backendName(opts.Backend), - "url": opts.URL, - "database": opts.Database, - "namespace": opts.Namespace, - "seconds": time.Since(connectStart).Seconds(), + "backend": "arango", + "url": opts.URL, + "database": opts.Database, + "seconds": time.Since(connectStart).Seconds(), }) emitEvent(opts.EventSink, "go_bootstrap_start", map[string]any{ "database": opts.Database, @@ -321,18 +320,6 @@ func Load(ctx context.Context, opts LoadOptions) (LoadSummary, error) { go func() { defer writersWG.Done() localTimings := make(map[string]float64) - writerClient := client - if backendName(opts.Backend) == backendSurreal { - openStart := time.Now() - dedicatedClient, err := openBackend(fileCtx, opts.ConnectionOptions) - localTimings["writer_client_open"] += time.Since(openStart).Seconds() - if err != nil { - setPipelineErr(err) - return - } - writerClient = dedicatedClient - defer writerClient.Close(fileCtx) - } for { select { case <-fileCtx.Done(): @@ -348,7 +335,7 @@ func Load(ctx context.Context, opts LoadOptions) (LoadSummary, error) { insertStart := time.Now() overwrite := !opts.Truncate - if err := insertRawDocuments(fileCtx, writerClient, task.collection, task.docs, overwrite, opts.WriteAPI); err != nil { + if err := insertRawDocuments(fileCtx, client, task.collection, task.docs, overwrite, opts.WriteAPI); err != nil { setPipelineErr(err) return } diff --git a/internal/proto/parity_test.go b/internal/ingest/parity_test.go similarity index 99% rename from internal/proto/parity_test.go rename to internal/ingest/parity_test.go index 35597e4..7c2c2b1 100644 --- a/internal/proto/parity_test.go +++ b/internal/ingest/parity_test.go @@ -1,4 +1,4 @@ -package proto +package ingest import ( "bufio" @@ -10,7 +10,7 @@ import ( "strings" "testing" - "arangodb-proto/internal/fhir" + "github.com/calypr/loom/internal/fhir" jsgarango "github.com/bmeg/jsonschemagraph/arango" "github.com/bmeg/jsonschemagraph/graph" diff --git a/internal/proto/progress.go b/internal/ingest/progress.go similarity index 83% rename from internal/proto/progress.go rename to internal/ingest/progress.go index 3a68cae..5056454 100644 --- a/internal/proto/progress.go +++ b/internal/ingest/progress.go @@ -1,4 +1,4 @@ -package proto +package ingest import ( "encoding/json" @@ -9,10 +9,6 @@ import ( type EventSink func(event string, fields map[string]any) -func Emit(event string, fields map[string]any) { - emitEvent(nil, event, fields) -} - func emitEvent(sink EventSink, event string, fields map[string]any) { if sink != nil { sink(event, fields) diff --git a/internal/proto/row_builder.go b/internal/ingest/row_builder.go similarity index 99% rename from internal/proto/row_builder.go rename to internal/ingest/row_builder.go index 9a91831..9e493a4 100644 --- a/internal/proto/row_builder.go +++ b/internal/ingest/row_builder.go @@ -1,4 +1,4 @@ -package proto +package ingest import ( "encoding/json" diff --git a/internal/proto/catalog.go b/internal/proto/catalog.go deleted file mode 100644 index d300eb2..0000000 --- a/internal/proto/catalog.go +++ /dev/null @@ -1,32 +0,0 @@ -package proto - -import ( - "context" - - "arangodb-proto/internal/catalog" -) - -const ( - FieldCatalogCollection = catalog.FieldCatalogCollection - TraversalModeStorage = catalog.TraversalModeStorage - TraversalModeBuilder = catalog.TraversalModeBuilder -) - -type AuthResourcePathOptions = catalog.AuthResourcePathOptions -type FieldCatalogDocument = catalog.FieldCatalogDocument -type PopulatedFieldOptions = catalog.PopulatedFieldOptions -type PopulatedField = catalog.PopulatedField -type PopulatedReferenceOptions = catalog.PopulatedReferenceOptions -type PopulatedReference = catalog.PopulatedReference - -func DiscoverExistingAuthResourcePaths(ctx context.Context, opts AuthResourcePathOptions) ([]string, error) { - return catalog.DiscoverExistingAuthResourcePaths(ctx, opts) -} - -func DiscoverPopulatedFields(ctx context.Context, opts PopulatedFieldOptions) ([]PopulatedField, error) { - return catalog.DiscoverPopulatedFields(ctx, opts) -} - -func DiscoverPopulatedReferences(ctx context.Context, opts PopulatedReferenceOptions) ([]PopulatedReference, error) { - return catalog.DiscoverPopulatedReferences(ctx, opts) -} diff --git a/internal/proto/querysvc.go b/internal/proto/querysvc.go deleted file mode 100644 index 663b119..0000000 --- a/internal/proto/querysvc.go +++ /dev/null @@ -1,42 +0,0 @@ -package proto - -import ( - "context" - - "arangodb-proto/internal/querysvc" -) - -type BuildScalarIndexOptions = querysvc.BuildScalarIndexOptions -type BuildScalarIndexSummary = querysvc.BuildScalarIndexSummary -type ExecuteQueryOptions = querysvc.ExecuteQueryOptions -type PrepareCaseAssayOptions = querysvc.PrepareCaseAssayOptions -type PrepareCaseAssaySummary = querysvc.PrepareCaseAssaySummary -type QueryOptions = querysvc.QueryOptions - -func BuildScalarIndex(ctx context.Context, opts BuildScalarIndexOptions) (BuildScalarIndexSummary, error) { - return querysvc.BuildScalarIndex(ctx, opts) -} - -func DefaultBulkIndex() string { - return querysvc.DefaultBulkIndex() -} - -func DefaultCaseAssayQueryPath() string { - return querysvc.DefaultCaseAssayQueryPath() -} - -func DefaultCaseAssayQueryPathForBackend(backend string) string { - return querysvc.DefaultCaseAssayQueryPathForBackend(backend) -} - -func ExecuteQueryRows(ctx context.Context, opts ExecuteQueryOptions, query string, bindVars map[string]any, visit func(map[string]any) error) error { - return querysvc.ExecuteQueryRows(ctx, opts, query, bindVars, visit) -} - -func PrepareGDCCaseAssayMatrix(ctx context.Context, opts PrepareCaseAssayOptions) (PrepareCaseAssaySummary, error) { - return querysvc.PrepareGDCCaseAssayMatrix(ctx, opts) -} - -func Query(ctx context.Context, opts QueryOptions) (int, error) { - return querysvc.Query(ctx, opts) -} diff --git a/internal/proto/value_decode.go b/internal/proto/value_decode.go deleted file mode 100644 index 4b0b4d0..0000000 --- a/internal/proto/value_decode.go +++ /dev/null @@ -1,32 +0,0 @@ -package proto - -import "fmt" - -func stringValue(value any) string { - if s, ok := value.(string); ok { - return s - } - return "" -} - -func int64Value(value any) (int64, error) { - switch v := value.(type) { - case int64: - return v, nil - case int32: - return int64(v), nil - case int: - return int64(v), nil - case float64: - return int64(v), nil - case float32: - return int64(v), nil - default: - return 0, fmt.Errorf("unsupported numeric type %T", value) - } -} - -func int64Must(value any) int64 { - v, _ := int64Value(value) - return v -} diff --git a/internal/querysvc/build_scalar_index.go b/internal/querysvc/build_scalar_index.go deleted file mode 100644 index fe98ff4..0000000 --- a/internal/querysvc/build_scalar_index.go +++ /dev/null @@ -1,177 +0,0 @@ -package querysvc - -import ( - "context" - "encoding/json" - "fmt" - "strings" - "time" - - "arangodb-proto/internal/dbio" - postgresstore "arangodb-proto/internal/experimental/store/postgres" - "arangodb-proto/internal/store" -) - -type BuildScalarIndexOptions struct { - dbio.ConnectionOptions - Project string - ResourceType string - BatchSize int - ProgressEvery int - Truncate bool -} - -type BuildScalarIndexSummary struct { - Project string `json:"project,omitempty"` - ResourceType string `json:"resource_type,omitempty"` - ResourcesScanned int `json:"resources_scanned"` - ScalarRows int `json:"scalar_rows"` - Seconds float64 `json:"seconds"` -} - -func BuildScalarIndex(ctx context.Context, opts BuildScalarIndexOptions) (BuildScalarIndexSummary, error) { - if dbio.BackendName(opts.Backend) != dbio.BackendPostgres { - return BuildScalarIndexSummary{}, fmt.Errorf("build-scalar-index currently supports only the postgres backend") - } - if opts.BatchSize <= 0 { - opts.BatchSize = 5000 - } - if opts.ProgressEvery <= 0 { - opts.ProgressEvery = 5000 - } - - rawClient, err := openBackend(ctx, opts.ConnectionOptions) - if err != nil { - return BuildScalarIndexSummary{}, err - } - defer rawClient.Close(ctx) - - client, ok := rawClient.(*postgresstore.Client) - if !ok { - return BuildScalarIndexSummary{}, fmt.Errorf("postgres backend did not return a postgres client") - } - - spec := helperBootstrapSpec([]store.CollectionSpec{ - { - Name: scalarIndexCollection, - Indexes: [][]string{{"project", "resource_type", "path", "value_text"}, {"project", "resource_type", "path", "system", "code", "display"}}, - }, - }, false) - - start := time.Now() - emit("go_scalar_index_start", map[string]any{ - "project": opts.Project, - "resource_type": opts.ResourceType, - "truncate": opts.Truncate, - "batch_size": opts.BatchSize, - }) - if err := client.Bootstrap(ctx, spec); err != nil { - return BuildScalarIndexSummary{}, err - } - if err := client.ResetScalarIndex(ctx, opts.Project, opts.ResourceType, opts.Truncate); err != nil { - return BuildScalarIndexSummary{}, err - } - - query := ` -SELECT - project, - resource_key, - resource_type, - body -FROM fhir_resource -WHERE (NULLIF(@project, '') IS NULL OR project = @project) - AND (NULLIF(@resource_type, '') IS NULL OR resource_type = @resource_type) -ORDER BY resource_key ASC; -` - bindVars := map[string]any{ - "project": opts.Project, - "resource_type": opts.ResourceType, - } - - scanned := 0 - totalScalarRows := 0 - batch := make([]postgresstore.ScalarIndexRow, 0, opts.BatchSize) - - flush := func() error { - if len(batch) == 0 { - return nil - } - if err := client.InsertScalarIndexRows(ctx, batch); err != nil { - return err - } - totalScalarRows += len(batch) - batch = make([]postgresstore.ScalarIndexRow, 0, opts.BatchSize) - return nil - } - - err = client.QueryRows(ctx, query, opts.BatchSize, bindVars, func(row map[string]any) error { - project := stringValue(row["project"]) - resourceKey := stringValue(row["resource_key"]) - resourceType := stringValue(row["resource_type"]) - payload, err := bodyPayload(row["body"]) - if err != nil { - return fmt.Errorf("decode body for %s: %w", resourceKey, err) - } - batch = append(batch, postgresstore.ScalarIndexRows(project, resourceKey, resourceType, payload)...) - scanned++ - if scanned%opts.ProgressEvery == 0 { - emit("go_scalar_index_progress", map[string]any{ - "resources_scanned": scanned, - "scalar_rows": totalScalarRows + len(batch), - "seconds": secondsSince(start), - }) - } - if len(batch) >= opts.BatchSize { - return flush() - } - return nil - }) - if err != nil { - return BuildScalarIndexSummary{}, err - } - if err := flush(); err != nil { - return BuildScalarIndexSummary{}, err - } - - summary := BuildScalarIndexSummary{ - Project: opts.Project, - ResourceType: opts.ResourceType, - ResourcesScanned: scanned, - ScalarRows: totalScalarRows, - Seconds: secondsSince(start), - } - emit("go_scalar_index_complete", map[string]any{ - "resources_scanned": scanned, - "scalar_rows": totalScalarRows, - "seconds": summary.Seconds, - }) - return summary, nil -} - -func bodyPayload(value any) (map[string]any, error) { - switch typed := value.(type) { - case map[string]any: - return typed, nil - case string: - return decodePayloadString(typed) - case []byte: - return decodePayloadBytes(typed) - default: - return nil, fmt.Errorf("unsupported body type %T", value) - } -} - -func decodePayloadString(value string) (map[string]any, error) { - return decodePayloadBytes([]byte(value)) -} - -func decodePayloadBytes(value []byte) (map[string]any, error) { - payload := make(map[string]any) - if len(strings.TrimSpace(string(value))) == 0 { - return payload, nil - } - if err := json.Unmarshal(value, &payload); err != nil { - return nil, err - } - return payload, nil -} diff --git a/internal/querysvc/prepare_case_assay.go b/internal/querysvc/prepare_case_assay.go deleted file mode 100644 index 7a5fa78..0000000 --- a/internal/querysvc/prepare_case_assay.go +++ /dev/null @@ -1,389 +0,0 @@ -package querysvc - -import ( - "context" - "encoding/json" - "fmt" - "sort" - "strings" - "time" - - "arangodb-proto/internal/dbio" - "arangodb-proto/internal/store" -) - -type PrepareCaseAssayOptions struct { - dbio.ConnectionOptions - Project string - AuthResourcePath string - BatchSize int - ProgressEvery int - Truncate bool -} - -type PrepareCaseAssaySummary struct { - Project string `json:"project"` - AuthResourcePath string `json:"auth_resource_path,omitempty"` - RowsPrepared int `json:"rows_prepared"` - Seconds float64 `json:"seconds"` -} - -type patientFileRollupDocument struct { - Key string `json:"_key"` - Project string `json:"project"` - PatientKey string `json:"patient_key"` - AuthResourcePath string `json:"auth_resource_path,omitempty"` - SpecimenCount int `json:"specimen_count"` - GroupCount int `json:"group_count"` - FileCount int `json:"file_count"` - SpecimenTypes []string `json:"specimen_types,omitempty"` - PreservationMethods []string `json:"preservation_methods,omitempty"` - FileKeys []string `json:"file_keys,omitempty"` -} - -type specimenMeta struct { - types []string - preservationMethods []string -} - -func PrepareGDCCaseAssayMatrix(ctx context.Context, opts PrepareCaseAssayOptions) (PrepareCaseAssaySummary, error) { - if dbio.BackendName(opts.Backend) != dbio.BackendSurreal && dbio.BackendName(opts.Backend) != dbio.BackendPostgres { - return PrepareCaseAssaySummary{}, fmt.Errorf("prepare-gdc-case-assay-matrix currently supports only the surreal and postgres backends") - } - if opts.BatchSize <= 0 { - opts.BatchSize = 1000 - } - if opts.ProgressEvery <= 0 { - opts.ProgressEvery = 5000 - } - - client, err := openBackend(ctx, opts.ConnectionOptions) - if err != nil { - return PrepareCaseAssaySummary{}, err - } - defer client.Close(ctx) - - spec := helperBootstrapSpec([]store.CollectionSpec{ - { - Name: patientFileRollupCollection, - Indexes: [][]string{{"project", "patient_key"}, {"project", "auth_resource_path", "patient_key"}}, - }, - }, opts.Truncate) - - start := time.Now() - emit("go_prepare_start", map[string]any{ - "project": opts.Project, - "auth_resource_path": opts.AuthResourcePath, - "collection": patientFileRollupCollection, - "truncate": opts.Truncate, - }) - if err := client.Bootstrap(ctx, spec); err != nil { - return PrepareCaseAssaySummary{}, err - } - - backend := dbio.BackendName(opts.Backend) - patientAuth, patientOrder, err := queryPatientsForPrepare(ctx, client, backend, opts.Project, opts.AuthResourcePath) - if err != nil { - return PrepareCaseAssaySummary{}, err - } - specimenMetadata, err := querySpecimenMetadata(ctx, client, backend, opts.Project) - if err != nil { - return PrepareCaseAssaySummary{}, err - } - patientSpecimens, err := queryEdgeMap(ctx, client, backend, opts.Project, "subject_Patient", "Specimen", "Patient") - if err != nil { - return PrepareCaseAssaySummary{}, err - } - patientFileKeys, err := queryEdgeMap(ctx, client, backend, opts.Project, "subject_Patient", "DocumentReference", "Patient") - if err != nil { - return PrepareCaseAssaySummary{}, err - } - specimenGroups, err := queryEdgeMap(ctx, client, backend, opts.Project, "member_entity_Specimen", "Group", "Specimen") - if err != nil { - return PrepareCaseAssaySummary{}, err - } - specimenFiles, err := queryEdgeMap(ctx, client, backend, opts.Project, "subject_Specimen", "DocumentReference", "Specimen") - if err != nil { - return PrepareCaseAssaySummary{}, err - } - groupFiles, err := queryEdgeMap(ctx, client, backend, opts.Project, "subject_Group", "DocumentReference", "Group") - if err != nil { - return PrepareCaseAssaySummary{}, err - } - - batch := make([]json.RawMessage, 0, opts.BatchSize) - rowsPrepared := 0 - overwrite := !opts.Truncate - - flush := func() error { - if len(batch) == 0 { - return nil - } - if err := client.InsertBatchRaw(ctx, patientFileRollupCollection, batch, overwrite, "import"); err != nil { - return err - } - batch = make([]json.RawMessage, 0, opts.BatchSize) - return nil - } - - for _, patientKey := range patientOrder { - specimenKeys := sortedStringKeys(patientSpecimens[patientKey]) - groupSet := make(map[string]struct{}) - fileSet := make(map[string]struct{}) - specimenTypesSet := make(map[string]struct{}) - preservationSet := make(map[string]struct{}) - - for _, specimenKey := range specimenKeys { - for key := range specimenGroups[specimenKey] { - groupSet[key] = struct{}{} - } - for key := range specimenFiles[specimenKey] { - fileSet[key] = struct{}{} - } - meta := specimenMetadata[specimenKey] - for _, value := range meta.types { - specimenTypesSet[value] = struct{}{} - } - for _, value := range meta.preservationMethods { - preservationSet[value] = struct{}{} - } - } - for groupKey := range groupSet { - for fileKey := range groupFiles[groupKey] { - fileSet[fileKey] = struct{}{} - } - } - for fileKey := range patientFileKeys[patientKey] { - fileSet[fileKey] = struct{}{} - } - - doc := patientFileRollupDocument{ - Key: rollupKey(opts.Project, patientKey), - Project: opts.Project, - PatientKey: patientKey, - AuthResourcePath: patientAuth[patientKey], - SpecimenCount: len(specimenKeys), - GroupCount: len(groupSet), - FileCount: len(fileSet), - SpecimenTypes: sortedStringKeys(specimenTypesSet), - PreservationMethods: sortedStringKeys(preservationSet), - FileKeys: sortedStringKeys(fileSet), - } - raw, err := json.Marshal(doc) - if err != nil { - return PrepareCaseAssaySummary{}, err - } - batch = append(batch, raw) - rowsPrepared++ - if rowsPrepared%opts.ProgressEvery == 0 { - emit("go_prepare_progress", map[string]any{ - "project": opts.Project, - "rows_prepared": rowsPrepared, - "seconds": secondsSince(start), - }) - } - if len(batch) >= opts.BatchSize { - if err := flush(); err != nil { - return PrepareCaseAssaySummary{}, err - } - } - } - if err := flush(); err != nil { - return PrepareCaseAssaySummary{}, err - } - - summary := PrepareCaseAssaySummary{ - Project: opts.Project, - AuthResourcePath: opts.AuthResourcePath, - RowsPrepared: rowsPrepared, - Seconds: secondsSince(start), - } - emit("go_prepare_complete", map[string]any{ - "project": opts.Project, - "rows_prepared": rowsPrepared, - "seconds": summary.Seconds, - }) - return summary, nil -} - -func queryPatientsForPrepare(ctx context.Context, client store.Backend, backend, project, authResourcePath string) (map[string]string, []string, error) { - query := ` -SELECT _key, auth_resource_path -FROM Patient -WHERE project = $project - AND ($auth_resource_path = "" OR auth_resource_path = $auth_resource_path) -ORDER BY _key ASC; -` - bindVars := map[string]any{ - "project": project, - "auth_resource_path": authResourcePath, - } - if backend == dbio.BackendPostgres { - query = ` -SELECT - split_part(resource_key, '/', 2) AS _key, - auth_resource_path -FROM fhir_resource -WHERE project = @project - AND resource_type = 'Patient' - AND (NULLIF(@auth_resource_path, '') IS NULL OR auth_resource_path = @auth_resource_path) -ORDER BY resource_key ASC; -` - } - authByPatient := make(map[string]string) - order := make([]string, 0, 1024) - err := client.QueryRows(ctx, query, 1000, bindVars, func(row map[string]any) error { - key := stringValue(row["_key"]) - if key == "" { - return nil - } - authByPatient[key] = stringValue(row["auth_resource_path"]) - order = append(order, key) - return nil - }) - return authByPatient, order, err -} - -func querySpecimenMetadata(ctx context.Context, client store.Backend, backend, project string) (map[string]specimenMeta, error) { - query := ` -SELECT _key, payload -FROM Specimen -WHERE project = $project; -` - if backend == dbio.BackendPostgres { - query = ` -SELECT - split_part(resource_key, '/', 2) AS _key, - body AS payload -FROM fhir_resource -WHERE project = @project - AND resource_type = 'Specimen'; -` - } - out := make(map[string]specimenMeta) - err := client.QueryRows(ctx, query, 1000, map[string]any{"project": project}, func(row map[string]any) error { - key := stringValue(row["_key"]) - payload, _ := row["payload"].(map[string]any) - out[key] = specimenMeta{ - types: specimenTypesFromPayload(payload), - preservationMethods: preservationMethodsFromPayload(payload), - } - return nil - }) - return out, err -} - -func queryEdgeMap(ctx context.Context, client store.Backend, backend, project, label, fromType, toType string) (map[string]map[string]struct{}, error) { - query := ` -SELECT _from, _to -FROM fhir_edge -WHERE project = $project - AND label = $label - AND from_type = $from_type - AND to_type = $to_type; -` - rowFrom := "_from" - rowTo := "_to" - bindVars := map[string]any{ - "project": project, - "label": label, - "from_type": fromType, - "to_type": toType, - } - if backend == dbio.BackendPostgres { - query = ` -SELECT - src_key AS _from, - dst_key AS _to -FROM fhir_edge -WHERE project = @project - AND edge_type = @label - AND src_type = @from_type - AND dst_type = @to_type; -` - rowFrom = "_from" - rowTo = "_to" - } - out := make(map[string]map[string]struct{}) - err := client.QueryRows(ctx, query, 2000, bindVars, func(row map[string]any) error { - fromKey := refKey(stringValue(row[rowFrom])) - toKey := refKey(stringValue(row[rowTo])) - if fromKey == "" || toKey == "" { - return nil - } - set := out[toKey] - if set == nil { - set = make(map[string]struct{}) - out[toKey] = set - } - set[fromKey] = struct{}{} - return nil - }) - return out, err -} - -func specimenTypesFromPayload(payload map[string]any) []string { - typeField, _ := payload["type"].(map[string]any) - codings, _ := typeField["coding"].([]any) - set := make(map[string]struct{}) - for _, codingValue := range codings { - coding, _ := codingValue.(map[string]any) - value := strings.TrimSpace(stringValue(coding["display"])) - if value == "" { - value = strings.TrimSpace(stringValue(coding["code"])) - } - if value != "" { - set[value] = struct{}{} - } - } - return sortedStringKeys(set) -} - -func preservationMethodsFromPayload(payload map[string]any) []string { - processings, _ := payload["processing"].([]any) - set := make(map[string]struct{}) - for _, processingValue := range processings { - processing, _ := processingValue.(map[string]any) - method, _ := processing["method"].(map[string]any) - codings, _ := method["coding"].([]any) - for _, codingValue := range codings { - coding, _ := codingValue.(map[string]any) - system := stringValue(coding["system"]) - if !strings.Contains(system, "preservation_method") { - continue - } - value := strings.TrimSpace(stringValue(coding["display"])) - if value == "" { - value = strings.TrimSpace(stringValue(coding["code"])) - } - if value != "" { - set[value] = struct{}{} - } - } - } - return sortedStringKeys(set) -} - -func refKey(ref string) string { - parts := strings.SplitN(ref, "/", 2) - if len(parts) != 2 { - return "" - } - return parts[1] -} - -func rollupKey(project, patientKey string) string { - return strings.ReplaceAll(project, "/", "_") + "::" + patientKey -} - -func sortedStringKeys(set map[string]struct{}) []string { - if len(set) == 0 { - return nil - } - out := make([]string, 0, len(set)) - for key := range set { - out = append(out, key) - } - sort.Strings(out) - return out -} diff --git a/internal/querysvc/query.go b/internal/querysvc/query.go deleted file mode 100644 index fb81f37..0000000 --- a/internal/querysvc/query.go +++ /dev/null @@ -1,175 +0,0 @@ -package querysvc - -import ( - "bufio" - "context" - "fmt" - "os" - "time" - - "arangodb-proto/internal/dbio" -) - -type QueryOptions struct { - dbio.ConnectionOptions - QueryFile string - Output string - Index string - Project string - AuthResourcePath string - PatientKey string - BatchSize int - ProgressEvery int - MaxRows int - Bulk bool -} - -type ExecuteQueryOptions struct { - dbio.ConnectionOptions - BatchSize int -} - -func Query(ctx context.Context, opts QueryOptions) (int, error) { - if opts.BatchSize <= 0 { - opts.BatchSize = 1000 - } - if opts.ProgressEvery <= 0 { - opts.ProgressEvery = 50000 - } - if opts.QueryFile == "" { - opts.QueryFile = DefaultCaseAssayQueryPathForBackend(opts.Backend) - } - queryBytes, err := os.ReadFile(opts.QueryFile) - if err != nil { - return 0, err - } - var out *os.File - if opts.Output != "" { - out, err = os.Create(opts.Output) - if err != nil { - return 0, err - } - defer out.Close() - } else { - out = os.Stdout - } - writer := bufio.NewWriter(out) - defer writer.Flush() - - start := time.Now() - rows := 0 - emit("go_query_start", map[string]any{ - "query": opts.QueryFile, - "output": opts.Output, - "bulk": opts.Bulk, - "cursor_batch_size": opts.BatchSize, - "auth_resource_path": opts.AuthResourcePath, - }) - bindVars := queryBindVars(opts) - err = ExecuteQueryRows(ctx, ExecuteQueryOptions{ - ConnectionOptions: opts.ConnectionOptions, - BatchSize: opts.BatchSize, - }, string(queryBytes), bindVars, func(row map[string]any) error { - return visitQueryRow(writer, opts, row, &rows, start) - }) - if _, ok := err.(stopQuery); ok { - err = nil - } - if err != nil { - return rows, err - } - emit("go_query_complete", map[string]any{"rows": rows, "seconds": secondsSince(start), "output": opts.Output}) - return rows, nil -} - -func ExecuteQueryRows(ctx context.Context, opts ExecuteQueryOptions, query string, bindVars map[string]any, visit func(map[string]any) error) error { - if opts.BatchSize <= 0 { - opts.BatchSize = 1000 - } - client, err := openBackend(ctx, opts.ConnectionOptions) - if err != nil { - return err - } - defer client.Close(ctx) - return client.QueryRows(ctx, query, opts.BatchSize, bindVars, func(row map[string]any) error { - return visit(row) - }) -} - -func queryBindVars(opts QueryOptions) map[string]any { - switch dbio.BackendName(opts.Backend) { - case dbio.BackendSurreal, dbio.BackendPostgres: - return map[string]any{ - "project": opts.Project, - "max_rows": opts.MaxRows, - "patient_key": opts.PatientKey, - "auth_resource_path": opts.AuthResourcePath, - } - default: - authPaths := []string(nil) - if opts.AuthResourcePath != "" { - authPaths = []string{opts.AuthResourcePath} - } - bindVars := map[string]any{ - "project": opts.Project, - "auth_resource_paths": authPaths, - "auth_resource_paths_unrestricted": authPaths == nil, - } - if opts.AuthResourcePath != "" { - bindVars["auth_resource_path"] = opts.AuthResourcePath - } else { - bindVars["auth_resource_path"] = nil - } - return bindVars - } -} - -func visitQueryRow(writer *bufio.Writer, opts QueryOptions, row map[string]any, rows *int, start time.Time) error { - if opts.MaxRows > 0 && *rows >= opts.MaxRows { - return stopQuery{} - } - *rows++ - if opts.Bulk { - rowID := row["_key"] - if rowID == nil { - rowID = row["case_fhir_id"] - } - delete(row, "_key") - delete(row, "_id") - delete(row, "_rev") - meta := map[string]any{"index": map[string]any{"_index": opts.Index, "_id": rowID}} - if err := writeJSONLine(writer, meta); err != nil { - return err - } - } - if err := writeJSONLine(writer, row); err != nil { - return err - } - if *rows%opts.ProgressEvery == 0 { - emit("go_query_progress", map[string]any{"rows": *rows, "seconds": secondsSince(start)}) - } - return nil -} - -type stopQuery struct{} - -func (stopQuery) Error() string { return "stop query" } - -func DefaultCaseAssayQueryPath() string { - return DefaultCaseAssayQueryPathForBackend(dbio.BackendArango) -} - -func DefaultCaseAssayQueryPathForBackend(backend string) string { - switch dbio.BackendName(backend) { - case dbio.BackendPostgres: - return "experimental/queries/postgres/gdc_case_assay_matrix_postgres_rows.sql" - case dbio.BackendSurreal: - return "experimental/queries/surreal/gdc_case_assay_matrix_surreal_rows.surql" - default: - return "queries/gdc_case_assay_matrix_arango_rows.aql" - } -} - -func DefaultBulkIndex() string { - return fmt.Sprintf("gdc_case_assay_matrix") -} diff --git a/internal/querysvc/support.go b/internal/querysvc/support.go deleted file mode 100644 index 750d633..0000000 --- a/internal/querysvc/support.go +++ /dev/null @@ -1,65 +0,0 @@ -package querysvc - -import ( - "bufio" - "context" - "encoding/json" - "fmt" - "os" - "time" - - "arangodb-proto/internal/dbio" - "arangodb-proto/internal/store" -) - -const ( - edgeCollection = "fhir_edge" - patientFileRollupCollection = "patient_file_rollup" - scalarIndexCollection = "fhir_scalar_index" -) - -func openBackend(ctx context.Context, opts dbio.ConnectionOptions) (store.Backend, error) { - return dbio.OpenBackend(ctx, opts) -} - -func emit(event string, fields map[string]any) { - payload := map[string]any{"event": event} - for key, value := range fields { - payload[key] = value - } - data, err := json.Marshal(payload) - if err != nil { - fmt.Fprintln(os.Stderr, err) - return - } - fmt.Fprintln(os.Stdout, string(data)) -} - -func secondsSince(start time.Time) float64 { - return time.Since(start).Seconds() -} - -func helperBootstrapSpec(collections []store.CollectionSpec, truncate bool) store.BootstrapSpec { - for i := range collections { - collections[i].Truncate = truncate - } - return store.BootstrapSpec{Collections: collections} -} - -func writeJSONLine(writer *bufio.Writer, value any) error { - data, err := json.Marshal(value) - if err != nil { - return err - } - if _, err := writer.Write(data); err != nil { - return err - } - return writer.WriteByte('\n') -} - -func stringValue(value any) string { - if s, ok := value.(string); ok { - return s - } - return "" -} diff --git a/internal/store/arango/client.go b/internal/store/arango/client.go index 200fba0..43dfbae 100644 --- a/internal/store/arango/client.go +++ b/internal/store/arango/client.go @@ -12,8 +12,6 @@ import ( "sync" "time" - "arangodb-proto/internal/store" - driver "github.com/arangodb/go-driver/v2/arangodb" "github.com/arangodb/go-driver/v2/arangodb/shared" "github.com/arangodb/go-driver/v2/connection" @@ -75,7 +73,7 @@ func Open(ctx context.Context, url, database string) (*Client, error) { }, nil } -func (c *Client) Bootstrap(ctx context.Context, spec store.BootstrapSpec) error { +func (c *Client) Bootstrap(ctx context.Context, spec BootstrapSpec) error { total := len(spec.Collections) for i, collection := range spec.Collections { reportBootstrap(spec, "go_bootstrap_collection_start", map[string]any{ @@ -147,7 +145,7 @@ func (c *Client) InsertBatchRaw(ctx context.Context, collection string, docs []j return c.insertBatchDocumentRaw(ctx, collection, docs, overwrite) } -func (c *Client) QueryRows(ctx context.Context, query string, batchSize int, bindVars map[string]interface{}, visit store.RowVisitor) error { +func (c *Client) QueryRows(ctx context.Context, query string, batchSize int, bindVars map[string]interface{}, visit RowVisitor) error { cursor, err := c.db.Query(ctx, query, &driver.QueryOptions{BatchSize: batchSize, BindVars: bindVars}) if err != nil { return err @@ -173,7 +171,7 @@ func (c *Client) Close(ctx context.Context) error { return nil } -func reportBootstrap(spec store.BootstrapSpec, event string, fields map[string]any) { +func reportBootstrap(spec BootstrapSpec, event string, fields map[string]any) { if spec.Reporter != nil { spec.Reporter(event, fields) } diff --git a/internal/store/arango/options.go b/internal/store/arango/options.go new file mode 100644 index 0000000..87a4643 --- /dev/null +++ b/internal/store/arango/options.go @@ -0,0 +1,6 @@ +package arango + +type ConnectionOptions struct { + URL string + Database string +} diff --git a/internal/store/store.go b/internal/store/arango/types.go similarity index 97% rename from internal/store/store.go rename to internal/store/arango/types.go index eed868c..52684ee 100644 --- a/internal/store/store.go +++ b/internal/store/arango/types.go @@ -1,4 +1,4 @@ -package store +package arango import ( "context" diff --git a/internal/writeapi/http.go b/internal/writeapi/http.go deleted file mode 100644 index a232fe0..0000000 --- a/internal/writeapi/http.go +++ /dev/null @@ -1,351 +0,0 @@ -package writeapi - -import ( - "context" - "errors" - "fmt" - "io" - "log/slog" - "mime/multipart" - "net/http" - "os" - "path/filepath" - "strconv" - "strings" - "time" - - "github.com/gofiber/fiber/v3" - "github.com/gofiber/fiber/v3/middleware/adaptor" - "github.com/google/uuid" -) - -type Authenticator interface { - Authenticate(ctx context.Context, headers map[string][]string) (*Principal, error) -} - -type Authorizer interface { - AuthorizeWrite(ctx context.Context, principal *Principal, project, authResourcePath string) error -} - -type StaticAuthenticator struct { - Principal Principal -} - -func (a StaticAuthenticator) Authenticate(ctx context.Context, headers map[string][]string) (*Principal, error) { - principal := a.Principal - if principal.Subject == "" { - principal.Subject = "anonymous" - } - return &principal, nil -} - -type AllowAllAuthorizer struct{} - -func (AllowAllAuthorizer) AuthorizeWrite(ctx context.Context, principal *Principal, project, authResourcePath string) error { - return nil -} - -type HTTPConfig struct { - Service *Service - Authenticator Authenticator - Authorizer Authorizer - GraphQLHandler http.Handler - GraphQLPlaygroundHandler http.Handler - ApolloSandboxHandler http.Handler - Logger *slog.Logger - BodyLimit int - ReadBufferSize int -} - -type HTTPServer struct { - app *fiber.App - service *Service - authn Authenticator - authz Authorizer - logger *slog.Logger - cfgGraphQLHandler http.Handler - cfgGraphQLPlaygroundHandler http.Handler - cfgApolloSandboxHandler http.Handler -} - -type apiError struct { - Status int - Code string - Message string -} - -func (e *apiError) Error() string { return e.Message } - -type errorEnvelope struct { - Error errorBody `json:"error"` -} - -type errorBody struct { - Code string `json:"code"` - Message string `json:"message"` - RequestID string `json:"request_id,omitempty"` -} - -func NewHTTPServer(cfg HTTPConfig) (*HTTPServer, error) { - if cfg.Service == nil { - return nil, errors.New("service is required") - } - if cfg.Authenticator == nil { - cfg.Authenticator = BearerTokenAuthenticator{} - } - if cfg.Authorizer == nil { - cfg.Authorizer = AllowAllAuthorizer{} - } - if cfg.Logger == nil { - cfg.Logger = slog.Default() - } - if cfg.BodyLimit <= 0 { - cfg.BodyLimit = 1024 * 1024 * 1024 - } - if cfg.ReadBufferSize <= 0 { - cfg.ReadBufferSize = 1024 * 1024 - } - - server := &HTTPServer{ - service: cfg.Service, - authn: cfg.Authenticator, - authz: cfg.Authorizer, - logger: cfg.Logger, - cfgGraphQLHandler: cfg.GraphQLHandler, - cfgGraphQLPlaygroundHandler: cfg.GraphQLPlaygroundHandler, - cfgApolloSandboxHandler: cfg.ApolloSandboxHandler, - } - app := fiber.New(fiber.Config{ - BodyLimit: cfg.BodyLimit, - ReadBufferSize: cfg.ReadBufferSize, - ErrorHandler: func(c fiber.Ctx, err error) error { - requestID := requestIDFromCtx(c) - var apiErr *apiError - if errors.As(err, &apiErr) { - return c.Status(apiErr.Status).JSON(errorEnvelope{ - Error: errorBody{Code: apiErr.Code, Message: apiErr.Message, RequestID: requestID}, - }) - } - server.logger.Error("unhandled request error", "request_id", requestID, "path", c.Path(), "error", err.Error()) - return c.Status(fiber.StatusInternalServerError).JSON(errorEnvelope{ - Error: errorBody{Code: "internal_error", Message: "internal server error", RequestID: requestID}, - }) - }, - }) - server.app = app - server.register() - return server, nil -} - -func (s *HTTPServer) App() *fiber.App { - return s.app -} - -func (s *HTTPServer) register() { - s.app.Use(s.requestIDMiddleware, s.recoveryMiddleware, s.loggingMiddleware, s.authenticationMiddleware) - s.app.Get("/healthz", func(c fiber.Ctx) error { - return c.Status(fiber.StatusOK).JSON(fiber.Map{"status": "ok"}) - }) - if s.cfgGraphQLPlaygroundHandler != nil { - s.app.Get("/graphql", adaptor.HTTPHandlerWithContext(s.cfgGraphQLPlaygroundHandler)) - } - if s.cfgApolloSandboxHandler != nil { - s.app.Get("/apollo", adaptor.HTTPHandlerWithContext(s.cfgApolloSandboxHandler)) - } - if s.cfgGraphQLHandler != nil { - s.app.Post("/graphql", adaptor.HTTPHandlerWithContext(s.cfgGraphQLHandler)) - } - group := s.app.Group("/api/v1") - group.Post("/imports", s.createImport) - group.Get("/imports/:id", s.getImport) - group.Get("/imports/:id/events", s.getImportEvents) -} - -func (s *HTTPServer) requestIDMiddleware(c fiber.Ctx) error { - requestID := c.Get("X-Request-ID") - if requestID == "" { - requestID = uuid.NewString() - } - c.Locals("request_id", requestID) - c.Set("X-Request-ID", requestID) - return c.Next() -} - -func (s *HTTPServer) recoveryMiddleware(c fiber.Ctx) (err error) { - defer func() { - if recovered := recover(); recovered != nil { - s.logger.Error("panic recovered", "request_id", requestIDFromCtx(c), "path", c.Path(), "panic", recovered) - err = &apiError{Status: fiber.StatusInternalServerError, Code: "internal_error", Message: "internal server error"} - } - }() - return c.Next() -} - -func (s *HTTPServer) loggingMiddleware(c fiber.Ctx) error { - start := time.Now() - err := c.Next() - if err != nil { - var apiErr *apiError - if errors.As(err, &apiErr) && c.Response().StatusCode() < 400 { - c.Status(apiErr.Status) - } - } - s.logger.Info("http request", "request_id", requestIDFromCtx(c), "method", c.Method(), "path", c.Path(), "status", c.Response().StatusCode(), "duration_ms", time.Since(start).Milliseconds()) - return err -} - -func (s *HTTPServer) authenticationMiddleware(c fiber.Ctx) error { - principal, err := s.authn.Authenticate(c.Context(), c.GetReqHeaders()) - if err != nil { - return &apiError{Status: fiber.StatusUnauthorized, Code: "unauthorized", Message: err.Error()} - } - c.Locals("principal", principal) - c.SetContext(ContextWithPrincipal(c.Context(), principal)) - return c.Next() -} - -func (s *HTTPServer) createImport(c fiber.Ctx) error { - if !c.IsMultipart() { - return &apiError{Status: fiber.StatusUnsupportedMediaType, Code: "unsupported_media_type", Message: "expected multipart/form-data"} - } - form, err := c.Req().MultipartForm() - if err != nil { - return &apiError{Status: fiber.StatusBadRequest, Code: "invalid_multipart_form", Message: err.Error()} - } - fileCount := 0 - for _, files := range form.File { - fileCount += len(files) - } - if fileCount != 1 { - return &apiError{Status: fiber.StatusBadRequest, Code: "invalid_file_count", Message: "exactly one uploaded file is required"} - } - - project := strings.TrimSpace(c.Req().FormValue("project")) - if project == "" { - return &apiError{Status: fiber.StatusBadRequest, Code: "missing_project", Message: "project is required"} - } - resourceType := strings.TrimSpace(c.Req().FormValue("resource_type")) - if resourceType == "" { - return &apiError{Status: fiber.StatusBadRequest, Code: "missing_resource_type", Message: "resource_type is required"} - } - authResourcePath := strings.TrimSpace(c.Req().FormValue("auth_resource_path")) - truncate, err := parseOptionalBool(c.Req().FormValue("truncate")) - if err != nil { - return &apiError{Status: fiber.StatusBadRequest, Code: "invalid_truncate", Message: err.Error()} - } - useGeneric, err := parseOptionalBool(c.Req().FormValue("use_generic")) - if err != nil { - return &apiError{Status: fiber.StatusBadRequest, Code: "invalid_use_generic", Message: err.Error()} - } - - principal, _ := c.Locals("principal").(*Principal) - if err := s.authz.AuthorizeWrite(c.Context(), principal, project, authResourcePath); err != nil { - return &apiError{Status: fiber.StatusForbidden, Code: "forbidden", Message: err.Error()} - } - - fileHeader, err := c.Req().FormFile("file") - if err != nil { - return &apiError{Status: fiber.StatusBadRequest, Code: "missing_file", Message: "file upload is required"} - } - stagedPath, err := stageUploadedFile(fileHeader) - if err != nil { - return &apiError{Status: fiber.StatusInternalServerError, Code: "stage_failed", Message: err.Error()} - } - - req := ImportRequest{ - Project: project, - ResourceType: resourceType, - AuthResourcePath: authResourcePath, - Truncate: truncate, - UseGeneric: useGeneric, - StagedFilePath: stagedPath, - OriginalFilename: fileHeader.Filename, - } - if principal != nil { - req.SubmittedBy = principal.Subject - } - op, err := s.service.Submit(c.Context(), req) - if err != nil { - _ = os.Remove(stagedPath) - return &apiError{Status: fiber.StatusBadRequest, Code: "invalid_import_request", Message: err.Error()} - } - - return c.Status(fiber.StatusAccepted).JSON(fiber.Map{ - "import_id": op.ID, - "status": op.Status, - "status_url": op.StatusURL, - "events_url": op.EventsURL, - "project": op.Project, - "resource_type": op.ResourceType, - "auth_resource_path": op.AuthResourcePath, - "original_filename": op.OriginalFilename, - "submitted_at": op.SubmittedAt, - }) -} - -func (s *HTTPServer) getImport(c fiber.Ctx) error { - id := c.Params("id") - op, ok := s.service.Get(id) - if !ok { - return &apiError{Status: fiber.StatusNotFound, Code: "import_not_found", Message: fmt.Sprintf("import %s not found", id)} - } - return c.Status(fiber.StatusOK).JSON(op) -} - -func (s *HTTPServer) getImportEvents(c fiber.Ctx) error { - id := c.Params("id") - events, ok := s.service.Events(id) - if !ok { - return &apiError{Status: fiber.StatusNotFound, Code: "import_not_found", Message: fmt.Sprintf("import %s not found", id)} - } - return c.Status(fiber.StatusOK).JSON(fiber.Map{ - "import_id": id, - "events": events, - }) -} - -func requestIDFromCtx(c fiber.Ctx) string { - if requestID, ok := c.Locals("request_id").(string); ok && requestID != "" { - return requestID - } - return "" -} - -func parseOptionalBool(raw string) (bool, error) { - raw = strings.TrimSpace(raw) - if raw == "" { - return false, nil - } - value, err := strconv.ParseBool(raw) - if err != nil { - return false, fmt.Errorf("invalid boolean value %q", raw) - } - return value, nil -} - -func stageUploadedFile(fileHeader *multipart.FileHeader) (string, error) { - src, err := fileHeader.Open() - if err != nil { - return "", err - } - defer src.Close() - - ext := filepath.Ext(fileHeader.Filename) - if ext == "" { - ext = ".ndjson" - } - dst, err := os.CreateTemp("", "arango-fhir-upload-*"+ext) - if err != nil { - return "", err - } - if _, err := io.Copy(dst, src); err != nil { - dst.Close() - os.Remove(dst.Name()) - return "", err - } - if err := dst.Close(); err != nil { - os.Remove(dst.Name()) - return "", err - } - return dst.Name(), nil -} diff --git a/internal/writeapi/service.go b/internal/writeapi/service.go deleted file mode 100644 index ab5b731..0000000 --- a/internal/writeapi/service.go +++ /dev/null @@ -1,315 +0,0 @@ -package writeapi - -import ( - "context" - "errors" - "log/slog" - "os" - "sync" - "time" - - "arangodb-proto/internal/proto" - - "github.com/google/uuid" -) - -type Status string - -const ( - StatusPending Status = "pending" - StatusRunning Status = "running" - StatusSucceeded Status = "succeeded" - StatusFailed Status = "failed" -) - -type Principal struct { - Subject string `json:"subject"` - Claims map[string]string `json:"claims,omitempty"` - Projects []string `json:"projects,omitempty"` - AuthResourcePaths []string `json:"auth_resource_paths,omitempty"` - AuthorizationHeader string `json:"-"` -} - -type principalContextKey struct{} - -func ContextWithPrincipal(ctx context.Context, principal *Principal) context.Context { - if principal == nil { - return ctx - } - return context.WithValue(ctx, principalContextKey{}, principal) -} - -func PrincipalFromContext(ctx context.Context) (*Principal, bool) { - if ctx == nil { - return nil, false - } - principal, ok := ctx.Value(principalContextKey{}).(*Principal) - return principal, ok -} - -type ImportRequest struct { - Project string `json:"project"` - ResourceType string `json:"resource_type"` - AuthResourcePath string `json:"auth_resource_path,omitempty"` - Truncate bool `json:"truncate"` - UseGeneric bool `json:"use_generic"` - StagedFilePath string `json:"-"` - OriginalFilename string `json:"original_filename"` - SubmittedBy string `json:"submitted_by,omitempty"` -} - -type Event struct { - Time time.Time `json:"time"` - Name string `json:"name"` - Fields map[string]any `json:"fields,omitempty"` -} - -type Operation struct { - ID string `json:"id"` - Status Status `json:"status"` - Project string `json:"project"` - ResourceType string `json:"resource_type"` - AuthResourcePath string `json:"auth_resource_path,omitempty"` - OriginalFilename string `json:"original_filename"` - SubmittedBy string `json:"submitted_by,omitempty"` - SubmittedAt time.Time `json:"submitted_at"` - StartedAt *time.Time `json:"started_at,omitempty"` - CompletedAt *time.Time `json:"completed_at,omitempty"` - Error string `json:"error,omitempty"` - Summary *proto.LoadSummary `json:"summary,omitempty"` - EventCount int `json:"event_count"` - StatusURL string `json:"status_url"` - EventsURL string `json:"events_url"` -} - -type Runner interface { - Run(ctx context.Context, req ImportRequest, sink proto.EventSink) (proto.LoadSummary, error) -} - -type ProtoRunner struct { - BaseOptions proto.LoadOptions -} - -func (r ProtoRunner) Run(ctx context.Context, req ImportRequest, sink proto.EventSink) (proto.LoadSummary, error) { - opts := r.BaseOptions - opts.Project = req.Project - opts.AuthResourcePath = req.AuthResourcePath - opts.Truncate = req.Truncate - opts.UseGeneric = req.UseGeneric - opts.EventSink = sink - return proto.LoadSingleResourceFile(ctx, opts, req.ResourceType, req.StagedFilePath) -} - -type ServiceConfig struct { - Runner Runner - MaxConcurrent int - Logger *slog.Logger - OnSuccess func(project string) -} - -type Service struct { - runner Runner - sem chan struct{} - logger *slog.Logger - onSuccess func(project string) - - mu sync.RWMutex - ops map[string]*operationState -} - -type operationState struct { - mu sync.RWMutex - - op Operation - events []Event -} - -func NewService(cfg ServiceConfig) (*Service, error) { - if cfg.Runner == nil { - return nil, errors.New("runner is required") - } - if cfg.MaxConcurrent <= 0 { - cfg.MaxConcurrent = 1 - } - if cfg.Logger == nil { - cfg.Logger = slog.Default() - } - return &Service{ - runner: cfg.Runner, - sem: make(chan struct{}, cfg.MaxConcurrent), - logger: cfg.Logger, - onSuccess: cfg.OnSuccess, - ops: make(map[string]*operationState), - }, nil -} - -func (s *Service) Submit(ctx context.Context, req ImportRequest) (Operation, error) { - if req.Project == "" { - return Operation{}, errors.New("project is required") - } - if req.ResourceType == "" { - return Operation{}, errors.New("resource_type is required") - } - if req.StagedFilePath == "" { - return Operation{}, errors.New("staged file path is required") - } - - now := time.Now().UTC() - id := uuid.NewString() - state := &operationState{ - op: Operation{ - ID: id, - Status: StatusPending, - Project: req.Project, - ResourceType: req.ResourceType, - AuthResourcePath: req.AuthResourcePath, - OriginalFilename: req.OriginalFilename, - SubmittedBy: req.SubmittedBy, - SubmittedAt: now, - StatusURL: "/api/v1/imports/" + id, - EventsURL: "/api/v1/imports/" + id + "/events", - }, - } - state.events = append(state.events, Event{ - Time: now, - Name: "import_submitted", - Fields: map[string]any{ - "project": req.Project, - "resource_type": req.ResourceType, - "auth_resource_path": req.AuthResourcePath, - "truncate": req.Truncate, - "use_generic": req.UseGeneric, - "original_filename": req.OriginalFilename, - }, - }) - state.op.EventCount = len(state.events) - - s.mu.Lock() - s.ops[id] = state - s.mu.Unlock() - - go s.runOperation(context.Background(), state, req) - - return state.snapshot(), nil -} - -func (s *Service) Get(id string) (Operation, bool) { - s.mu.RLock() - state, ok := s.ops[id] - s.mu.RUnlock() - if !ok { - return Operation{}, false - } - return state.snapshot(), true -} - -func (s *Service) Events(id string) ([]Event, bool) { - s.mu.RLock() - state, ok := s.ops[id] - s.mu.RUnlock() - if !ok { - return nil, false - } - return state.eventSnapshot(), true -} - -func (s *Service) runOperation(ctx context.Context, state *operationState, req ImportRequest) { - s.sem <- struct{}{} - defer func() { <-s.sem }() - defer os.Remove(req.StagedFilePath) - - startedAt := time.Now().UTC() - state.mu.Lock() - state.op.Status = StatusRunning - state.op.StartedAt = &startedAt - state.events = append(state.events, Event{ - Time: startedAt, - Name: "import_started", - Fields: map[string]any{"resource_type": req.ResourceType, "project": req.Project}, - }) - state.op.EventCount = len(state.events) - state.mu.Unlock() - - sink := func(event string, fields map[string]any) { - state.appendEvent(event, fields) - } - - summary, err := s.runner.Run(ctx, req, sink) - - completedAt := time.Now().UTC() - state.mu.Lock() - defer state.mu.Unlock() - state.op.CompletedAt = &completedAt - if err != nil { - state.op.Status = StatusFailed - state.op.Error = err.Error() - state.events = append(state.events, Event{ - Time: completedAt, - Name: "import_failed", - Fields: map[string]any{"error": err.Error()}, - }) - s.logger.Error("import failed", "import_id", state.op.ID, "project", req.Project, "resource_type", req.ResourceType, "error", err.Error()) - } else { - state.op.Status = StatusSucceeded - summaryCopy := summary - state.op.Summary = &summaryCopy - state.events = append(state.events, Event{ - Time: completedAt, - Name: "import_succeeded", - Fields: map[string]any{ - "files": summary.Files, - "vertices_inserted": summary.VerticesInserted, - "edges_inserted": summary.EdgesInserted, - }, - }) - s.logger.Info("import succeeded", "import_id", state.op.ID, "project", req.Project, "resource_type", req.ResourceType, "vertices", summary.VerticesInserted, "edges", summary.EdgesInserted) - if s.onSuccess != nil { - s.onSuccess(req.Project) - } - } - state.op.EventCount = len(state.events) -} - -func (o *operationState) appendEvent(name string, fields map[string]any) { - o.mu.Lock() - defer o.mu.Unlock() - copied := make(map[string]any, len(fields)) - for k, v := range fields { - copied[k] = v - } - o.events = append(o.events, Event{ - Time: time.Now().UTC(), - Name: name, - Fields: copied, - }) - o.op.EventCount = len(o.events) -} - -func (o *operationState) snapshot() Operation { - o.mu.RLock() - defer o.mu.RUnlock() - snapshot := o.op - if o.op.Summary != nil { - summaryCopy := *o.op.Summary - snapshot.Summary = &summaryCopy - } - return snapshot -} - -func (o *operationState) eventSnapshot() []Event { - o.mu.RLock() - defer o.mu.RUnlock() - out := make([]Event, 0, len(o.events)) - for _, event := range o.events { - fields := make(map[string]any, len(event.Fields)) - for k, v := range event.Fields { - fields[k] = v - } - out = append(out, Event{ - Time: event.Time, - Name: event.Name, - Fields: fields, - }) - } - return out -} diff --git a/internal/writeapi/service_test.go b/internal/writeapi/service_test.go deleted file mode 100644 index c9842b5..0000000 --- a/internal/writeapi/service_test.go +++ /dev/null @@ -1,198 +0,0 @@ -package writeapi - -import ( - "context" - "errors" - "os" - "testing" - "time" - - "arangodb-proto/internal/proto" -) - -type fakeRunner struct { - summary proto.LoadSummary - err error - delay time.Duration -} - -func (r fakeRunner) Run(ctx context.Context, req ImportRequest, sink proto.EventSink) (proto.LoadSummary, error) { - sink("go_load_file_start", map[string]any{"resource": req.ResourceType}) - if r.delay > 0 { - time.Sleep(r.delay) - } - if r.err != nil { - return proto.LoadSummary{}, r.err - } - sink("go_load_complete", map[string]any{"vertices_inserted": r.summary.VerticesInserted}) - return r.summary, nil -} - -func TestServiceLifecycleSuccess(t *testing.T) { - tmp, err := os.CreateTemp("", "writeapi-service-*.ndjson") - if err != nil { - t.Fatal(err) - } - tmp.Close() - defer os.Remove(tmp.Name()) - - svc, err := NewService(ServiceConfig{ - Runner: fakeRunner{summary: proto.LoadSummary{Files: 1, VerticesInserted: 3, EdgesInserted: 5}}, - }) - if err != nil { - t.Fatal(err) - } - - op, err := svc.Submit(context.Background(), ImportRequest{ - Project: "P1", - ResourceType: "Patient", - StagedFilePath: tmp.Name(), - OriginalFilename: "Patient.ndjson", - }) - if err != nil { - t.Fatal(err) - } - if op.Status != StatusPending { - t.Fatalf("status = %s, want %s", op.Status, StatusPending) - } - - final := waitForStatus(t, svc, op.ID) - if final.Status != StatusSucceeded { - t.Fatalf("status = %s, want %s", final.Status, StatusSucceeded) - } - if final.Summary == nil || final.Summary.VerticesInserted != 3 || final.Summary.EdgesInserted != 5 { - t.Fatalf("unexpected summary: %#v", final.Summary) - } - events, ok := svc.Events(op.ID) - if !ok { - t.Fatal("events not found") - } - if len(events) < 4 { - t.Fatalf("expected lifecycle and loader events, got %d", len(events)) - } -} - -func TestServiceLifecycleFailure(t *testing.T) { - tmp, err := os.CreateTemp("", "writeapi-service-*.ndjson") - if err != nil { - t.Fatal(err) - } - tmp.Close() - defer os.Remove(tmp.Name()) - - svc, err := NewService(ServiceConfig{ - Runner: fakeRunner{err: errors.New("boom")}, - }) - if err != nil { - t.Fatal(err) - } - - op, err := svc.Submit(context.Background(), ImportRequest{ - Project: "P1", - ResourceType: "Patient", - StagedFilePath: tmp.Name(), - OriginalFilename: "Patient.ndjson", - }) - if err != nil { - t.Fatal(err) - } - - final := waitForStatus(t, svc, op.ID) - if final.Status != StatusFailed { - t.Fatalf("status = %s, want %s", final.Status, StatusFailed) - } - if final.Error == "" { - t.Fatal("expected error to be recorded") - } -} - -func TestServiceSuccessInvalidatesProject(t *testing.T) { - tmp, err := os.CreateTemp("", "writeapi-service-*.ndjson") - if err != nil { - t.Fatal(err) - } - tmp.Close() - defer os.Remove(tmp.Name()) - - var invalidated []string - svc, err := NewService(ServiceConfig{ - Runner: fakeRunner{summary: proto.LoadSummary{Files: 1, VerticesInserted: 3, EdgesInserted: 5}}, - OnSuccess: func(project string) { - invalidated = append(invalidated, project) - }, - }) - if err != nil { - t.Fatal(err) - } - - op, err := svc.Submit(context.Background(), ImportRequest{ - Project: "P1", - ResourceType: "Patient", - StagedFilePath: tmp.Name(), - OriginalFilename: "Patient.ndjson", - }) - if err != nil { - t.Fatal(err) - } - final := waitForStatus(t, svc, op.ID) - if final.Status != StatusSucceeded { - t.Fatalf("status = %s, want %s", final.Status, StatusSucceeded) - } - if len(invalidated) != 1 || invalidated[0] != "P1" { - t.Fatalf("invalidated = %#v", invalidated) - } -} - -func TestServiceFailureDoesNotInvalidateProject(t *testing.T) { - tmp, err := os.CreateTemp("", "writeapi-service-*.ndjson") - if err != nil { - t.Fatal(err) - } - tmp.Close() - defer os.Remove(tmp.Name()) - - called := false - svc, err := NewService(ServiceConfig{ - Runner: fakeRunner{err: errors.New("boom")}, - OnSuccess: func(project string) { - called = true - }, - }) - if err != nil { - t.Fatal(err) - } - - op, err := svc.Submit(context.Background(), ImportRequest{ - Project: "P1", - ResourceType: "Patient", - StagedFilePath: tmp.Name(), - OriginalFilename: "Patient.ndjson", - }) - if err != nil { - t.Fatal(err) - } - final := waitForStatus(t, svc, op.ID) - if final.Status != StatusFailed { - t.Fatalf("status = %s, want %s", final.Status, StatusFailed) - } - if called { - t.Fatal("expected no invalidation on failure") - } -} - -func waitForStatus(t *testing.T, svc *Service, id string) Operation { - t.Helper() - deadline := time.Now().Add(2 * time.Second) - for time.Now().Before(deadline) { - op, ok := svc.Get(id) - if !ok { - t.Fatalf("operation %s not found", id) - } - if op.Status == StatusSucceeded || op.Status == StatusFailed { - return op - } - time.Sleep(10 * time.Millisecond) - } - t.Fatalf("timed out waiting for operation %s", id) - return Operation{} -} diff --git a/scripts/delete-ds-store.sh b/scripts/delete-ds-store.sh deleted file mode 100755 index 262c936..0000000 --- a/scripts/delete-ds-store.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" -cd "$repo_root" - -find . -name .DS_Store -type f -delete - -git add -A -- .gitignore -git add -u -- '**/.DS_Store' 2>/dev/null || true -git add -u From f14ac558f7c8891f1334a34df7c3df6f03256efb Mon Sep 17 00:00:00 2001 From: matthewpeterkort Date: Sat, 11 Jul 2026 20:02:23 -0700 Subject: [PATCH 02/15] refactor compiler to be generalizable and not patient centric --- .gitignore | 4 +- Dockerfile | 2 - Makefile | 11 +- README.md | 71 +- cmd/arango-fhir-proto/main.go | 167 +- cmd/arango-fhir-proto/main_test.go | 116 + cmd/arango-fhir-server/main.go | 165 +- cmd/generate/main.go | 113 +- cmd/generate/main_test.go | 144 + docs/COMPILER_CLEANUP_AUDIT.md | 133 + docs/COMPILER_FIRST_PLAN.md | 900 +++ docs/COMPILER_IMPLEMENTATION_STATUS.md | 198 + docs/DATAFRAME_BUILDER_PORTABILITY.md | 720 --- docs/DEVELOPER_ARCHITECTURE.md | 497 +- docs/FORMAL_GAP_ANALYSIS.md | 1544 ++++++ docs/PRODUCT_RECIPE_DISCOVERY.md | 589 ++ docs/TERRA_ULTRA_EXECUTION_PLAN.md | 1107 ++++ experimental/README.md | 19 +- experimental/docker-compose.yml | 2 +- internal/api/http_test.go | 33 + internal/api/routes.go | 10 + internal/api/server.go | 37 +- internal/authscope/scope.go | 141 +- internal/authscope/scope_test.go | 121 + internal/catalog/auth_scope.go | 19 + internal/catalog/auth_scope_test.go | 35 + internal/catalog/cache/cache.go | 25 +- internal/catalog/cache/cache_test.go | 62 + internal/catalog/generation.go | 32 + internal/catalog/generation_test.go | 62 + internal/catalog/helpers.go | 44 + internal/catalog/read_auth_paths.go | 26 +- internal/catalog/read_fields.go | 33 +- internal/catalog/read_references.go | 50 +- internal/catalog/types.go | 72 +- internal/catalog/write_profiler.go | 78 +- internal/catalog/write_profiler_test.go | 152 + internal/dataframe/active_generation.go | 37 + internal/dataframe/active_generation_test.go | 221 + internal/dataframe/aggregate_compile_test.go | 53 + internal/dataframe/auth.go | 30 +- internal/dataframe/auth_scope.go | 28 + internal/dataframe/auth_scope_test.go | 110 + internal/dataframe/builder_types.go | 49 +- internal/dataframe/compile.go | 91 +- internal/dataframe/compile_fields.go | 39 +- internal/dataframe/compile_validation_test.go | 75 + .../compiler_arango_integration_test.go | 323 ++ internal/dataframe/compiler_explanation.go | 478 ++ .../dataframe/compiler_explanation_test.go | 218 + internal/dataframe/dataframe_test.go | 117 +- internal/dataframe/dataset_generation.go | 24 + internal/dataframe/dataset_generation_test.go | 216 + .../dataframe/document_reference_semantics.go | 87 - internal/dataframe/execution.go | 68 +- internal/dataframe/execution_test.go | 131 + internal/dataframe/explain.go | 22 + internal/dataframe/explain_test.go | 20 + internal/dataframe/filter.go | 248 + internal/dataframe/filter_compile.go | 134 + internal/dataframe/filter_compile_test.go | 102 + internal/dataframe/filter_semantics.go | 79 + internal/dataframe/filter_semantics_test.go | 83 + internal/dataframe/filter_test.go | 122 + internal/dataframe/generic_lowering.go | 316 ++ internal/dataframe/generic_lowering_test.go | 111 + internal/dataframe/generic_physical_plan.go | 183 + .../dataframe/generic_physical_plan_test.go | 92 + internal/dataframe/grain.go | 221 + internal/dataframe/grain_test.go | 133 + internal/dataframe/lowered_compile.go | 179 +- internal/dataframe/lowered_types.go | 147 +- internal/dataframe/optimizer.go | 21 + .../optimizer_traversal_sharing_test.go | 280 + internal/dataframe/physical_execution.go | 92 + internal/dataframe/physical_execution_test.go | 139 + internal/dataframe/physical_plan.go | 345 ++ internal/dataframe/physical_plan_test.go | 100 + internal/dataframe/physical_render.go | 639 +++ internal/dataframe/physical_render_test.go | 297 + internal/dataframe/physical_scope.go | 281 + internal/dataframe/physical_scope_test.go | 165 + internal/dataframe/pivots.go | 78 +- internal/dataframe/pivots_test.go | 46 + internal/dataframe/planner.go | 571 +- internal/dataframe/relationship_match.go | 132 + ...ationship_match_arango_integration_test.go | 51 + .../dataframe/relationship_match_compile.go | 67 + internal/dataframe/relationship_match_test.go | 214 + internal/dataframe/selection_semantics.go | 178 + .../dataframe/selection_semantics_test.go | 90 + internal/dataframe/selectors.go | 18 + internal/dataframe/semantic_plan.go | 431 ++ internal/dataframe/semantic_plan_test.go | 97 + internal/dataframe/semantic_validation.go | 102 + .../dataframe/semantic_validation_test.go | 96 + internal/dataframe/service.go | 76 +- internal/dataframe/shaping.go | 200 + internal/dataframe/shaping_plan.go | 202 + internal/dataframe/shaping_plan_test.go | 74 + internal/dataframe/shaping_test.go | 98 + internal/dataframe/storage_route.go | 201 + internal/dataframe/storage_route_test.go | 274 + internal/dataframe/traversal_rules.go | 102 - internal/dataframe/validation.go | 90 +- internal/dataframe/value_mode_test.go | 82 + .../dataframebuilder/active_generation.go | 22 + .../active_generation_test.go | 212 + internal/dataframebuilder/auth_scope_test.go | 155 + internal/dataframebuilder/guided_discovery.go | 79 + .../dataframebuilder/guided_discovery_test.go | 76 + internal/dataframebuilder/input_resolution.go | 79 +- internal/dataframebuilder/introspection.go | 56 +- internal/dataframebuilder/recipe.go | 146 + internal/dataframebuilder/recipe_test.go | 308 ++ internal/dataframebuilder/service.go | 40 +- internal/dataframeexport/doc.go | 16 + internal/dataframeexport/stream.go | 65 + internal/dataframeexport/stream_test.go | 176 + internal/dataset/active.go | 182 + internal/dataset/active_resolver.go | 41 + internal/dataset/active_resolver_test.go | 51 + internal/dataset/active_test.go | 139 + internal/dataset/binding.go | 112 + internal/dataset/doc.go | 10 + internal/dataset/manifest.go | 248 + internal/dataset/manifest_test.go | 123 + internal/dataset/ref.go | 67 + internal/dataset/ref_test.go | 58 + internal/dataset/schema.go | 201 + internal/dataset/schema_test.go | 123 + internal/dataset/scope.go | 164 + internal/dataset/scope_test.go | 78 + internal/dataset/test_helpers_test.go | 67 + internal/dataset/validation.go | 86 + internal/datasetstore/collections.go | 35 + internal/datasetstore/doc.go | 17 + internal/datasetstore/store.go | 704 +++ internal/datasetstore/store_test.go | 477 ++ internal/discovery/build.go | 640 +++ internal/discovery/discovery_test.go | 253 + internal/discovery/resolution.go | 169 + internal/discovery/resolution_test.go | 201 + internal/discovery/types.go | 186 + internal/discovery/validation.go | 326 ++ internal/export/encode.go | 369 ++ internal/export/encode_test.go | 215 + internal/fhir/extract.go | 1742 +++--- internal/fhir/model.go | 4927 ++++++++--------- internal/fhir/validate.go | 305 +- internal/fhirschema/compiler_semantics.go | 185 + .../fhirschema/compiler_semantics_test.go | 68 + internal/fhirschema/generated.go | 438 +- internal/fhirschema/root_resources_test.go | 22 + internal/fhirschema/schema.go | 2 + internal/fhirschema/terminal_metadata.go | 76 + internal/fhirschema/terminal_metadata_test.go | 98 + internal/graphqlapi/http_integration_test.go | 8 +- internal/graphqlapi/output_mapping.go | 7 - internal/graphqlapi/scalars.go | 6 +- internal/ingest/backend.go | 71 +- internal/ingest/backend_test.go | 108 + internal/ingest/generated_load.go | 14 + internal/ingest/generated_load_test.go | 61 + internal/ingest/generation_identity.go | 227 + internal/ingest/generation_identity_test.go | 257 + internal/ingest/generation_load.go | 669 +++ internal/ingest/generation_load_test.go | 203 + internal/ingest/integration_test.go | 51 - internal/ingest/load.go | 199 +- internal/ingest/preflight.go | 196 + internal/ingest/preflight_test.go | 176 + internal/ingest/row_builder.go | 23 + internal/ingest/row_builder_auth_test.go | 56 + internal/recipe/recipe_test.go | 91 + internal/recipe/templates.go | 229 + internal/recipe/templates_test.go | 109 + internal/recipe/types.go | 91 + internal/recipe/validation.go | 179 + internal/recipecompiler/bridge.go | 417 ++ internal/recipecompiler/bridge_test.go | 336 ++ internal/schemaidentity/identity.go | 208 + internal/schemaidentity/identity_test.go | 191 + internal/store/arango/explain.go | 271 + internal/store/arango/explain_assessment.go | 147 + .../store/arango/explain_assessment_test.go | 71 + internal/store/arango/explain_client.go | 53 + internal/store/arango/explain_client_test.go | 70 + internal/store/arango/explain_test.go | 129 + queries/build_focus_ref.aql | 30 - queries/build_member_ref.aql | 30 - queries/build_subject_ref.aql | 29 - queries/document_reference_rows.aql | 200 - queries/gdc_case_assay_matrix_arango_rows.aql | 285 - queries/gdc_case_assay_matrix_rows.aql | 270 - queries/gdc_file_sample_matrix_rows.aql | 193 - 196 files changed, 31527 insertions(+), 7119 deletions(-) create mode 100644 cmd/arango-fhir-proto/main_test.go create mode 100644 cmd/generate/main_test.go create mode 100644 docs/COMPILER_CLEANUP_AUDIT.md create mode 100644 docs/COMPILER_FIRST_PLAN.md create mode 100644 docs/COMPILER_IMPLEMENTATION_STATUS.md delete mode 100644 docs/DATAFRAME_BUILDER_PORTABILITY.md create mode 100644 docs/FORMAL_GAP_ANALYSIS.md create mode 100644 docs/PRODUCT_RECIPE_DISCOVERY.md create mode 100644 docs/TERRA_ULTRA_EXECUTION_PLAN.md create mode 100644 internal/catalog/auth_scope.go create mode 100644 internal/catalog/auth_scope_test.go create mode 100644 internal/catalog/generation.go create mode 100644 internal/catalog/generation_test.go create mode 100644 internal/dataframe/active_generation.go create mode 100644 internal/dataframe/active_generation_test.go create mode 100644 internal/dataframe/aggregate_compile_test.go create mode 100644 internal/dataframe/auth_scope.go create mode 100644 internal/dataframe/auth_scope_test.go create mode 100644 internal/dataframe/compile_validation_test.go create mode 100644 internal/dataframe/compiler_arango_integration_test.go create mode 100644 internal/dataframe/compiler_explanation.go create mode 100644 internal/dataframe/compiler_explanation_test.go create mode 100644 internal/dataframe/dataset_generation.go create mode 100644 internal/dataframe/dataset_generation_test.go delete mode 100644 internal/dataframe/document_reference_semantics.go create mode 100644 internal/dataframe/execution_test.go create mode 100644 internal/dataframe/explain.go create mode 100644 internal/dataframe/explain_test.go create mode 100644 internal/dataframe/filter.go create mode 100644 internal/dataframe/filter_compile.go create mode 100644 internal/dataframe/filter_compile_test.go create mode 100644 internal/dataframe/filter_semantics.go create mode 100644 internal/dataframe/filter_semantics_test.go create mode 100644 internal/dataframe/filter_test.go create mode 100644 internal/dataframe/generic_lowering.go create mode 100644 internal/dataframe/generic_lowering_test.go create mode 100644 internal/dataframe/generic_physical_plan.go create mode 100644 internal/dataframe/generic_physical_plan_test.go create mode 100644 internal/dataframe/grain.go create mode 100644 internal/dataframe/grain_test.go create mode 100644 internal/dataframe/optimizer.go create mode 100644 internal/dataframe/optimizer_traversal_sharing_test.go create mode 100644 internal/dataframe/physical_execution.go create mode 100644 internal/dataframe/physical_execution_test.go create mode 100644 internal/dataframe/physical_plan.go create mode 100644 internal/dataframe/physical_plan_test.go create mode 100644 internal/dataframe/physical_render.go create mode 100644 internal/dataframe/physical_render_test.go create mode 100644 internal/dataframe/physical_scope.go create mode 100644 internal/dataframe/physical_scope_test.go create mode 100644 internal/dataframe/pivots_test.go create mode 100644 internal/dataframe/relationship_match.go create mode 100644 internal/dataframe/relationship_match_arango_integration_test.go create mode 100644 internal/dataframe/relationship_match_compile.go create mode 100644 internal/dataframe/relationship_match_test.go create mode 100644 internal/dataframe/selection_semantics.go create mode 100644 internal/dataframe/selection_semantics_test.go create mode 100644 internal/dataframe/semantic_plan.go create mode 100644 internal/dataframe/semantic_plan_test.go create mode 100644 internal/dataframe/semantic_validation.go create mode 100644 internal/dataframe/semantic_validation_test.go create mode 100644 internal/dataframe/shaping.go create mode 100644 internal/dataframe/shaping_plan.go create mode 100644 internal/dataframe/shaping_plan_test.go create mode 100644 internal/dataframe/shaping_test.go create mode 100644 internal/dataframe/storage_route.go create mode 100644 internal/dataframe/storage_route_test.go delete mode 100644 internal/dataframe/traversal_rules.go create mode 100644 internal/dataframe/value_mode_test.go create mode 100644 internal/dataframebuilder/active_generation.go create mode 100644 internal/dataframebuilder/active_generation_test.go create mode 100644 internal/dataframebuilder/auth_scope_test.go create mode 100644 internal/dataframebuilder/guided_discovery.go create mode 100644 internal/dataframebuilder/guided_discovery_test.go create mode 100644 internal/dataframebuilder/recipe.go create mode 100644 internal/dataframebuilder/recipe_test.go create mode 100644 internal/dataframeexport/doc.go create mode 100644 internal/dataframeexport/stream.go create mode 100644 internal/dataframeexport/stream_test.go create mode 100644 internal/dataset/active.go create mode 100644 internal/dataset/active_resolver.go create mode 100644 internal/dataset/active_resolver_test.go create mode 100644 internal/dataset/active_test.go create mode 100644 internal/dataset/binding.go create mode 100644 internal/dataset/doc.go create mode 100644 internal/dataset/manifest.go create mode 100644 internal/dataset/manifest_test.go create mode 100644 internal/dataset/ref.go create mode 100644 internal/dataset/ref_test.go create mode 100644 internal/dataset/schema.go create mode 100644 internal/dataset/schema_test.go create mode 100644 internal/dataset/scope.go create mode 100644 internal/dataset/scope_test.go create mode 100644 internal/dataset/test_helpers_test.go create mode 100644 internal/dataset/validation.go create mode 100644 internal/datasetstore/collections.go create mode 100644 internal/datasetstore/doc.go create mode 100644 internal/datasetstore/store.go create mode 100644 internal/datasetstore/store_test.go create mode 100644 internal/discovery/build.go create mode 100644 internal/discovery/discovery_test.go create mode 100644 internal/discovery/resolution.go create mode 100644 internal/discovery/resolution_test.go create mode 100644 internal/discovery/types.go create mode 100644 internal/discovery/validation.go create mode 100644 internal/export/encode.go create mode 100644 internal/export/encode_test.go create mode 100644 internal/fhirschema/compiler_semantics.go create mode 100644 internal/fhirschema/compiler_semantics_test.go create mode 100644 internal/fhirschema/root_resources_test.go create mode 100644 internal/fhirschema/terminal_metadata.go create mode 100644 internal/fhirschema/terminal_metadata_test.go create mode 100644 internal/ingest/backend_test.go create mode 100644 internal/ingest/generated_load_test.go create mode 100644 internal/ingest/generation_identity.go create mode 100644 internal/ingest/generation_identity_test.go create mode 100644 internal/ingest/generation_load.go create mode 100644 internal/ingest/generation_load_test.go create mode 100644 internal/ingest/preflight.go create mode 100644 internal/ingest/preflight_test.go create mode 100644 internal/ingest/row_builder_auth_test.go create mode 100644 internal/recipe/recipe_test.go create mode 100644 internal/recipe/templates.go create mode 100644 internal/recipe/templates_test.go create mode 100644 internal/recipe/types.go create mode 100644 internal/recipe/validation.go create mode 100644 internal/recipecompiler/bridge.go create mode 100644 internal/recipecompiler/bridge_test.go create mode 100644 internal/schemaidentity/identity.go create mode 100644 internal/schemaidentity/identity_test.go create mode 100644 internal/store/arango/explain.go create mode 100644 internal/store/arango/explain_assessment.go create mode 100644 internal/store/arango/explain_assessment_test.go create mode 100644 internal/store/arango/explain_client.go create mode 100644 internal/store/arango/explain_client_test.go create mode 100644 internal/store/arango/explain_test.go delete mode 100644 queries/build_focus_ref.aql delete mode 100644 queries/build_member_ref.aql delete mode 100644 queries/build_subject_ref.aql delete mode 100644 queries/document_reference_rows.aql delete mode 100644 queries/gdc_case_assay_matrix_arango_rows.aql delete mode 100644 queries/gdc_case_assay_matrix_rows.aql delete mode 100644 queries/gdc_file_sample_matrix_rows.aql diff --git a/.gitignore b/.gitignore index f02ae2a..d1a296b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,5 @@ bin/ data/ META/ -arango-fhir-proto -arango-fhir-server +/arango-fhir-proto +/arango-fhir-server diff --git a/Dockerfile b/Dockerfile index 6187787..3265b77 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,6 @@ RUN --mount=type=cache,target=/go/pkg/mod \ COPY cmd ./cmd COPY internal ./internal -COPY queries ./queries COPY schemas ./schemas ARG TARGETOS=linux @@ -35,7 +34,6 @@ WORKDIR /app COPY --from=builder /out/arango-fhir-server /app/arango-fhir-server COPY --from=builder /src/schemas /app/schemas -COPY --from=builder /src/queries /app/queries USER arango-fhir EXPOSE 8080 diff --git a/Makefile b/Makefile index ebff3e3..3354be8 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: build build-cli build-server clean generate-fhir generate-graphql graphql-check gqlgen-check test docker-build docker-run +.PHONY: build build-cli build-server clean compiler-bench conformance generate-fhir generate-graphql graphql-check gqlgen-check test docker-build docker-run GO ?= go GOCACHE_DIR ?= $(CURDIR)/.gocache @@ -29,6 +29,7 @@ generate-graphql: generate-fhir: mkdir -p $(GOCACHE_DIR) GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) run ./cmd/generate -schema $(SCHEMA_PATH) -out-dir internal/fhir + gofmt -w internal/fhir/model.go internal/fhir/validate.go internal/fhir/extract.go internal/fhirschema/generated.go graphql-check: mkdir -p $(GOCACHE_DIR) @@ -40,6 +41,14 @@ test: mkdir -p $(GOCACHE_DIR) GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) test $(GOFLAGS) ./... -count=1 +compiler-bench: + mkdir -p $(GOCACHE_DIR) + GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) test $(GOFLAGS) ./conformance/compiler -run '^$$' -bench '^BenchmarkCompilerOracle$$' -benchmem + +conformance: + mkdir -p $(GOCACHE_DIR) + GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) test $(GOFLAGS) ./conformance/... -count=1 + docker-build: docker build -t $(IMAGE) . diff --git a/README.md b/README.md index 6be90ff..fcb3288 100644 --- a/README.md +++ b/README.md @@ -3,27 +3,35 @@ FHIR graph loader and dataframe server, with ArangoDB as the primary execution backend. -This repo now has two main runtime surfaces: +This repo has two main runtime surfaces: -- `arango-fhir-proto`: CLI for load, discovery, query, prepare, and benchmark work -- `arango-fhir-server`: Fiber server for GraphQL reads plus a direct REST import endpoint +- `arango-fhir-proto`: CLI for FHIR loading (including immutable complete + generations) and catalog diagnostics +- `arango-fhir-server`: Fiber server for compiler-backed GraphQL reads and a + temporary one-file import compatibility endpoint The current product direction is: - load raw FHIR NDJSON into one collection per resource type - store graph edges in `fhir_edge` - profile populated fields into `fhir_field_catalog` -- expose builder introspection and dataframe execution through GraphQL -ArangoDB is the first-class backend for dataframe execution. SurrealDB and -Postgres code remains under [`experimental/`](experimental/) for research and -benchmarking only. +- lower typed dataframe requests through the FHIR-aware compiler into scoped AQL +- expose the current expert/compatibility GraphQL transport while the guided + recipe transport is being added + +ArangoDB is the only runtime backend. The tracked [`experimental/`](experimental/) +directory contains the local Arango compose setup. ## Docs - [Quickstart](docs/QUICKSTART.md) - [Developer Architecture](docs/DEVELOPER_ARCHITECTURE.md) -- [GraphQL/Dataframe Portability Notes](docs/DATAFRAME_BUILDER_PORTABILITY.md) -- [Arango vs. Surreal post-mortem](experimental/ARANGO_VS_SURREAL_FHIR_POSTMORTEM.md) +- [Product Recipes and Dataset Discovery](docs/PRODUCT_RECIPE_DISCOVERY.md) +- [Formal Product Gap Analysis](docs/FORMAL_GAP_ANALYSIS.md) +- [Compiler-First FHIR/AQL Plan](docs/COMPILER_FIRST_PLAN.md) +- [Compiler-First Implementation Status](docs/COMPILER_IMPLEMENTATION_STATUS.md) +- [Terra Ultra Parallel Execution Plan](docs/TERRA_ULTRA_EXECUTION_PLAN.md) +- [Compiler Cleanup Audit](docs/COMPILER_CLEANUP_AUDIT.md) ## Current Layout @@ -32,14 +40,20 @@ benchmarking only. - [`internal/ingest`](internal/ingest): load pipeline and Arango ingest bootstrap/runtime - [`internal/catalog`](internal/catalog): populated-field and populated-reference discovery - [`internal/catalog/cache`](internal/catalog/cache): per-project discovery cache +- [`internal/discovery`](internal/discovery): safe guided capability snapshots built from scoped catalog facts +- [`internal/dataset`](internal/dataset): dataset generation, schema, and scope lifecycle contract +- [`internal/datasetstore`](internal/datasetstore): Arango-backed immutable manifest and active-generation pointer store - [`internal/graphqlapi`](internal/graphqlapi): GraphQL schema, request mapping, introspection service - [`internal/dataframe`](internal/dataframe): dataframe validation, lowering, and AQL compilation +- [`internal/export`](internal/export): strict flat-row NDJSON and CSV encoding primitives +- [`internal/dataframeexport`](internal/dataframeexport): streaming bridge from dataframe execution to flat encoders - [`internal/fhirschema`](internal/fhirschema): generated schema metadata used by planner/validation -- [`internal/fhirsemantics`](internal/fhirsemantics): friendly `fieldRef`s and semantic lowering hints -- [`internal/api`](internal/api): HTTP API surface and ingest import wiring +- [`internal/dataframebuilder`](internal/dataframebuilder): builder introspection, friendly `fieldRef`s, and GraphQL input translation +- [`internal/recipe`](internal/recipe): versioned product recipe intent and guided template metadata +- [`internal/schemaidentity`](internal/schemaidentity): exact graph-schema identity captured by dataset generations +- [`internal/api`](internal/api): HTTP host, authenticated GraphQL mounting, and legacy import compatibility wiring - [`internal/authscope`](internal/authscope): shared request principal context and auth-resource-path scope resolution -- [`queries/`](queries/): Arango AQL query artifacts -- [`experimental/`](experimental/): non-primary backend work and benchmark artifacts +- [`experimental/`](experimental/): local Arango development compose setup ## Local Dev @@ -69,6 +83,21 @@ Load the bundled sample dataset: --auth-resource-path EllrottLab-GDC_Data ``` +For an immutable, generation-qualified load instead of the mutable prototype +load above, use a complete `META` directory and an operator-supplied opaque +generation ID. This command deliberately has no `--truncate` flag: + +```bash +./bin/arango-fhir-proto load-generation \ + --generation local-meta-2026-07-11 \ + --backend arango \ + --url http://127.0.0.1:8529 \ + --database fhir_proto \ + --meta-dir META \ + --project ARANGODB_PROTO \ + --auth-resource-path EllrottLab-GDC_Data +``` + Start the server in local demo mode: ```bash @@ -80,6 +109,10 @@ Start the server in local demo mode: --database fhir_proto ``` +To read the active immutable generation instead, add `--dataset-generations`. +That mode disables `POST /api/v1/imports`; use `load-generation` (or the future +bundle/job API) to create a complete snapshot. + Then open: - Apollo Sandbox: [http://127.0.0.1:8080/apollo](http://127.0.0.1:8080/apollo) @@ -104,6 +137,8 @@ Important make targets: - `make build-cli` - `make graphql-check` - `make test` +- `make conformance` +- `make compiler-bench` `make generate-graphql` is important now. The GraphQL schema and generated artifacts are not purely static, and the repo includes a small reproducible @@ -117,7 +152,7 @@ The server mounts: - `GET /apollo` - `GET /graphql` - `POST /graphql` -- `POST /api/v1/imports` +- `POST /api/v1/imports` (legacy one-file import; disabled with `--dataset-generations`) HTTP wiring lives in [`internal/api/routes.go`](internal/api/routes.go) and [`internal/api/server.go`](internal/api/server.go). @@ -128,7 +163,7 @@ The loader bootstraps: - one collection per FHIR resource type discovered in the NDJSON input - `fhir_edge` - `fhir_field_catalog` -- `patient_file_rollup` +- `loom_dataset_lifecycle` for generation-aware loads (never truncated) See [`internal/ingest/backend.go`](internal/ingest/backend.go). @@ -139,9 +174,9 @@ What is current and real: - GraphQL introspection for populated traversals/fields/pivots - GraphQL dataframe execution on Arango - generated schema metadata in `internal/fhirschema` -- semantic alias/lowering hints in `internal/fhirsemantics` +- derived field aliases in `internal/dataframebuilder` and explicit lowering rules in `internal/dataframe` What is explicitly experimental: -- SurrealDB/Postgres benchmarking and comparison -- alternate query artifacts under [`experimental/queries/`](experimental/queries/) +- the guided discovery, recipe, and streaming-export foundations until their + public delivery API exists diff --git a/cmd/arango-fhir-proto/main.go b/cmd/arango-fhir-proto/main.go index 11fba4d..0a9f526 100644 --- a/cmd/arango-fhir-proto/main.go +++ b/cmd/arango-fhir-proto/main.go @@ -11,6 +11,7 @@ import ( "runtime/trace" "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/dataset" "github.com/calypr/loom/internal/ingest" ) @@ -32,10 +33,8 @@ func main() { switch os.Args[1] { case "load": err = runLoad(ctx, os.Args[2:]) - case "query-gdc-case-assay-matrix": - err = runQuery(ctx, os.Args[2:], false) - case "export-gdc-case-assay-matrix": - err = runQuery(ctx, os.Args[2:], true) + case "load-generation": + err = runLoadGeneration(ctx, os.Args[2:]) case "discover-populated-references": err = runDiscoverPopulatedReferences(ctx, os.Args[2:]) case "discover-populated-fields": @@ -50,30 +49,93 @@ func main() { } } +type loadCommandConfig struct { + Options ingest.LoadOptions + Backend string + + CPUProfile string + MemProfile string + TraceProfile string + BlockProfile string + + Generation string +} + func runLoad(ctx context.Context, args []string) error { - fs := flag.NewFlagSet("load", flag.ExitOnError) - opts := ingest.LoadOptions{} - cpuProfile := fs.String("cpu-profile", "", "Write CPU profile to file") - memProfile := fs.String("mem-profile", "", "Write heap profile to file at end of run") - traceProfile := fs.String("trace-profile", "", "Write runtime trace to file") - blockProfile := fs.String("block-profile", "", "Write block profile to file at end of run") - fs.StringVar(&opts.URL, "url", defaultURL, "Backend base URL") - fs.StringVar(&opts.Database, "database", defaultDatabase, "Backend database") - fs.StringVar(&opts.Schema, "schema", defaultSchema, "graph-fhir JSON schema") - fs.StringVar(&opts.MetaDir, "meta-dir", defaultMetaDir, "Directory containing META/*.ndjson") - fs.StringVar(&opts.Project, "project", defaultProject, "Project label") - fs.StringVar(&opts.AuthResourcePath, "auth-resource-path", "", "Optional auth resource path copied onto vertex data, for example EllrottLab-GDC_Data") - fs.IntVar(&opts.BatchSize, "batch-size", 5000, "Bulk insert batch size") - fs.IntVar(&opts.ProgressEvery, "progress-every", 50000, "Emit progress every N input rows") - fs.IntVar(&opts.WriterCount, "writers", 8, "Concurrent writer goroutines") - fs.BoolVar(&opts.Truncate, "truncate", true, "Truncate prototype collections before loading") - fs.BoolVar(&opts.FailFast, "fail-fast", false, "Stop on the first decode, validation, or edge conversion error") - fs.BoolVar(&opts.UseGeneric, "use-generic", false, "Use the generic jsonschema + jsonschemagraph validator and extractor") - fs.StringVar(&opts.WriteAPI, "write-api", "import", "Bulk write API: import or document") - if err := fs.Parse(args); err != nil { + return runLoadCommand(ctx, args, false) +} + +func runLoadGeneration(ctx context.Context, args []string) error { + return runLoadCommand(ctx, args, true) +} + +func runLoadCommand(ctx context.Context, args []string, generationMode bool) error { + config, err := parseLoadCommand(args, generationMode, flag.ExitOnError) + if err != nil { return err } - stopProfiles, profileErr := startProfiles(*cpuProfile, *memProfile, *traceProfile, *blockProfile) + return runConfiguredLoad(ctx, config) +} + +func parseLoadCommand(args []string, generationMode bool, errorHandling flag.ErrorHandling) (loadCommandConfig, error) { + name := "load" + if generationMode { + name = "load-generation" + } + fs := flag.NewFlagSet(name, errorHandling) + config := loadCommandConfig{} + configureLoadFlags(fs, &config, generationMode) + if err := fs.Parse(args); err != nil { + return loadCommandConfig{}, err + } + if config.Backend != "arango" { + return loadCommandConfig{}, fmt.Errorf("unsupported backend %q: only arango is supported", config.Backend) + } + if !generationMode { + return config, nil + } + if config.Generation == "" { + return loadCommandConfig{}, fmt.Errorf("--generation is required for load-generation") + } + if config.Options.Truncate { + return loadCommandConfig{}, fmt.Errorf("--truncate=true is not permitted for load-generation") + } + ref, err := dataset.NewDatasetRef(config.Options.Project, config.Generation) + if err != nil { + return loadCommandConfig{}, fmt.Errorf("invalid --generation for load-generation: %w", err) + } + config.Options.Dataset = &ref + return config, nil +} + +func configureLoadFlags(fs *flag.FlagSet, config *loadCommandConfig, generationMode bool) { + fs.StringVar(&config.Backend, "backend", "arango", "Storage backend; only arango is supported") + fs.StringVar(&config.CPUProfile, "cpu-profile", "", "Write CPU profile to file") + fs.StringVar(&config.MemProfile, "mem-profile", "", "Write heap profile to file at end of run") + fs.StringVar(&config.TraceProfile, "trace-profile", "", "Write runtime trace to file") + fs.StringVar(&config.BlockProfile, "block-profile", "", "Write block profile to file at end of run") + fs.StringVar(&config.Options.URL, "url", defaultURL, "Backend base URL") + fs.StringVar(&config.Options.Database, "database", defaultDatabase, "Backend database") + fs.StringVar(&config.Options.Schema, "schema", defaultSchema, "graph-fhir JSON schema") + fs.StringVar(&config.Options.MetaDir, "meta-dir", defaultMetaDir, "Directory containing META/*.ndjson") + fs.StringVar(&config.Options.Project, "project", defaultProject, "Project label") + fs.StringVar(&config.Options.AuthResourcePath, "auth-resource-path", "", "Optional auth resource path copied onto vertex data, for example EllrottLab-GDC_Data") + fs.IntVar(&config.Options.BatchSize, "batch-size", 5000, "Bulk insert batch size") + fs.IntVar(&config.Options.ProgressEvery, "progress-every", 50000, "Emit progress every N input rows") + fs.IntVar(&config.Options.WriterCount, "writers", 8, "Concurrent writer goroutines") + if !generationMode { + fs.BoolVar(&config.Options.Truncate, "truncate", true, "Truncate prototype collections before loading") + } + fs.BoolVar(&config.Options.FailFast, "fail-fast", false, "Stop on the first decode, validation, or edge conversion error") + fs.BoolVar(&config.Options.UseGeneric, "use-generic", false, "Use the generic jsonschema + jsonschemagraph validator and extractor") + fs.StringVar(&config.Options.WriteAPI, "write-api", "import", "Bulk write API: import or document") + if generationMode { + fs.StringVar(&config.Generation, "generation", "", "Required opaque immutable dataset generation identifier") + } +} + +func runConfiguredLoad(ctx context.Context, config loadCommandConfig) error { + stopProfiles, profileErr := startProfiles(config.CPUProfile, config.MemProfile, config.TraceProfile, config.BlockProfile) if profileErr != nil { return profileErr } @@ -83,7 +145,7 @@ func runLoad(ctx context.Context, args []string) error { deferredErr = stopErr } }() - summary, err := ingest.Load(ctx, opts) + summary, err := ingest.Load(ctx, config.Options) if err != nil { return err } @@ -94,14 +156,8 @@ func runLoad(ctx context.Context, args []string) error { } func runDiscoverPopulatedReferences(ctx context.Context, args []string) error { - fs := flag.NewFlagSet("discover-populated-references", flag.ExitOnError) - opts := catalog.PopulatedReferenceOptions{} - fs.StringVar(&opts.URL, "url", defaultURL, "Backend base URL") - fs.StringVar(&opts.Database, "database", defaultDatabase, "Backend database") - fs.StringVar(&opts.Project, "project", defaultProject, "Project label") - fs.StringVar(&opts.FromType, "from-type", "", "Optional source collection/resource type filter, for example Patient") - fs.IntVar(&opts.CursorBatch, "cursor-batch-size", 1000, "Query cursor batch size") - if err := fs.Parse(args); err != nil { + opts, err := parseDiscoverPopulatedReferenceOptions(args, flag.ExitOnError) + if err != nil { return err } results, err := catalog.DiscoverPopulatedReferences(ctx, opts) @@ -112,22 +168,46 @@ func runDiscoverPopulatedReferences(ctx context.Context, args []string) error { } func runDiscoverPopulatedFields(ctx context.Context, args []string) error { - fs := flag.NewFlagSet("discover-populated-fields", flag.ExitOnError) + opts, err := parseDiscoverPopulatedFieldOptions(args, flag.ExitOnError) + if err != nil { + return err + } + results, err := catalog.DiscoverPopulatedFields(ctx, opts) + if err != nil { + return err + } + return printJSON(results) +} + +func parseDiscoverPopulatedReferenceOptions(args []string, errorHandling flag.ErrorHandling) (catalog.PopulatedReferenceOptions, error) { + fs := flag.NewFlagSet("discover-populated-references", errorHandling) + opts := catalog.PopulatedReferenceOptions{} + fs.StringVar(&opts.URL, "url", defaultURL, "Backend base URL") + fs.StringVar(&opts.Database, "database", defaultDatabase, "Backend database") + fs.StringVar(&opts.Project, "project", defaultProject, "Project label") + fs.StringVar(&opts.DatasetGeneration, "dataset-generation", "", "Optional generation to inspect; empty selects the legacy namespace and never resolves an active generation") + fs.StringVar(&opts.FromType, "from-type", "", "Optional source collection/resource type filter, for example Patient") + fs.IntVar(&opts.CursorBatch, "cursor-batch-size", 1000, "Query cursor batch size") + if err := fs.Parse(args); err != nil { + return catalog.PopulatedReferenceOptions{}, err + } + return opts, nil +} + +func parseDiscoverPopulatedFieldOptions(args []string, errorHandling flag.ErrorHandling) (catalog.PopulatedFieldOptions, error) { + fs := flag.NewFlagSet("discover-populated-fields", errorHandling) opts := catalog.PopulatedFieldOptions{} fs.StringVar(&opts.URL, "url", defaultURL, "Backend base URL") fs.StringVar(&opts.Database, "database", defaultDatabase, "Backend database") fs.StringVar(&opts.Project, "project", defaultProject, "Project label") + fs.StringVar(&opts.DatasetGeneration, "dataset-generation", "", "Optional generation to inspect; empty selects the legacy namespace and never resolves an active generation") fs.StringVar(&opts.ResourceType, "resource-type", "", "Optional resource type filter, for example Patient") fs.BoolVar(&opts.PivotOnly, "pivot-only", false, "Return only pivot-candidate fields") fs.IntVar(&opts.CursorBatch, "cursor-batch-size", 1000, "Query cursor batch size") if err := fs.Parse(args); err != nil { - return err - } - results, err := catalog.DiscoverPopulatedFields(ctx, opts) - if err != nil { - return err + return catalog.PopulatedFieldOptions{}, err } - return printJSON(results) + return opts, nil } func printJSON(value any) error { @@ -141,9 +221,8 @@ func printJSON(value any) error { func usage() { fmt.Fprintf(os.Stderr, `usage: - arango-fhir-proto load [flags] - arango-fhir-proto query-gdc-case-assay-matrix [flags] - arango-fhir-proto export-gdc-case-assay-matrix --output FILE [flags] + arango-fhir-proto load [flags] # legacy mutable import; default --truncate=true + arango-fhir-proto load-generation --generation OPAQUE_ID [flags] # immutable complete META directory; no --truncate flag arango-fhir-proto discover-populated-references [flags] arango-fhir-proto discover-populated-fields [flags] `) diff --git a/cmd/arango-fhir-proto/main_test.go b/cmd/arango-fhir-proto/main_test.go new file mode 100644 index 0000000..e9587e5 --- /dev/null +++ b/cmd/arango-fhir-proto/main_test.go @@ -0,0 +1,116 @@ +package main + +import ( + "flag" + "strings" + "testing" +) + +func TestParseLegacyLoadPreservesMutableDefaults(t *testing.T) { + config, err := parseLoadCommand([]string{ + "--project", "legacy-project", + "--meta-dir", "META_SMALL", + }, false, flag.ContinueOnError) + if err != nil { + t.Fatalf("parseLoadCommand() error = %v", err) + } + if !config.Options.Truncate { + t.Fatal("legacy load truncate = false, want true default") + } + if config.Options.Dataset != nil { + t.Fatalf("legacy load Dataset = %#v, want nil", config.Options.Dataset) + } + if got, want := config.Options.Project, "legacy-project"; got != want { + t.Fatalf("legacy load project = %q, want %q", got, want) + } + if got, want := config.Options.MetaDir, "META_SMALL"; got != want { + t.Fatalf("legacy load meta dir = %q, want %q", got, want) + } +} + +func TestParseGenerationLoadWiresImmutableDataset(t *testing.T) { + config, err := parseLoadCommand([]string{ + "--project", "project-a", + "--generation", "load:2026-07-11/v1", + "--meta-dir", "META_SMALL", + }, true, flag.ContinueOnError) + if err != nil { + t.Fatalf("parseLoadCommand() error = %v", err) + } + if config.Options.Truncate { + t.Fatal("generation load truncate = true, want false") + } + if config.Options.Dataset == nil { + t.Fatal("generation load Dataset = nil, want immutable dataset reference") + } + if got, want := config.Options.Dataset.Project, "project-a"; got != want { + t.Fatalf("generation dataset project = %q, want %q", got, want) + } + if got, want := config.Options.Dataset.Generation, "load:2026-07-11/v1"; got != want { + t.Fatalf("generation dataset generation = %q, want %q", got, want) + } +} + +func TestParseGenerationLoadRejectsUnsafeOrInvalidInput(t *testing.T) { + tests := []struct { + name string + args []string + want string + }{ + { + name: "missing generation", + args: []string{"--project", "project-a"}, + want: "--generation is required", + }, + { + name: "invalid opaque generation", + args: []string{"--project", "project-a", "--generation", " generation-a"}, + want: "invalid --generation", + }, + { + name: "truncate is not exposed", + args: []string{"--project", "project-a", "--generation", "generation-a", "--truncate=true"}, + want: "flag provided but not defined", + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + _, err := parseLoadCommand(test.args, true, flag.ContinueOnError) + if err == nil || !strings.Contains(err.Error(), test.want) { + t.Fatalf("parseLoadCommand() error = %v, want containing %q", err, test.want) + } + }) + } +} + +func TestParseDiscoveryCommandsPassExplicitDatasetGeneration(t *testing.T) { + fields, err := parseDiscoverPopulatedFieldOptions([]string{ + "--project", "project-a", + "--dataset-generation", "generation-a", + "--resource-type", "Patient", + }, flag.ContinueOnError) + if err != nil { + t.Fatalf("parseDiscoverPopulatedFieldOptions() error = %v", err) + } + if got, want := fields.DatasetGeneration, "generation-a"; got != want { + t.Fatalf("field discovery generation = %q, want %q", got, want) + } + if got, want := fields.ResourceType, "Patient"; got != want { + t.Fatalf("field discovery resource type = %q, want %q", got, want) + } + + references, err := parseDiscoverPopulatedReferenceOptions([]string{ + "--project", "project-a", + "--dataset-generation", "generation-a", + "--from-type", "Specimen", + }, flag.ContinueOnError) + if err != nil { + t.Fatalf("parseDiscoverPopulatedReferenceOptions() error = %v", err) + } + if got, want := references.DatasetGeneration, "generation-a"; got != want { + t.Fatalf("reference discovery generation = %q, want %q", got, want) + } + if got, want := references.FromType, "Specimen"; got != want { + t.Fatalf("reference discovery source type = %q, want %q", got, want) + } +} diff --git a/cmd/arango-fhir-server/main.go b/cmd/arango-fhir-server/main.go index da86818..39bac8d 100644 --- a/cmd/arango-fhir-server/main.go +++ b/cmd/arango-fhir-server/main.go @@ -1,65 +1,104 @@ package main import ( + "context" "flag" "fmt" "log/slog" "os" + "os/signal" + "syscall" "github.com/calypr/loom/internal/api" "github.com/calypr/loom/internal/authscope" "github.com/calypr/loom/internal/catalog" - "github.com/calypr/loom/internal/catalog/cache" + catalogcache "github.com/calypr/loom/internal/catalog/cache" + "github.com/calypr/loom/internal/dataframe" + "github.com/calypr/loom/internal/dataframebuilder" + "github.com/calypr/loom/internal/datasetstore" "github.com/calypr/loom/internal/graphqlapi" "github.com/calypr/loom/internal/ingest" -) - -const ( - defaultURL = "http://127.0.0.1:8529" - defaultDatabase = "fhir_proto" - defaultSchema = "schemas/graph-fhir.json" + arangostore "github.com/calypr/loom/internal/store/arango" ) func main() { - fs := flag.NewFlagSet("arango-fhir-server", flag.ExitOnError) - listenAddr := fs.String("listen", ":8080", "HTTP listen address") - bodyLimit := fs.Int("body-limit", 1024*1024*1024, "Maximum request body size in bytes") - readBufferSize := fs.Int("read-buffer-size", 1024*1024, "Fiber request read buffer size in bytes; also limits max header size") - noAuth := fs.Bool("no-auth", false, "Disable scope-based auth for local demo use") + var ( + listen = flag.String("listen", ":8080", "HTTP listen address") + noAuth = flag.Bool("no-auth", false, "disable scoped authorization for local development") + backend = flag.String("backend", "arango", "storage backend") + url = flag.String("url", "http://127.0.0.1:8529", "ArangoDB URL") + database = flag.String("database", "fhir_proto", "ArangoDB database") + schema = flag.String("schema", "schemas/graph-fhir.json", "FHIR graph schema path for imports") + // Dataset generations opt the server into resolving a project's READY + // active manifest before dataframe discovery or execution. This mode + // disables the legacy one-file import route because that route cannot + // safely construct a complete immutable snapshot. + datasetGenerations = flag.Bool("dataset-generations", false, "resolve active immutable dataset generations for dataframe reads and disable legacy single-resource imports") + ) + flag.Parse() - loadOpts := ingest.LoadOptions{} - fs.StringVar(&loadOpts.URL, "url", defaultURL, "Backend base URL") - fs.StringVar(&loadOpts.Database, "database", defaultDatabase, "Backend database") - fs.StringVar(&loadOpts.Schema, "schema", defaultSchema, "graph-fhir JSON schema") - fs.IntVar(&loadOpts.BatchSize, "batch-size", 5000, "Bulk insert batch size") - fs.IntVar(&loadOpts.ProgressEvery, "progress-every", 50000, "Emit progress every N input rows") - fs.IntVar(&loadOpts.WriterCount, "writers", 8, "Concurrent writer goroutines") - fs.BoolVar(&loadOpts.FailFast, "fail-fast", false, "Stop on the first decode, validation, or edge conversion error") - fs.StringVar(&loadOpts.WriteAPI, "write-api", "import", "Bulk write API: import or document") + if *backend != "arango" { + exitf("unsupported backend %q: only arango is wired in this server", *backend) + } - if err := fs.Parse(os.Args[1:]); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(2) + logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{})) + connOpts := arangostore.ConnectionOptions{ + URL: *url, + Database: *database, } - logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) - discoveryCache := cache.New() + var activeManifestResolver *datasetstore.Store + if *datasetGenerations { + lifecycleClient, err := arangostore.Open(context.Background(), connOpts.URL, connOpts.Database) + if err != nil { + exitf("open dataset lifecycle store: %v", err) + } + defer lifecycleClient.Close(context.Background()) + if err := lifecycleClient.Bootstrap(context.Background(), datasetstore.BootstrapSpec()); err != nil { + exitf("bootstrap dataset lifecycle store: %v", err) + } + activeManifestResolver, err = datasetstore.New(lifecycleClient) + if err != nil { + exitf("create dataset lifecycle store: %v", err) + } + } + + discoveryCache := catalogcache.New() + discoverFields := discoveryCache.DiscoverFields(catalog.DiscoverPopulatedFields) + discoverReferences := discoveryCache.DiscoverReferences(catalog.DiscoverPopulatedReferences) + var scopeResolver *authscope.ScopeResolver - authenticator := authscope.Authenticator(authscope.BearerTokenAuthenticator{}) - authorizer := authscope.Authorizer(authscope.ScopeAuthorizer{}) + var authorizer authscope.Authorizer if *noAuth { - authenticator = authscope.StaticAuthenticator{ - Principal: authscope.Principal{Subject: "local-demo"}, - } authorizer = authscope.AllowAllAuthorizer{} } else { scopeResolver = authscope.NewScopeResolver(authscope.ScopeResolverConfig{ - ConnectionOptions: loadOpts.ConnectionOptions, + ConnectionOptions: connOpts, }) authorizer = authscope.ScopeAuthorizer{Resolver: scopeResolver} } - service, err := api.NewService(api.ServiceConfig{ - Runner: api.IngestRunner{BaseOptions: loadOpts}, + + dataframes := dataframe.NewService(dataframe.ServiceConfig{ + ConnectionOptions: connOpts, + DiscoverReferences: discoverReferences, + DiscoverFields: discoverFields, + ScopeResolver: scopeResolver, + ActiveManifestResolver: activeManifestResolver, + }) + resolver := graphqlapi.NewResolver(dataframebuilder.Config{ + ConnectionOptions: connOpts, + DiscoverReferences: discoverReferences, + DiscoverFields: discoverFields, + Dataframes: dataframes, + ScopeResolver: scopeResolver, + ActiveManifestResolver: activeManifestResolver, + }) + + importService, err := api.NewService(api.ServiceConfig{ + Runner: api.IngestRunner{BaseOptions: ingest.LoadOptions{ + ConnectionOptions: connOpts, + Schema: *schema, + }}, Logger: logger, OnSuccess: func(project string) { discoveryCache.InvalidateProject(project) @@ -69,35 +108,45 @@ func main() { }, }) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) + exitf("create import service: %v", err) } - graphResolver := graphqlapi.NewResolver(graphqlapi.ResolverConfig{ - ConnectionOptions: loadOpts.ConnectionOptions, - DiscoverReferences: discoveryCache.DiscoverReferences(catalog.DiscoverPopulatedReferences), - DiscoverFields: discoveryCache.DiscoverFields(catalog.DiscoverPopulatedFields), - ScopeResolver: scopeResolver, - }) - graphHandler := graphqlapi.NewHandler(graphResolver) + server, err := api.NewHTTPServer(api.HTTPConfig{ - Service: service, - Authenticator: authenticator, - Authorizer: authorizer, - GraphQLHandler: graphHandler, - GraphQLPlaygroundHandler: graphqlapi.NewPlaygroundHandler("/graphql"), - ApolloSandboxHandler: graphqlapi.NewApolloSandboxHandler("/graphql"), - Logger: logger, - BodyLimit: *bodyLimit, - ReadBufferSize: *readBufferSize, + Service: importService, + Authorizer: authorizer, + GraphQLHandler: graphqlapi.NewHandler(resolver), + GraphQLPlaygroundHandler: graphqlapi.NewPlaygroundHandler("/graphql"), + ApolloSandboxHandler: graphqlapi.NewApolloSandboxHandler("/graphql"), + DisableSingleResourceImports: *datasetGenerations, + Logger: logger, }) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) + exitf("create HTTP server: %v", err) } - logger.Info("starting server", "listen", *listenAddr, "backend", "arango", "database", loadOpts.Database, "no_auth", *noAuth) - if err := server.App().Listen(*listenAddr); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) + errCh := make(chan error, 1) + go func() { + logger.Info("starting HTTP server", "listen", *listen, "database", *database, "no_auth", *noAuth, "dataset_generations", *datasetGenerations) + errCh <- server.App().Listen(*listen) + }() + + stop := make(chan os.Signal, 1) + signal.Notify(stop, os.Interrupt, syscall.SIGTERM) + + select { + case err := <-errCh: + if err != nil { + exitf("server stopped: %v", err) + } + case sig := <-stop: + logger.Info("shutting down HTTP server", "signal", sig.String()) + if err := server.App().ShutdownWithContext(context.Background()); err != nil { + exitf("shutdown failed: %v", err) + } } } + +func exitf(format string, args ...any) { + _, _ = fmt.Fprintf(os.Stderr, format+"\n", args...) + os.Exit(1) +} diff --git a/cmd/generate/main.go b/cmd/generate/main.go index d5d826f..f9999c9 100644 --- a/cmd/generate/main.go +++ b/cmd/generate/main.go @@ -134,6 +134,22 @@ func targetTypeFromLabel(label string) string { return parts[len(parts)-1] } +// generatedForwardTargetType preserves the existing extractor convention +// unless a compiler-owned storage route has a schema-proven exception. This +// is deliberately not a general conversion from link labels to targetSchema: +// unrelated legacy graph edges remain outside the generic compiler's forward +// storage contract. +func generatedForwardTargetType(structName string, link Link) string { + labelTargetType := targetTypeFromLabel(link.Rel) + if strings.TrimSpace(structName) != "ResearchSubject" || strings.TrimSpace(link.Rel) != "study" { + return labelTargetType + } + if targetType := refName(link.TargetSchema.Ref); targetType == "ResearchStudy" { + return targetType + } + return labelTargetType +} + func toGoName(s string) string { if s == "" { return "" @@ -854,8 +870,13 @@ func generateTraversalCode(schema *Schema, structName string, path []string, var indent += "\t" } - // Calculate UUIDs and append EdgeDocuments - forwardTargetType := targetTypeFromLabel(link.Rel) + // Calculate UUIDs and append EdgeDocuments. Most generated forward edge + // targets retain the long-standing label-derived convention. The one + // compiler-owned exception is ResearchSubject.study: its bare label + // cannot encode a target type, while the checked-in schema proves its + // concrete ResearchStudy target. Keep this narrow until each other bare + // label has an equivalent storage-route proof. + forwardTargetType := generatedForwardTargetType(structName, link) sb.WriteString(fmt.Sprintf("%s\tforwardKey := getEdgeUUID(targetID, id, %q)\n", indent, link.Rel)) sb.WriteString(fmt.Sprintf("%s\tif seen == nil {\n", indent)) sb.WriteString(fmt.Sprintf("%s\t\tseen = make(map[string]struct{}, 4)\n", indent)) @@ -998,10 +1019,8 @@ func generateFHIRSchema(schema *Schema, path string) error { sb.WriteString("// Code generated by cmd/generate/main.go. DO NOT EDIT.\n") sb.WriteString("package fhirschema\n\n") sb.WriteString("var generatedResourceTypes = []string{\n") - for _, k := range supportedFHIRSchemaResources() { - if isFHIRResourceDefinition(schema.Defs[k]) { - sb.WriteString(fmt.Sprintf("\t%q,\n", k)) - } + for _, k := range schemaFHIRRootResourceTypes(schema) { + sb.WriteString(fmt.Sprintf("\t%q,\n", k)) } sb.WriteString("}\n\n") sb.WriteString("var generatedDefinitions = map[string]generatedDefinition{\n") @@ -1049,35 +1068,65 @@ func generateFHIRSchema(schema *Schema, path string) error { return os.WriteFile(path, []byte(sb.String()), 0644) } -func supportedFHIRSchemaResources() []string { - return []string{ - "BodyStructure", - "Condition", - "DocumentReference", - "Group", - "ImagingStudy", - "Medication", - "MedicationAdministration", - "Observation", - "Organization", - "Patient", - "Practitioner", - "ResearchStudy", - "ResearchSubject", - "Specimen", +// schemaFHIRRootResourceTypes discovers compiler-visible collections from the +// checked-in graph schema. It deliberately does not carry a copied list of +// FHIR resource names: a schema definition is a concrete root only when its +// own resourceType constant names that definition and it has the FHIR Resource +// root fields (a string id plus an explicit metadata object). +// +// The graph schema also publishes the abstract Resource base definition so +// generated field references can resolve. Its resourceType constant is the +// generic "Resource" placeholder rather than a concrete graph collection, so +// it is excluded by role rather than maintaining a list of concrete types. +func schemaFHIRRootResourceTypes(schema *Schema) []string { + if schema == nil { + return nil + } + + keys := make([]string, 0, len(schema.Defs)) + for name := range schema.Defs { + keys = append(keys, name) } + sort.Strings(keys) + + roots := make([]string, 0, len(keys)) + for _, name := range keys { + if isFHIRRootResourceDefinition(name, schema.Defs[name]) { + roots = append(roots, name) + } + } + return roots } -func isFHIRResourceDefinition(def *Definition) bool { - if def == nil { +func isFHIRRootResourceDefinition(name string, def *Definition) bool { + name = strings.TrimSpace(name) + if name == "" || def == nil { + return false + } + + resourceType, ok := stringConstant(def.Properties["resourceType"]) + if !ok || resourceType != name { + return false + } + if resourceType == "Resource" { return false } - prop, ok := def.Properties["resourceType"] - if !ok || prop == nil || prop.Const == nil { + + id := def.Properties["id"] + if id == nil || propertyType(id) != "string" { return false } - _, ok = prop.Const.(string) - return ok + meta := def.Properties["meta"] + return meta != nil && strings.TrimSpace(meta.Ref) != "" +} + +func stringConstant(prop *Property) (string, bool) { + if prop == nil { + return "", false + } + value, ok := prop.Const.(string) + value = strings.TrimSpace(value) + return value, ok && value != "" } func propertyType(prop *Property) string { @@ -1116,6 +1165,10 @@ func writeGeneratedProperties(sb *strings.Builder, props map[string]*Property, i sb.WriteString(fmt.Sprintf("Name: %q,\n", k)) writeIndent(sb, indent+1) sb.WriteString(fmt.Sprintf("Kind: %q,\n", propertyType(prop))) + if prop.Format != "" { + writeIndent(sb, indent+1) + sb.WriteString(fmt.Sprintf("Format: %q,\n", prop.Format)) + } if prop.Ref != "" { writeIndent(sb, indent+1) sb.WriteString(fmt.Sprintf("Ref: %q,\n", refName(prop.Ref))) @@ -1123,6 +1176,10 @@ func writeGeneratedProperties(sb *strings.Builder, props map[string]*Property, i if prop.Items != nil { writeIndent(sb, indent+1) sb.WriteString(fmt.Sprintf("ItemKind: %q,\n", propertyType(prop.Items))) + if prop.Items.Format != "" { + writeIndent(sb, indent+1) + sb.WriteString(fmt.Sprintf("ItemFormat: %q,\n", prop.Items.Format)) + } if prop.Items.Ref != "" { writeIndent(sb, indent+1) sb.WriteString(fmt.Sprintf("ItemRef: %q,\n", refName(prop.Items.Ref))) diff --git a/cmd/generate/main_test.go b/cmd/generate/main_test.go new file mode 100644 index 0000000..1d5ce48 --- /dev/null +++ b/cmd/generate/main_test.go @@ -0,0 +1,144 @@ +package main + +import ( + "bytes" + "encoding/json" + "go/format" + "os" + "path/filepath" + "slices" + "strings" + "testing" +) + +func TestSchemaFHIRRootResourceTypesUsesCheckedInRootShape(t *testing.T) { + schema := loadCheckedInGraphFHIRSchema(t) + + roots := schemaFHIRRootResourceTypes(schema) + if !slices.IsSorted(roots) { + t.Fatalf("root resource types are not sorted: %v", roots) + } + for _, name := range []string{ + "DiagnosticReport", + "MedicationRequest", + "MedicationStatement", + "Procedure", + "Task", + } { + if !slices.Contains(roots, name) { + t.Errorf("schema-derived roots do not include %q: %v", name, roots) + } + } + for _, name := range []string{"Address", "PatientContact", "Resource"} { + if slices.Contains(roots, name) { + t.Errorf("schema-derived roots unexpectedly include non-root %q: %v", name, roots) + } + } +} + +func TestFHIRSchemaMetadataGenerationMatchesCheckedInArtifact(t *testing.T) { + schema := loadCheckedInGraphFHIRSchema(t) + generatedPath := filepath.Join(t.TempDir(), "generated.go") + if err := generateFHIRSchema(schema, generatedPath); err != nil { + t.Fatalf("generate FHIR schema metadata: %v", err) + } + got, err := os.ReadFile(generatedPath) + if err != nil { + t.Fatalf("read generated metadata: %v", err) + } + got, err = format.Source(got) + if err != nil { + t.Fatalf("format generated metadata: %v", err) + } + want, err := os.ReadFile(filepath.Join("..", "..", "internal", "fhirschema", "generated.go")) + if err != nil { + t.Fatalf("read checked-in metadata: %v", err) + } + if !bytes.Equal(got, want) { + t.Fatal("checked-in internal/fhirschema/generated.go is stale; run make generate-fhir") + } +} + +func TestGenerateExtractUsesSchemaTargetTypeForResearchSubjectStudy(t *testing.T) { + schema := loadCheckedInGraphFHIRSchema(t) + generatedPath := filepath.Join(t.TempDir(), "extract.go") + if err := generateExtract(schema, generatedPath); err != nil { + t.Fatalf("generate FHIR edge extractor: %v", err) + } + generated, err := os.ReadFile(generatedPath) + if err != nil { + t.Fatalf("read generated FHIR edge extractor: %v", err) + } + + const signature = "func (x *ResearchSubject) ExtractEdges" + start := strings.Index(string(generated), signature) + if start < 0 { + t.Fatalf("generated extractor is missing %s", signature) + } + section := string(generated[start:]) + if next := strings.Index(section[len(signature):], "// ExtractEdges extracts graph links from "); next >= 0 { + section = section[:len(signature)+next] + } + if !strings.Contains(section, `collectionID("ResearchStudy", targetID)`) || !strings.Contains(section, `"ResearchStudy",`) { + t.Fatalf("ResearchSubject.study forward edge did not use its schema target type:\n%s", section) + } + if strings.Contains(section, `collectionID("study", targetID)`) { + t.Fatalf("ResearchSubject.study forward edge derived target collection from bare label:\n%s", section) + } +} + +func TestFHIRRootResourceDefinitionRequiresConcreteResourceShape(t *testing.T) { + stringType := any("string") + root := &Definition{Properties: map[string]*Property{ + "resourceType": {Const: "Task"}, + "id": {Type: stringType}, + "meta": {Ref: "http://graph-fhir.io/schema/0.0.2/Meta"}, + }} + if !isFHIRRootResourceDefinition("Task", root) { + t.Fatal("concrete resource root shape was rejected") + } + + for testName, testCase := range map[string]struct { + definitionName string + definition *Definition + }{ + "mismatched resource type": {definitionName: "Task", definition: &Definition{Properties: map[string]*Property{ + "resourceType": {Const: "Patient"}, + "id": {Type: stringType}, + "meta": {Ref: "http://graph-fhir.io/schema/0.0.2/Meta"}, + }}}, + "missing metadata root field": {definitionName: "Task", definition: &Definition{Properties: map[string]*Property{ + "resourceType": {Const: "Task"}, + "id": {Type: stringType}, + }}}, + "non-string id": {definitionName: "Task", definition: &Definition{Properties: map[string]*Property{ + "resourceType": {Const: "Task"}, + "id": {Type: any("integer")}, + "meta": {Ref: "http://graph-fhir.io/schema/0.0.2/Meta"}, + }}}, + "abstract Resource placeholder": {definitionName: "Resource", definition: &Definition{Properties: map[string]*Property{ + "resourceType": {Const: "Resource"}, + "id": {Type: stringType}, + "meta": {Ref: "http://graph-fhir.io/schema/0.0.2/Meta"}, + }}}, + } { + t.Run(testName, func(t *testing.T) { + if isFHIRRootResourceDefinition(testCase.definitionName, testCase.definition) { + t.Fatal("non-root resource shape was accepted") + } + }) + } +} + +func loadCheckedInGraphFHIRSchema(t *testing.T) *Schema { + t.Helper() + data, err := os.ReadFile(filepath.Join("..", "..", "schemas", "graph-fhir.json")) + if err != nil { + t.Fatalf("read graph schema: %v", err) + } + var schema Schema + if err := json.Unmarshal(data, &schema); err != nil { + t.Fatalf("decode graph schema: %v", err) + } + return &schema +} diff --git a/docs/COMPILER_CLEANUP_AUDIT.md b/docs/COMPILER_CLEANUP_AUDIT.md new file mode 100644 index 0000000..a444255 --- /dev/null +++ b/docs/COMPILER_CLEANUP_AUDIT.md @@ -0,0 +1,133 @@ +# Compiler-Era Cleanup Audit + +This audit asks a narrower question than `go tool deadcode`: which package +tracks no longer belong in Loom now that dataframe requests have a real, +generation-aware FHIR compiler? It traces production call sites and storage +contracts as of this checkout. It does not treat a new compiler foundation as +dead merely because it has not yet reached the final product transport. + +## Runtime authority + +The executing dataframe path is: + +```text +POST /graphql + -> graphqlapi resolver + -> dataframebuilder.Service.Run + -> dataframe.Service + -> semantic validation / Lower + -> compileLowered + -> Arango QueryRows or Stream +``` + +The current compiler, catalog, generated FHIR metadata, loader, and Arango +client all remain live core. Generic lowering is real execution code; the +physical-plan renderer is currently an Explain/diagnostic foundation, not its +replacement. + +## Removed in this cleanup + +| Track | Why it was removed | Evidence | +| --- | --- | --- | +| Hard-coded GDC AQL CLI/exporter | It bypassed compiler validation and generation scope. Its default query performed unqualified document lookup and had no `dataset_generation` predicate. It was not an Elasticsearch delivery implementation. | The only command entries were `query-gdc-case-assay-matrix` and `export-gdc-case-assay-matrix`; the only integration dependency was its own raw-AQL assertion. | +| `queries/*.aql` | The files encoded GDC-specific rows, old `project::id` keys, or alternate edge collections which current ingest neither creates nor reads. | No generic compiler or catalog call site used them. | +| `/builder` browser page | The 1,062-line page hard-coded a GDC project, fields, pivots, and an eight-item edge-label map, then submitted raw graph-editor inputs. It did not build requests from compiler-safe catalog capabilities. | Its only production entry was `GET /builder`. | +| `patient_file_rollup` bootstrap collection | No loader wrote it and no compiler, query, or reader consumed it. Creating its indexes at every bootstrap advertised a materialization that did not exist. | References were limited to bootstrap, its bootstrap test, and docs. Existing operator-created collections are deliberately not dropped by this code cleanup. | +| `fhir_scalar_index` constant | It had no bootstrap, writer, reader, or test. | The declaration was its only reference. | + +The Docker image no longer copies manual AQL files. The legacy integration test +now verifies load/catalog behavior rather than an obsolete query recipe. + +## Package decisions + +| Area | Decision | Reason | +| --- | --- | --- | +| `cmd/arango-fhir-proto` | Keep as an operator surface, simplify | It now owns loading and catalog diagnostics only; the hard-coded GDC query/export commands were removed. | +| `cmd/arango-fhir-server` | Keep | It wires the compiler, catalog cache, authorization, GraphQL, and optional active-generation resolver. | +| `internal/api` | Keep, remove only the demo page | It is the HTTP host and principal-propagation boundary. The one-file import route is a separate compatibility decision. | +| `internal/graphqlapi` and generated model | Keep temporarily; stop extending | This is the live compiler transport. It should be replaced by the guided product contract in one deliberate schema/codegen cutover, not deleted piecemeal. | +| `internal/authscope` | Keep | It is the runtime authorization-scope contract used by catalog discovery and compiler execution. | +| `internal/store/arango` | Keep | It is the only executing backend and owns native query, lifecycle, and Explain operations. | +| `internal/fhir`, `internal/fhirschema`, `cmd/generate` | Keep | They are generator-owned FHIR/schema authority and support every active root. | +| `internal/ingest`, `fhir_edge`, `fhir_field_catalog` | Keep | They are the actual write path and compiler evidence layer. Do not prune traversal/index strategy without new Explain coverage. | +| `internal/catalog` and cache | Keep | They supply scoped observed fields, values, pivots, and relationship facts to both current GraphQL and guided discovery. | +| `internal/datasetstore` and `schemaidentity` | Keep | Immutable manifest/pointer lifecycle and exact schema identity are on the generation-aware read/write path. | +| `internal/dataset` read-binding helpers | Defer a focused decision | Some value types are only unit-tested while runtime reads use `authscope.ReadScope`; they are new lifecycle work, not an old compiler track. | +| `internal/dataframe` generic lowering | Keep and extend | It is the live compiler execution path for general requests. | +| Specialized Patient/case-assay lowering | Retain behind explicit deletion gates | It still changes semantics and shares sibling traversals more aggressively than generic lowering. | +| `internal/dataframe` physical plan/renderer | Retain as incomplete new compiler work | It is navigation-only Explain/diagnostic IR, not a stale pre-compiler implementation. Do not describe it as an execution replacement until it renders all semantic operations. | +| `internal/dataframebuilder` and current GraphQL AST | Keep temporarily; stop extending | They are the only public execution transport, but expose raw graph-editor concepts that conflict with the guided product contract. | +| `internal/discovery`, `recipe`, `recipecompiler`, `export`, `dataframeexport` | Keep as product foundations | They are intentionally not yet publicly wired; they are not duplicate AQL implementations. | +| Mutable CLI load and one-file HTTP import | Keep temporarily; do not extend | They remain reachable compatibility paths. Generation-mode server already rejects the HTTP route. Delete only with a complete bundle/job replacement. | +| `experimental/docker-compose.yml` | Keep | It is the tracked local Arango development runtime. | + +## Compiler correctness found during audit + +Generic lowering had one semantic inconsistency: an `AUTO` selection of a +repeated related field was documented as `FIRST` but rendered as a sorted unique +array. The generic lowering path now lowers it as deterministic `FIRST` and +sorts the related set by `_key`; the pre-existing specialized Patient behavior +is left unchanged pending its dedicated migration. Focused value-mode tests +cover both `AUTO` and `FIRST` traversal selection. + +## Do not delete the specialized Patient lowerer yet + +Deleting `planner.go`'s Patient/case-assay branch, `traversal_rules.go`, or +`document_reference_semantics.go` today would remove real behavior, not dead +code. The deletion requires all of the following: + +1. A generic sibling-prefix sharing pass that traverses the common Patient + neighbor prefix once, then applies resource-type subsets. The specialized + plan currently shares this work across Condition, Specimen, Observation, + and related children; generic sharing only recognizes identical target + types. +2. Explicit, authorization-scoped outbound lowering for + `ResearchSubject -> study -> ResearchStudy`. Current generic storage-route + validation correctly rejects the forward stored edge; the legacy lookup is + an implicit workaround, not an equivalent generic route. +3. Result-shape and Arango Explain/cost parity for representative patient, + specimen/file, DocumentReference, and study-enrollment fixtures. +4. An explicit product decision about GDC-style DocumentReference summaries. + That special logic chooses `content[0]`, applies code/display fallbacks, + and emits GDC classifications. If it is needed, it belongs in a named + manifest/recipe capability rather than generic FHIR lowering. + +Only then should the old set kinds, special traversal registry, lookup logic, +and legacy conformance fixtures be removed together. + +## Next cleanup boundaries + +These items are deliberately deferred rather than silently removed: + +- Current GraphQL exposes `cursor` and `selectionHint` that the input mapper + does not use, while the compiler has typed filters and required traversal + matching that GraphQL cannot express. Fix this in one transport cutover: + publish guided capabilities/recipe preview, then remove the raw GraphQL + graph-editor contract and regenerate gqlgen. +- The direct pre-lowered `Builder` surface contains legacy set/derived + operation variants and nested traversal fields with no runtime producer. + Encapsulate it after conformance fixtures compile request-level plans rather + than construct lowered internals directly; this avoids deleting a test-only + escape hatch while it is still a de facto API. +- `shaping.go` and `shaping_plan.go` are currently test-only normalization + helpers whose policies are not consumed by the executing renderer. Either + connect them to semantic lowering or remove/quarantine them in the same + lowered-IR encapsulation pass. +- `internal/dataset` has a few read-binding/fingerprint helpers used only by + their own tests, while live reads use `authscope.ReadScope` and + `datasetstore.ResolveActiveManifest`. They are newly added lifecycle + foundations, so decide whether to integrate or prune them in a dedicated + lifecycle pass rather than mixing that decision into removal of old code. + +## Verification expectation + +After any cleanup touching compiler behavior, run: + +```bash +GOCACHE=$(pwd)/.gocache GOTOOLCHAIN=auto go test ./... +make conformance +make compiler-bench +``` + +For traversal/index changes, also run the opt-in local Arango Explain gate from +[`COMPILER_IMPLEMENTATION_STATUS.md`](COMPILER_IMPLEMENTATION_STATUS.md). diff --git a/docs/COMPILER_FIRST_PLAN.md b/docs/COMPILER_FIRST_PLAN.md new file mode 100644 index 0000000..36812dc --- /dev/null +++ b/docs/COMPILER_FIRST_PLAN.md @@ -0,0 +1,900 @@ +# Compiler-First FHIR Graph Lowering and AQL Optimization Plan + +## 1. Purpose + +This is the primary implementation program for Loom. + +Loom's durable value is not its current browser page, job API, or export +wrapper. Its durable value is the compiler that turns a user-oriented FHIR +dataframe request into correct, authorization-safe, efficient AQL over an +observed FHIR graph. + +The product should be built outward from this boundary: + +```text +dataframe intent + -> typed semantic request + -> FHIR graph logical plan + -> cardinality-aware relational/dataframe plan + -> optimized physical AQL plan + -> generated AQL + bind variables + -> Arango EXPLAIN validation + -> execution / preview / export +``` + +The compiler must be useful without a frontend. A frontend or future language +assistant should only have to produce the typed request and display validation, +plan explanation, and results. + +This plan refactors the earlier 20-gap roadmap. Compiler work happens first. +Jobs, recipe persistence, Elasticsearch, deployment polish, and a larger +frontend are downstream consumers and must not dictate the compiler design. + +## 2. Existing Compiler Backbone + +This is not a greenfield compiler. + +### Existing request and validation path + +- `internal/graphqlapi/schema.graphqls` defines fields, traversals, pivots, + aggregates, slices, and value modes. +- `internal/dataframebuilder` maps and resolves GraphQL input. +- `internal/dataframe/validation.go` validates fields and traversals against + populated catalog records and generated schema metadata. +- `internal/fhirschema/generated.go` contains generated FHIR definitions and + traversals. +- `internal/fhirschema/schema.go` resolves fields, selectors, traversals, and + pivot families. + +### Existing lowering path + +- `internal/dataframe/planner.go` converts the public traversal tree to named + sets and derived fields. +- `internal/dataframe/traversal_rules.go` classifies the currently optimized + traversal tuples. +- `internal/dataframe/lowered_types.go` defines named sets, derived fields, and + representative slices. +- `internal/dataframe/document_reference_semantics.go` defines specialized file + summary behavior. + +### Existing AQL compilation path + +- `internal/dataframe/lowered_compile.go` emits the optimized named-set AQL. +- `internal/dataframe/compile_fields.go` emits traversal, selection, pivot, and + aggregate expressions. +- `internal/dataframe/selectors.go` parses the current selector subset. +- `internal/dataframe/query_runtime.go` executes AQL through a callback cursor. + +### Existing optimizations worth preserving + +The current implementation already performs meaningful work: + +- shares one root-neighbor traversal when several Patient child resource types + use the same edge label +- filters the shared neighbor set into resource-specific named sets +- reuses named sets for multiple fields and aggregates +- unions DocumentReference routes before file-summary classification +- classifies DocumentReference payloads once for compatible selectors +- hydrates ResearchStudy through direct `DOCUMENT` lookup when required +- groups compatible pivots so one pivot map can serve multiple projections +- filters requested pivot columns through bind variables +- uses `LIMIT 1` for existence checks +- pushes project and auth-resource-path predicates into root and traversal AQL +- uses bind variables for user values and traversal labels/types +- validates against populated fields and references before compilation + +Those behaviors need parity tests before the compiler is reorganized. + +## 3. Current Compiler Gaps + +### Semantic limitations + +- Root lowering is limited to `Patient`. +- Traversal roles are a hardcoded subset of generated traversal metadata. +- A structurally valid root-only or simple one-hop request can be rejected + because it does not trigger the specialized optimized profile. +- Row grain is implicit. The planner does not formally distinguish selecting + arrays from exploding rows, aggregating related resources, or changing the + output entity. +- FHIR reference direction, multiplicity, choice types, extensions, + terminology, and repeated values do not have one complete semantic model. +- DocumentReference behavior is embedded as a special family rather than an + optimizer rule over typed semantics. + +### Intermediate representation limitations + +- `logicalNode` is still close to GraphQL input and does not express joins, + filters, grouping, row identity, or cardinality explicitly. +- `NamedSet` and `DerivedField` combine physical execution decisions with + semantic operations. +- Set modes are tracked through string-keyed maps. +- Important behavior depends on string constants and sanitized variable names. +- There is no structured physical AQL AST or operation graph. +- There is no stable compiler explain artifact between the request and AQL. + +### Filter and expression limitations + +- The selector grammar is intentionally narrow. +- Predicate support is primarily existence and equality/contains behavior. +- Typed comparisons, code/system matching, date ranges, null semantics, and + array quantifiers are incomplete. +- Filter pushdown is not represented as an optimizer decision. +- Some compiler paths treat invalid selector parsing as impossible after + validation rather than carrying typed validated expressions. +- Internal raw-expression support is difficult to reason about and should not + be reachable from untrusted product input. + +### Physical AQL limitations + +- AQL is assembled directly as formatted strings. +- `UNIQUE`, `FLATTEN`, and `MERGE` are used broadly and can eagerly materialize + large arrays per root row. +- Traversal deduplication policy is not cost-based and is sometimes unconditional. +- Repeated selections can rescan the same set or payload path. +- Filters cannot consistently move before set materialization. +- Projection pruning does not remove unused data from specialized summaries. +- There is no choice between traversal, indexed lookup, precomputed rollup, or + alternative join shapes based on observed statistics. +- Root `SORT`/`LIMIT` supports preview but is not a complete stable cursor or + filtered-query strategy. + +### Optimization evidence limitations + +- Tests mostly validate generated query fragments and selected result paths. +- There is no systematic corpus of logical-plan and physical-plan goldens. +- There is no automated Arango `EXPLAIN` inspection. +- There are no plan budgets for scanned rows, peak memory, intermediate arrays, + or execution time. +- There is no optimizer comparison against an unoptimized correct reference + plan. +- `META/` is not yet used as a formal compiler benchmark corpus. + +## 4. Compiler Definition of Done + +The compiler is ready to support the product when it can: + +1. accept any supported root/grain represented by generated FHIR metadata +2. validate every field, traversal, filter, aggregate, and pivot before AQL +3. model row identity and cardinality explicitly +4. produce a correct generic plan for every advertised supported request +5. apply optional optimizations without changing results +6. generate AQL only through typed validated physical operations +7. keep project, dataset generation, and authorization predicates on every + applicable read/traversal +8. explain why a traversal, aggregate, or pivot was chosen +9. report unsupported semantics through stable reason codes +10. show benchmark and `EXPLAIN` evidence for important plan families +11. preserve result parity between generic and optimized plans +12. stream rows without materializing the complete dataframe in Loom + +## 5. Compiler Work Packages + +The compiler program is divided into ten work packages. These replace the old +single large planner gap. + +--- + +# CP0: Compiler Corpus, Reference Semantics, and Baselines + +## Objective + +Create the executable oracle against which every compiler refactor and +optimization is judged. + +## Implementation + +1. Inventory the resource types, populated fields, pivot candidates, and + relationship tuples in `META/`. +2. Record the current GraphQL input, normalized builder, lowered sets, AQL, + bind variables, output columns, and result rows for representative queries. +3. Cover these current plan behaviors: + - root fields + - shared Patient neighbor set + - Patient to Condition + - Patient to Specimen + - Specimen/Group to DocumentReference + - DocumentReference summary classification + - ResearchSubject to ResearchStudy hydration + - Observation pivot + - count, count-distinct, exists, and distinct-values + - representative slices + - multi-auth-path and unrestricted scope +4. Add minimal synthetic fixtures only for semantics missing from `META/`. +5. Define output comparison rules: + - stable row key + - scalar equality + - array order or order-insensitive semantics + - sparse pivot columns + - null versus absent +6. Add a generic/reference execution mode or test evaluator. It may be slower, + but it must favor obvious correctness over optimization. +7. Add compiler benchmark commands using `META/` and configurable larger data. +8. Capture baseline Arango `EXPLAIN` plans and execution statistics. + +## Deliverables + +- `conformance/compiler/` +- compiler fixture schema +- logical/result goldens +- benchmark harness +- baseline report + +## Tests and gates + +- current compiler outputs are reproducible +- generated and generic ingestion produce equivalent graph inputs +- every later optimization runs result parity against the reference mode + +## Parallelism + +May run in parallel with read-only CP1/CP2 design, but its comparison contract +must freeze before those packages implement new IR. + +--- + +# CP1: Typed Dataframe and FHIR Semantic IR + +## Objective + +Replace compiler behavior inferred from nested GraphQL structs and strings with +a typed, backend-independent semantic request. + +## Implementation + +1. Define a `SemanticPlan` or equivalent in a new planner package. +2. Represent: + - project/generation/auth scope + - requested row grain + - root resource type + - semantic nodes and relationships + - fields/projections + - typed filters + - aggregates + - pivots + - representative slices + - output names and types +3. Introduce typed IDs for nodes, fields, relationships, and output columns. +4. Resolve raw GraphQL/recipe input into this IR once. +5. Store validated selectors as typed paths, not reparsed strings. +6. Keep source locations so errors point to the user's field/filter. +7. Define stable unsupported-reason and validation codes. +8. Make the IR serializable for golden tests and developer explain output. +9. Do not include AQL variable names, named-set choices, or optimizer hints. +10. Adapt the existing public builder into the semantic IR without breaking the + current API during migration. + +## Ownership + +- new `internal/dataframe/planner/semantic/` or equivalent +- adapters from `internal/dataframebuilder` + +## Tests and gates + +- deterministic semantic-plan goldens +- all current supported builders resolve without semantic loss +- malformed/unsupported input fails before physical lowering +- no backend/AQL types leak into the semantic IR + +## Parallelism + +One contract owner. CP2 and CP3 may contribute requirements but cannot define +parallel competing semantic types. + +--- + +# CP2: Generated FHIR Graph Semantics + +## Objective + +Turn existing generated schema and traversal metadata into the authoritative +compiler knowledge base instead of maintaining a hardcoded Patient tuple list. + +## Implementation + +1. Inventory what `internal/fhirschema/generated.go` already records: + - definitions + - properties/kinds + - traversals + - direction + - multiplicity + - backreferences +2. Define compiler-facing semantic APIs over `fhirschema`: + - resolve field and result kind + - resolve relationship/direction + - determine source/target multiplicity + - identify reference/choice/extension paths + - identify pivot-compatible code/value families +3. Replace tuple recognition as the support source with generated traversal + lookup plus explicit optimizer capabilities. +4. Retain domain-specific aliases or preferred paths as optional semantic rules, + not proof that a relationship exists. +5. Define how extensions are addressed: + - generic URL/value selectors + - friendly aliases layered above them +6. Define terminology-aware field semantics using system/code/display. +7. Add FHIR date, dateTime, instant, quantity, Coding, CodeableConcept, and + Reference type descriptors needed by filters and output typing. +8. Add generator changes only when the active graph schema contains information + that current generated metadata omits. +9. Regenerate through `make generate-fhir` and preserve deterministic output. +10. Test every traversal and generated field represented by `META/`. + +## Ownership + +- `internal/fhirschema/` +- `cmd/generate/` only when necessary +- no copied FHIR structs or handwritten replacement schema + +## Tests and gates + +- generated metadata reproducibility +- every observed `META/` relationship resolves through the semantic API +- optimizer support is distinct from schema existence +- generated/generic ingestion parity remains intact + +## Parallelism + +Can proceed beside CP3 after CP1's node/field/relationship identifiers freeze. + +--- + +# CP3: Row Grain and Cardinality Algebra + +## Objective + +Make "one row per" a formal compiler property rather than a frontend hint. + +## Implementation + +1. Define grain identity for: + - Patient + - Specimen + - DocumentReference/File + - Condition/Diagnosis + - Observation + - ResearchSubject/Study enrollment +2. Define relationship cardinalities: + - required one + - optional one + - repeated/many + - unknown/observed-many +3. Define projection modes: + - scalar + - first/representative + - repeated array + - distinct array + - aggregate + - pivot + - explode to rows +4. Require every semantic plan to have one stable row identity. +5. Define duplicate semantics when multiple graph paths reach the same resource. +6. Define how joins affect row multiplicity. +7. Reject accidental Cartesian products. +8. Use generated multiplicity plus observed fanout statistics; never replace + formal semantics with observed data alone. +9. Emit row-expansion and ambiguous-grain warnings. +10. Add algebraic tests for nested one-to-many paths. + +## Tests and gates + +- exact row counts for compiler fixtures +- stable row identity across generic/optimized plans +- no implicit row explosion +- duplicate path convergence has defined behavior + +## Parallelism + +May proceed with CP2 after CP1's core semantic IR freezes. Must finish before +generic lowering and cost optimization are considered stable. + +--- + +# CP4: Typed Expression and Filter Compiler + +## Objective + +Implement safe, FHIR-aware fields and filtering independently of frontend +wording and raw AQL. + +## Implementation + +1. Define a typed expression tree: + - path access + - literal/bind value + - boolean composition + - comparison + - existence/missing + - array quantifiers + - terminology match + - date/range comparison +2. Support initial operators: + - equals/not-equals + - in/not-in + - exists/missing + - contains text + - greater/less comparisons + - between/date range +3. Define `ANY`, `NONE`, and only later `ALL` repeated-value semantics. +4. Define missing versus null versus empty array. +5. Match Coding/CodeableConcept by system and code when available; display is + presentation, not the canonical identity. +6. Normalize FHIR date/dateTime/instant comparison and timezone policy. +7. Type-check every operator against CP2 descriptors. +8. Lower all user values to bind variables. +9. Make raw AQL expressions inaccessible from public input. +10. Compile filters into logical predicates before physical AQL. +11. Support filter pushdown metadata: which node/path owns each predicate. +12. Add fuzz tests for selector and expression parsing. + +## Tests and gates + +- result-based operator tests +- repeated-value quantifier tests +- code/system tests +- null/missing tests +- injection tests +- auth predicates cannot be removed by filter rewrites + +## Parallelism + +Expression types need one owner. Operator implementations can be split after +the AST and type rules freeze. + +--- + +# CP5: Correct Generic FHIR Graph Lowering + +## Objective + +Guarantee a correct physical plan for every advertised semantic request before +applying special optimizations. + +## Implementation + +1. Define a generic logical-to-physical lowering using CP2 graph metadata. +2. Support arbitrary validated root resource types. +3. Represent physical operations: + - root scan + - indexed root lookup + - graph traversal + - filter + - project + - distinct/deduplicate + - aggregate/group + - pivot + - explode + - slice + - union + - direct document lookup +4. Propagate project, generation, and auth scope through every operation. +5. Choose traversal direction from generated semantics plus observed + `fhir_edge` layout. The current catalog's parent-to-child contract is + inbound; do not mistake FHIR reference direction for physical AQL direction. +6. Preserve row identity and grain from CP3. +7. Implement root-only and simple one-hop requests; they must not require a + specialized optimization profile. +8. Detect cycles and cap graph depth. +9. Produce a typed `PhysicalPlan`, not AQL strings. +10. Preserve the current Patient-case-assay planner as an optimization path for + parity comparison, not the only working path. + +## Tests and gates + +- all six initial grains lower generically +- simple/root-only requests work +- every traversal carries scope predicates +- generic plan results match reference semantics +- cycles and unsupported directions fail clearly + +## Parallelism + +One core lowerer owner. After physical operation interfaces freeze, workers may +add root/grain adapters in separate files. + +--- + +# CP6: Aggregation, Pivot, and Representative-Selection Engine + +## Objective + +Make dataframe shaping a first-class, correct subsystem rather than scattered +string templates. + +## Implementation + +1. Define aggregate semantics and output types for: + - count + - count distinct + - exists/any + - distinct values + - min/max where required +2. Define whether nulls participate in every aggregate. +3. Define pivot inputs: + - key expression + - value expression + - duplicate key/value policy + - requested versus discovered columns + - sparse output policy +4. Support CodeableConcept and Observation code/value pivot families through + CP2 metadata. +5. Preserve the existing compatible-pivot grouping optimization. +6. Prevent high-cardinality unbounded pivot materialization. +7. Define representative selection with explicit ordering and stable tie-break. +8. Distinguish representative selection from arbitrary `FIRST`. +9. Define array output encoding independently of CSV/Elasticsearch. +10. Add generic and optimized implementations for parity testing. + +## Tests and gates + +- duplicate pivot-key cases +- multiple values per key +- sparse/missing pivot keys +- high-cardinality rejection/warning +- aggregate null behavior +- deterministic representative rows +- current `META/` pivot parity + +## Parallelism + +Aggregate, pivot, and representative-selection implementations can run in +parallel after their shared semantic contracts freeze. + +--- + +# CP7: Typed AQL Physical IR and Code Generation + +## Objective + +Separate plan construction from AQL rendering so optimization operates on typed +nodes instead of formatted strings. + +## Implementation + +1. Define an AQL-oriented physical AST or strongly typed operation graph. +2. Represent: + - collection scans + - traversals + - LET bindings + - loops + - filters + - sorts/limits + - collect/group + - projections + - subqueries + - bind variables +3. Generate collision-free internal variables without user-controlled names. +4. Make collection/resource identifiers come only from validated schema + metadata. +5. Make every user value a bind variable. +6. Add a scope verifier that walks the physical plan and proves required + project/generation/auth predicates exist. +7. Render deterministic AQL for snapshot and cache use. +8. Attach source semantic node and optimizer-rule provenance to physical nodes. +9. Keep an escape hatch for audited internal expressions only; mark them + explicitly and prohibit product input from creating them. +10. Port existing named-set code generation incrementally behind this boundary. + +## Tests and gates + +- deterministic render tests +- bind-variable completeness +- identifier injection tests +- scope-verifier negative tests +- current AQL result parity during incremental port + +## Parallelism + +One AST/renderer contract owner. Individual operation renderers can be split +after the node interfaces freeze. + +--- + +# CP8: AQL Optimization Passes + +## Objective + +Build explicit, independently testable optimizer passes that reduce graph work, +intermediate materialization, and repeated payload extraction. + +## Required passes + +### Projection pruning + +- remove unused fields from summaries and slice projections +- avoid building payload-derived values that no output/filter consumes + +### Predicate pushdown + +- move root filters before traversal +- move child predicates into traversal subqueries +- apply resource type, label, project, generation, and auth filters at the + earliest valid point + +### Traversal sharing + +- generalize the existing shared Patient-neighbor optimization +- share identical traversal prefixes across selected fields/aggregates +- split only when predicates or cardinality semantics differ + +### Common-subexpression elimination + +- reuse identical selector extraction +- reuse identical distinct sets +- reuse compatible pivot maps +- reuse DocumentReference classification and study lookup + +### Set fusion and materialization control + +- fuse filter/project operations where doing so preserves reuse +- avoid `FLATTEN` when direct iteration suffices +- avoid `UNIQUE` when schema/cardinality proves uniqueness +- choose `COLLECT`/distinct strategy deliberately +- avoid creating a full union when downstream consumers can stream branches + +### Lookup selection + +- choose graph traversal, indexed collection lookup, direct `DOCUMENT`, or + precomputed rollup using semantics and evidence +- keep specialized paths optional and result-equivalent + +### Aggregate/pivot pushdown + +- count or test existence without materializing complete node arrays +- filter pivot keys before value aggregation +- share grouped pivot computation + +### Limit and cursor pushdown + +- apply preview/export boundaries only where they preserve requested semantics +- use stable grain identity for keyset cursors +- never limit a child set before an aggregate unless semantics request it + +## Optimizer framework + +1. Each rule has: + - stable name + - preconditions + - transformation + - correctness tests + - estimated effect +2. Apply rules to a fixed point or controlled sequence. +3. Record applied/skipped rules in plan explain. +4. Allow rules to be disabled for parity/debugging. +5. Compare optimized results against CP5 generic plans. +6. Add plan-size and intermediate-cardinality estimates. + +## Tests and gates + +- one test family per rule +- multi-rule interaction tests +- generic/optimized result parity +- scope verifier runs after all rewrites +- no rule is accepted based only on shorter AQL text + +## Parallelism + +After the optimizer framework and physical IR freeze, individual passes are +highly parallelizable. Each worker owns additive rule files and tests; one +optimizer lead owns pass ordering and central registration. + +--- + +# CP9: Arango-Aware Costing, Indexing, EXPLAIN, and Performance Gates + +## Objective + +Make optimization evidence-driven against real Arango behavior and the actual +FHIR data distribution. + +## Implementation + +1. Add an Arango `EXPLAIN` adapter that captures: + - plan nodes + - indexes used + - estimated cost/items + - optimizer rules + - warnings +2. Add execution profiling for benchmark mode: + - runtime + - scanned/full-scan counts + - peak/estimated memory where available + - result rows + - intermediate cardinalities when observable +3. Define required index families for: + - root project/generation/auth/key scans + - edge traversal and label/type/scope constraints + - direct resource ID/reference lookup + - any scalar index used for pushdown +4. Review existing edge indexes against emitted traversal direction and filter + order. Do not add indexes speculatively. +5. Feed resource counts, field coverage, distinct counts, and relationship + fanout into a small cost model. +6. Start with rule-based thresholds. Do not build an elaborate cost-based + optimizer until measurements require it. +7. Define performance budgets for plan families: + - root-only filtered table + - one-hop projection + - multi-hop file manifest + - high-volume Observation filter + - pivot + - aggregate-only query +8. Benchmark generic and optimized plans on `META/` and a scaled dataset. +9. Reject optimizer changes that regress important plans without an explicit + documented tradeoff. +10. Publish a compiler performance report from CI/scheduled runs. + +## Tests and gates + +- expected critical index used +- no unexpected full collection scan for indexed benchmark cases +- output parity +- p50/p95 timing and scanned-item budgets +- memory/intermediate-size budgets +- repeatable benchmark commands + +## Parallelism + +Index analysis, EXPLAIN tooling, cost inputs, and benchmark execution can be +parallelized after CP7 produces stable physical plans. + +--- + +# 6. Compiler Work-Package Dependency Graph + +```text +CP0 Corpus/baseline + ├──────────────┐ + v v +CP1 Semantic IR CP2 FHIR semantics + │ │ + ├──────┬───────┘ + v v +CP3 Grain/cardinality CP4 Expressions/filters + └──────────┬───────────┘ + v + CP5 Generic lowering + │ + ├────────> CP6 Aggregate/pivot engine + │ + v + CP7 Physical AQL IR + │ + v + CP8 Optimizer passes + │ + v + CP9 EXPLAIN/cost/index/performance +``` + +CP6 can begin its semantic contracts after CP1-CP4, but optimized code generation +must integrate through CP7/CP8. + +## 7. Compiler-First Parallel Waves + +### Compiler Wave A: Oracle and contracts + +- Worker A: CP0 corpus and result comparison +- Worker B: CP1 semantic IR contract +- Worker C: CP2 generated FHIR semantic APIs +- Worker D: current AQL/EXPLAIN baseline tooling + +Gate: + +- semantic IDs and result comparison freeze +- current supported results reproducible +- no replacement FHIR model introduced + +### Compiler Wave B: Semantics + +- Worker A: CP3 grain/cardinality +- Worker B: CP4 expression/filter AST and typing +- Worker C: CP6 aggregate semantic contract +- Worker D: CP6 pivot semantic contract +- Worker E: conformance fixtures for all above + +Gate: + +- typed semantic plan can express the six product families +- every operation has defined null/cardinality/output semantics + +### Compiler Wave C: Correct lowering + +- Worker A: CP5 generic lowering core +- Worker B: additive root/grain adapters after core freeze +- Worker C: CP7 physical AQL IR/renderer core +- Worker D: scope-verifier and bind/identifier safety +- Worker E: generic/reference parity suite + +Gate: + +- every advertised query has a correct generic plan +- root-only/simple queries work +- current Patient results remain correct + +### Compiler Wave D: Optimizer + +After CP7 freezes, parallel workers implement: + +- projection pruning and predicate pushdown +- traversal sharing and prefix reuse +- common-subexpression elimination +- set fusion/materialization control +- aggregate/existence pushdown +- grouped pivot optimization +- lookup/rollup selection, including a proven inbound/outbound direction choice +- cursor/limit pushdown + +One optimizer lead owns rule registration, ordering, and integration. + +Gate: + +- every rule has generic/optimized parity +- scope verifier passes after rewrites +- plan explain lists applied rules + +### Compiler Wave E: Arango performance + +- EXPLAIN/index worker +- cost/statistics worker +- benchmark execution worker +- large Observation/pivot stress worker +- regression and performance-report worker + +Gate: + +- important plan families meet written budgets +- optimizer decisions have Arango evidence +- slow paths are visible in explain/metrics + +## 8. What Moves Later + +The following former gaps become smaller downstream work because the compiler +owns the difficult semantics: + +### Reduced product facade + +- recipe templates become presets that construct semantic requests +- capability API delegates to compiler validation/capabilities +- frontend asks grain, columns, and filters, then displays compiler explain +- recipe persistence stores normalized compiler input + +### Reduced preview/export work + +- preview adds limits/cursor around compiled physical plans +- export consumes the compiler row stream +- NDJSON, CSV, and Elasticsearch are row sinks, not separate dataframe engines + +### Deferred infrastructure + +These remain necessary for a development service but should not block compiler +quality: + +- durable load/export jobs +- immutable dataset generations +- saved recipe CRUD +- artifact storage +- Elasticsearch retries +- readiness, metrics, and runbooks + +Implement only the minimum dataset identity, authorization context, catalog +statistics, and execution harness required to build and measure the compiler. + +## 9. Compiler Release Gate Before Product Expansion + +Do not invest in a larger frontend or broad service machinery until: + +- CP0-CP7 are complete +- at least the first CP8 optimizer passes are complete +- Patient, Specimen, File, Diagnosis, Observation, and Study Enrollment grains + have correct generic plans +- typed filters cover the initial product conversations +- pivots and aggregates have explicit tested semantics +- generic and optimized results match +- project/auth predicates are mechanically verified +- `META/` compiler benchmarks are repeatable +- Arango `EXPLAIN` output is available to developers +- current specialized Patient behavior is either preserved as a rule or beaten + by the new generic/optimized plan + +At that point the product layer becomes relatively thin and can be built with +far less risk. diff --git a/docs/COMPILER_IMPLEMENTATION_STATUS.md b/docs/COMPILER_IMPLEMENTATION_STATUS.md new file mode 100644 index 0000000..b7e52de --- /dev/null +++ b/docs/COMPILER_IMPLEMENTATION_STATUS.md @@ -0,0 +1,198 @@ +# Compiler-First Implementation Status + +This is a factual handoff/status document for the compiler-first program in +[`COMPILER_FIRST_PLAN.md`](COMPILER_FIRST_PLAN.md). It records what Loom can +actually do in this checkout, what evidence exists, and what still must not be +advertised as a finished product feature. + +## Current Contract + +Loom now accepts a typed dataframe request, resolves it against the checked-in +FHIR graph schema and populated catalog, and lowers supported requests into +authorization-scoped AQL. The generic path supports every concrete root type +currently generated from `schemas/graph-fhir.json`; it is not a claim of +universal support for every FHIR release or a resource not represented by that +schema. + +The checked-in schema currently produces 23 concrete dataframe roots: + +```text +BodyStructure, Condition, DiagnosticReport, DocumentReference, +FamilyMemberHistory, Group, ImagingStudy, Medication, +MedicationAdministration, MedicationRequest, MedicationStatement, +Observation, Organization, Patient, Practitioner, PractitionerRole, +Procedure, ResearchStudy, ResearchSubject, Specimen, Substance, +SubstanceDefinition, Task +``` + +The 14 cases in the optimized generated-loader dispatcher remain the fast +ingest path. The other active-schema roots use the existing generic, +schema-backed row builder. A resource type absent from the active graph schema +is deliberately rejected rather than guessed. + +## Implemented Compiler Work + +| Area | State in this checkout | Evidence / boundary | +| --- | --- | --- | +| Corpus and regression checks | Implemented | `conformance/compiler/` covers compiler fixtures, generated-root coverage, and benchmark entrypoints; `conformance/recipes/` freezes guided conversation examples. `make conformance` runs the suite and `make compiler-bench` runs the compiler oracle. | +| Semantic request and grain | Implemented | `SemanticPlan`, explicit root/row identity, typed selection, cardinality validation, and stable plan explanation live in `internal/dataframe/`. | +| Schema-derived roots and fields | Implemented | `cmd/generate` derives roots from the checked-in graph schema and verifies generated metadata stays fresh. No handwritten parallel FHIR model was introduced. | +| Generic FHIR graph lowering | Implemented, storage-route constrained | Generic root and traversal lowering work across the active generated root surface, while the older Patient path remains an optional specialized optimization. A related-resource route must have a compiler-owned stored-edge proof: generated reverse/builder routes map to `INBOUND`, and the explicitly proven `ResearchSubject --study--> ResearchStudy` route maps to `OUTBOUND`. Other schema-valid forward FHIR references remain rejected rather than compiled in the wrong direction. | +| Typed filters | Implemented | Root and child filters, date/date-time metadata, filter pushdown, scoped binds, and validation are represented before AQL generation. | +| Relationship existence | Implemented | `REQUIRED` traversal matches lower to bounded root-correlated semi-joins before root sorting and limiting; optional traversal behavior is retained. | +| Pivots and aggregates | Implemented | Bounded pivot shaping, stable values, and aggregate behavior have compiler tests. | +| Physical-plan contract | Partial | Typed generic physical plans, scope verification, and a navigation-only renderer exist. The renderer is not yet the execution compiler for selections, filters, pivots, aggregates, or required matches. | +| Optimizer rules | Implemented baseline | Filter pushdown, traversal sharing, and required relationship semi-join rules are explicit. Cost-based join choice and rollup selection are still future work. | +| Explain and Arango plan checks | Implemented baseline | Safe compiler explanation plus Arango `EXPLAIN` parsing/assessment are covered by unit tests and opt-in local integration tests. | + +## Observed Performance Evidence + +The opt-in local Arango gate runs generic lowering, required relationship +matching, specialized/generic result parity, root-preview index selection, and +the physical navigation renderer: + +```bash +LOOM_COMPILER_ARANGO_INTEGRATION=1 \ + GOCACHE=$(pwd)/.gocache GOTOOLCHAIN=auto \ + go test ./internal/dataframe -run 'Test(GenericSpecimenPlanExplainsAndRunsAgainstArango|GenericRootPreviewUsesScopedSortIndexAgainstArango|RenderedGenericPhysicalNavigationExplainsAgainstArango|GenericAndSpecializedPatientPlansHaveResultParityAgainstArango|RequiredTraversalMatchExplainsAndRunsAgainstArango)' -count=1 -v +``` + +The observed generic traversal plan uses the native `fhir_edge` edge index on +`_to` and has no full collection scan. Root preview compilation now needs the +project-plus-stable-key access path, so bootstrap creates `project,_key` and +`project,auth_resource_path,_key` indexes for every staged resource +collection—not just Patient or DocumentReference. + +That index is created at bootstrap for fresh loads. An already-loaded local +collection does not gain it until Loom bootstraps that collection again or an +operator adds the equivalent index. Do not read current local `EXPLAIN` cost +for an old collection as evidence that the new fresh-load index policy ran. + +## Ingest Safety Added Alongside the Compiler + +Before opening an Arango connection, `Load` now: + +1. loads the configured graph schema; +2. groups staged NDJSON files by their filename resource type; +3. samples a bounded number of payloads in each file to verify + `resourceType` and JSON shape; +4. reports generated, generic, or unsupported loader mode per resource; and +5. rejects the complete staged request before database bootstrap if any issue + exists. + +`PreflightError` preserves every structured issue for a future HTTP/CLI +presentation. Full validation still occurs while streaming the complete input, +so the bounded preflight does not pretend to validate an entire large import. + +Generic ingestion now also copies the auth-resource-path scope to its generated +edges. This keeps the generic fallback subject to the same edge authorization +predicates used by lowering and catalog discovery. + +`internal/schemaidentity` fingerprints the exact configured schema bytes and +exposes only source-explicit schema metadata plus this binary's generated FHIR +roots. `LoadSummary` and preflight telemetry carry that identity before Arango +is opened, and immutable generation manifests persist a defensive schema +snapshot rather than inventing a second identity representation. + +`internal/datasetstore` persists the C1 lifecycle in the non-truncating +`loom_dataset_lifecycle` collection: immutable project/generation manifests, +PREFLIGHT/LOADING/ANALYZING/READY/terminal transitions, and one active pointer +per project. Activation is one guarded AQL operation that selects a READY +candidate and supersedes the prior active generation atomically. + +`ingest.Load` keeps the old mutable behavior when `LoadOptions.Dataset` is nil. +With a validated dataset reference, it requires a complete nonempty directory, +runs schema and payload preflight before opening Arango, prohibits truncation, +namespaces vertex/edge physical keys by project and generation, writes +immutable graph and field-catalog documents, then activates only after all +files and catalog finalization succeed. Any row, edge, generation, +cancellation, or catalog failure leaves the manifest FAILED; a READY activation +transport failure is reported as an unknown outcome rather than falsely marking +it failed. The one-file loader intentionally rejects generation mode. + +The CLI command `arango-fhir-proto load-generation --generation OPAQUE_ID` +owns that complete-directory load path. `arango-fhir-server +--dataset-generations` resolves the active READY manifest before dataframe +discovery/execution and disables the legacy one-file `/api/v1/imports` route. +There is not yet an HTTP bundle-upload or background-load endpoint. + +## Thin Product Foundation Added + +The product layer deliberately stays independent from FHIR paths and AQL: + +- `internal/recipe` defines versioned recipe intent, opaque selected-column and + filter IDs, destination intent, and six stable starting templates. +- `ListTemplates` and `LookupTemplate` provide the user-facing options: + patient cohort, specimen inventory, file manifest, diagnoses, + labs/observations, and study enrollment. +- Existing `internal/dataframebuilder.Introspect` already queries the populated + field catalog, bounded distinct values, pivot candidates, and observed + one-hop relationships under caller project and authorization scope. This is + the live source for the proposed “include” and “only include” controls. +- `dataframebuilder.Service.DiscoverGuided` now composes those existing scoped + catalog readers into `internal/discovery.Snapshot`: generated-schema roots, + compiler-safe observed relationships, opaque candidate-column IDs, and + bounded guided filter suggestions. It intentionally has no GraphQL/HTTP + exposure yet. When an active-manifest resolver is configured, the snapshot, + authorization scope, catalog facts, compiler, and execution are all pinned + to the same immutable generation. +- `internal/recipecompiler.Build` and + `dataframebuilder.Service.PrepareRecipe`/`RunRecipe`/`StreamRecipe` resolve + those opaque IDs only against fresh, authorization-scoped catalog facts into + typed **root-only scalar** dataframe plans. They can preview or stream the + result through the existing compiler without accepting a browser-supplied + FHIR selector, graph label, or AQL fragment. A stale, related-resource, + repeated, pivot-only, raw-path, or pinned-generation choice is rejected + rather than guessed. +- `internal/export` now has strict flat-row NDJSON and CSV encoders, and + `internal/dataframeexport` connects them to `dataframe.Service.Stream` + without collecting result rows. They remain foundations only: no artifact + storage, jobs, public endpoint, stable generation snapshot, or Elasticsearch + transport exists yet. Inferred CSV deliberately replays the query; explicit + CSV columns are a single streaming execution. +- `dataframe.Service.Stream` now executes the same validated request path as a + preview while handing flattened rows to a caller one at a time. When the + service is configured with the active-generation resolver, it uses the same + immutable-generation binding as preview execution. It has not yet been + exposed as a delivery endpoint. + +The root-only bridge is deliberately not a claim that every recipe template is +currently executable. Relationship columns/filters, pivots, repeated-value +quantifiers, aggregates, and recipes pinned to an immutable dataset generation +still need explicit contracts and generation-bound capability facts. The next +bridge extension must preserve the same rule: it may resolve only capabilities +emitted for the current project/generation/scope, never an arbitrary FHIR path +or AQL snippet from a browser recipe. + +## Still Deliberately Incomplete + +The following are planned work, not present-product claims: + +- a public guided-capability API that joins template, observed catalog data, + and compiler support reasons; +- GraphQL/REST exposure for typed filters, required relationship match modes, + recipe creation, and safe compiler explanation; +- a full physical-plan renderer wired into execution; +- cost-based traversal/index/rollup choice and enforced scan/memory budgets; +- cursor-stable row streaming from the Arango driver; +- durable NDJSON/CSV export files, background jobs, cancellation, and retry; +- Elasticsearch transport, mapping policy, idempotency, and failure recovery; +- readiness/dependency diagnostics and production deployment controls. + +## Correct Integration Order + +1. Persist the next analysis/capability snapshot beside the now-bound immutable + dataset generation, then expose it through one public guided-capability + response. +2. Extend the existing capability-to-typed-request resolver only after its + relationship, cardinality, and generation-binding contracts are explicit; + make recipe validation call it before preview/export. +3. Wire the existing row result path to bounded streaming output and then add + durable delivery jobs around that same stream. +4. Bind reusable recipes and asynchronous delivery to an active generation and + its future analysis version; do not infer either from a mutable project. +5. Extend physical execution only when every new physical operator has result + parity and `EXPLAIN` evidence against the generic reference path. + +This order keeps a small guided UI possible without turning the browser into a +FHIR/AQL compiler or claiming support that the backend cannot prove. diff --git a/docs/DATAFRAME_BUILDER_PORTABILITY.md b/docs/DATAFRAME_BUILDER_PORTABILITY.md deleted file mode 100644 index 24ff8b1..0000000 --- a/docs/DATAFRAME_BUILDER_PORTABILITY.md +++ /dev/null @@ -1,720 +0,0 @@ -# FHIR-Native GraphQL Dataframe Builder Draft - -This file is now a historical design document, not the source of truth for the -live GraphQL contract. - -Use these current docs first: - -- [README](../README.md) -- [Quickstart](./QUICKSTART.md) -- [Developer Architecture](./DEVELOPER_ARCHITECTURE.md) - -The live schema is: - -- [`internal/graphqlapi/schema.graphqls`](../internal/graphqlapi/schema.graphqls) - -## Summary - -This document defines a draft GraphQL contract for the future dataframe-builder -read API. The contract is intentionally **FHIR-native** and mirrors the mental -model already proven out by the Arango prototype: - -1. choose a root FHIR resource type and auth scope, -2. traverse through actual populated FHIR reference labels, -3. attach field selectors directly to each traversed node, -4. attach pivot operations directly to the node that owns the pivotable field, -5. execute either a preview or an export. - -This is not a generic graph-builder schema. It is a builder contract for the -specific graph and field surfaces already present in this repo: - -- populated references discovered from `fhir_edge`, as implemented in - [internal/catalog/read_references.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/catalog/read_references.go) -- populated canonical field paths and pivot metadata discovered at load time in - [internal/catalog/write_profiler.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/catalog/write_profiler.go) -- traversal and field-plucking behavior demonstrated by the live - `gdc_case_assay_matrix` AQL in - [queries/gdc_case_assay_matrix_arango_rows.aql](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/queries/gdc_case_assay_matrix_arango_rows.aql:1) - -GraphQL is the user-facing contract. AQL remains the likely execution target -underneath for the Arango-backed implementation. - -## Source Model in the Current Prototype - -### Populated Traversals - -The traversal surface is already represented in `fhir_edge` as: - -- `from_type` -- `label` -- `to_type` -- `edge_count` - -That is the exact shape returned by -[internal/catalog/read_references.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/catalog/read_references.go), -which currently groups edges by `from_type`, `label`, and `to_type`. - -Example logical edges already used by the case-assay query: - -- `Patient <-subject_Patient- Specimen` -- `Specimen <-member_entity_Specimen- Group` -- `Specimen <-subject_Specimen- DocumentReference` -- `Group <-subject_Group- DocumentReference` -- `Patient <-subject_Patient- Condition` -- `Patient <-subject_Patient- ResearchSubject` -- `Patient <-subject_Patient- MedicationAdministration` - -Those traversals are visible directly in -[queries/gdc_case_assay_matrix_arango_rows.aql](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/queries/gdc_case_assay_matrix_arango_rows.aql:13), -[queries/gdc_case_assay_matrix_arango_rows.aql](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/queries/gdc_case_assay_matrix_arango_rows.aql:47), -and -[queries/gdc_case_assay_matrix_arango_rows.aql](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/queries/gdc_case_assay_matrix_arango_rows.aql:55). - -### Populated Fields - -The field catalog already records observed canonical FHIR paths per -`project/resource_type/path`, including: - -- `path` -- `kind` -- `doc_count` -- `distinct_values` -- `distinct_truncated` -- `pivot_candidate` -- `pivot_kind` -- `pivot_columns` - -This is the stored shape of -`FieldCatalogDocument` in -[internal/catalog/types.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/catalog/types.go). - -The path walker canonicalizes arrays with bracket wildcards such as: - -- `identifier[].value` -- `code.coding[].display` -- `valueCodeableConcept` -- `valueCodeableConcept.coding[].display` - -That behavior is implemented by `walkShapeValue`, `appendPath`, and -`extractAccessorValues` in -[internal/catalog/write_profiler.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/catalog/write_profiler.go), -and tested in -[internal/catalog/write_profiler_test.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/catalog/write_profiler_test.go). - -### Pivot Semantics - -V1 pivot semantics already exist in the load-time field profiler: - -- only `CodeableConcept`-shaped objects are pivot candidates -- pivot kind is `codeable_concept_display_value` -- candidate pivot columns come from observed coding displays - -The current implementation marks a field as a pivot candidate when -`classifyObjectShape` detects a `CodeableConcept`, via -[internal/catalog/write_profiler.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/catalog/write_profiler.go). -Observed pivot columns are accumulated by `addPivotColumn` in -[internal/catalog/write_profiler.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/catalog/write_profiler.go). -The expected behavior is tested in -[internal/catalog/write_profiler_test.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/catalog/write_profiler_test.go). - -This contract draft keeps those semantics intact. It does not invent generalized -pivoting beyond what the prototype already observes. - -## Contract Goals - -The GraphQL contract should let the frontend express: - -- what resource type is the root driver, -- which auth-scoped projects are included, -- which traversals are followed, -- which FHIR fields are plucked from each node, -- which fields are pivoted, -- whether the user wants a small preview or an export artifact. - -The contract should **not** force nested GraphQL resolvers to perform per-hop -fanout. The contract describes the dataframe shape; the backend remains free to -compile that request into one backend query plan or one staged export pipeline. - -## Draft SDL - -```graphql -scalar JSON -scalar DateTime - -enum FhirPivotKind { - CODEABLE_CONCEPT_DISPLAY_VALUE -} - -enum DataframeRunMode { - PREVIEW - EXPORT -} - -input FhirDataframeBuilderInput { - project: String! - authResourcePaths: [String!]! - rootResourceType: String! - fields: [FhirFieldSelectInput!]! - pivots: [FhirPivotSelectInput!] = [] - traversals: [FhirTraversalStepInput!] = [] -} - -input FhirTraversalStepInput { - label: String! - toResourceType: String! - alias: String! - fields: [FhirFieldSelectInput!]! - pivots: [FhirPivotSelectInput!] = [] - traversals: [FhirTraversalStepInput!] = [] -} - -input FhirFieldSelectInput { - name: String! - select: String! -} - -input FhirPivotSelectInput { - name: String! - select: String! - pivotKind: FhirPivotKind = CODEABLE_CONCEPT_DISPLAY_VALUE - columns: [String!] -} - -input FhirDataframeRunInput { - builder: FhirDataframeBuilderInput! - mode: DataframeRunMode! = EXPORT - previewLimit: Int = 25 -} - -type FhirPopulatedReference { - fromType: String! - label: String! - toType: String! - edgeCount: Int! -} - -type FhirPopulatedField { - resourceType: String! - path: String! - kind: String! - docCount: Int! - distinctValues: [String!]! - distinctTruncated: Boolean! - pivotCandidate: Boolean! - pivotKind: String - pivotColumns: [String!]! -} - -type FhirDataframePreview { - columns: [String!]! - rows: [JSON!]! - rowCount: Int! -} - -type FhirDataframeExportHandle { - exportId: String! - status: String! - format: String! -} - -type FhirDataframeRunResult { - mode: DataframeRunMode! - preview: FhirDataframePreview - export: FhirDataframeExportHandle -} - -input FhirBuilderMetadataInput { - project: String! - authResourcePaths: [String!]! - rootResourceType: String! - fromResourceType: String - resourceType: String - pivotOnly: Boolean = false -} - -type Query { - fhirPopulatedReferences(input: FhirBuilderMetadataInput!): [FhirPopulatedReference!]! - fhirPopulatedFields(input: FhirBuilderMetadataInput!): [FhirPopulatedField!]! -} - -type Mutation { - runFhirDataframe(input: FhirDataframeRunInput!): FhirDataframeRunResult! -} -``` - -## Selector Expression Syntax - -Each selected field uses a compact FHIR-aware extraction expression through the -`select` string. This is intentionally smaller than a full query language. - -### Path Form - -Supported path style in the draft: - -- `identifier[].value` -- `identifier[0].value` -- `extension[].valueString` -- `code.coding[].display` -- `valueCodeableConcept` -- `valueCodeableConcept.coding[].display` - -Array behavior is explicit in the selector: - -- `[]` means iterate the array -- `[0]` means address the first item explicitly - -The contract does not rely on hidden flattening behavior outside the selector. - -### Predicate Form - -The selector may narrow values by sibling-field predicates, for example: - -- `identifier[].value where system contains "case_id"` -- `identifier[].value where system contains "case_submitter_id"` -- `extension[].valueString where url contains "us-core-race"` -- `category[].coding[].display where system contains "data_category"` -- `category[].coding[].display where system contains "experimental_strategy"` - -The intent is to match the style already used in the current AQL, such as -filtering identifiers by `system` and extensions by `url`, visible in -[queries/gdc_case_assay_matrix_arango_rows.aql](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/queries/gdc_case_assay_matrix_arango_rows.aql:7) -and -[queries/gdc_case_assay_matrix_arango_rows.aql](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/queries/gdc_case_assay_matrix_arango_rows.aql:90). - -This selector syntax is a frontend contract, not a commitment to a specific -parser implementation yet. - -## Builder Inspection Queries - -Builder inspection is how the frontend learns what is actually populated in the -current dataset, rather than relying only on the full FHIR schema. - -### Populated Traversals - -```graphql -query BuilderReferences($input: FhirBuilderMetadataInput!) { - fhirPopulatedReferences(input: $input) { - fromType - label - toType - edgeCount - } -} -``` - -Example variables: - -```json -{ - "input": { - "project": "ARANGODB_PROTO", - "authResourcePaths": ["EllrottLab-GDC_Data"], - "rootResourceType": "Patient", - "fromResourceType": "Patient" - } -} -``` - -This is a GraphQL wrapper over the existing discovery surface implemented by -`discover-populated-references`. - -### Populated Fields - -```graphql -query BuilderFields($input: FhirBuilderMetadataInput!) { - fhirPopulatedFields(input: $input) { - resourceType - path - kind - docCount - distinctValues - distinctTruncated - pivotCandidate - pivotKind - pivotColumns - } -} -``` - -Example variables: - -```json -{ - "input": { - "project": "ARANGODB_PROTO", - "authResourcePaths": ["EllrottLab-GDC_Data"], - "rootResourceType": "Observation", - "resourceType": "Observation", - "pivotOnly": true - } -} -``` - -This is a GraphQL wrapper over the existing field catalog read path and should -ultimately map to `discover-populated-fields`, including the current -`--pivot-only` behavior already wired in -[cmd/arango-fhir-proto/main.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/cmd/arango-fhir-proto/main.go:269). - -## Execution Example: Case-Assay Dataframe - -This example is intentionally modeled on the current -`gdc_case_assay_matrix` AQL recipe. - -```graphql -mutation RunCaseAssayMatrix($input: FhirDataframeRunInput!) { - runFhirDataframe(input: $input) { - mode - export { - exportId - status - format - } - } -} -``` - -Example variables: - -```json -{ - "input": { - "mode": "EXPORT", - "builder": { - "project": "ARANGODB_PROTO", - "authResourcePaths": ["EllrottLab-GDC_Data"], - "rootResourceType": "Patient", - "fields": [ - { - "name": "case_id", - "select": "identifier[].value where system contains \"case_id\"" - }, - { - "name": "case_submitter_id", - "select": "identifier[].value where system contains \"case_submitter_id\"" - }, - { - "name": "gender", - "select": "gender" - }, - { - "name": "race", - "select": "extension[].valueString where url contains \"us-core-race\"" - }, - { - "name": "ethnicity", - "select": "extension[].valueString where url contains \"us-core-ethnicity\"" - }, - { - "name": "birth_sex", - "select": "extension[].valueCode where url contains \"us-core-birthsex\"" - }, - { - "name": "patient_age", - "select": "extension[].valueQuantity.value where url contains \"Patient-age\"" - } - ], - "pivots": [], - "traversals": [ - { - "label": "subject_Patient", - "toResourceType": "Specimen", - "alias": "specimen", - "fields": [ - { - "name": "specimen_type", - "select": "type.coding[].display" - }, - { - "name": "preservation_method", - "select": "processing[].method.coding[].display where system contains \"preservation_method\"" - } - ], - "pivots": [], - "traversals": [ - { - "label": "member_entity_Specimen", - "toResourceType": "Group", - "alias": "group", - "fields": [], - "pivots": [], - "traversals": [ - { - "label": "subject_Group", - "toResourceType": "DocumentReference", - "alias": "group_file", - "fields": [ - { - "name": "group_file_data_category", - "select": "category[].coding[].display where system contains \"data_category\"" - }, - { - "name": "group_file_data_type", - "select": "category[].coding[].display where system contains \"data_type\"" - }, - { - "name": "group_file_experimental_strategy", - "select": "category[].coding[].display where system contains \"experimental_strategy\"" - }, - { - "name": "group_file_workflow_type", - "select": "category[].coding[].display where system contains \"workflow_type\"" - } - ], - "pivots": [] - } - ] - }, - { - "label": "subject_Specimen", - "toResourceType": "DocumentReference", - "alias": "specimen_file", - "fields": [ - { - "name": "specimen_file_data_category", - "select": "category[].coding[].display where system contains \"data_category\"" - }, - { - "name": "specimen_file_data_type", - "select": "category[].coding[].display where system contains \"data_type\"" - }, - { - "name": "specimen_file_experimental_strategy", - "select": "category[].coding[].display where system contains \"experimental_strategy\"" - }, - { - "name": "specimen_file_workflow_type", - "select": "category[].coding[].display where system contains \"workflow_type\"" - } - ], - "pivots": [] - } - ] - }, - { - "label": "subject_Patient", - "toResourceType": "DocumentReference", - "alias": "patient_file", - "fields": [ - { - "name": "patient_file_data_category", - "select": "category[].coding[].display where system contains \"data_category\"" - }, - { - "name": "patient_file_data_type", - "select": "category[].coding[].display where system contains \"data_type\"" - }, - { - "name": "patient_file_experimental_strategy", - "select": "category[].coding[].display where system contains \"experimental_strategy\"" - }, - { - "name": "patient_file_workflow_type", - "select": "category[].coding[].display where system contains \"workflow_type\"" - } - ], - "pivots": [] - }, - { - "label": "subject_Patient", - "toResourceType": "Condition", - "alias": "condition", - "fields": [ - { - "name": "diagnosis_id", - "select": "identifier[].value where system contains \"diagnosis_id\"" - }, - { - "name": "primary_diagnosis", - "select": "code.coding[].display" - }, - { - "name": "diagnosis_body_site", - "select": "bodySite[].coding[].display" - } - ], - "pivots": [] - }, - { - "label": "subject_Patient", - "toResourceType": "ResearchSubject", - "alias": "research_subject", - "fields": [ - { - "name": "research_subject_id", - "select": "id" - }, - { - "name": "research_subject_status", - "select": "status" - } - ], - "pivots": [] - }, - { - "label": "subject_Patient", - "toResourceType": "MedicationAdministration", - "alias": "treatment", - "fields": [ - { - "name": "treatment_category", - "select": "category[].coding[].display" - } - ], - "pivots": [] - } - ] - } - } -} -``` - -This example intentionally does not attempt to encode every rollup detail from -the current AQL. The contract expresses the traversal and field-selection -intent. Backend compilation can still produce counts, representative arrays, and -aggregated booleans in the final exported dataframe shape. - -## Pivot Example - -The draft must keep pivot operations first-class because the load-time field -catalog already detects pivotable `CodeableConcept` fields. - -For example, the current tests verify that `valueCodeableConcept` may be marked -as: - -- `pivot_candidate = true` -- `pivot_kind = codeable_concept_display_value` -- `pivot_columns` containing observed coding displays - -That exact behavior is tested in -[internal/catalog/write_profiler_test.go](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/internal/catalog/write_profiler_test.go). - -Example GraphQL mutation: - -```graphql -mutation RunObservationPivot($input: FhirDataframeRunInput!) { - runFhirDataframe(input: $input) { - mode - preview { - columns - rows - rowCount - } - } -} -``` - -Example variables: - -```json -{ - "input": { - "mode": "PREVIEW", - "previewLimit": 10, - "builder": { - "project": "ARANGODB_PROTO", - "authResourcePaths": ["EllrottLab-GDC_Data"], - "rootResourceType": "Observation", - "fields": [ - { - "name": "observation_id", - "select": "id" - }, - { - "name": "observation_code", - "select": "code.coding[].display" - } - ], - "pivots": [ - { - "name": "observation_value_codeable_concept", - "select": "valueCodeableConcept", - "pivotKind": "CODEABLE_CONCEPT_DISPLAY_VALUE", - "columns": [ - "American Joint Committee on Cancer pM0" - ] - } - ], - "traversals": [] - } - } -} -``` - -Interpretation: - -- the selected field `valueCodeableConcept` is not flattened as a plain scalar -- instead, the builder declares that this field should be pivoted using the - currently supported `CodeableConcept` pivot semantics -- the candidate columns come from the observed `pivot_columns` metadata - -This stays aligned with the current implementation rather than inventing a new -pivot engine. - -## Multi-Path Auth Scope - -The current AQL prototype filters on a singular `@auth_resource_path`, for -example in -[queries/gdc_case_assay_matrix_arango_rows.aql](/Users/peterkor/Desktop/BMEG/ARANGODB_PROTO/queries/gdc_case_assay_matrix_arango_rows.aql:1). -The GraphQL contract broadens this to: - -```graphql -authResourcePaths: [String!]! -``` - -Execution semantics in the draft are: - -- all rows are still scoped to one logical `project` -- the caller may include multiple authorized resource paths -- the effective visibility scope is the union of those paths - -This is a contract-level requirement for the future API. It does not require the -current prototype to already accept multiple paths in the same backend query. - -## Preview vs Export - -The contract separates two execution modes: - -- `PREVIEW` -- `EXPORT` - -### Preview - -Preview exists only to support the builder UX: - -- quick sanity check on selected traversals and fields -- small row sample -- not the primary delivery surface for large dataframe output - -### Export - -Export is the primary execution mode: - -- returns an export handle -- avoids pushing large dataframe payloads inline through GraphQL -- leaves room for async materialization and file delivery - -This keeps the contract compatible with the actual workload shape, which is a -graph-to-table export rather than a small nested object read. - -## Acceptance Criteria - -This draft is correct if: - -- it uses real FHIR resource types already present in the prototype -- it uses real reference labels already present in `fhir_edge` -- it uses canonical observed-style field paths -- it includes pivot operations explicitly -- it supports multiple `authResourcePaths` -- it reads as “build this dataframe” rather than “inspect a generic graph” -- it stays compatible with compiling to one backend query plan instead of - requiring GraphQL resolver fanout - -## Assumptions and Defaults - -- V1 pivot support remains limited to current `CodeableConcept` detection. -- `alias` remains the stable traversal-hop identifier. -- Field selection uses compact selector expressions instead of low-level - extraction knobs. -- GraphQL is the builder and read contract; backend-native query languages - remain the execution substrate. -- Export remains the primary mode; preview exists to support the builder UI. diff --git a/docs/DEVELOPER_ARCHITECTURE.md b/docs/DEVELOPER_ARCHITECTURE.md index afa7bb4..3f18ac2 100644 --- a/docs/DEVELOPER_ARCHITECTURE.md +++ b/docs/DEVELOPER_ARCHITECTURE.md @@ -1,357 +1,144 @@ # Developer Architecture -This document describes the repo as it exists now, not the older `prototype.py` - era. - -The current system is a Go codebase with: - -- a CLI for load/discovery/query work -- a Fiber HTTP server -- a gqlgen-backed GraphQL contract -- an Arango-first dataframe compiler/executor -- generated FHIR schema metadata used by the planner - -## 1. Runtime Surfaces - -### CLI - -The CLI entrypoint is: - -- [`cmd/arango-fhir-proto/main.go`](../cmd/arango-fhir-proto/main.go) - -Current commands: - -- `load` -- `query-gdc-case-assay-matrix` -- `export-gdc-case-assay-matrix` -- `discover-populated-references` -- `discover-populated-fields` -- `prepare-gdc-case-assay-matrix` -- `build-scalar-index` -- `benchmark` - -The CLI is still useful for: - -- bulk load runs -- dataset discovery/debugging -- direct AQL-driven exports -- backend benchmarking and parity experiments - -### HTTP Server - -The server entrypoint is: - -- [`cmd/arango-fhir-server/main.go`](../cmd/arango-fhir-server/main.go) - -It wires together: - -- Fiber HTTP server -- GraphQL dataframe service -- optional scope-aware auth for reads/writes - -Mounted routes are registered in: - -- [`internal/api/routes.go`](../internal/api/routes.go) - -Current routes: - -- `GET /healthz` -- `GET /graphql` -- `POST /graphql` -- `GET /apollo` - -## 2. Storage Model - -The repo’s logical collections are defined in: - -- [`internal/ingest/backend.go`](../internal/ingest/backend.go) - -Current primary collections: - -- one collection per FHIR resource type -- `fhir_edge` -- `fhir_field_catalog` -- `patient_file_rollup` - -Important details: - -- every resource collection gets `project` and `id`-oriented indexes -- `Patient` gets extra `_key` indexes for project-scoped ordered traversal -- `fhir_edge` stores graph connections plus `project`, `from_type`, `to_type`, `label` -- `fhir_field_catalog` stores load-time populated-field metadata -- `patient_file_rollup` is a helper/materialized collection for prepared dataframe paths - -The common backend interface is: - -- `internal/store/arango` - -Arango is the only runtime backend. Connection setup lives in: - -- [`internal/store/arango/`](../internal/store/arango/) - -## 3. Load Pipeline - -The primary load implementation is: - -- [`internal/ingest/load.go`](../internal/ingest/load.go) - -High-level flow: - -1. discover NDJSON files from `META` -2. open the selected backend -3. bootstrap collections and indexes -4. choose row-builder mode -5. decode rows and generate: - - vertex documents - - `fhir_edge` documents - - field-catalog profile updates -6. batch writes concurrently -7. emit JSON progress events - -Key load-related pieces: - -- [`internal/ingest/files.go`](../internal/ingest/files.go): NDJSON discovery and scanners -- [`internal/ingest/row_builder.go`](../internal/ingest/row_builder.go): generated vs generic row-builder surface -- [`internal/ingest/generated_load.go`](../internal/ingest/generated_load.go): generated fast-path extraction -- [`internal/catalog/write_profiler.go`](../internal/catalog/write_profiler.go): load-time field profiling -- [`internal/catalog/write_persist.go`](../internal/catalog/write_persist.go): field catalog persistence - -The loader can still run in a slower generic mode, but the intended fast path is -the generated FHIR-specific path. - -## 4. Discovery and Builder Metadata - -Builder introspection depends on two discovery surfaces: - -- populated traversals -- populated fields/pivots - -These live in: - -- [`internal/catalog/read_references.go`](../internal/catalog/read_references.go) -- [`internal/catalog/read_fields.go`](../internal/catalog/read_fields.go) -- [`internal/catalog/read_auth_paths.go`](../internal/catalog/read_auth_paths.go) - -Important behavior: - -- discovery is project-scoped -- discovery can also be auth-resource-path-scoped -- builder traversal hints come from `fhir_edge` -- builder field hints come from `fhir_field_catalog` -- pivot hints are derived at load time and persisted in the catalog - -The server wraps discovery in a cache: - -- [`internal/catalog/cache/cache.go`](../internal/catalog/cache/cache.go) - -That cache is invalidated after successful writes by the server bootstrap code in: - -- [`cmd/arango-fhir-server/main.go`](../cmd/arango-fhir-server/main.go) - -## 5. GraphQL Layer - -The GraphQL schema is: - -- [`internal/graphqlapi/schema.graphqls`](../internal/graphqlapi/schema.graphqls) - -The GraphQL package owns: - -- schema -- request/response mapping -- auth-aware introspection orchestration -- GraphQL-to-dataframe request normalization - -Key files: - -- [`internal/graphqlapi/service.go`](../internal/graphqlapi/service.go): main orchestration service -- [`internal/graphqlapi/mappers.go`](../internal/graphqlapi/mappers.go): GraphQL model to internal dataframe builder mapping -- [`internal/graphqlapi/schema.resolvers.go`](../internal/graphqlapi/schema.resolvers.go): gqlgen resolver entrypoints -- [`internal/graphqlapi/handler.go`](../internal/graphqlapi/handler.go): GraphQL, playground, and Apollo handlers -- [`internal/graphqlapi/scalars.go`](../internal/graphqlapi/scalars.go): custom JSON scalar support - -The GraphQL split is intentional: - -- introspection query: - - `dataframeBuilderIntrospection` -- dataframe execution mutation: - - `runFhirDataframe` - -GraphQL is the read/builder contract. - -## 6. FHIR Schema Metadata vs. FHIR Semantics - -One of the biggest current repo boundaries is the distinction between: - -- raw structural FHIR schema knowledge -- optimizer/domain semantics layered on top - -### Structural schema metadata - -Generated schema metadata lives in: - -- [`internal/fhirschema/schema.go`](../internal/fhirschema/schema.go) -- [`internal/fhirschema/generated.go`](../internal/fhirschema/generated.go) - -This package answers questions like: - -- what canonical fields exist for a resource type -- how to decompose a selector into `sourcePath`, `where`, `valuePath` -- whether a path resolves to `CodeableConcept` -- whether a path resolves to `Coding` -- whether an Observation-style pivot key/value pair is structurally valid - -This metadata is generated from: - -- [`schemas/graph-fhir.json`](../schemas/graph-fhir.json) -- [`cmd/generate/main.go`](../cmd/generate/main.go) - -### Semantic/domain rules - -Friendly field aliases and lowering hints live in: - -- [`internal/fhirsemantics/registry.go`](../internal/fhirsemantics/registry.go) - -This package owns things like: - -- `fieldRef` aliases such as `Patient.case_id` -- document-reference summary normalization hints -- traversal roles such as patient-neighbor vs direct traversal -- study hydration hints - -The intended split is: - -- `fhirschema`: what the FHIR structure is -- `fhirsemantics`: how this repo wants to optimize or present it - -## 7. Dataframe Compiler and Lowering - -The dataframe subsystem is: - -- [`internal/dataframe`](../internal/dataframe) - -Current important files: - -- [`internal/dataframe/service.go`](../internal/dataframe/service.go): service entrypoint and run orchestration -- [`internal/dataframe/validation.go`](../internal/dataframe/validation.go): builder and traversal validation against catalog discovery -- [`internal/dataframe/auth.go`](../internal/dataframe/auth.go): auth-scope and project authorization handling -- [`internal/dataframe/compile.go`](../internal/dataframe/compile.go): compiled query contract and compile entrypoint -- [`internal/dataframe/planner.go`](../internal/dataframe/planner.go): request lowering and optimization planning -- [`internal/dataframe/lowered_types.go`](../internal/dataframe/lowered_types.go): lowered internal builder structures -- [`internal/dataframe/lowered_compile.go`](../internal/dataframe/lowered_compile.go): lowered builder -> optimized AQL - -Current execution model: - -1. GraphQL request is normalized into internal dataframe `Builder` -2. selectors, pivots, aggregates, and slices are validated against discovery + schema metadata -3. the planner lowers the public traversal-first request into the advanced internal form -4. the advanced compiler emits Arango AQL -5. rows are streamed through the backend query executor - -Important current truth: - -- GraphQL stays simple -- optimizer complexity lives under the covers -- Arango is the only supported runtime for `runFhirDataframe` - -## 8. Query Execution - -Row-oriented AQL execution now lives with the dataframe runtime: - -- [`internal/dataframe/query_runtime.go`](../internal/dataframe/query_runtime.go) - -CLI-oriented canned query/export behavior lives with the CLI command surface: - -- [`cmd/arango-fhir-proto/query.go`](../cmd/arango-fhir-proto/query.go) - -This keeps the split honest: - -- `internal/dataframe` owns the callback-based row execution hook used by GraphQL/dataframe reads -- `cmd/arango-fhir-proto` owns file-based query/export command behavior and stdout/file shaping - -## 9. HTTP/Auth Layer - -The import HTTP server lives in: - -- [`internal/api/routes.go`](../internal/api/routes.go) -- [`internal/api/service.go`](../internal/api/service.go) -- [`internal/authscope/principal.go`](../internal/authscope/principal.go) -- [`internal/authscope/scope.go`](../internal/authscope/scope.go) - -The API package now owns: - -- Fiber app construction -- request ID / recovery / logging / auth middleware -- principal extraction and request context propagation -- scope resolution for GraphQL auth-aware reads - -It no longer exposes import job endpoints. - -## 10. Experimental Code - -Non-primary backend work has been pushed under: - -- [`experimental/`](../experimental/) - -Important contents: - -- [`experimental/docker-compose.yml`](../experimental/docker-compose.yml): local Arango-only compose -- [`experimental/docker/docker-compose.full.yml`](../experimental/docker/docker-compose.full.yml): Arango + Surreal + Postgres research stack -- [`experimental/queries/`](../experimental/queries/): backend-specific query artifacts outside the primary Arango path -- [`experimental/ARANGO_VS_SURREAL_FHIR_POSTMORTEM.md`](../experimental/ARANGO_VS_SURREAL_FHIR_POSTMORTEM.md): technical comparison write-up - -The main repo should now be understood as Arango-first. Experimental backends -remain available for comparison work, but they are not the primary product path. - -## 11. Generated Artifacts - -There are two generation steps that matter: - -- [`cmd/generate/main.go`](../cmd/generate/main.go) for generated FHIR code and schema metadata -- gqlgen for GraphQL generated code - -Make targets: - -- `make generate-fhir` -- `make generate-graphql` - -Relevant generated outputs: - -- [`internal/fhir`](../internal/fhir) -- [`internal/fhirschema/generated.go`](../internal/fhirschema/generated.go) -- [`internal/graphqlapi/generated.go`](../internal/graphqlapi/generated.go) -- [`internal/graphqlapi/model/models.go`](../internal/graphqlapi/model/models.go) - -## 12. Recommended Places To Change Things - -If you want to: - -- add a new friendly field alias: - - [`internal/fhirsemantics/registry.go`](../internal/fhirsemantics/registry.go) -- extend structural selector or pivot validation: - - [`internal/fhirschema/schema.go`](../internal/fhirschema/schema.go) -- change GraphQL contract: - - [`internal/graphqlapi/schema.graphqls`](../internal/graphqlapi/schema.graphqls) - - then run `make generate-graphql` -- change dataframe lowering or optimization: - - [`internal/dataframe/planner.go`](../internal/dataframe/planner.go) - - [`internal/dataframe/lowered_compile.go`](../internal/dataframe/lowered_compile.go) -- change HTTP middleware or auth wiring: - - [`internal/api/routes.go`](../internal/api/routes.go) - - [`internal/authscope/scope.go`](../internal/authscope/scope.go) -- change backend bootstrap/index strategy: - - [`internal/ingest/backend.go`](../internal/ingest/backend.go) - -## 13. Current Reality Check - -The repo is no longer “a few hardcoded AQL scripts plus a loader.” - -It is currently: - -- a generated FHIR-aware load pipeline -- a persisted discovery/catalog system -- a GraphQL builder/read contract -- a semantic lowering layer -- an Arango dataframe compiler/executor -- a REST ingest surface - -That is the architecture the docs and future work should assume. +Loom is an Arango-backed compiler for flat, exportable FHIR dataframes. The +authority for FHIR structure is the checked-in +[`schemas/graph-fhir.json`](../schemas/graph-fhir.json) graph schema and the +generated Go metadata derived from it. Code should not add a second handwritten +FHIR model or a parallel AQL implementation. + +## Runtime surfaces + +`cmd/arango-fhir-proto` is the operator CLI. Its supported commands are: + +- `load` for the temporary mutable compatibility load; +- `load-generation` for a complete immutable dataset generation; +- `discover-populated-references` and `discover-populated-fields` for + catalog diagnostics. + +`cmd/arango-fhir-server` owns the HTTP process. It mounts health, GraphQL, and +developer GraphQL tools. In `--dataset-generations` mode it resolves one active +READY generation and rejects the legacy one-file HTTP import endpoint. + +The GraphQL dataframe mutation is a live compatibility/expert transport to the +compiler, not the intended non-technical product UI. Do not add graph-editor +features to it. Guided discovery and recipe preparation live below transport +in `internal/dataframebuilder`, `internal/discovery`, and +`internal/recipecompiler` until the dedicated product endpoint is added. + +## Load and storage model + +`internal/ingest` reads an NDJSON directory, preflights it against the local +schema, builds vertices and `fhir_edge` documents, profiles populated fields, +and writes batches to Arango. Generated loaders are the fast path for covered +resources; the schema-backed generic loader is the fallback for the other +active graph roots. + +Fresh loads bootstrap: + +- one document collection per loaded FHIR resource type; +- `fhir_edge`, the only stored relationship representation; +- `fhir_field_catalog`, the evidence source for available fields, pivots, and + relationships; +- `loom_dataset_lifecycle` in immutable-generation mode. + +There is no maintained `patient_file_rollup`, scalar-index collection, or +alternate relationship collection. A future materialization must be introduced +as a compiler-selected physical optimization with write/read ownership, +generation scope, freshness policy, and Explain coverage; it must not be added +as an unused bootstrap collection. + +Immutable loads use `internal/dataset`, `internal/datasetstore`, and +`internal/schemaidentity`. Their manifest records project, generation, and +schema identity; the active pointer selects one READY generation per project. +The generation-qualified physical keys and mandatory generation predicates are +part of the query correctness contract, not an optional filter. + +## Compiler path + +The current runtime call path is: + +```text +GraphQL request + -> graphqlapi resolver + -> dataframebuilder.Service + -> dataframe.Service + -> semantic validation and lowering + -> lowered AQL compiler + -> Arango query execution/streaming +``` + +`internal/dataframe` owns semantics, authorization-aware query compilation, +and execution. `internal/catalog` owns scoped observed-field and relationship +facts. `internal/fhirschema` owns generated structural metadata. These +boundaries matter: catalog observations constrain what is populated, while +schema metadata constrains what a request means. + +Generic lowering is the default direction. It accepts generated reverse/builder +relationship routes proven to correspond to the physical `INBOUND` `fhir_edge` +layout, plus the explicitly proven `ResearchSubject --study--> ResearchStudy` +`OUTBOUND` route. A schema-valid forward FHIR reference alone is still not +sufficient proof; every other forward route remains rejected until it has a +verified storage contract. + +The older specialized Patient/case-assay lowerer is still production-reachable +for selected request shapes. It cannot be deleted merely because generic +lowering exists: it currently supplies shared sibling traversal behavior, +DocumentReference normalization, and ResearchSubject-to-ResearchStudy lookup +semantics. See [`COMPILER_CLEANUP_AUDIT.md`](COMPILER_CLEANUP_AUDIT.md) for its +explicit removal gates. + +`internal/dataframe/physical_plan.go` and its renderer are a typed diagnostic +and optimization foundation. They are not yet the execution renderer for all +selections, filters, aggregates, pivots, and required relationships. Keep them +as new compiler work rather than treating their current limited runtime +reachability as dead code. + +## Product foundations + +The product-facing contract should exchange opaque catalog capability IDs and +recipe intent, never browser-provided FHIR selectors, graph labels, auth paths, +or AQL. Relevant ownership is: + +- `internal/discovery`: scoped guided capability snapshots; +- `internal/recipe`: versioned user intent and templates; +- `internal/recipecompiler`: capability-to-typed-dataframe translation; +- `internal/export` and `internal/dataframeexport`: flat NDJSON/CSV streaming + primitives. + +These are foundations, not a claim that the product API, job system, saved +recipes, Elasticsearch delivery, or all relationship/pivot recipes are done. +Keep the boundary clean so those features can be added without reviving a +hand-maintained AQL track. + +## Compatibility tracks and removal order + +The following compatibility tracks remain deliberately, but should not grow: + +- mutable CLI `load` and `POST /api/v1/imports`, until a complete + generation-aware upload/job flow replaces them; +- raw-structure GraphQL dataframe input, until guided capability/recipe + transport is public; +- specialized Patient lowering, until generic lowering has equivalent result + and Explain/cost coverage. + +The former hard-coded GDC AQL files, GDC export command, browser `/builder` +demo, and unowned bootstrap materializations were removed. They bypassed the +compiler and did not work with immutable generation keys. + +## Generated code and tests + +Run `make generate-fhir` after changing the graph schema and +`make generate-graphql` after changing the GraphQL schema. Do not hand-edit +generated FHIR or gqlgen output. + +The normal verification targets are: + +```bash +make test +make conformance +make compiler-bench +``` + +Opt-in Arango tests validate actual execution and Explain behavior. New query +optimizations must add result-shape tests plus Explain/cost expectations before +changing bootstrap indexes or deleting a semantic fallback. diff --git a/docs/FORMAL_GAP_ANALYSIS.md b/docs/FORMAL_GAP_ANALYSIS.md new file mode 100644 index 0000000..c19e2da --- /dev/null +++ b/docs/FORMAL_GAP_ANALYSIS.md @@ -0,0 +1,1544 @@ +# Formal Gap Analysis: From Prototype to Development Service + +## 1. Purpose + +This document is the implementation plan for moving Loom from a working +dataframe prototype to a deployable development service that can: + +1. ingest an unfamiliar FHIR dataset into ArangoDB +2. analyze what the dataset actually contains +3. ask a non-technical user a small number of meaningful questions +4. create a versioned dataframe recipe +5. validate and explain the recipe +6. compile the recipe into performant, authorization-safe AQL +7. preview the result +8. export flat NDJSON or CSV +9. optionally load the same row stream into Elasticsearch + +This is a plan, not a claim that those capabilities already exist. + +The compiler is the first implementation priority. The detailed authoritative +program for FHIR semantic lowering, filters, grains, pivots, aggregates, +physical AQL generation, optimizer passes, and Arango performance is +[`COMPILER_FIRST_PLAN.md`](COMPILER_FIRST_PLAN.md). The service-oriented gaps +below are downstream work and must not distort or precede the compiler core. + +The intended implementer is an engineering agent working directly in this +repository. Every gap therefore includes concrete ownership, implementation +steps, tests, dependencies, and completion criteria. + +## 2. Product Boundary + +### 2.1 What "any FHIR" should mean + +The first production contract should be precise: + +> Loom can losslessly ingest any valid resource type represented by its active +> FHIR graph schema, preserve unknown profile extensions in the raw payload, +> discover populated fields and references, and offer dataframe recipes for +> query shapes supported by its planner. + +It should not initially mean: + +- every historical and future FHIR release without selecting a schema package +- arbitrary cross-resource graph queries +- automatic clinical interpretation of unknown extensions +- every possible FHIRPath function +- automatic production of a useful dataframe when the source data has no + stable identifiers or usable relationships + +FHIR version, graph schema, semantic vocabulary, and planner capability must be +visible metadata. Unsupported query shapes must be reported honestly. + +### 2.2 Product architecture + +The target flow is: + +```text +FHIR input + -> validated project load + -> dataset manifest and analysis snapshot + -> recipe templates filtered by observed data and planner support + -> short guided conversation + -> normalized versioned recipe + -> validation and cardinality explanation + -> logical plan + -> optimized AQL + -> preview row stream or asynchronous export row stream + -> NDJSON / CSV / Elasticsearch +``` + +The frontend must not build AQL, infer graph safety, calculate authorization +scope, or decide whether a traversal is supported. + +## 3. Current Baseline + +The repository already contains valuable production-shaped components: + +- the 14-resource development dataset under `META/` and smaller `META_SMALL/` +- the active graph schema at `schemas/graph-fhir.json` +- generated Go FHIR structs, validators, and edge extractors in `internal/fhir` +- generated FHIR field/traversal metadata in `internal/fhirschema/generated.go` +- existing generation commands in `cmd/generate`, `Makefile`, and `gqlgen.yml` +- NDJSON and gzip discovery and scanning in `internal/ingest` +- generated and generic FHIR row builders +- one Arango collection per discovered resource type +- a shared `fhir_edge` graph +- load-time field profiling in `fhir_field_catalog` +- project and auth-resource-path scoping +- populated field and relationship discovery +- discovery caching with project invalidation +- generated FHIR schema metadata +- mechanically derived friendly `fieldRef` support in `dataframebuilder` +- explicit optimized traversal semantics in `dataframe/traversal_rules.go` +- GraphQL introspection and dataframe execution +- a logical request, lowering planner, optimized AQL compiler, and query runner +- a browser builder suitable for development diagnostics +- unit and integration tests for important compiler paths + +All implementation packages in this plan must extend those owners. The plan +does not authorize a parallel FHIR object model, handwritten copies of generated +validators/extractors, a replacement graph schema, or manual edits to +gqlgen-generated files. Use `META/` for baseline characterization and add +synthetic conformance fixtures only where the existing sample lacks a required +case. + +The current limiting facts are: + +- generated ingestion rejects resource types outside its generated switch +- generic ingestion still requires a class in the configured graph schema +- HTTP import is synchronous and accepts one staged resource file +- the field catalog stores bounded distinct samples but not a complete dataset + manifest, relationship coverage, fanout, or value frequencies +- product-level recipes and templates do not exist +- planner lowering requires a Patient root +- planner traversal support is a hardcoded list of recognized tuples +- simple structurally valid requests may be rejected if they do not match the + optimized lowering family +- input supports only a narrow filter/predicate surface +- preview applies a limit but accumulates all returned rows in memory +- cursor fields exist in the GraphQL input but are not an implemented paging + contract +- export handles, durable jobs, files, and Elasticsearch delivery do not exist +- `/healthz` is liveness only; readiness and dependency diagnostics are absent + +## 4. Delivery Strategy + +Implement the compiler program first, then build thin product and delivery +layers around it. Do not begin with a larger frontend. +For multi-worker execution, use +[`TERRA_ULTRA_EXECUTION_PLAN.md`](TERRA_ULTRA_EXECUTION_PLAN.md), which splits +the durable job work into an early substrate and later export recovery, defines +contract freezes, and prevents unsafe parallel edits to shared packages. + +| Milestone | Outcome | Work | +| --- | --- | --- | +| M0 | Compiler oracle and typed contracts | CP0-CP2 | +| M1 | FHIR grain, filters, pivots, and correct generic lowering | CP3-CP6 | +| M2 | Typed AQL generation and optimizer | CP7-CP8 | +| M3 | Arango evidence and compiler release gate | CP9 | +| M4 | Thin recipe/capability/preview/export layer | reduced G6-G14 | +| M5 | Development-service durability and delivery | reduced G2-G5, G15-G20 | + +Each milestone must leave the repository testable and internally consistent. +Do not merge a new public API before its service and contract tests exist. + +--- + +# Gap 1: No Executable Product Use-Case Contract + +## Current state + +The repository has examples and a working browser builder, but it does not have +a machine-readable set of user conversations defining what the product must +successfully create. + +Without those fixtures, planner expansion can become an unbounded attempt to +support all graph shapes, and frontend work can expose capabilities the backend +does not implement. + +## Target state + +The repository contains a versioned conformance corpus covering at least these +recipe families: + +- patient cohort +- specimen inventory +- file manifest +- diagnoses +- labs/observations +- study enrollment + +Each fixture declares the user's words, normalized intent, required dataset +features, expected recipe, expected row grain, output schema, and support state. + +## Implementation plan + +1. Create `conformance/recipes/`. +2. Define a JSON fixture schema in `conformance/recipes/schema.json`. +3. Give every fixture these fields: + - `id` + - `description` + - `conversation` + - `projectFixture` + - `requiredResources` + - `requiredRelationships` + - `expectedRecipe` + - `expectedColumns` + - `expectedGrain` + - `expectedWarnings` + - `expectedSupportState` +4. Add positive fixtures for all six recipe families. +5. Add ambiguity fixtures, for example "files by patient" without an explicit + row grain. +6. Add unsupported fixtures, including missing relationships and unknown + clinical concepts. +7. Reuse `META/` for baseline and representative end-to-end cases. Add small + NDJSON datasets under `conformance/data//` only for isolated, + missing, ambiguous, or failure cases that `META/` cannot express. +8. Create `conformance/run_conformance.py` as an orchestrator that can invoke Go + tests or a running server and produce JSON results. Keep correctness logic in + Go tests; the script should coordinate rather than reimplement Loom. +9. Add `make conformance`. +10. Document how to add a fixture. + +## Tests + +- JSON Schema validation for every fixture. +- A Go test that loads every fixture definition and rejects duplicate IDs. +- A conformance smoke test that runs at least one fixture end to end. +- CI must fail when a fixture marked `supported` does not pass. + +## Dependencies + +None. This is M0 and should be implemented first. + +## Exit criteria + +- At least 12 positive and 8 negative/ambiguous conversations exist. +- Every future planner or frontend change can name the fixtures it enables. +- `make conformance` produces a deterministic result summary. + +--- + +# Gap 2: FHIR Version and Schema Support Is Implicit + +## Current state + +The server defaults to `schemas/graph-fhir.json`. The generated loader supports +only generated resource cases, while the generic loader requires a matching +class in the graph schema. The loaded project does not persist which FHIR +version, schema digest, generator version, or ingestion mode produced it. + +## Target state + +Every project load is tied to an explicit, inspectable schema identity. Unknown +profiles and extensions remain in the raw payload. Unsupported resource types +fail during preflight with a complete report rather than partway through load. + +## Implementation plan + +1. Add `internal/schemaidentity` with: + - `FHIRVersion` + - `SchemaName` + - `SchemaVersion` + - `SchemaSHA256` + - `GeneratorVersion` + - `GeneratedResourceTypes` +2. Compute the schema digest at process startup. +3. Add a `loom_dataset` collection containing one document per project and + dataset generation. +4. Persist schema identity in the dataset document before ingestion begins. +5. Add ingestion preflight that scans filenames and the first bounded number of + records to identify resource types. +6. Compare discovered resource types with: + - graph-schema classes + - generated loader support +7. Select ingestion mode per resource type: + - generated when supported + - generic fallback when the graph schema contains the class + - unsupported otherwise +8. Remove the requirement that a whole load uses one global `UseGeneric` mode. + Retain an override for debugging and parity testing. +9. Return one structured preflight report listing every resource type and + selected mode before writing begins. +10. Add server endpoints/GraphQL fields to inspect active server schema identity + and dataset schema identity. +11. Reject queries when the dataset schema identity is incompatible with the + active semantic/schema metadata unless an explicit migration is run. + +## Files and packages + +- add `internal/schemaidentity/` +- modify `internal/ingest/load.go` +- modify `internal/ingest/row_builder.go` +- modify `internal/ingest/generated_load.go` or generation output contract +- modify `internal/ingest/backend.go` +- modify both command entrypoints + +## Tests + +- generated-supported resource selects generated mode +- schema-known but nongenerated resource selects generic mode +- schema-unknown resource fails preflight without writes +- extension data survives round-trip in `payload` +- schema digest mismatch is detected +- mixed generated/generic load produces graph-equivalent documents + +## Migration + +Existing projects have no dataset identity. Mark them `legacy-unversioned` and +require analysis rebuild before exposing them through the product API. + +## Exit criteria + +- A project always reports the schema under which it was loaded. +- Mixed-resource loads choose the safest available builder automatically. +- Unsupported resource types are reported before mutation. + +--- + +# Gap 3: Loads Are Not Atomic Dataset Operations + +## Current state + +CLI directory loads and synchronous single-file HTTP imports write directly to +live collections. The HTTP route stages one file and waits for completion. A +failed multi-resource load can leave partially updated data and discovery +metadata. + +## Target state + +A dataset load is a durable operation with preflight, generation identity, +progress, error accounting, finalization, and an explicit ready state. Queries +only use finalized generations. + +## Implementation plan + +1. Extend `loom_dataset` with states: + - `PREFLIGHT` + - `LOADING` + - `ANALYZING` + - `READY` + - `FAILED` + - `SUPERSEDED` +2. Assign every load a `dataset_generation` UUID. +3. Store generation on every vertex, edge, and catalog document. +4. Update all indexes and query filters to include project plus active + generation. +5. Introduce `internal/dataset` to own lifecycle transitions. +6. Split ingestion into: + - preflight + - bootstrap + - resource ingestion + - reference reconciliation + - catalog finalization + - analysis + - activation +7. Write into a new generation while the previous generation remains readable. +8. Atomically switch the project's active generation only after validation. +9. Retain the prior generation until a configured cleanup period expires. +10. Replace synchronous HTTP import as the primary deployment path with a load + job endpoint. Keep synchronous import only as a bounded development helper. +11. Persist per-resource counts, rejected rows, validation errors, inserted + edges, elapsed stages, and source checksums. +12. Add cancellation checks through the load loops. +13. Add a cleanup command for superseded/failed generations. + +## Tests + +- failed load never replaces active generation +- previous generation remains queryable during a new load +- activation switches all discovery/query reads consistently +- cancellation leaves a failed/cancelled generation, not a ready one +- cleanup removes only inactive generations +- partial resource failure has a durable error report + +## Dependencies + +Gap 2. + +## Exit criteria + +- A development operator can observe and retry a failed load. +- No query sees a mixture of old and new generations. +- Dataset readiness is a persisted state, not inferred from collection presence. + +--- + +# Gap 4: Reference Integrity Is Not Measured After Load + +## Current state + +Edges are generated during resource ingestion. The system counts edges but does +not publish a post-load integrity report covering dangling targets, duplicate +references, cross-project edges, or relationships that resolve only partially. + +## Target state + +Every finalized dataset has a reference-integrity report used by both operators +and recipe capability analysis. + +## Implementation plan + +1. Add `internal/analysis/referenceintegrity`. +2. Run bounded AQL analyses for every observed relationship tuple. +3. Record: + - total references + - resolved edges + - dangling `_from` and `_to` counts + - distinct sources and targets + - duplicate logical reference count + - cross-project/generation violations + - source coverage +4. Persist results in `loom_relationship_analysis` keyed by project, + generation, source type, label, and target type. +5. Classify relationship quality: + - `HEALTHY` + - `SPARSE` + - `PARTIAL` + - `BROKEN` +6. Block generation activation only for structural isolation violations. + Preserve sparse/partial datasets but surface warnings. +7. Feed relationship quality into recipe capability results. +8. Add a CLI inspection command for operators. + +## Tests + +- complete references produce healthy analysis +- dangling target is counted and warned +- cross-project edge fails activation +- sparse relationship remains usable with a warning + +## Dependencies + +Gap 3. + +## Exit criteria + +- Every active dataset has a reference-integrity summary. +- The product never recommends a path without reporting observed coverage. + +--- + +# Gap 5: Catalog Analysis Is Too Shallow for Product Decisions + +## Current state + +`fhir_field_catalog` records path, kind, document count, sample count, bounded +distinct values, and pivot metadata. Reference discovery reports tuple and edge +count. It does not provide resource counts, coverage denominators, value +frequencies, high-cardinality search, fanout percentiles, or freshness metadata. + +## Target state + +A finalized, generation-scoped analysis snapshot answers the questions needed +by recipe selection and guided filtering without expensive ad hoc scans on each +page load. + +## Implementation plan + +1. Create `internal/analysis` as the orchestration package. Keep catalog raw + reads in `internal/catalog`. +2. Add `loom_resource_analysis`: + - document count + - valid/rejected count + - distinct logical ID count + - profile/extension URL frequencies where available +3. Extend field analysis with: + - coverage numerator and denominator + - missing count + - scalar/repeated cardinality classification + - approximate distinct count + - bounded example values + - top values with counts for low/medium-cardinality scalar fields + - sensitivity/display classification hook +4. Extend relationship analysis with: + - distinct source/target counts + - source and target coverage + - average, p50, p95, and max fanout +5. Do not compute unbounded exact distinct values during every load. Introduce + configurable caps and approximate counts. +6. Add on-demand, paged value search for high-cardinality fields. Require a + minimum search prefix and enforce query timeouts. +7. Persist `analysis_version`, generation, start/end timestamps, and status. +8. Make analysis idempotent and restartable. +9. Extend cache keys with dataset generation and analysis version. +10. Invalidate cache on generation activation rather than individual resource + writes. +11. Add service methods for dataset summary, relationship inventory, candidate + fields, and value suggestions. + +## Suggested packages + +```text +internal/analysis/ + service.go + resource.go + relationships.go + fields.go + values.go + types.go +``` + +## Tests + +- coverage uses the correct resource denominator +- auth scope changes counts and values correctly +- fanout percentiles match a deterministic fixture +- truncated value sets explicitly report truncation +- on-demand value search cannot escape project/generation/auth scope +- analysis rerun replaces one snapshot without duplicate records + +## Dependencies + +Gaps 3 and 4. + +## Exit criteria + +- The frontend can render recipe availability, columns, examples, coverage, and + filters without issuing raw AQL. +- Analysis has a known version and freshness state. + +--- + +# Gap 6: No Versioned Product Recipe Model + +## Current state + +The public input is a compiler-oriented GraphQL tree of roots, selectors, +traversals, aggregates, pivots, and slices. There is no stable artifact that +captures user intent independently of current planner internals. + +## Target state + +The product owns a versioned recipe model that can be created by the frontend, +CLI, or future language interface and translated into the existing dataframe +builder. + +## Implementation plan + +1. Add `internal/recipe`. +2. Define V1 types: + - `Recipe` + - `TemplateID` + - `Grain` + - `ColumnSelection` + - `Filter` + - `Sort` only if required for deterministic slices + - `Destination` +3. Use stable semantic IDs, not raw AQL or display labels. +4. Include: + - recipe version + - template version + - project + - dataset generation constraint or compatibility policy + - row grain + - selected columns + - filters + - user-provided output names +5. Define JSON Schema and GraphQL input/output types. +6. Implement normalization: + - trim names + - canonicalize operators + - deduplicate columns + - apply explicit defaults + - produce deterministic serialization +7. Implement `Recipe -> dataframe.Builder` translation behind an interface. +8. Keep `FhirDataframeInput` as an advanced/developer contract during + migration; do not force the browser product to construct it. +9. Return typed error codes with field paths in addition to messages. +10. Add migration functions from V1 to future recipe versions. + +## Tests + +- JSON and GraphQL round trips +- deterministic normalization +- duplicate/output-name collision rejection +- V1 fixture translation into expected builder input +- unknown version fails with an actionable error + +## Dependencies + +Gap 1. It can begin in parallel with analysis but cannot be declared usable +until Gap 7 exists. + +## Exit criteria + +- User intent can be saved without storing GraphQL or AQL. +- Conformance fixtures use the real recipe types. + +--- + +# Gap 7: No Template and Semantic Vocabulary Registry + +## Current state + +Friendly field references and some traversal semantics exist, but there is no +product registry defining recipe families, grains, common columns, synonyms, +required relationships, or destination compatibility. + +## Target state + +Templates are versioned code/data definitions that map user concepts to FHIR +semantics and declare capability requirements without embedding canned AQL. + +## Implementation plan + +1. Add `internal/recipe/templates`. +2. Define `TemplateDefinition` with: + - stable ID/version + - title/description + - supported grains + - required and optional semantic relationships + - suggested/common/advanced columns + - common filters + - required planner capabilities + - stable identifier strategy + - supported destinations +3. Define `SemanticField` with: + - semantic ID + - labels and synonyms + - candidate resource types/profiles + - prioritized `fieldRef`/selector fallbacks + - data kind + - sensitivity classification +4. Define `SemanticRelationship` separately from physical edge labels. +5. Consolidate the mechanically derived field references in + `internal/dataframebuilder/fieldrefs.go` and the optimized traversal roles in + `internal/dataframe/traversal_rules.go` behind these stable concepts. Avoid + leaving product semantics split across unrelated packages. +6. Implement initial template definitions for all six product families. +7. Add a capability evaluator that intersects: + - template requirements + - active dataset analysis + - planner capabilities +8. Return `AVAILABLE`, `DEGRADED`, or `UNAVAILABLE` with reasons. +9. Add human-readable fallback text, but keep reason codes stable. +10. Make registry validation run in tests and process startup. + +## Tests + +- every template references valid semantic fields/relationships +- every suggested column has at least one resolver +- capability evaluation handles missing resources, sparse links, and planner + limitations +- synonyms do not create ambiguous IDs + +## Dependencies + +Gaps 5 and 6. + +## Exit criteria + +- The UI can ask "What are you making?" using backend-returned templates. +- An unavailable template includes a concrete reason. + +--- + +# Gap 8: No Unified Capability API + +## Current state + +The current introspection operation returns fields and one-hop related resource +hints. Clients could combine those records, but they cannot ask whether a full +recipe is supported, what grain is viable, or what warnings apply. + +## Target state + +One backend service is authoritative for dataset summary, templates, recipe +options, value suggestions, validation, and explanation. + +## Implementation plan + +1. Add `internal/productapi` or extend `internal/dataframebuilder` only if the + latter remains semantically accurate. +2. Implement service methods: + - `DatasetSummary` + - `ListRecipeTemplates` + - `RecipeOptions` + - `FieldValueSuggestions` + - `ValidateRecipe` + - `ExplainRecipe` +3. Add matching GraphQL queries while retaining current introspection for + advanced clients. +4. Every input must resolve project, active generation, and auth paths before + analysis reads. +5. Return stable support and warning codes. +6. Include analysis freshness and dataset generation in responses. +7. Add request cost limits for recursive option expansion and value search. +8. Cache read-only results by project, generation, auth scope, template, grain, + and analysis version. + +## Tests + +- GraphQL contract tests for every new operation +- cross-scope cache isolation +- unavailable template reason propagation +- stale analysis response behavior +- no raw selector/AQL required in the primary recipe-options flow + +## Dependencies + +Gaps 5-7. + +## Exit criteria + +- A thin frontend can implement the full conversation using documented API + calls. +- Backend capability responses never advertise a planner-unsupported path. + +--- + +# Gap 9: No Recipe Persistence and Ownership + +## Current state + +Recipes cannot be saved, named, versioned, cloned, or audited. + +## Target state + +Users can save reusable recipes while Loom preserves ownership, normalized +content, compatibility state, and execution history. + +## Implementation plan + +1. Add `loom_recipe` collection. +2. Store: + - recipe ID + - project + - owner subject + - name/description + - normalized recipe JSON + - recipe/template versions + - created/updated timestamps + - last validated generation + - optimistic concurrency revision +3. Implement create, read, update, clone, list, and archive operations. +4. Enforce project authorization and owner/admin mutation policy. +5. On load, revalidate against the active dataset generation and report: + - compatible + - compatible with warnings + - incompatible +6. Never silently rewrite a saved recipe after template changes. +7. Add explicit migration/upgrade operation producing a new revision. + +## Tests + +- owner and project authorization +- optimistic concurrency conflict +- generation revalidation +- template upgrade preserves the previous revision +- archived recipes do not appear by default + +## Dependencies + +Gaps 6-8. + +## Exit criteria + +- A recipe is a durable, auditable product artifact. +- Loading new data cannot silently change saved intent. + +--- + +# Gap 10: Planner Is Patient-Root and Hardcoded to One Family + +## Current state + +`internal/dataframe/planner.go` rejects non-Patient roots. Supported traversal +tuples are classified in a hardcoded switch in `traversal_rules.go`. The +lowered plan is optimized around patient/case/assay and document summary sets. + +## Target state + +The planner supports declared row grains for Patient, Specimen, +DocumentReference/File, Condition/Diagnosis, Observation, and ResearchSubject +or study enrollment. Optimization remains explicit, testable, and safe. + +## Implementation plan + +This gap is superseded by CP0-CP9 in +[`COMPILER_FIRST_PLAN.md`](COMPILER_FIRST_PLAN.md). The steps below remain a +summary only; do not assign Gap 10 as one worker packet. + +1. Refactor planning into three layers: + - semantic logical plan + - generic physical plan + - optional optimized physical rewrites +2. Introduce `LogicalPlan` types that explicitly represent: + - grain/root set + - joins/traversals + - projections + - filters + - grouping/aggregation + - pivots + - representative slices +3. Replace the Patient check with grain-specific root planning. +4. Implement a generic one-hop/n-hop traversal physical operator using + schema-validated relationship definitions. +5. Preserve current patient-case-assay logic as an optimization rule over the + generic plan, not the only compilable shape. +6. Replace the switch-only traversal registry with data-driven semantic rules + generated or validated against `fhirschema`. +7. Add planner capability descriptors so Gap 7 can ask what operations are + implemented for each grain/path. +8. Implement grains in this order: + - Patient + - Specimen + - DocumentReference/File + - Condition/Diagnosis + - Observation + - ResearchSubject/Study enrollment +9. For each grain, define stable row identity and duplicate semantics. +10. Reject cycles and cap traversal depth in V1. +11. Add plan normalization to ensure semantically equivalent recipes compile + consistently. +12. Add plan explain output separate from raw AQL. + +## Suggested file split + +```text +internal/dataframe/planner/ + logical.go + capabilities.go + validate.go + physical.go + generic.go + optimize_patient.go + explain.go +``` + +Perform the move incrementally; do not rewrite the compiler and planner in one +unreviewable change. + +## Tests + +- golden logical plans for every conformance recipe +- root-grain tests for all six grains +- no duplicate rows unless the recipe explicitly requests an exploding grain +- cycle/depth rejection +- old Patient queries compile to equivalent AQL/results +- generic and optimized plans have result parity + +## Dependencies + +Gaps 1, 6, and 7. + +## Exit criteria + +- Every initial template has at least one supported grain. +- Planner support is queryable rather than inferred from error strings. +- Current optimized Patient behavior remains covered by parity tests. + +--- + +# Gap 11: Filters and FHIR Selection Semantics Are Too Narrow + +## Current state + +Selectors support a constrained path grammar and predicates are largely +`contains`/equality-oriented. The recipe experience needs typed filters, +missing-value rules, terminology-aware code selection, numeric/date comparison, +and repeated-value semantics. + +## Target state + +Recipe filters use a typed, safe expression model compiled to bound AQL. The +supported subset is explicit and sufficient for the six initial templates. + +## Implementation plan + +1. Define typed recipe filter operators: + - `EQUALS` + - `NOT_EQUALS` + - `IN` + - `EXISTS` + - `MISSING` + - `CONTAINS_TEXT` + - `GT`, `GTE`, `LT`, `LTE` + - bounded date/range operators +2. Define repeated-value semantics: + - `ANY` + - `ALL` only if required + - `NONE` +3. Add data types to semantic fields and candidate-column responses. +4. Validate operator compatibility before planning. +5. Compile all values through bind variables; never interpolate user values. +6. Add terminology representation for code/system/display triples. Do not rely + only on display strings when a code is available. +7. Implement missing/null semantics consistently for absent path, null value, + and empty array. +8. Add timezone policy for FHIR date/dateTime/instant comparisons. +9. Expose filter capabilities per field through Recipe Options. +10. Add cost limits for large `IN` lists. + +## Tests + +- operator/type compatibility +- array `ANY` semantics +- missing versus empty versus null +- code/system matching +- date boundary behavior +- bind-variable injection safety +- auth filters remain present in every compiled traversal + +## Dependencies + +Gaps 6, 7, and 10. + +## Exit criteria + +- Every initial conversation fixture can express its filters without raw + FHIRPath or AQL. +- Filter semantics have result-based tests, not only query-string tests. + +--- + +# Gap 12: Cardinality and Query Cost Are Not Explained + +## Current state + +The compiler can aggregate and slice, but the product does not explain whether +a relationship multiplies rows, produces arrays, or creates a costly plan. +Users can request a technically valid shape that is surprising or expensive. + +## Target state + +Recipe validation returns row-grain, cardinality, null-coverage, and cost +warnings before preview or export. + +## Implementation plan + +1. Add `PlanAnalysis` to the planner result. +2. For every relationship classify: + - one-to-one observed + - optional-one observed + - one-to-many + - many-to-many/unknown +3. Use dataset fanout analysis from Gap 5. +4. Estimate base rows, output rows, scanned vertices, and maximum fanout. +5. Mark each selected column as: + - scalar + - repeated array + - aggregated + - pivoted + - row-expanding +6. Return stable warnings such as: + - `HIGH_FANOUT` + - `SPARSE_COLUMN` + - `ROW_EXPANSION` + - `HIGH_CARDINALITY_PIVOT` + - `EXPENSIVE_VALUE_FILTER` +7. Add configurable preview/export cost policies. +8. Require explicit acknowledgement or asynchronous export for plans above the + synchronous threshold. +9. Surface AQL optimizer/explain diagnostics in developer mode only. + +## Tests + +- deterministic cardinality estimates on fixture datasets +- warning thresholds +- high-fanout plan cannot run synchronously +- scalar versus array output classification +- developer explain contains no credentials or sensitive values + +## Dependencies + +Gaps 5 and 10. + +## Exit criteria + +- The user can understand what one row means before running the query. +- Loom blocks obviously unsafe synchronous plans. + +--- + +# Gap 13: Preview Is Not a Bounded Production API + +## Current state + +Preview uses a row limit but collects every returned row in a Go slice. Cursor +input is not a real paging implementation. There are no explicit query timeout, +concurrency, cancellation, response-size, or stable-order guarantees. + +## Target state + +Preview is a bounded, cancellable API with deterministic pagination and resource +limits. + +## Implementation plan + +1. Create a preview-specific service rather than overloading export behavior. +2. Define hard server limits: + - maximum requested rows + - maximum encoded bytes + - maximum query duration + - maximum concurrent previews per subject/project +3. Establish a stable ordering and cursor contract based on grain identity plus + a tie-breaker. +4. Compile cursor predicates rather than offset pagination. +5. Return `nextCursor`, truncated state, elapsed time, and warnings. +6. Cancel the Arango cursor when the request context ends. +7. Stop row iteration when encoded-byte or row limits are reached. +8. Reject preview for plans above the configured synchronous cost threshold. +9. Keep a small in-memory result only up to the enforced maximum. +10. Add request-level metrics and structured error codes. + +## Tests + +- stable next-page behavior with duplicate sort values +- cancellation closes the query cursor +- byte limit truncates safely +- maximum concurrency enforcement +- timeout maps to a stable API error +- authorization scope is identical across pages + +## Dependencies + +Gaps 10-12. + +## Exit criteria + +- Preview cannot consume unbounded Loom memory. +- Pagination neither skips nor duplicates rows for a stable dataset generation. + +--- + +# Gap 14: No Shared Streaming Export Runtime + +## Current state + +The row executor uses a callback, but the dataframe service materializes all +rows into `Result`. File export remains CLI/canned-query territory. + +## Target state + +One streaming runtime executes a compiled plan and feeds bounded destination +writers without materializing the full dataframe. + +## Implementation plan + +1. Define `RowStream`/`RowSink` interfaces in `internal/export` or + `internal/dataframe/stream`. +2. Make the stream provide: + - schema/columns before or with first row + - rows + - progress counters + - close/cancel/error semantics +3. Refactor query execution so preview and export share compilation but use + different consumers. +4. Implement NDJSON writer with one flat object per line. +5. Implement CSV writer with deterministic columns and configurable array + encoding policy. +6. Add checksum, byte count, row count, start/end timestamps, and recipe/plan + provenance. +7. Write to a temporary artifact and atomically finalize it. +8. Define an artifact-store interface. Implement local filesystem first, with + configuration that makes later object storage possible. +9. Add maximum artifact size and disk-space preflight. +10. Ensure cancellation deletes incomplete temporary artifacts or marks them + failed for cleanup. + +## Tests + +- million-row synthetic stream keeps memory bounded +- NDJSON is valid and newline-terminated +- CSV columns remain stable when rows omit values +- cancellation removes incomplete artifact +- checksum and counts match content +- preview/export result parity for the same recipe and generation + +## Dependencies + +Gaps 10-13. + +## Exit criteria + +- Export memory usage is independent of total row count. +- CSV and NDJSON use the same compiled plan and row semantics. + +--- + +# Gap 15: No Durable Job System + +## Current state + +Imports run synchronously and exports do not exist. There is no persistent +queue, lease, retry, cancellation, progress, or recovery after process restart. + +## Target state + +Load, analysis, export, and Elasticsearch delivery execute as durable jobs with +observable state. + +## Implementation plan + +Implement this gap in three packets: + +- **15A:** generic job substrate, required by Gap 3 dataset load jobs +- **15B:** export recovery and row-stream progress, after Gap 14 +- **15C:** retention and operational hardening + +1. Add `loom_job` collection and `internal/jobs` as 15A. +2. Define job types: + - `DATASET_LOAD` + - `DATASET_ANALYSIS` + - `DATAFRAME_EXPORT` + - `ELASTICSEARCH_LOAD` + - `GENERATION_CLEANUP` +3. Define states: + - `QUEUED` + - `RUNNING` + - `SUCCEEDED` + - `FAILED` + - `CANCELLING` + - `CANCELLED` +4. Persist payload reference, project, generation, owner, progress, attempts, + lease owner/expiry, timestamps, result, and structured error. +5. Implement an in-process worker using Arango-backed leasing first. Keep the + queue interface replaceable. +6. Use atomic compare/update for job claims. +7. Renew leases and reclaim expired jobs after restart. +8. Classify retryable versus terminal errors. +9. Make destination writes idempotent or resume-safe before enabling retries. +10. Add create/status/list/cancel API operations. +11. Enforce per-project and global concurrency. +12. Add retention and cleanup policies. + +## Tests + +- two workers cannot own one lease +- expired lease is reclaimed +- process restart resumes or safely retries work +- cancellation propagates to Arango query and sink +- terminal validation errors are not retried +- status authorization prevents cross-project access + +## Dependencies + +Gap 2 for identity fields. Gap 3 depends on 15A. Gap 14 is required for 15B +export behavior. Gap 18 consumes 15C operational behavior. + +## Exit criteria + +- A server restart does not erase job history or strand running work forever. +- Operators and users can see progress and failure reasons. + +--- + +# Gap 16: No Elasticsearch Destination + +## Current state + +Loom does not validate an Elasticsearch target, create bulk payloads, handle +partial bulk failures, or record delivery provenance. + +## Target state + +A validated recipe can stream flat documents into Elasticsearch through a +durable job with deterministic IDs, bounded batches, retry safety, and an +auditable result. + +## Implementation plan + +1. Add `internal/export/elasticsearch` implementing the shared row sink. +2. Define destination configuration by secret reference, never inline password: + - endpoint + - credential/secret reference + - index or alias + - TLS settings + - operation mode (`create` or `index`) +3. Add connection and permission preflight. +4. Require a deterministic document ID strategy. Default to a stable hash of: + - project + - dataset generation or logical dataset identity + - recipe ID/version + - row-grain identity +5. Validate that every recipe can produce the identity fields before enabling + Elasticsearch. +6. Implement NDJSON Bulk API encoding with action and source lines. +7. Batch by both document count and encoded bytes. +8. Parse every bulk item response. Treat HTTP success with item failures as a + partial failure. +9. Retry only retryable items with capped exponential backoff and jitter. +10. Persist success/failure counts and a bounded error sample. +11. Provide optional mapping preflight: + - infer Loom output types + - compare against existing mappings + - report conflicts before job start +12. Do not silently create or replace production index templates. Make index + provisioning an explicit policy/configuration. +13. Support alias-based promotion as a later, separate operation if full index + rebuild workflows require it. +14. Redact endpoint credentials and sensitive row values from logs. + +## Tests + +- exact bulk wire format and final newline +- byte/count batch boundaries +- deterministic IDs across retries +- 429/503 retry behavior +- mixed-success bulk response handling +- mapping conflict preflight +- cancellation and timeout +- secrets absent from logs and persisted job payloads + +## Dependencies + +Gaps 14 and 15. + +## Exit criteria + +- A retry cannot create uncontrolled duplicate documents. +- Partial failures are visible and attributable. +- Elasticsearch delivery and file export have identical row content. + +--- + +# Gap 17: Authorization Is Not Yet Proven End to End + +## Current state + +Project and auth-resource-path scoping exists across discovery and dataframe +queries. Production features will add analysis snapshots, saved recipes, jobs, +artifacts, and external destinations, all of which create new authorization +surfaces. + +## Target state + +The same resolved principal scope applies to discovery, validation, preview, +export, artifact access, and Elasticsearch delivery. No cached or persisted +derived data leaks information across scopes. + +## Implementation plan + +1. Write an authorization matrix covering every API operation and stored + collection. +2. Centralize project/scope resolution in a request-scoped service dependency. +3. Store the effective auth scope or an immutable scope fingerprint on jobs and + artifacts. +4. Decide whether saved recipes store requested scope, inherit runtime scope, or + both. Prefer runtime reauthorization. +5. Ensure analysis responses are either: + - computed per auth scope; or + - safely filtered from scope-partitioned aggregates +6. Include generation and auth scope in all cache keys. +7. Authorize artifact download independently from job creation. +8. Add SSRF protections for Elasticsearch endpoints: + - configured allowlist or administrator-managed destinations + - block arbitrary user-provided internal URLs +9. Add audit events for load, recipe mutation, export creation, artifact access, + and external delivery. +10. Add query and export rate limits by subject/project. + +## Tests + +- two auth paths in one project see different analysis and preview results +- cache cannot leak values between scopes +- job creator losing access cannot download artifact +- arbitrary Elasticsearch URL is rejected +- audit event contains identity and action but not sensitive data + +## Dependencies + +Cross-cutting. Add tests as each earlier gap lands; complete before M5. + +## Exit criteria + +- An end-to-end isolation suite covers discovery through destination delivery. +- Security-sensitive destinations are administrator-controlled. + +--- + +# Gap 18: Service Operations and Deployment Are Incomplete + +## Current state + +The server has a liveness endpoint and local flags. There is no readiness check, +graceful worker drain contract, formal configuration validation, deployment +manifest, or dependency health report. + +## Target state + +Loom can be deployed to a development server, restarted safely, configured by +environment/secret references, and inspected by an operator. + +## Implementation plan + +1. Separate liveness and readiness: + - `/healthz`: process alive + - `/readyz`: Arango reachable, schema compatible, migrations complete, + artifact store writable, worker ready +2. Add startup configuration validation and a sanitized configuration summary. +3. Add graceful shutdown: + - stop accepting new jobs + - cancel/finish bounded HTTP requests + - release or expire worker leases + - close Arango clients +4. Add explicit database migration/version collection. +5. Add container image and non-root runtime verification. +6. Add a development deployment example, preferably Helm values/manifests if + that matches the surrounding platform. +7. Move secrets to environment/file references. +8. Configure request body, preview, query, job, artifact, and retention limits. +9. Add backup/restore notes for Loom metadata collections separately from raw + reloadable FHIR data. +10. Add an operator runbook for: + - failed load + - stale analysis + - stuck job + - disk pressure + - Arango outage + - Elasticsearch partial failure + +## Tests + +- readiness fails when Arango is unavailable +- readiness fails for pending migration +- SIGTERM releases work safely +- invalid configuration fails before serving traffic +- container smoke test loads a small dataset and previews a recipe + +## Dependencies + +Gaps 2, 3, 14, and 15. + +## Exit criteria + +- A clean development environment can deploy Loom from documented artifacts. +- Restart and dependency failure behavior is documented and tested. + +--- + +# Gap 19: Observability and Performance Budgets Are Missing + +## Current state + +The repository emits logs and ingest progress events, but it does not define +service-level metrics or budgets for analysis, planning, preview, export, and +jobs. + +## Target state + +Operators can determine whether Loom is healthy and developers can detect +performance regressions before deployment. + +## Implementation plan + +1. Add Prometheus-compatible metrics for: + - request count/latency/error by operation + - active Arango queries + - planner duration and support failures + - preview rows/bytes/duration + - job queue depth and age + - job duration/retries/failures + - export rows/bytes/throughput + - Elasticsearch item retries/failures + - analysis age and duration + - cache hit/miss/eviction +2. Add structured fields: + - request ID + - job ID + - project + - generation + - recipe ID + - plan profile + Do not log PHI field values. +3. Define initial budgets: + - recipe options p95 + - validation/explain p95 + - preview p95 for fixture sizes + - maximum preview memory + - export throughput and memory +4. Add benchmark fixtures at small, medium, and development-scale sizes. +5. Capture Arango `EXPLAIN` output for golden performance cases and assert + critical indexes/plan properties without overfitting the full plan text. +6. Add load tests for concurrent previews and background exports. +7. Document measurement commands and expected ranges. + +## Tests + +- metrics endpoint smoke test +- sensitive value redaction +- benchmark memory assertions for streaming export +- performance regression thresholds in a nonflaky scheduled CI job + +## Dependencies + +Instrument each gap as implemented; finish after Gap 16. + +## Exit criteria + +- A slow preview or stalled export can be diagnosed without attaching a + debugger. +- Product-critical paths have written budgets and repeatable benchmarks. + +--- + +# Gap 20: Test Coverage Does Not Yet Prove Product Generality + +## Current state + +There are strong focused unit tests and some Arango integration tests, but no +matrix proving mixed-resource ingestion, analysis, multiple row grains, +authorization isolation, restart recovery, and delivery parity. + +## Target state + +CI and scheduled tests prove the supported product envelope. + +## Implementation plan + +1. Organize tests into: + - fast unit tests + - contract tests + - conformance tests + - Arango integration tests + - end-to-end deployment smoke tests + - scheduled performance tests +2. Build dataset fixtures representing: + - complete research dataset + - sparse dataset + - dangling references + - extension-heavy resources + - multiple auth paths + - high-fanout observations + - high-cardinality filter values +3. For every supported recipe, assert: + - availability + - normalized recipe + - logical plan + - output schema + - row identity/cardinality + - preview/export parity +4. Add generated/generic ingestion parity for every generated resource type. +5. Add fuzz tests for selector parsing, recipe normalization, cursor decoding, + and bulk response parsing. +6. Add failure injection for Arango cursor errors, filesystem full, worker + restart, and Elasticsearch partial failure. +7. Add compatibility tests for saved V1 recipes across future template/planner + changes. +8. Publish the supported capability matrix from conformance results. + +## Dependencies + +Gap 1 and all implementation gaps as they land. + +## Exit criteria + +- "Supported" means a passing end-to-end fixture, not an available UI control. +- The development deployment runs the same conformance suite used by CI. + +--- + +# 5. Thin Frontend Plan + +The frontend is intentionally not a numbered backend gap because it should be +built after M2 exposes honest capabilities. + +Implement it in this order: + +1. project/dataset readiness screen +2. backend-provided recipe gallery +3. "one row per" grain selection +4. suggested/searchable populated columns +5. guided filters using value suggestions +6. validation and cardinality warnings +7. bounded preview +8. save recipe +9. start/export job and status view +10. advanced developer diagnostics behind an explicit disclosure + +Frontend acceptance test: + +> A user who knows the desired data but does not know FHIRPath, GraphQL, AQL, +> or Loom can complete the supported conformance tasks without developer help. + +The former hard-coded `/builder` demo was removed: it encoded one GDC-shaped +graph editor and could not use the compiler-safe capability contract. Developer +diagnostics should use compiler explanations and conformance fixtures; the +product interface should be the guided recipe flow. + +# 6. Recommended Execution Order + +An implementation agent should use this dependency-aware sequence: + +1. CP0: compiler corpus, reference semantics, and baselines +2. CP1-CP2: semantic IR and generated FHIR graph semantics +3. CP3-CP4: row grain/cardinality and typed filters +4. CP5-CP6: correct generic lowering plus aggregate/pivot engine +5. CP7: typed AQL physical IR and code generation +6. CP8: explicit optimization passes +7. CP9: Arango EXPLAIN, cost, indexes, and performance gates +8. Reduced G6-G8: recipe presets and thin capability API over the compiler +9. Reduced G12-G14: explain, bounded preview, and row-stream sinks +10. G2-G5 as needed for durable arbitrary dataset lifecycle and statistics +11. G15-G20 for jobs, destinations, deployment, security, and release proof + +Recipe persistence and frontend expansion should follow compiler validation and +explain. They are not prerequisites for compiler implementation. + +For every gap, the implementing agent must: + +1. inspect the named current owners before editing +2. add or update public types before generated GraphQL artifacts +3. keep authorization and generation in every query +4. write unit tests before or with implementation +5. add integration evidence for database behavior +6. update the capability matrix +7. run `go test ./...` plus the relevant conformance target +8. update developer documentation when the runtime contract changes + +# 7. First Development-Server Release Gate + +The first deployable development release does not require every conceivable +FHIR query. It does require all of the following: + +- explicit FHIR/schema identity +- automatic generated/generic ingestion selection +- atomic dataset generation activation +- load and analysis jobs with persisted status +- dataset/resource/relationship/field analysis +- versioned recipes and six registered template families +- capability API that hides unsupported templates and paths +- at least one passing supported recipe for every advertised family +- Patient, Specimen, File, Diagnosis, Observation, and Study Enrollment grains +- typed filters required by conformance fixtures +- cardinality and cost warnings +- bounded, cancellable preview +- streaming NDJSON and CSV export +- saved recipes +- end-to-end authorization isolation tests +- readiness, graceful shutdown, metrics, and runbook +- a published capability matrix produced by tests + +Elasticsearch delivery should be part of the same release only if deterministic +row IDs, partial-failure handling, and retry safety are complete. Otherwise ship +file export first and keep Elasticsearch disabled rather than exposing an +unreliable destination. + +# 8. Definition of Done for the Product Direction + +Loom has moved beyond demoware when this scenario is routine: + +1. An operator uploads or mounts an unfamiliar, schema-compatible FHIR NDJSON + dataset. +2. Loom preflights every resource type and reports its ingestion strategy. +3. The load completes into a new immutable dataset generation. +4. Loom measures resources, fields, values, references, integrity, coverage, + and fanout. +5. The API offers only recipe templates supported by both the data and planner. +6. A non-technical user selects what they are making, one row per entity, + desired columns, and guided filters. +7. Loom returns a normalized recipe, warnings, and an understandable row-grain + explanation. +8. Preview is fast, bounded, and representative. +9. Export survives process restart, streams with bounded memory, and records + provenance. +10. The resulting flat data is identical whether written as NDJSON, CSV, or + delivered to Elasticsearch. +11. Operators can observe, cancel, retry, and diagnose every long-running step. +12. The advertised capability is backed by passing conformance tests. + +That is the production boundary this plan is designed to reach. diff --git a/docs/PRODUCT_RECIPE_DISCOVERY.md b/docs/PRODUCT_RECIPE_DISCOVERY.md new file mode 100644 index 0000000..56a71b6 --- /dev/null +++ b/docs/PRODUCT_RECIPE_DISCOVERY.md @@ -0,0 +1,589 @@ +# Product Recipes and Dataset Discovery + +This document describes a product direction for turning freshly loaded FHIR +data into useful flat dataframes without asking users to understand FHIRPath, +GraphQL, AQL, or graph traversal mechanics. + +The central product idea is: + +> The user describes a familiar dataset, Loom turns that intent into a validated +> recipe, and the backend compiles the recipe into performant AQL. + +The frontend should not be an unrestricted visual query builder. It should be a +small, guided interface backed by dataset-aware analysis queries and a stable +recipe contract. + +## 1. Target User Experience + +The primary flow should read like a short conversation. + +### What are you making? + +Start from a curated use case: + +- Patient cohort +- Specimen inventory +- File manifest +- Diagnoses +- Labs or observations +- Study enrollment + +This choice establishes a recipe family. A recipe family supplies sensible +defaults, supported row grains, known FHIR relationships, common columns, and +backend planning hints. It is not a saved AQL string. + +### One row per... + +Choose the meaning of one output row: + +- Patient +- Specimen +- File +- Observation + +The row grain is the most important semantic choice in the workflow. It +determines which resource anchors the output, which relationships are safe to +traverse, and whether related values should be selected, aggregated, pivoted, +or emitted as additional rows. + +The frontend should use the phrase "one row per" rather than "root resource" +or "traversal root." + +### Include... + +Present a searchable, plain-language column checklist: + +- show common, populated columns first +- group columns by familiar concepts rather than raw resource names +- display a short example value when safe and useful +- show approximate coverage, such as "present for 92% of patients" +- hide advanced FHIR paths and internal graph identifiers by default +- explain when a selection changes the row grain or creates multiple values + +The column picker should be populated from Loom's analysis API. It should not +be a hardcoded copy of the theoretical FHIR schema. + +### Only include... + +Build filters as guided sentences, for example: + +- diagnosis is melanoma +- specimen type is Primary Tumor +- file type is BAM +- observation name is Hemoglobin +- study is TCGA-LUAD + +The available operators and values should come from field metadata and bounded +value-frequency queries. Free text should be used only when the field cannot +provide a useful enumerated value list. + +### Preview, then deliver + +After validation, the user can: + +- preview a small sample +- download flat NDJSON +- download CSV +- send the rows to Elasticsearch +- save the configuration as a reusable recipe + +Preview and export are different workloads. Preview should be synchronous, +small, and optimized for rapid correction. Export should eventually be a +streaming or asynchronous job with durable status and bounded memory. + +## 2. The Product Contract Is a Recipe + +The frontend, a future natural-language assistant, the CLI, and API clients +should all produce the same versioned recipe object. + +A conceptual recipe looks like this: + +```json +{ + "version": 1, + "template": "file_manifest", + "project": "example-project", + "grain": "file", + "columns": [ + "cap_patient_submitter_id", + "cap_specimen_type", + "cap_file_name", + "cap_file_type", + "cap_file_size" + ], + "filters": [ + { + "field": "cap_file_type", + "operator": "equals", + "value": "BAM" + } + ], + "destination": { + "type": "preview" + } +} +``` + +This is intentionally not the current GraphQL dataframe input and not AQL. +The `cap_*` values are illustrative opaque capability identifiers issued by +Loom; a browser never constructs a FHIR path from them. It is a product-level +intermediate representation. + +The recipe compiler is responsible for translating friendly concepts into: + +1. concrete FHIR resource types and fields +2. a supported relationship path +3. field selections, filters, aggregates, pivots, and representative slices +4. the existing dataframe builder request +5. the lowered internal plan +6. AQL and bind variables + +Keeping these layers separate has several benefits: + +- the frontend remains small +- recipes can be saved and migrated +- a future LLM only needs to emit a constrained object +- validation can return user-facing errors before compiling AQL +- planner improvements do not invalidate saved user intent +- the same recipe can target preview, file export, or Elasticsearch + +## 3. Why Dataset Analysis Comes First + +FHIR defines what may exist. A newly loaded dataset determines what actually +exists, how it is connected, and whether it is useful. + +Loom already profiles populated fields in `fhir_field_catalog` and discovers +populated references from `fhir_edge`. These are necessary primitives, but the +product needs higher-level answers. + +The analysis layer must build on the repository's existing generated FHIR +backbone: `schemas/graph-fhir.json`, generated Go structs/validators/edge +extractors under `internal/fhir`, generated metadata under `internal/fhirschema`, +and the sample data in `META/`. It should not introduce a second FHIR model or +infer schema structure independently from those owners. + +The frontend should not call a collection of unrelated low-level queries and +attempt to infer the product model itself. Loom should expose analysis results +that already use the same semantics and authorization rules as recipe +validation and compilation. + +### Implemented foundation + +`dataframebuilder.Service.DiscoverGuided` now composes the existing scoped +catalog readers into an internal `discovery.Snapshot`. The snapshot contains +only generated-schema roots, compiler-safe observed relationships, opaque +candidate-column IDs, and bounded guided filter suggestions. It deliberately +does not yet have a public GraphQL/HTTP endpoint. When configured with an +active-manifest resolver, it is bound to that active dataset generation before +catalog discovery so cached/persisted capabilities cannot be used outside the +scope or load they describe. + +The lifecycle vocabulary is persisted by `internal/datasetstore` (schema +snapshot, immutable generation reference, lifecycle state, and active pointer), +and generation-aware discovery/compiler requests propagate that selection. It +is still not a public discovery response or a finalized analysis-capability +snapshot. + +The first internal capability bridge is also implemented: +`internal/recipecompiler.Build` and +`dataframebuilder.Service.PrepareRecipe`/`RunRecipe`/`StreamRecipe` resolve +opaque IDs from fresh, authorization-scoped catalog facts into typed root-only +scalar dataframe selections and filters. That makes an internal preview/row +stream possible today while rejecting raw paths, stale IDs, cross-resource +choices, repeated fields without a quantifier, pivots, and pinned generations. +It does not yet make a saved recipe, relationship-aware template, download, or +Elasticsearch delivery product-supported. + +## 4. Required Analysis Query Families + +Analysis queries should be project-scoped and auth-resource-path-scoped. Their +results should be cacheable and invalidated when a load changes the project. + +### 4.1 Dataset summary + +Purpose: determine what kind of dataset was loaded. + +Return: + +- populated resource types and document counts +- available auth resource paths +- total edge counts +- field-catalog freshness/version +- load or analysis timestamp +- high-level warnings, such as resources with no usable references + +This powers the initial landing state and prevents the frontend from offering +recipe families that have no backing data. + +### 4.2 Relationship inventory + +Purpose: understand which FHIR resource types are actually linked. + +Return for each observed relationship: + +- source resource type +- relationship label +- target resource type +- edge count +- distinct source count +- distinct target count +- source coverage +- average and percentile fanout +- whether the relationship is recognized by Loom's semantic planner + +The current populated-reference discovery returns the relationship and edge +count. Product discovery additionally needs coverage and fanout. An edge count +alone cannot tell the UI whether a relationship is nearly universal or a rare +outlier, nor whether it will multiply output rows unexpectedly. + +### 4.3 Reachable recipe paths + +Purpose: expose useful, supported paths rather than arbitrary graph walks. + +Given a row grain or recipe family, return paths such as: + +- Patient to Specimen +- Patient to DocumentReference +- Patient to Specimen to DocumentReference +- Patient to Condition +- Patient to Observation +- Patient to ResearchSubject to ResearchStudy + +Each path should include: + +- friendly label +- concrete edge labels and resource types +- observed coverage +- estimated fanout +- supported planner operations +- support state: supported, preview-only, experimental, or unavailable +- reason when unavailable + +This endpoint must reflect the planner's real capabilities. A path is not +product-supported merely because matching edges exist. + +### 4.4 Candidate columns + +Purpose: populate the plain-language column checklist. + +Given a recipe family, grain, and optional path, return: + +- stable friendly field identifier +- display label and description +- owning concept/resource +- underlying canonical selector +- data kind +- document count and coverage percentage +- bounded example values +- cardinality estimate +- whether values are scalar, repeated, or complex +- allowed value modes +- whether aggregation or pivoting is required at the selected grain +- common, suggested, or advanced classification +- sensitivity or display restrictions when applicable + +The existing field catalog supplies much of the raw evidence. The analysis +layer adds grain-aware presentation and planner compatibility. + +### 4.5 Filter suggestions and value frequencies + +Purpose: power guided filter sentences. + +Given a candidate field, return: + +- supported operators +- common distinct values and counts +- approximate or exact frequency indicator +- truncation state +- null/missing count +- search over high-cardinality values + +The existing catalog's bounded distinct values are useful for initial hints. +They are not sufficient for every filter UI because they do not necessarily +represent value frequency or support searching a high-cardinality domain. + +Expensive value analysis should be requested on demand, bounded, cached, and +subject to the same authorization scope as dataframe execution. + +### 4.6 Grain and cardinality analysis + +Purpose: explain what one output row means before execution. + +Given a proposed recipe, estimate: + +- number of base entities at the selected grain +- expected output rows +- which selections can multiply rows +- which selections produce arrays +- which selections will be aggregated or pivoted +- expected null coverage +- whether a stable document identifier can be produced + +This is both a correctness feature and a user-experience feature. Many failed +dataframe requests are really misunderstandings about cardinality. + +### 4.7 Recipe validation and explain + +Purpose: provide one authoritative preflight operation. + +Given a recipe, return: + +- normalized recipe +- validation status +- user-facing warnings and errors +- selected relationship path +- output column names and types +- estimated cardinality +- planner support state +- a safe logical-plan explanation +- whether preview, export, and Elasticsearch delivery are available + +The explain response should not expose raw AQL by default. Raw GraphQL, AQL, +and bind variables can remain available in a developer-only diagnostics view. + +### 4.8 Preview + +Purpose: let the user validate meaning with real rows. + +Preview should: + +- use the normalized recipe returned by validation +- enforce a small maximum row count +- return stable columns and representative rows +- report elapsed time and relevant warnings +- avoid retaining an unbounded result in memory +- make missing values and repeated values visually understandable + +### 4.9 Export and destination readiness + +Purpose: determine whether a validated recipe can be delivered safely. + +For file export, check: + +- output format +- expected size +- stable column schema +- whether the query can stream + +For Elasticsearch, additionally check: + +- destination/index permissions +- index or index-template compatibility +- field-name and type conflicts +- deterministic document ID strategy +- bulk batch limits +- behavior for partial failures and retries + +Elasticsearch delivery should consume the same row stream as NDJSON/CSV export; +it should not introduce a second dataframe compiler. + +## 5. Query Templates vs. Capabilities + +It is useful to create reusable backend query templates, but they should be +organized as capabilities rather than frontend pages or conversational turns. + +For example: + +| Capability | Likely backing data | Product consumer | +| --- | --- | --- | +| Dataset summary | resource collections, catalog, edges | recipe gallery | +| Relationship inventory | `fhir_edge` | grain/path selection | +| Candidate columns | `fhir_field_catalog`, schema metadata | column picker | +| Filter values | catalog plus bounded live aggregation | filter sentence | +| Recipe explain | catalog, semantics, planner | preflight panel | +| Preview | compiled dataframe AQL | result table | +| Export | compiled dataframe AQL row stream | files/Elasticsearch | + +The conversation is then a client of these capabilities. This prevents UI +wording from becoming part of the database API and makes it possible to add a +CLI, alternate frontend, or LLM later. + +## 6. Recommended API Shape + +The exact GraphQL names can be decided during implementation, but the public +surface should conceptually support: + +```graphql +datasetSummary(project: ID!): DatasetSummary! +recipeTemplates(project: ID!): [RecipeTemplate!]! +recipeOptions(input: RecipeContextInput!): RecipeOptions! +fieldValueSuggestions(input: FieldValueSuggestionInput!): FieldValuePage! +validateRecipe(input: DataframeRecipeInput!): RecipeValidation! +previewRecipe(input: DataframeRecipeInput!, limit: Int!): DataframePreview! +startRecipeExport(input: DataframeRecipeInput!, destination: ExportDestinationInput!): ExportJob! +``` + +This does not require seven unrelated implementations. Several operations can +compose the current catalog readers, generated FHIR schema, derived field +references, traversal rules, and dataframe planner. The formal gap analysis +proposes consolidating those current semantics behind one registry. + +Avoid making the frontend assemble raw `FhirTraversalStepInput` trees. That +contract remains useful as a lower-level developer API, but it is too close to +the compiler for the primary product experience. + +## 7. Recipe Template Definition + +A recipe template should declare intent and constraints, not contain canned +AQL. + +Each template should define: + +- stable template ID and version +- user-facing name and description +- supported row grains +- required and optional semantic relationships +- suggested columns +- optional default filters +- supported aggregates and pivots +- planner capability requirements +- expected identifier strategy +- supported destinations + +Initial templates should be deliberately small: + +### Patient cohort + +- default grain: Patient +- common columns: submitter ID, sex/gender, vital status, study +- common filters: diagnosis, study, demographics + +### Specimen inventory + +- default grain: Specimen +- common columns: patient ID, specimen ID/type, collection metadata +- common filters: specimen type, study, diagnosis + +### File manifest + +- default grain: File/DocumentReference +- common columns: patient ID, specimen ID/type, file name/type/size/access +- common filters: file type, specimen type, study + +### Diagnoses + +- default grain: diagnosis/Condition +- common columns: patient ID, diagnosis, stage, age/date fields +- common filters: diagnosis, stage, study + +### Labs or observations + +- default grain: Observation +- common columns: patient ID, observation code/name, value, unit, date +- common filters: observation code, status, date range + +### Study enrollment + +- default grain: ResearchSubject or patient-study membership +- common columns: patient ID, study ID/name, enrollment status, arm +- common filters: study and status + +These definitions are hypotheses until exercised against representative loaded +datasets and the actual planner. + +## 8. Implementation Sequence + +### Phase 1: capture conversations as fixtures + +Write 10 to 20 realistic user requests and expected recipe objects. Include +ambiguous and impossible requests. + +Examples: + +- "Give me a file manifest for BAM files with patient and specimen type." +- "One row per patient with melanoma diagnosis and all studies." +- "Show hemoglobin observations with value, unit, and collection date." + +These fixtures become the acceptance contract for the frontend and any future +language interface. + +### Phase 2: inventory current evidence + +For each fixture, record whether the current catalog can answer: + +- is the recipe family present? +- is the requested grain available? +- is the required path populated? +- are requested columns populated? +- are requested filter values discoverable? +- will the planner lower the request? + +This identifies missing analysis queries using evidence rather than guesswork. + +### Phase 3: add analysis services + +Start with: + +1. dataset summary +2. relationship coverage/fanout +3. grain-aware candidate columns +4. filter values/frequencies +5. recipe validation/explain + +Prefer extending the existing catalog and dataframebuilder services over adding +raw AQL strings directly to HTTP handlers. + +### Phase 4: add versioned recipes and templates + +Implement recipe types, normalization, semantic identifiers, template +definitions, and translation into the existing dataframe builder. + +### Phase 5: build the thin guided frontend + +The frontend should call the analysis and recipe APIs. It should contain little +FHIR-specific logic beyond display grouping and state management. + +### Phase 6: add streaming export + +Build NDJSON and CSV from one row-stream abstraction, then add Elasticsearch as +another destination over the same stream. + +## 9. Acceptance Criteria for the First Product Slice + +The first slice is complete when a non-technical user can: + +1. open a freshly loaded project +2. see only recipe families supported by its data and planner +3. select a row grain using plain language +4. choose suggested populated columns +5. create a filter from observed values +6. understand warnings about missing data or row multiplication +7. preview meaningful rows +8. save and reload the recipe +9. download flat NDJSON or CSV + +Direct Elasticsearch delivery can follow once the export stream and schema +validation are reliable. + +## 10. Design Guardrails + +- Do not expose arbitrary graph traversal as the default experience. +- Do not equate "edge exists" with "planner supports this recipe." +- Do not equate "FHIR field is legal" with "field is populated." +- Do not make the frontend calculate coverage, fanout, or planner support. +- Do not store AQL as the durable user artifact. +- Do not let an LLM emit or execute raw AQL. +- Do not return unbounded exports inline through GraphQL. +- Do keep project and authorization scope identical across analysis, preview, + and export. +- Do preserve a developer diagnostics view for recipe, logical plan, GraphQL, + AQL, and bind-variable inspection. + +## 11. First Concrete Work Package + +The recommended first implementation work package is a gap-analysis harness, +not a new frontend. + +It should contain: + +- representative conversation fixtures +- expected normalized recipes +- expected row grain and columns +- catalog/discovery evidence captured for each fixture +- planner validation result +- preview correctness result +- missing-capability classification + +That harness will show whether the next investment belongs in catalog analysis, +FHIR semantics, planner coverage, AQL performance, or user experience. It also +becomes the regression suite that keeps the frontend honest as Loom expands. diff --git a/docs/TERRA_ULTRA_EXECUTION_PLAN.md b/docs/TERRA_ULTRA_EXECUTION_PLAN.md new file mode 100644 index 0000000..399e20e --- /dev/null +++ b/docs/TERRA_ULTRA_EXECUTION_PLAN.md @@ -0,0 +1,1107 @@ +# Terra Ultra Parallel Execution Plan + +## 1. Purpose + +This document converts the 20 gaps in +[`FORMAL_GAP_ANALYSIS.md`](FORMAL_GAP_ANALYSIS.md) into a safe multi-worker +execution program for a long-running Terra Ultra session. + +The compiler-first schedule in +[`COMPILER_FIRST_PLAN.md`](COMPILER_FIRST_PLAN.md) is now authoritative. Run +CP0-CP9 before the service-heavy waves in this document. The package ownership, +worktree, contract-freeze, handoff, and merge rules here still apply to compiler +workers. + +The objective is not to maximize the number of active workers. It is to +maximize completed, mergeable work while preventing workers from implementing +against contracts that another worker is still changing. + +The governing rule is: + +> Parallelize implementations behind frozen interfaces. Do not parallelize the +> definition of the same interface. + +Twenty gaps must not become twenty simultaneous branches. Dataset generation, +analysis, recipes, planner semantics, row identity, GraphQL, jobs, and generated +files are shared contracts. Uncoordinated work on them would create substantial +rework. + +## 1.1 Existing FHIR Backbone Is a Frozen Starting Asset + +Workers must begin from the implementation that is already present. They must +not design a replacement FHIR model, parser, graph schema, GraphQL framework, +or sample-data convention unless a specific failing conformance fixture proves +that the current owner cannot be extended. + +The baseline includes: + +- `META/`: the primary 14-resource sample dataset used for development and + end-to-end characterization +- `META_SMALL/`: the smaller sample dataset for faster local tests +- `schemas/graph-fhir.json`: the active graph/FHIR schema used by generation, + generic validation, and edge extraction +- `cmd/generate/main.go`: the existing FHIR generator +- `internal/fhir/model.go`: generated Go FHIR structs +- `internal/fhir/validate.go`: generated validation methods +- `internal/fhir/extract.go`: generated graph-edge extraction +- `internal/fhirschema/generated.go`: generated field and traversal metadata +- `internal/fhirschema/schema.go`: the handwritten lookup, selector, and pivot + logic over generated metadata +- `internal/ingest/generated_load.go`: generated fast-path resource dispatch +- `internal/ingest/row_builder.go`: generated/generic row-builder boundary +- `internal/catalog/`: existing populated-field, distinct-value, pivot, and + populated-reference profiling/discovery +- `internal/graphqlapi/schema.graphqls`: the handwritten GraphQL contract +- `gqlgen.yml` and generated gqlgen artifacts under `internal/graphqlapi/` +- `Makefile` targets `generate-fhir`, `generate-graphql`, `graphql-check`, and + `test` + +The generator already emits more than structs. It emits validation, edge +extraction, generated load dispatch, and `fhirschema` definitions/traversals. +A worker must inspect the relevant generator output and generator source before +adding handwritten resource-specific equivalents. + +The required extension policy is: + +1. use `META/` to characterize current behavior before creating synthetic data +2. add minimal synthetic fixtures only for cases not represented in `META/` +3. extend `schemas/graph-fhir.json` or `cmd/generate` when the missing behavior + is schema/generation-owned +4. regenerate with the existing Make targets +5. keep handwritten behavior in the existing owner package when it is not + generated +6. prove generated/generic parity when changing ingestion semantics +7. never copy generated FHIR types into a new recipe, analysis, or planner + package +8. keep GraphQL changes in `schema.graphqls` and regenerate through gqlgen; + never hand-edit generated GraphQL artifacts as the source of truth + +"Support any FHIR" therefore means extending and generalizing the existing +schema-driven backbone, not discarding it. + +## 2. Orchestrator Responsibilities + +Terra Ultra acts as the integration owner. It must: + +1. maintain one green integration branch +2. create worker packets from a known integration commit +3. assign exclusive package and shared-file ownership +4. enforce contract freeze gates +5. merge foundational contracts before launching their consumers +6. stop or rebase workers when an upstream contract changes +7. run integration and conformance tests after every merge +8. publish a handoff manifest for each completed packet +9. keep unsupported capabilities explicit +10. prevent workers from weakening validation merely to make fixtures pass +11. reject work that duplicates existing generated FHIR or gqlgen ownership +12. require a baseline run against `META/` for every ingestion, catalog, + planner, or analysis packet + +Terra should use spare workers for review, tests, fixtures, performance +measurement, and threat analysis rather than assigning two workers to the same +hotspot. + +## 3. Corrected Dependency Graph + +The formal gap analysis lists a mostly sequential execution order. For parallel +delivery, Gap 15 must be split: + +- **15A Job substrate:** durable state machine, leasing, cancellation, status, + concurrency, handler interface +- **15B Export recovery:** row-stream progress, retries, resume/idempotency, + artifact results +- **15C Job hardening:** retention, cleanup, operational recovery + +Gap 3 requires 15A. Gap 14 can consume the job handler contract. Gap 15B cannot +finish until the streaming runtime exists. + +```text +G1 Conformance corpus + ├──> G6 Recipe V1 ───────────────────────────────────────────┐ + └──> shared product fixtures │ + │ +G2 Schema identity ──> G3 Dataset generations ──> G4 Integrity ──> G5 Analysis + │ ^ │ + │ │ v + └──────────────> G15A Job substrate G7 Templates + │ +G6 Recipe V1 ─────────────────────────────────────────────────────┤ + v + G8 Capability API ──> G9 Persistence + │ +G6 Recipe V1 ──> G10 Planner ──> G11 Filters │ + │ │ + └──────────> G12 Cost/cardinality <───────────┘ + │ + v + G13 Preview + │ + v + G14 Row stream + │ + ┌────────────┴────────────┐ + v v + G15B Jobs G16 Elasticsearch + +G17 Authorization: continuous lane, final audit after G16 +G18 Operations: skeleton after G2/G3, finish after G14/G15 +G19 Observability: primitives early, budgets after G16 +G20 Testing: framework first, continuous evidence, final matrix last +``` + +## 4. Contract Freeze Gates + +No downstream worker starts before the applicable freeze has been merged into +the integration branch. + +### C0: Conformance vocabulary + +Freeze: + +- recipe-family IDs +- row-grain IDs +- fixture schema and fixture IDs +- support states +- warning/error-code naming rules +- conformance result format + +Required evidence: + +- fixture schema tests +- duplicate-ID test +- deterministic conformance smoke result + +### C1: Identity envelope + +Freeze: + +- project identity +- schema identity +- dataset generation ID and states +- active-generation resolution +- legacy dataset behavior +- analysis version placeholder +- authorization-scope fingerprint representation + +Canonical concepts consumed by all later work: + +```text +project +datasetGeneration +schemaIdentity +analysisVersion +authScopeFingerprint +``` + +Required evidence: + +- schema digest tests +- generation activation tests +- no mixed-generation reads + +### C2: Recipe V1 + +Freeze: + +- semantic IDs +- grain representation +- column selections +- filter expression serialization +- destination representation +- normalized JSON +- typed error paths/codes +- recipe/template version fields + +Required evidence: + +- golden serialization tests +- deterministic normalization +- fixture round trips + +Gap 11 may add operator implementations later, but it must not invent a second +serialized filter model. + +### C3: Job contract + +Freeze: + +- job types and states +- claim/lease rules +- cancellation contract +- progress, result, and error envelopes +- idempotency key +- handler interface +- restart recovery behavior + +Required evidence: + +- two-worker lease test +- expired-lease reclaim test +- cancellation state test + +### C4: Analysis snapshot + +Freeze: + +- resource, field, relationship, and value-analysis document keys +- project/generation/scope fields +- coverage denominators +- fanout representation +- truncation markers +- snapshot version/freshness +- relationship quality states + +Required evidence: + +- deterministic snapshot for fixture data +- auth-scope isolation test +- generation replacement test + +### C5: Planner IR + +Freeze: + +- logical operators +- grain/root representation +- traversal representation +- projection and filter representation +- row identity +- duplicate/expansion semantics +- capability descriptors +- explain result shape + +Required evidence: + +- existing Patient result parity +- logical-plan goldens +- generic-versus-optimized parity + +Only after C5 may separate workers add grain modules. + +### C6: Product capability API + +Freeze: + +- support decision and reason codes +- dataset summary +- template availability +- recipe options +- validation result +- plan/cardinality explanation +- cache identity + +Required evidence: + +- capability and planner agreement for every fixture +- stale-analysis behavior +- GraphQL contract tests + +### C7: Row-stream contract + +Freeze: + +- output column schema +- row representation +- missing-value policy +- array encoding policy +- cancellation/error semantics +- progress counters +- provenance +- checksum and row-count rules + +Required evidence: + +- preview/stream row parity +- bounded-memory test +- cancellation test + +### C8: Artifact and destination contract + +Freeze: + +- artifact lifecycle +- temporary/finalization semantics +- destination secret references +- deterministic Elasticsearch document IDs +- retry classification +- partial-failure reporting + +Required evidence: + +- interrupted-artifact cleanup +- deterministic-ID test +- partial bulk response test + +## 5. Package Ownership Lanes + +Assign workers to durable package lanes rather than one worker per gap. + +### Lane A: Dataset loading and lifecycle + +Owns: + +- G2 schema identity +- G3 dataset generations +- load integration with G15A + +Primary files: + +- new `internal/schemaidentity/` +- new `internal/dataset/` +- `internal/ingest/` +- generation-aware ingestion storage + +Exclusive hotspots during its integration window: + +- `internal/ingest/load.go` +- `internal/ingest/backend.go` +- `internal/ingest/row_builder.go` +- command entrypoints for load wiring + +Published boundary: + +```go +type DatasetRef struct { + Project string + Generation string +} + +type Resolver interface { + Active(ctx context.Context, project string) (DatasetRef, error) +} +``` + +Exact names may change during C1, but only one canonical resolver may survive. + +### Lane B: Analysis and catalog + +Owns: + +- G4 reference integrity +- G5 analysis snapshots + +Primary files: + +- new `internal/analysis/` +- new `internal/analysis/referenceintegrity/` +- `internal/catalog/` +- analysis cache behavior + +Consumes Lane A's finalized `DatasetRef`. It must not invent generation +lifecycle or query inactive data. + +Lane A invokes an analysis/finalization interface; Lane B implements it. The two +lanes must not both edit load orchestration. + +### Lane C: Recipe domain and templates + +Owns: + +- G6 Recipe V1 +- G7 semantic vocabulary and templates + +Primary files: + +- new `internal/recipe/` +- new `internal/recipe/templates/` +- recipe JSON Schema + +During C2, consume current field and traversal behavior through adapters. Do +not immediately move: + +- `internal/dataframebuilder/fieldrefs.go` +- `internal/dataframe/traversal_rules.go` + +Consolidation occurs after recipe and planner contracts agree. + +### Lane D: Planner and filters + +Owns: + +- G10 planner +- G11 filter compiler + +Primary files: + +- `internal/dataframe/` +- eventual `internal/dataframe/planner/` + +This is the highest-collision lane. It has one lead until C5. After C5, additive +workers may implement: + +- Patient parity/optimizations +- Specimen and DocumentReference/File +- Condition and Observation +- ResearchSubject/Study enrollment + +Only the planner lead edits central dispatch and shared IR. + +### Lane E: Product API and recipe persistence + +Owns: + +- G8 capability orchestration +- G9 recipe persistence +- product GraphQL integration + +Primary files: + +- new `internal/productapi/` +- recipe storage implementation +- GraphQL product operations + +This lane is the exclusive GraphQL owner. Other workers return Go services and +types; they do not independently change public GraphQL. + +### Lane F: Plan analysis and preview + +Owns: + +- G12 cardinality/cost analysis +- G13 bounded preview + +Primary files: + +- planner analysis/cost model +- preview service +- cursor codec + +It consumes C4 and C5. It does not redefine the planner IR or edit GraphQL. + +### Lane G: Streaming export and artifacts + +Owns: + +- G14 row stream +- NDJSON/CSV sinks +- artifact-store abstraction + +Primary files: + +- new `internal/export/` +- new `internal/export/artifact/` + +It consumes C7 and does not modify planner semantics. + +### Lane H: Durable jobs + +Owns: + +- G15A substrate early +- G15B export recovery +- G15C hardening + +Primary files: + +- new `internal/jobs/` + +Implement the core with fake handlers. Lane A and Lane G add real handlers only +through the frozen job interface. + +### Lane I: Elasticsearch + +Owns: + +- G16 bulk sink +- destination/mapping preflight + +Primary files: + +- new `internal/export/elasticsearch/` + +Most tests use an HTTP test server. Retry scheduling remains owned by Lane H; +the Elasticsearch package classifies item errors and reports retryable items. + +### Lane J: Security, operations, and observability + +G17-G19 are continuous concerns, not permission to edit every package. + +Own additive infrastructure: + +- authorization test helpers and matrix +- scope fingerprint helper +- readiness/configuration package +- audit-event interface +- metrics registry +- deployment manifests and runbook + +Every feature owner authorizes and instruments its own path. A final Lane J +worker audits the integrated system. + +### Lane K: Conformance and system tests + +Owns: + +- G1 +- continuous G20 evidence +- `conformance/` +- capability matrix publication + +It must not add production shortcuts merely to pass fixtures. + +## 6. Shared-File Hotspots + +These files have one integration owner per wave: + +- `internal/graphqlapi/schema.graphqls` +- `internal/graphqlapi/schema.resolvers.go` +- `internal/graphqlapi/generated.go` +- `internal/graphqlapi/model/models.go` +- `internal/api/routes.go` +- `internal/api/service.go` +- `internal/dataframe/service.go` +- current `internal/dataframe/planner.go` +- `internal/dataframe/lowered_types.go` +- `internal/dataframe/lowered_compile.go` +- `internal/ingest/load.go` +- `internal/ingest/backend.go` +- `cmd/arango-fhir-server/main.go` +- `cmd/arango-fhir-proto/main.go` +- `Makefile` +- `go.mod` +- `go.sum` +- top-level README and capability matrix + +Generated GraphQL artifacts are regenerated once by Lane E or the integration +owner after service contracts merge. Parallel workers must not commit their own +independently generated copies. + +If a worker needs a shared-file change it does not own, its handoff includes a +contract-change request or minimal integration patch description. + +## 7. Parallel Execution Waves + +The waves below assume four to six implementation workers plus one integrator. + +### Wave 0: Product oracle and baseline + +Start all workers from the same current green commit. + +#### W0-A: Conformance corpus + +Implements G1: + +- fixture schema +- conversation fixtures +- fixture datasets +- runner +- deterministic results + +Owns `conformance/`. + +#### W0-B: Baseline characterization + +Adds tests only for current: + +- generated/generic ingestion +- planner support/rejections +- auth scoping +- GraphQL contracts +- preview memory/result behavior +- the resource types and link tuples observed in `META/` +- generated versus generic behavior for the `META/` resource types +- current field/pivot catalog output produced from `META/` +- current generator and gqlgen reproducibility + +Must not improve production behavior in this packet. + +#### W0-C: Architecture verification + +Read-only review producing: + +- package/caller map +- current collection/index map +- public API map +- hotspot confirmation + +#### Gate C0 + +Merge fixtures and baseline tests. Freeze vocabulary before downstream work. + +### Wave 1: Independent foundational contracts + +#### W1-A: Schema identity and ingestion preflight + +Implements G2 without dataset generation activation. + +#### W1-B: Recipe V1 contract + +Implements G6 types, JSON Schema, normalization, and error model. Does not yet +translate into live analysis/templates. + +#### W1-C: Job substrate + +Implements G15A with fake handlers. + +#### W1-D: Security/test primitives + +Adds: + +- authorization matrix +- scope fingerprint proposal/helper +- reusable negative-test helpers +- test taxonomy + +#### W1-E: Metrics/config primitives + +Adds additive metrics and configuration packages only. Does not instrument all +features yet. + +#### Gates C1-C3 + +The integrator aligns and freezes the shared identity, recipe, and job +contracts. Dependent worktrees are recreated or rebased from this merge. + +### Wave 2: Atomic ingestion and semantic foundations + +#### W2-A: Dataset generations + +Implements G3 using C1 and C3. + +#### W2-B: Template registry structure + +Implements G7 registry mechanics with fake analysis/planner capability sources. +Do not finalize template availability yet. + +#### W2-C: Planner foundation + +Implements only: + +- logical IR +- generic physical interfaces +- capability descriptor interface +- Patient parity path + +This worker owns planner hotspots. + +#### W2-D: Operational skeleton + +Implements: + +- migration registry +- startup configuration validation +- readiness framework +- graceful worker shutdown interfaces + +#### W2-E: Generation and auth tests + +Expands conformance/system tests without editing production owners' packages. + +#### Gate + +Dataset generation storage/query behavior must be frozen before analysis begins. +This is the most consequential repository-wide merge point. + +### Wave 3: Dataset intelligence and planner expansion + +#### W3-A: Reference integrity + +Implements G4 against active-generation helpers. + +#### W3-B: Resource and field analysis + +Implements the G5 resource/field half using the analysis schema owner. + +#### W3-C: Relationship, fanout, and value analysis + +Implements the G5 relationship/value half. It consumes the same shared analysis +document types as W3-B. + +One of W3-B/W3-C owns collection registration and migrations; the other may +only add analyzers and tests. + +#### W3-D through W3-F: Grain modules + +After C5 is merged, assign additive planner modules: + +- Specimen and File +- Condition and Observation +- ResearchSubject and Study enrollment + +The planner lead remains the only central dispatch owner. + +#### W3-G: Typed filter implementation + +Implements G11 against C2 and C5. It may add operators but cannot change Recipe +V1 serialization without a contract amendment. + +#### Gate C4-C5 + +Freeze deterministic analysis snapshots and planner IR. Require fixture-based +result parity before product APIs consume them. + +### Wave 4: Product capability plane + +#### W4-A: Final templates and capability evaluator + +Completes G7 using real analysis and planner descriptors. + +Template-family entries may be split among workers only after registry schema +is frozen. Those workers add definitions and fixtures, not mechanics. + +#### W4-B: Capability service and GraphQL + +Implements G8 and exclusively owns GraphQL changes/generated artifacts. + +#### W4-C: Recipe storage + +Implements G9 CRUD and ownership. Compatibility/revalidation integrates after +the capability service lands. + +#### W4-D: Cardinality and cost + +Implements G12 against C4/C5. + +#### W4-E: Security integration tests + +Tests analysis, capability caching, recipes, and plan explanation across scopes. + +#### W4-F: Thin frontend mock + +May build against the proposed C6 contract using a faithful mock. It must not +invent missing fields or use raw catalog records. + +#### Gate C6 + +Capability API and planner must agree on every conformance fixture. Only then +connect the frontend to live services. + +### Wave 5: Execution plane + +#### W5-A: Bounded preview + +Implements G13. + +#### W5-B: Row-stream foundation and executor seam + +Defines C7 and performs the one shared execution refactor. This is the only +worker editing existing dataframe execution entrypoints during the wave. + +#### W5-C: NDJSON sink + +Starts after C7, owns additive export files. + +#### W5-D: CSV and artifact store + +Starts after C7, owns additive serializer/artifact files. + +#### W5-E: Export job integration + +Implements G15B against C3/C7. + +#### W5-F: Execution verification + +Owns: + +- preview/export parity +- cancellation propagation +- stable paging +- bounded-memory evidence +- worker restart tests + +#### Gates C7-C8 + +Freeze stream and artifact contracts before external delivery work. + +### Wave 6: External delivery and release hardening + +#### W6-A: Elasticsearch bulk transport + +Implements encoding, batching, response parsing, and retry classification. + +#### W6-B: Elasticsearch preflight + +Implements destination configuration, permission/mapping checks, deterministic +ID verification, and secret handling. + +#### W6-C: Final security audit + +Completes G17, including cache isolation, artifact authorization, SSRF controls, +and audit events. + +#### W6-D: Deployment and runbook + +Completes G18. + +#### W6-E: Metrics and performance + +Completes G19 with budgets, load tests, dashboards, and Arango plan evidence. + +#### W6-F: Release conformance + +Completes G20, failure injection, and generated capability matrix. + +#### Release gate + +A clean development deployment must pass the same conformance suite as CI, +including restart, authorization isolation, preview/export parity, and any +advertised Elasticsearch capability. + +## 8. False Parallelism to Prohibit + +Terra must not launch these combinations without the named freeze: + +- G2 and G3 both editing ingestion orchestration before C1 +- G3 and G5 independently defining catalog/generation keys +- G4 and G5 independently defining relationship-analysis documents +- G6 and G11 independently defining filter serialization +- G7 and G10 independently defining semantic relationships +- multiple grain workers before C5 +- G8 before real G5/G7/G10 capability sources exist +- G9 compatibility logic before template versioning +- G12 before C4/C5 +- G13 and G14 both refactoring dataframe execution +- all of G15 deferred until export +- G16 before deterministic row identity and C8 +- G17, G19, or G20 deferred as final cleanup +- frontend work against low-level catalog records +- multiple workers regenerating GraphQL artifacts + +## 9. Worker Packet Template + +Every Terra worker receives a packet using this exact structure. + +```markdown +# Packet W-- + +## Identity +- Objective: +- Gap(s): +- Packet type: contract | implementation | integration | verification +- Base integration commit: +- Integration owner: + +## Required reading +- Repository instructions +- Exact gap sections +- Applicable conformance fixture IDs +- Frozen contract documents/examples +- Current owner files and callers +- Existing backbone files listed in section 1.1 when the packet touches FHIR, + ingestion, schema metadata, GraphQL, catalog, or planner behavior + +## Frozen contracts consumed +- Contract name/version: +- Types and serialization that must not change: +- Dataset-generation invariant: +- Authorization invariant: + +## Scope +- Owned packages/files: +- Read-only packages/files: +- Shared files requiring integrator changes: +- Generated files allowed: yes/no +- Migrations allowed: yes/no + +## Non-goals +- Explicitly excluded behavior +- Existing generated or schema-driven behavior that must be reused + +## Deliverables +- Production types/implementation +- Unit tests +- Integration/conformance evidence +- Migration/compatibility note +- API/operator documentation +- Handoff manifest + +## Required verification +- Baseline command/result against `META/` when applicable +- Targeted package tests +- `go test ./...` +- race tests where applicable +- fixture subset +- integration command +- `git diff --check` +- generated-artifact check +- required negative/cancellation/performance tests + +## Stop conditions +- Frozen contract is insufficient or contradictory +- Required fixture or upstream commit is absent +- Another active worker owns a required file +- Generation or authorization invariants cannot be preserved +- Destructive migration is required +- Public/generated contract must change +- Baseline tests fail for unrelated reasons +- Performance evidence disproves the design +- The proposed implementation would duplicate generated FHIR structs, + validators, extractors, traversal metadata, or gqlgen-owned artifacts + +## Handoff +- Structured manifest required +``` + +Do not issue a packet whose objective is simply "implement Gap N." Name the +exact packages, types, endpoints, collections, fixtures, and observable result. + +## 10. Handoff Manifest + +Every worker returns a machine-readable handoff: + +```yaml +packet: W3-D-specimen-file-grains +base_commit: +result_commit: +status: complete | blocked | partial +contracts_consumed: + - recipe/v1 + - analysis-snapshot/v1 + - logical-plan/v1 +contracts_added: [] +files_changed: [] +migrations: [] +fixtures_enabled: [] +tests: + - command: go test ./internal/dataframe/... + result: pass +known_limits: [] +downstream_actions: [] +contract_change_requests: [] +``` + +Blocked workers must include evidence, affected packet IDs, and the smallest +proposed contract amendment. They must not silently redesign an upstream +contract. + +## 11. Worktree and Branch Strategy + +Use a separate Git worktree per implementation worker. Workers sharing one +checkout would observe and overwrite incomplete files, especially generated +GraphQL artifacts. + +`META/` and `META_SMALL/` are currently local workspace data rather than files +that a new Git worktree can be assumed to contain. Terra must make them +available explicitly to workers that need them, for example through a +read-only shared absolute path, a worktree-local symlink, or a configured +`META_DIR`. Workers must not silently fall back to invented data because their +worktree lacks `META/`. Do not commit or duplicate a large dataset merely to +solve worktree setup; keep small committed conformance fixtures separate. + +Suggested layout: + +```text +../loom-terra/ + integration/ + w0-conformance/ + w1-schema/ + w1-recipe/ + w1-jobs/ + w2-dataset/ + w3-analysis/ + w3-planner/ + w5-export/ +``` + +Branch naming: + +```text +codex/terra-w-- +``` + +Rules: + +1. Start every worker from the current wave's tagged green integration commit. +2. Provision and verify the shared sample-data path before launching any packet + that requires a `META/` baseline. +3. Do not start from another active worker branch. +4. Workers commit only owned files unless explicitly assigned an integration + patch. +5. The integrator merges or cherry-picks into `codex/terra-integration`. +6. After a contract merge, rebase or recreate dependent worktrees. +7. Split multi-day work into contract, implementation, and integration commits. +8. Regenerate shared generated code once on the integration branch. +9. Keep fixtures/generated data separate from production changes where + practical. +10. Do not maintain one long-lived mega-branch per original gap. + +## 12. Merge Procedure + +For every packet: + +1. Verify the base commit matches the declared integration gate. +2. Review the handoff manifest. +3. Reject edits outside package ownership unless preapproved. +4. Run targeted tests. +5. Merge into integration. +6. Regenerate shared artifacts if the integration owner is responsible. +7. Run `go test ./...`. +8. Run the relevant conformance subset. +9. Run `git diff --check`. +10. Update the capability matrix from test results. +11. Tag or record the new green integration commit. +12. Rebase/recreate downstream workers before they continue. + +If integration exposes a contract defect: + +1. pause all consumers of that contract +2. publish a versioned amendment +3. merge the amendment alone with contract tests +4. rebase consumers +5. rerun their contract/conformance tests + +## 13. Required Integration Gates + +Every branch: + +```bash +rtk go test .//... +rtk go test ./... +rtk git diff --check +``` + +Additional gates: + +- FHIR backbone: existing `META/` resources still load; generator output is + reproducible; generated/generic parity is maintained +- GraphQL: generation is clean and HTTP contract tests pass +- persistence: migrations are idempotent; legacy startup behavior is explicit +- dataset: no read mixes generations +- analysis: every query contains project, generation, and authorization scope +- planner: Patient parity and logical-plan goldens pass +- preview/export: row/schema parity and cancellation pass +- jobs: lease race and restart recovery pass +- Elasticsearch: partial success and deterministic retry IDs pass +- security: cross-project and cross-scope negative tests pass +- release: `make conformance` passes against a clean deployment + +## 14. Terra Scheduling Rules + +Use these rules for long-running efficiency: + +- Keep one integrator slot available whenever a wave has more than three active + workers. +- Limit the planner lane to one core owner until C5. +- Limit GraphQL to one owner at all times. +- Limit collection/migration registration to one owner per wave. +- When a worker blocks on a contract, reassign it to fixtures/tests for the same + lane rather than allowing speculative implementation. +- Cancel or restart workers whose base commit predates a changed frozen + contract. +- Prefer short contract packets followed by long additive implementation + packets. +- Merge usable internal slices quickly; do not let foundational interfaces live + only on a multi-day worker branch. +- Enable a capability only when its conformance fixture passes on integration. + +## 15. First Terra Ultra Launch Set + +The safest initial launch is now the Compiler Wave A set: + +1. **CP0-A Compiler corpus and result comparison** +2. **CP0-B Current compiler/AQL/Arango baseline characterization** +3. **CP1-A Semantic IR contract design** +4. **CP2-A Generated FHIR semantic API inventory/design** + +After the compiler oracle and semantic IDs freeze, launch Compiler Wave B: + +1. **CP3-A Row grain/cardinality** +2. **CP4-A Typed expression/filter AST** +3. **CP6-A Aggregate semantics** +4. **CP6-B Pivot semantics** +5. **CP0-C Conformance fixture expansion**, if capacity remains + +Do not launch a large frontend, recipe persistence, Elasticsearch, or broad job +infrastructure before the compiler release gate. Waiting is cheaper than +building product machinery around unstable grain, filter, pivot, or row-identity +semantics. diff --git a/experimental/README.md b/experimental/README.md index 3463830..b221c7f 100644 --- a/experimental/README.md +++ b/experimental/README.md @@ -1,13 +1,12 @@ -# Experimental Benchmarks +# Local Arango development -This directory is now Arango-only. +This directory contains the checked-in ArangoDB compose setup used by the +quickstart. Start it from the repository root: -Use it for benchmark helper scripts, benchmark notes, and other non-runtime -artifacts that support the main Arango path. +```bash +rtk docker compose -f experimental/docker-compose.yml up -d +``` -The primary runtime lives at: - -- root [`docker-compose.yml`](../docker-compose.yml) -- [`queries/`](../queries/) -- [`internal/store/arango/`](../internal/store/arango/) -- [`internal/ingest/`](../internal/ingest/) +The runtime implementation lives under [`internal/store/arango/`](../internal/store/arango/) +and [`internal/ingest/`](../internal/ingest/). This is not a home for a second +query engine or manually maintained AQL recipes. diff --git a/experimental/docker-compose.yml b/experimental/docker-compose.yml index 975e888..e74edfb 100644 --- a/experimental/docker-compose.yml +++ b/experimental/docker-compose.yml @@ -1,7 +1,7 @@ services: arangodb: image: arangodb:3.12 - container_name: github.com/calypr/loom + container_name: arangodb-proto environment: ARANGO_NO_AUTH: "1" ports: diff --git a/internal/api/http_test.go b/internal/api/http_test.go index 2ff797f..ba97d9d 100644 --- a/internal/api/http_test.go +++ b/internal/api/http_test.go @@ -147,6 +147,39 @@ func TestCreateImportRejectsUnsupportedMediaType(t *testing.T) { } } +func TestCreateImportIsDisabledForGenerationAwareDeployment(t *testing.T) { + svc, err := NewService(ServiceConfig{ + Runner: fakeRunner{summary: ingest.LoadSummary{Files: 1}}, + }) + if err != nil { + t.Fatal(err) + } + server, err := NewHTTPServer(HTTPConfig{Service: svc, DisableSingleResourceImports: true}) + if err != nil { + t.Fatal(err) + } + req := newMultipartRequest(t, map[string]string{ + "project": "P1", + "resource_type": "Patient", + }, "file", "Patient.ndjson", []byte(`{"resourceType":"Patient","id":"1"}`+"\n")) + resp, err := server.App().Test(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusConflict { + body, _ := io.ReadAll(resp.Body) + t.Fatalf("status = %d, want %d; body = %s", resp.StatusCode, http.StatusConflict, string(body)) + } + var payload errorEnvelope + if err := json.NewDecoder(resp.Body).Decode(&payload); err != nil { + t.Fatal(err) + } + if payload.Error.Code != "legacy_import_disabled" { + t.Fatalf("error payload = %#v, want legacy_import_disabled", payload) + } +} + func TestApolloSandboxRouteServed(t *testing.T) { svc, err := NewService(ServiceConfig{ Runner: fakeRunner{summary: ingest.LoadSummary{Files: 1}}, diff --git a/internal/api/routes.go b/internal/api/routes.go index b27de1b..718b81e 100644 --- a/internal/api/routes.go +++ b/internal/api/routes.go @@ -32,5 +32,15 @@ func (s *HTTPServer) registerGraphQLRoutes() { func (s *HTTPServer) registerImportRoutes() { api := s.app.Group("/api/v1") + if s.disableSingleResourceImports { + api.Post("/imports", func(c fiber.Ctx) error { + return &apiError{ + Status: fiber.StatusConflict, + Code: "legacy_import_disabled", + Message: "single-resource imports are disabled while dataset-generation mode is enabled; load a complete dataset generation instead", + } + }) + return + } api.Post("/imports", s.createImport) } diff --git a/internal/api/server.go b/internal/api/server.go index d346f91..9de9918 100644 --- a/internal/api/server.go +++ b/internal/api/server.go @@ -20,17 +20,23 @@ type HTTPConfig struct { Logger *slog.Logger BodyLimit int ReadBufferSize int + // DisableSingleResourceImports prevents the legacy multipart endpoint from + // mutating shared graph collections. Generation-aware deployments must use + // a complete staged bundle loader instead: one uploaded resource file can + // never safely become an immutable active dataset generation. + DisableSingleResourceImports bool } type HTTPServer struct { - app *fiber.App - service *Service - authn authscope.Authenticator - authz authscope.Authorizer - logger *slog.Logger - cfgGraphQLHandler http.Handler - cfgGraphQLPlaygroundHandler http.Handler - cfgApolloSandboxHandler http.Handler + app *fiber.App + service *Service + authn authscope.Authenticator + authz authscope.Authorizer + logger *slog.Logger + cfgGraphQLHandler http.Handler + cfgGraphQLPlaygroundHandler http.Handler + cfgApolloSandboxHandler http.Handler + disableSingleResourceImports bool } type apiError struct { @@ -72,13 +78,14 @@ func NewHTTPServer(cfg HTTPConfig) (*HTTPServer, error) { } server := &HTTPServer{ - service: cfg.Service, - authn: cfg.Authenticator, - authz: cfg.Authorizer, - logger: cfg.Logger, - cfgGraphQLHandler: cfg.GraphQLHandler, - cfgGraphQLPlaygroundHandler: cfg.GraphQLPlaygroundHandler, - cfgApolloSandboxHandler: cfg.ApolloSandboxHandler, + service: cfg.Service, + authn: cfg.Authenticator, + authz: cfg.Authorizer, + logger: cfg.Logger, + cfgGraphQLHandler: cfg.GraphQLHandler, + cfgGraphQLPlaygroundHandler: cfg.GraphQLPlaygroundHandler, + cfgApolloSandboxHandler: cfg.ApolloSandboxHandler, + disableSingleResourceImports: cfg.DisableSingleResourceImports, } app := fiber.New(fiber.Config{ BodyLimit: cfg.BodyLimit, diff --git a/internal/authscope/scope.go b/internal/authscope/scope.go index 65242db..0e4d2e3 100644 --- a/internal/authscope/scope.go +++ b/internal/authscope/scope.go @@ -34,7 +34,45 @@ type ScopeResolver struct { cacheTTL time.Duration mu sync.RWMutex - cache map[string]cachedPaths + cache map[scopeCacheKey]cachedPaths +} + +// ReadScopeMode records whether an effective read scope may bypass the +// auth_resource_path predicate. It is deliberately separate from the path +// list: a restricted caller can legitimately resolve to zero paths, and that +// must never be confused with an unrestricted caller. +// +// The empty value is reserved for legacy callers that carry only a path list. +// Those callers retain the historical rule that an empty list is unrestricted. +type ReadScopeMode string + +const ( + ReadScopeUnrestricted ReadScopeMode = "unrestricted" + ReadScopeRestricted ReadScopeMode = "restricted" +) + +// ReadScope is the authorization result that downstream catalog and dataframe +// code must propagate together. AuthResourcePaths may be empty in either mode; +// Mode is therefore authoritative for the AQL bypass bind variable. +type ReadScope struct { + AuthResourcePaths []string + Mode ReadScopeMode +} + +// Unrestricted reports whether this scope may bypass auth_resource_path +// filtering. Unknown modes are treated as restricted so an invalid internal +// value cannot widen access. +func (s ReadScope) Unrestricted() bool { + return s.Mode == ReadScopeUnrestricted +} + +// Clone returns an independent copy suitable for passing between request +// layers without sharing a resolver-owned path slice. +func (s ReadScope) Clone() ReadScope { + return ReadScope{ + AuthResourcePaths: cloneStrings(s.AuthResourcePaths), + Mode: s.Mode, + } } type cachedPaths struct { @@ -42,6 +80,16 @@ type cachedPaths struct { expiresAt time.Time } +// scopeCacheKey keeps authorization-path discovery isolated between immutable +// dataset generations. A project can legitimately have a different set of +// populated auth_resource_path values after a reload, so caching by project +// alone would otherwise leak stale paths into a new generation's catalog and +// dataframe queries. +type scopeCacheKey struct { + project string + datasetGeneration string +} + type BearerTokenAuthenticator struct{} type ScopeAuthorizer struct { @@ -76,7 +124,7 @@ func NewScopeResolver(cfg ScopeResolverConfig) *ScopeResolver { resourceAccess: cfg.ResourceAccess, listExisting: cfg.ListExistingAuthResourcePaths, cacheTTL: cfg.CacheTTL, - cache: make(map[string]cachedPaths), + cache: make(map[scopeCacheKey]cachedPaths), } } @@ -87,22 +135,38 @@ func (a ScopeAuthorizer) AuthorizeWrite(ctx context.Context, principal *Principa return a.Resolver.AuthorizeWrite(ctx, principal, project, authResourcePath) } -func (r *ScopeResolver) ResolveReadAuthResourcePaths(ctx context.Context, principal *Principal, project string, requested []string) ([]string, error) { +// ResolveReadScope returns the effective read authorization mode and paths. +// In particular, it preserves a restricted-empty intersection instead of +// encoding it as an empty slice that a later AQL layer could mistake for an +// unrestricted scope. +func (r *ScopeResolver) ResolveReadScope(ctx context.Context, principal *Principal, project string, requested []string) (ReadScope, error) { + return r.ResolveReadScopeForGeneration(ctx, principal, project, "", requested) +} + +// ResolveReadScopeForGeneration resolves an authorization scope against the +// populated auth-resource paths for exactly one dataset generation. An empty +// generation preserves the legacy null-generation namespace; it never means +// every generation. Callers that have selected an active manifest must use +// this method so the scope cache and catalog reads remain generation-aligned. +func (r *ScopeResolver) ResolveReadScopeForGeneration(ctx context.Context, principal *Principal, project, datasetGeneration string, requested []string) (ReadScope, error) { callerPaths, restricted, err := r.resolveCallerPaths(ctx, principal, "read", "*") if err != nil { - return nil, err + return ReadScope{}, err } normalizedRequested := normalizeAuthResourcePathList(requested) if !restricted { if len(normalizedRequested) == 0 { - return nil, nil + return ReadScope{Mode: ReadScopeUnrestricted}, nil } - return normalizedRequested, nil + // An unrestricted caller can still deliberately narrow a read to a + // requested subset. That subset is a real AQL constraint, not an + // authorization bypass. + return ReadScope{AuthResourcePaths: normalizedRequested, Mode: ReadScopeRestricted}, nil } - existingPaths, err := r.listExistingPaths(ctx, project) + existingPaths, err := r.listExistingPaths(ctx, project, datasetGeneration) if err != nil { - return nil, err + return ReadScope{}, err } allowedSet := make(map[string]struct{}, len(callerPaths)) for _, path := range callerPaths { @@ -115,7 +179,7 @@ func (r *ScopeResolver) ResolveReadAuthResourcePaths(ctx context.Context, princi } } if len(normalizedRequested) == 0 { - return effective, nil + return ReadScope{AuthResourcePaths: effective, Mode: ReadScopeRestricted}, nil } effectiveSet := make(map[string]struct{}, len(effective)) for _, path := range effective { @@ -123,10 +187,29 @@ func (r *ScopeResolver) ResolveReadAuthResourcePaths(ctx context.Context, princi } for _, path := range normalizedRequested { if _, ok := effectiveSet[path]; !ok { - return nil, fmt.Errorf("authResourcePath %q is outside caller scope", path) + return ReadScope{}, fmt.Errorf("authResourcePath %q is outside caller scope", path) } } - return normalizedRequested, nil + return ReadScope{AuthResourcePaths: normalizedRequested, Mode: ReadScopeRestricted}, nil +} + +// ResolveReadAuthResourcePaths is retained for existing callers that only +// accept paths. New query-building code must use ResolveReadScope so a +// restricted empty result cannot become an unrestricted AQL query. +func (r *ScopeResolver) ResolveReadAuthResourcePaths(ctx context.Context, principal *Principal, project string, requested []string) ([]string, error) { + return r.ResolveReadAuthResourcePathsForGeneration(ctx, principal, project, "", requested) +} + +// ResolveReadAuthResourcePathsForGeneration is the compatibility payload form +// of ResolveReadScopeForGeneration. New query callers must carry the returned +// ReadScope mode as well so a restricted empty result cannot become an +// unrestricted AQL query. +func (r *ScopeResolver) ResolveReadAuthResourcePathsForGeneration(ctx context.Context, principal *Principal, project, datasetGeneration string, requested []string) ([]string, error) { + scope, err := r.ResolveReadScopeForGeneration(ctx, principal, project, datasetGeneration, requested) + if err != nil { + return nil, err + } + return cloneStrings(scope.AuthResourcePaths), nil } func (r *ScopeResolver) AuthorizeWrite(ctx context.Context, principal *Principal, project, authResourcePath string) error { @@ -172,13 +255,16 @@ func (r *ScopeResolver) resolveCallerPaths(ctx context.Context, principal *Princ return nil, false, nil } -func (r *ScopeResolver) listExistingPaths(ctx context.Context, project string) ([]string, error) { - if strings.TrimSpace(project) == "" { +func (r *ScopeResolver) listExistingPaths(ctx context.Context, project, datasetGeneration string) ([]string, error) { + project = strings.TrimSpace(project) + datasetGeneration = catalog.NormalizeDatasetGeneration(datasetGeneration) + if project == "" { return []string{}, nil } + key := scopeCacheKey{project: project, datasetGeneration: datasetGeneration} now := time.Now() r.mu.RLock() - entry, ok := r.cache[project] + entry, ok := r.cache[key] r.mu.RUnlock() if ok && now.Before(entry.expiresAt) { return cloneStrings(entry.paths), nil @@ -186,13 +272,14 @@ func (r *ScopeResolver) listExistingPaths(ctx context.Context, project string) ( paths, err := r.listExisting(ctx, catalog.AuthResourcePathOptions{ ConnectionOptions: r.connOpts, Project: project, + DatasetGeneration: datasetGeneration, }) if err != nil { return nil, err } paths = normalizeAuthResourcePathList(paths) r.mu.Lock() - r.cache[project] = cachedPaths{ + r.cache[key] = cachedPaths{ paths: cloneStrings(paths), expiresAt: now.Add(r.cacheTTL), } @@ -204,12 +291,32 @@ func (r *ScopeResolver) InvalidateProject(project string) { project = strings.TrimSpace(project) if project == "" { r.mu.Lock() - r.cache = make(map[string]cachedPaths) + r.cache = make(map[scopeCacheKey]cachedPaths) r.mu.Unlock() return } r.mu.Lock() - delete(r.cache, project) + for key := range r.cache { + if key.project == project { + delete(r.cache, key) + } + } + r.mu.Unlock() +} + +// InvalidateGeneration removes a single project/generation auth-path entry. +// It is useful after a generation-specific catalog rebuild without evicting +// the active scope cache for every other immutable generation in the project. +func (r *ScopeResolver) InvalidateGeneration(project, datasetGeneration string) { + key := scopeCacheKey{ + project: strings.TrimSpace(project), + datasetGeneration: catalog.NormalizeDatasetGeneration(datasetGeneration), + } + if key.project == "" { + return + } + r.mu.Lock() + delete(r.cache, key) r.mu.Unlock() } diff --git a/internal/authscope/scope_test.go b/internal/authscope/scope_test.go index da60c04..3608cdf 100644 --- a/internal/authscope/scope_test.go +++ b/internal/authscope/scope_test.go @@ -2,6 +2,7 @@ package authscope import ( "context" + "reflect" "testing" "github.com/calypr/loom/internal/catalog" @@ -60,6 +61,126 @@ func TestScopeResolverRejectsRequestedPathOutsideIntersection(t *testing.T) { } } +func TestScopeResolverResolveReadScopeKeepsRestrictedEmptyIntersection(t *testing.T) { + resolver := NewScopeResolver(ScopeResolverConfig{ + ConnectionOptions: arangostore.ConnectionOptions{}, + ResourceAccess: fakeResourceAccessClient{ + resources: []string{"/programs/EllrottLab/projects/GDC_Data"}, + }, + ListExistingAuthResourcePaths: func(context.Context, catalog.AuthResourcePathOptions) ([]string, error) { + // The caller has access to GDC_Data, but this project currently has + // no matching catalog scope. This must be a deny-all scope, not a + // no-filter scope. + return []string{"Another-Project"}, nil + }, + }) + + scope, err := resolver.ResolveReadScope(context.Background(), &Principal{ + AuthorizationHeader: "Bearer header.payload.signature", + }, "P1", nil) + if err != nil { + t.Fatal(err) + } + if scope.Mode != ReadScopeRestricted || scope.Unrestricted() { + t.Fatalf("scope mode = %#v, want restricted", scope) + } + if len(scope.AuthResourcePaths) != 0 { + t.Fatalf("restricted empty scope paths = %#v, want none", scope.AuthResourcePaths) + } + + // Keep the legacy wrapper's payload contract while proving that new query + // callers must consume ResolveReadScope for its mode as well as its paths. + paths, err := resolver.ResolveReadAuthResourcePaths(context.Background(), &Principal{ + AuthorizationHeader: "Bearer header.payload.signature", + }, "P1", nil) + if err != nil { + t.Fatal(err) + } + if len(paths) != 0 { + t.Fatalf("legacy paths = %#v, want empty", paths) + } +} + +func TestScopeResolverCachesExistingPathsPerNormalizedGeneration(t *testing.T) { + var calls []catalog.AuthResourcePathOptions + resolver := NewScopeResolver(ScopeResolverConfig{ + ResourceAccess: fakeResourceAccessClient{ + resources: []string{"/programs/example/projects/allowed"}, + }, + ListExistingAuthResourcePaths: func(_ context.Context, opts catalog.AuthResourcePathOptions) ([]string, error) { + calls = append(calls, opts) + switch opts.DatasetGeneration { + case "generation-a": + return []string{"example-allowed"}, nil + case "generation-b": + return []string{"example-other"}, nil + default: + t.Fatalf("unexpected catalog generation %q", opts.DatasetGeneration) + return nil, nil + } + }, + }) + principal := &Principal{AuthorizationHeader: "Bearer header.payload.signature"} + + first, err := resolver.ResolveReadScopeForGeneration(context.Background(), principal, " P1 ", " generation-a ", nil) + if err != nil { + t.Fatalf("ResolveReadScopeForGeneration(generation-a) error = %v", err) + } + if first.Mode != ReadScopeRestricted || !reflect.DeepEqual(first.AuthResourcePaths, []string{"example-allowed"}) { + t.Fatalf("generation-a scope = %#v, want restricted example-allowed", first) + } + + second, err := resolver.ResolveReadScopeForGeneration(context.Background(), principal, "P1", "generation-b", nil) + if err != nil { + t.Fatalf("ResolveReadScopeForGeneration(generation-b) error = %v", err) + } + if second.Mode != ReadScopeRestricted || len(second.AuthResourcePaths) != 0 { + t.Fatalf("generation-b scope = %#v, want restricted empty", second) + } + + // The normalized generation-a lookup must use its own cache entry instead + // of reusing generation-b's empty intersection. + again, err := resolver.ResolveReadScopeForGeneration(context.Background(), principal, "P1", "generation-a", nil) + if err != nil { + t.Fatalf("cached ResolveReadScopeForGeneration(generation-a) error = %v", err) + } + if !reflect.DeepEqual(again.AuthResourcePaths, []string{"example-allowed"}) { + t.Fatalf("cached generation-a scope = %#v, want example-allowed", again) + } + if got, want := len(calls), 2; got != want { + t.Fatalf("existing-path catalog calls = %d, want %d distinct generations", got, want) + } + if calls[0].Project != "P1" || calls[0].DatasetGeneration != "generation-a" || calls[1].Project != "P1" || calls[1].DatasetGeneration != "generation-b" { + t.Fatalf("generation-aware catalog options = %#v", calls) + } +} + +func TestScopeResolverKeepsRestrictedEmptyScopeWithinGeneration(t *testing.T) { + called := false + resolver := NewScopeResolver(ScopeResolverConfig{ + ResourceAccess: fakeResourceAccessClient{ + resources: []string{"/programs/example/projects/allowed"}, + }, + ListExistingAuthResourcePaths: func(_ context.Context, opts catalog.AuthResourcePathOptions) ([]string, error) { + called = true + if opts.Project != "P1" || opts.DatasetGeneration != "generation-a" { + t.Fatalf("existing auth paths options = %+v, want P1/generation-a", opts) + } + return []string{"example-unrelated"}, nil + }, + }) + + scope, err := resolver.ResolveReadScopeForGeneration(context.Background(), &Principal{ + AuthorizationHeader: "Bearer header.payload.signature", + }, "P1", " generation-a ", nil) + if err != nil { + t.Fatalf("ResolveReadScopeForGeneration() error = %v", err) + } + if !called || scope.Mode != ReadScopeRestricted || scope.Unrestricted() || len(scope.AuthResourcePaths) != 0 { + t.Fatalf("generation-scoped restricted empty scope = %#v", scope) + } +} + func TestScopeAuthorizerRequiresScopedWritePath(t *testing.T) { authz := ScopeAuthorizer{ Resolver: NewScopeResolver(ScopeResolverConfig{ diff --git a/internal/catalog/auth_scope.go b/internal/catalog/auth_scope.go new file mode 100644 index 0000000..9512cfa --- /dev/null +++ b/internal/catalog/auth_scope.go @@ -0,0 +1,19 @@ +package catalog + +// ExplicitAuthResourcePathsUnrestricted returns an independent pointer for +// catalog options. The pointer distinguishes a deliberately restricted empty +// scope from legacy callers that provide only an empty path slice. +func ExplicitAuthResourcePathsUnrestricted(unrestricted bool) *bool { + return &unrestricted +} + +// EffectiveAuthResourcePathsUnrestricted resolves the compatibility rule for +// catalog callers. New request paths should always pass an explicit value; +// direct legacy callers retain their historical empty-means-unrestricted +// behavior until migrated. +func EffectiveAuthResourcePathsUnrestricted(paths []string, explicit *bool) bool { + if explicit != nil { + return *explicit + } + return len(paths) == 0 +} diff --git a/internal/catalog/auth_scope_test.go b/internal/catalog/auth_scope_test.go new file mode 100644 index 0000000..50b6d02 --- /dev/null +++ b/internal/catalog/auth_scope_test.go @@ -0,0 +1,35 @@ +package catalog + +import "testing" + +func TestCatalogBindVarsKeepRestrictedEmptyScopeRestricted(t *testing.T) { + restricted := ExplicitAuthResourcePathsUnrestricted(false) + + fieldBinds := populatedFieldsBindVars(PopulatedFieldOptions{ + Project: "P1", + AuthResourcePathsUnrestricted: restricted, + AuthResourcePaths: []string{}, + }) + if got, ok := fieldBinds["auth_resource_paths_unrestricted"].(bool); !ok || got { + t.Fatalf("field catalog unrestricted bind = %#v, want false", fieldBinds["auth_resource_paths_unrestricted"]) + } + if paths, ok := fieldBinds["auth_resource_paths"].([]string); !ok || len(paths) != 0 { + t.Fatalf("field catalog paths bind = %#v, want empty []string", fieldBinds["auth_resource_paths"]) + } + + referenceBinds := populatedReferencesBindVars(PopulatedReferenceOptions{ + Project: "P1", + AuthResourcePathsUnrestricted: restricted, + AuthResourcePaths: []string{}, + }, TraversalModeBuilder) + if got, ok := referenceBinds["auth_resource_paths_unrestricted"].(bool); !ok || got { + t.Fatalf("reference catalog unrestricted bind = %#v, want false", referenceBinds["auth_resource_paths_unrestricted"]) + } +} + +func TestCatalogBindVarsPreserveLegacyEmptyUnrestrictedScope(t *testing.T) { + binds := populatedFieldsBindVars(PopulatedFieldOptions{Project: "P1"}) + if got, ok := binds["auth_resource_paths_unrestricted"].(bool); !ok || !got { + t.Fatalf("legacy empty scope unrestricted bind = %#v, want true", binds["auth_resource_paths_unrestricted"]) + } +} diff --git a/internal/catalog/cache/cache.go b/internal/catalog/cache/cache.go index 085101f..75df9a6 100644 --- a/internal/catalog/cache/cache.go +++ b/internal/catalog/cache/cache.go @@ -98,24 +98,33 @@ func (c *Cache) InvalidateAll() { } func fieldKey(opts catalog.PopulatedFieldOptions) (string, error) { - scope, err := authScopeKey(opts.AuthResourcePaths) + scope, err := authScopeKey(opts.AuthResourcePaths, opts.AuthResourcePathsUnrestricted) if err != nil { return "", err } - return fmt.Sprintf("%s|%s|%t|%s", strings.TrimSpace(opts.Project), strings.TrimSpace(opts.ResourceType), opts.PivotOnly, scope), nil + return fmt.Sprintf("%s|%s|%t|%s|%s", strings.TrimSpace(opts.Project), strings.TrimSpace(opts.ResourceType), opts.PivotOnly, scope, datasetGenerationKey(opts.DatasetGeneration)), nil } func referenceKey(opts catalog.PopulatedReferenceOptions) (string, error) { - scope, err := authScopeKey(opts.AuthResourcePaths) + scope, err := authScopeKey(opts.AuthResourcePaths, opts.AuthResourcePathsUnrestricted) if err != nil { return "", err } - return fmt.Sprintf("%s|%s|%s|%s", strings.TrimSpace(opts.Project), strings.TrimSpace(opts.NodeType), strings.TrimSpace(opts.Mode), scope), nil + return fmt.Sprintf("%s|%s|%s|%s|%s", strings.TrimSpace(opts.Project), strings.TrimSpace(opts.NodeType), strings.TrimSpace(opts.Mode), scope, datasetGenerationKey(opts.DatasetGeneration)), nil } -func authScopeKey(paths []string) (string, error) { - if len(paths) == 0 { - return "*", nil +func datasetGenerationKey(generation string) string { + generation = catalog.NormalizeDatasetGeneration(generation) + if !catalog.HasDatasetGeneration(generation) { + return "legacy" + } + encoded, _ := json.Marshal(generation) + return "generation:" + string(encoded) +} + +func authScopeKey(paths []string, explicitUnrestricted *bool) (string, error) { + if catalog.EffectiveAuthResourcePathsUnrestricted(paths, explicitUnrestricted) { + return "unrestricted", nil } normalized := append([]string(nil), paths...) sort.Strings(normalized) @@ -123,7 +132,7 @@ func authScopeKey(paths []string) (string, error) { if err != nil { return "", err } - return string(encoded), nil + return "restricted:" + string(encoded), nil } func cloneFields(in []catalog.PopulatedField) []catalog.PopulatedField { diff --git a/internal/catalog/cache/cache_test.go b/internal/catalog/cache/cache_test.go index 763177a..bd7a83a 100644 --- a/internal/catalog/cache/cache_test.go +++ b/internal/catalog/cache/cache_test.go @@ -70,3 +70,65 @@ func TestCacheDiscoverReferencesSeparatesAuthScopes(t *testing.T) { t.Fatalf("calls = %d, want 2", calls) } } + +func TestCacheSeparatesRestrictedEmptyScopeFromUnrestrictedScope(t *testing.T) { + cache := New() + calls := 0 + discover := cache.DiscoverFields(func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + calls++ + return []catalog.PopulatedField{{ResourceType: "Patient", Path: "gender"}}, nil + }) + + unrestricted := catalog.PopulatedFieldOptions{Project: "P1", ResourceType: "Patient"} + restrictedEmpty := catalog.PopulatedFieldOptions{ + Project: "P1", + ResourceType: "Patient", + AuthResourcePathsUnrestricted: catalog.ExplicitAuthResourcePathsUnrestricted(false), + AuthResourcePaths: []string{}, + } + + if _, err := discover(context.Background(), unrestricted); err != nil { + t.Fatal(err) + } + if _, err := discover(context.Background(), restrictedEmpty); err != nil { + t.Fatal(err) + } + if calls != 2 { + t.Fatalf("calls = %d, want separate unrestricted and restricted-empty cache entries", calls) + } +} + +func TestCacheSeparatesDatasetGenerationNamespaces(t *testing.T) { + cache := New() + fieldCalls := 0 + discoverFields := cache.DiscoverFields(func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + fieldCalls++ + return []catalog.PopulatedField{{ResourceType: "Patient", Path: "gender"}}, nil + }) + referenceCalls := 0 + discoverReferences := cache.DiscoverReferences(func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + referenceCalls++ + return []catalog.PopulatedReference{{FromType: "Patient", Label: "subject_Patient", ToType: "Specimen"}}, nil + }) + + fieldBase := catalog.PopulatedFieldOptions{Project: "P1", ResourceType: "Patient"} + referenceBase := catalog.PopulatedReferenceOptions{Project: "P1", NodeType: "Patient", Mode: catalog.TraversalModeBuilder} + for _, generation := range []string{"", "generation-a", " generation-a ", "generation-b"} { + fields := fieldBase + fields.DatasetGeneration = generation + if _, err := discoverFields(context.Background(), fields); err != nil { + t.Fatal(err) + } + references := referenceBase + references.DatasetGeneration = generation + if _, err := discoverReferences(context.Background(), references); err != nil { + t.Fatal(err) + } + } + if fieldCalls != 3 { + t.Fatalf("field calls = %d, want legacy + two exact generation namespaces", fieldCalls) + } + if referenceCalls != 3 { + t.Fatalf("reference calls = %d, want legacy + two exact generation namespaces", referenceCalls) + } +} diff --git a/internal/catalog/generation.go b/internal/catalog/generation.go new file mode 100644 index 0000000..ea9c1aa --- /dev/null +++ b/internal/catalog/generation.go @@ -0,0 +1,32 @@ +package catalog + +import "strings" + +// NormalizeDatasetGeneration applies the optional opaque-generation convention +// at every catalog boundary. It prevents a whitespace-padded generation from +// using a cache key that differs from the AQL bind value. +func NormalizeDatasetGeneration(generation string) string { + return strings.TrimSpace(generation) +} + +// DatasetGenerationBindValue returns the only safe generation bind value for +// catalog queries. Generation-qualified callers match one exact opaque value; +// callers without one deliberately match only the legacy null namespace. +// +// The return type is any so the legacy case is carried to the Arango driver as +// JSON null rather than as an empty string, which would otherwise select an +// unrelated namespace (or accidentally drop legacy documents). +func DatasetGenerationBindValue(generation string) any { + generation = NormalizeDatasetGeneration(generation) + if generation == "" { + return nil + } + return generation +} + +// HasDatasetGeneration reports whether a request selected a concrete +// generation. Whitespace-only inputs follow the optional-field convention and +// select the legacy null namespace. +func HasDatasetGeneration(generation string) bool { + return NormalizeDatasetGeneration(generation) != "" +} diff --git a/internal/catalog/generation_test.go b/internal/catalog/generation_test.go new file mode 100644 index 0000000..70810ac --- /dev/null +++ b/internal/catalog/generation_test.go @@ -0,0 +1,62 @@ +package catalog + +import ( + "encoding/json" + "strings" + "testing" +) + +func TestCatalogGenerationBindsUseExactOrLegacyNullNamespace(t *testing.T) { + fields := populatedFieldsBindVars(PopulatedFieldOptions{ + Project: "P1", + DatasetGeneration: " generation-a ", + }) + if got := fields["dataset_generation"]; got != "generation-a" { + t.Fatalf("field dataset_generation bind = %#v, want normalized generation", got) + } + + references := populatedReferencesBindVars(PopulatedReferenceOptions{ + Project: "P1", + DatasetGeneration: "generation-a", + }, TraversalModeStorage) + if got := references["dataset_generation"]; got != "generation-a" { + t.Fatalf("reference dataset_generation bind = %#v, want generation-a", got) + } + + legacyFields := populatedFieldsBindVars(PopulatedFieldOptions{Project: "P1"}) + if got, present := legacyFields["dataset_generation"]; !present || got != nil { + t.Fatalf("legacy field dataset_generation bind = %#v (present=%t), want explicit nil", got, present) + } + legacyReferences := populatedReferencesBindVars(PopulatedReferenceOptions{Project: "P1"}, TraversalModeStorage) + if got, present := legacyReferences["dataset_generation"]; !present || got != nil { + t.Fatalf("legacy reference dataset_generation bind = %#v (present=%t), want explicit nil", got, present) + } + + for name, query := range map[string]string{ + "fields": populatedFieldsAQL, + "references": populatedReferencesAQL, + "auth paths": existingAuthResourcePathsAQL, + } { + if !strings.Contains(query, "FILTER "+map[string]string{"fields": "d", "references": "e", "auth paths": "d"}[name]+".dataset_generation == @dataset_generation") { + t.Fatalf("%s query is missing exact dataset-generation predicate:\n%s", name, query) + } + } +} + +func TestCatalogGenerationResultContractsExposeGeneration(t *testing.T) { + fields, err := json.Marshal(PopulatedField{DatasetGeneration: "generation-a", ResourceType: "Patient", Path: "id"}) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(string(fields), `"dataset_generation":"generation-a"`) { + t.Fatalf("field result JSON omitted generation: %s", fields) + } + + references, err := json.Marshal(PopulatedReference{DatasetGeneration: "generation-a", FromType: "Patient", Label: "subject_Patient", ToType: "Specimen"}) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(string(references), `"dataset_generation":"generation-a"`) { + t.Fatalf("reference result JSON omitted generation: %s", references) + } +} diff --git a/internal/catalog/helpers.go b/internal/catalog/helpers.go index 938eb07..4b3a0b1 100644 --- a/internal/catalog/helpers.go +++ b/internal/catalog/helpers.go @@ -1,6 +1,9 @@ package catalog import ( + "crypto/sha256" + "encoding/binary" + "encoding/hex" "encoding/json" "fmt" "os" @@ -99,6 +102,47 @@ func fieldCatalogKey(project, authResourcePath, resourceType, path string) strin return sanitizeCollectionKey(project + "::" + authResourcePath + "::" + resourceType + "::" + path) } +const generationFieldCatalogKeyPrefix = "gfc_" + +// fieldCatalogKeyForGeneration returns the persistent catalog document key for +// one profiler identity. The empty-generation branch deliberately calls the +// pre-generation key function unchanged: existing catalogs and callers that +// have not selected a generation must retain their exact legacy key layout. +// +// A non-empty generation uses a SHA-256 digest of every identity component. +// In particular, it must not append a sanitized generation string to the +// legacy key: sanitization is many-to-one (for example, a slash and a space +// both become an underscore) and would allow one immutable generation to +// overwrite another catalog row. +func fieldCatalogKeyForGeneration(project, datasetGeneration, authResourcePath, resourceType, path string) string { + datasetGeneration = NormalizeDatasetGeneration(datasetGeneration) + if datasetGeneration == "" { + return fieldCatalogKey(project, authResourcePath, resourceType, path) + } + return generationFieldCatalogKeyPrefix + catalogIdentityDigest( + "field-catalog/v1", + project, + datasetGeneration, + authResourcePath, + resourceType, + path, + ) +} + +// catalogIdentityDigest hashes a length-prefixed sequence rather than a +// delimiter-joined string. That keeps the input encoding injective even if a +// project, generation, or path itself contains a delimiter or NUL byte. +func catalogIdentityDigest(parts ...string) string { + hash := sha256.New() + for _, part := range parts { + var length [8]byte + binary.BigEndian.PutUint64(length[:], uint64(len(part))) + _, _ = hash.Write(length[:]) + _, _ = hash.Write([]byte(part)) + } + return hex.EncodeToString(hash.Sum(nil)) +} + func sanitizeCollectionKey(value string) string { value = strings.TrimSpace(value) if value == "" { diff --git a/internal/catalog/read_auth_paths.go b/internal/catalog/read_auth_paths.go index b5b26cc..16d28ee 100644 --- a/internal/catalog/read_auth_paths.go +++ b/internal/catalog/read_auth_paths.go @@ -10,6 +10,7 @@ import ( const existingAuthResourcePathsAQL = ` FOR d IN fhir_field_catalog FILTER d.project == @project + FILTER d.dataset_generation == @dataset_generation FILTER d.auth_resource_path != null AND d.auth_resource_path != "" COLLECT auth_resource_path = d.auth_resource_path SORT auth_resource_path @@ -27,14 +28,18 @@ func DiscoverExistingAuthResourcePaths(ctx context.Context, opts AuthResourcePat defer client.Close(ctx) start := time.Now() emit("go_discovery_start", map[string]any{ - "database": opts.Database, - "project": opts.Project, - "cursor_batch_size": opts.CursorBatch, - "query": "existing_auth_resource_paths", + "database": opts.Database, + "project": opts.Project, + "dataset_generation": DatasetGenerationBindValue(opts.DatasetGeneration), + "cursor_batch_size": opts.CursorBatch, + "query": "existing_auth_resource_paths", }) results := make([]string, 0, 16) - err = client.QueryRows(ctx, existingAuthResourcePathsAQL, opts.CursorBatch, map[string]any{"project": opts.Project}, func(row map[string]any) error { + err = client.QueryRows(ctx, existingAuthResourcePathsAQL, opts.CursorBatch, map[string]any{ + "project": opts.Project, + "dataset_generation": DatasetGenerationBindValue(opts.DatasetGeneration), + }, func(row map[string]any) error { if path := stringValue(row["auth_resource_path"]); path != "" { results = append(results, path) } @@ -44,11 +49,12 @@ func DiscoverExistingAuthResourcePaths(ctx context.Context, opts AuthResourcePat return nil, err } emit("go_discovery_complete", map[string]any{ - "database": opts.Database, - "project": opts.Project, - "rows": len(results), - "seconds": secondsSince(start), - "query": "existing_auth_resource_paths", + "database": opts.Database, + "project": opts.Project, + "dataset_generation": DatasetGenerationBindValue(opts.DatasetGeneration), + "rows": len(results), + "seconds": secondsSince(start), + "query": "existing_auth_resource_paths", }) return results, nil } diff --git a/internal/catalog/read_fields.go b/internal/catalog/read_fields.go index 67f2e2e..97bde76 100644 --- a/internal/catalog/read_fields.go +++ b/internal/catalog/read_fields.go @@ -10,12 +10,14 @@ import ( const populatedFieldsAQL = ` FOR d IN fhir_field_catalog FILTER d.project == @project + FILTER d.dataset_generation == @dataset_generation FILTER @auth_resource_paths_unrestricted == true OR d.auth_resource_path IN @auth_resource_paths FILTER @resource_type == null OR d.resource_type == @resource_type FILTER @pivot_only == false OR d.pivot_candidate == true SORT d.resource_type, d.doc_count DESC, d.path RETURN { project: d.project, + dataset_generation: d.dataset_generation, auth_resource_path: d.auth_resource_path, resource_type: d.resource_type, path: d.path, @@ -47,6 +49,7 @@ func DiscoverPopulatedFields(ctx context.Context, opts PopulatedFieldOptions) ([ emit("go_discovery_start", map[string]any{ "database": opts.Database, "project": opts.Project, + "dataset_generation": DatasetGenerationBindValue(opts.DatasetGeneration), "resource_type": opts.ResourceType, "pivot_only": opts.PivotOnly, "auth_resource_paths": opts.AuthResourcePaths, @@ -54,22 +57,13 @@ func DiscoverPopulatedFields(ctx context.Context, opts PopulatedFieldOptions) ([ "query": "populated_fields", }) - bindVars := map[string]any{ - "project": opts.Project, - "pivot_only": opts.PivotOnly, - "auth_resource_paths": cloneStrings(opts.AuthResourcePaths), - "auth_resource_paths_unrestricted": len(opts.AuthResourcePaths) == 0, - } - if opts.ResourceType != "" { - bindVars["resource_type"] = opts.ResourceType - } else { - bindVars["resource_type"] = nil - } + bindVars := populatedFieldsBindVars(opts) results := make([]PopulatedField, 0, 64) err = client.QueryRows(ctx, populatedFieldsAQL, opts.CursorBatch, bindVars, func(row map[string]any) error { results = append(results, PopulatedField{ Project: stringValue(row["project"]), + DatasetGeneration: stringValue(row["dataset_generation"]), AuthResourcePath: stringValue(row["auth_resource_path"]), ResourceType: stringValue(row["resource_type"]), Path: stringValue(row["path"]), @@ -94,6 +88,7 @@ func DiscoverPopulatedFields(ctx context.Context, opts PopulatedFieldOptions) ([ emit("go_discovery_complete", map[string]any{ "database": opts.Database, "project": opts.Project, + "dataset_generation": DatasetGenerationBindValue(opts.DatasetGeneration), "resource_type": opts.ResourceType, "pivot_only": opts.PivotOnly, "auth_resource_paths": opts.AuthResourcePaths, @@ -102,3 +97,19 @@ func DiscoverPopulatedFields(ctx context.Context, opts PopulatedFieldOptions) ([ }) return results, nil } + +func populatedFieldsBindVars(opts PopulatedFieldOptions) map[string]any { + bindVars := map[string]any{ + "project": opts.Project, + "dataset_generation": DatasetGenerationBindValue(opts.DatasetGeneration), + "pivot_only": opts.PivotOnly, + "auth_resource_paths": cloneStrings(opts.AuthResourcePaths), + "auth_resource_paths_unrestricted": EffectiveAuthResourcePathsUnrestricted(opts.AuthResourcePaths, opts.AuthResourcePathsUnrestricted), + } + if opts.ResourceType != "" { + bindVars["resource_type"] = opts.ResourceType + } else { + bindVars["resource_type"] = nil + } + return bindVars +} diff --git a/internal/catalog/read_references.go b/internal/catalog/read_references.go index a9d21f3..ba24ab3 100644 --- a/internal/catalog/read_references.go +++ b/internal/catalog/read_references.go @@ -11,6 +11,7 @@ import ( const populatedReferencesAQL = ` FOR e IN fhir_edge FILTER e.project == @project + FILTER e.dataset_generation == @dataset_generation FILTER @auth_resource_paths_unrestricted == true OR e.auth_resource_path IN @auth_resource_paths FILTER ( @mode == "builder" && (@node_type == null || e.to_type == @node_type) @@ -18,12 +19,14 @@ FOR e IN fhir_edge @mode != "builder" && (@from_type == null || e.from_type == @from_type) ) COLLECT + dataset_generation = e.dataset_generation, from_type = (@mode == "builder" ? @node_type : e.from_type), label = e.label, to_type = (@mode == "builder" ? e.from_type : e.to_type) WITH COUNT INTO edge_count SORT from_type, edge_count DESC, label, to_type RETURN { + dataset_generation, from_type, label, to_type, @@ -45,6 +48,7 @@ func DiscoverPopulatedReferences(ctx context.Context, opts PopulatedReferenceOpt emit("go_discovery_start", map[string]any{ "database": opts.Database, "project": opts.Project, + "dataset_generation": DatasetGenerationBindValue(opts.DatasetGeneration), "from_type": opts.FromType, "node_type": opts.NodeType, "mode": opts.Mode, @@ -58,29 +62,15 @@ func DiscoverPopulatedReferences(ctx context.Context, opts PopulatedReferenceOpt mode = TraversalModeStorage } - bindVars := map[string]any{ - "project": opts.Project, - "auth_resource_paths": cloneStrings(opts.AuthResourcePaths), - "auth_resource_paths_unrestricted": len(opts.AuthResourcePaths) == 0, - "mode": mode, - } - if opts.FromType != "" { - bindVars["from_type"] = opts.FromType - } else { - bindVars["from_type"] = nil - } - if opts.NodeType != "" { - bindVars["node_type"] = opts.NodeType - } else { - bindVars["node_type"] = nil - } + bindVars := populatedReferencesBindVars(opts, mode) results := make([]PopulatedReference, 0, 64) err = client.QueryRows(ctx, populatedReferencesAQL, opts.CursorBatch, bindVars, func(row map[string]any) error { ref := PopulatedReference{ - FromType: stringValue(row["from_type"]), - Label: stringValue(row["label"]), - ToType: stringValue(row["to_type"]), + DatasetGeneration: stringValue(row["dataset_generation"]), + FromType: stringValue(row["from_type"]), + Label: stringValue(row["label"]), + ToType: stringValue(row["to_type"]), } count, err := int64Value(row["edge_count"]) if err != nil { @@ -97,6 +87,7 @@ func DiscoverPopulatedReferences(ctx context.Context, opts PopulatedReferenceOpt emit("go_discovery_complete", map[string]any{ "database": opts.Database, "project": opts.Project, + "dataset_generation": DatasetGenerationBindValue(opts.DatasetGeneration), "from_type": opts.FromType, "node_type": opts.NodeType, "mode": mode, @@ -106,3 +97,24 @@ func DiscoverPopulatedReferences(ctx context.Context, opts PopulatedReferenceOpt }) return results, nil } + +func populatedReferencesBindVars(opts PopulatedReferenceOptions, mode string) map[string]any { + bindVars := map[string]any{ + "project": opts.Project, + "dataset_generation": DatasetGenerationBindValue(opts.DatasetGeneration), + "auth_resource_paths": cloneStrings(opts.AuthResourcePaths), + "auth_resource_paths_unrestricted": EffectiveAuthResourcePathsUnrestricted(opts.AuthResourcePaths, opts.AuthResourcePathsUnrestricted), + "mode": mode, + } + if opts.FromType != "" { + bindVars["from_type"] = opts.FromType + } else { + bindVars["from_type"] = nil + } + if opts.NodeType != "" { + bindVars["node_type"] = opts.NodeType + } else { + bindVars["node_type"] = nil + } + return bindVars +} diff --git a/internal/catalog/types.go b/internal/catalog/types.go index 4878263..83956bb 100644 --- a/internal/catalog/types.go +++ b/internal/catalog/types.go @@ -26,8 +26,13 @@ const ( // Write-side catalog records persisted during load. type FieldCatalogDocument struct { - Key string `json:"_key"` - Project string `json:"project"` + Key string `json:"_key"` + Project string `json:"project"` + // DatasetGeneration identifies the immutable dataset generation that + // produced this catalog row. An omitted value is intentionally the legacy + // dataset namespace; readers always bind either this exact value or null so + // legacy and generation-qualified observations never mix. + DatasetGeneration string `json:"dataset_generation,omitempty"` AuthResourcePath string `json:"auth_resource_path,omitempty"` ResourceType string `json:"resource_type"` Path string `json:"path"` @@ -47,15 +52,25 @@ type FieldCatalogDocument struct { // Read-side field discovery request and response types. type PopulatedFieldOptions struct { arangostore.ConnectionOptions - Project string - AuthResourcePaths []string - ResourceType string - PivotOnly bool - CursorBatch int + Project string + // DatasetGeneration is optional. An empty value means the legacy dataset + // namespace and therefore reads only catalog documents whose + // dataset_generation is null or absent. + DatasetGeneration string + // AuthResourcePathsUnrestricted is the effective AQL bypass mode. A nil + // value preserves the legacy convention that an empty path list is + // unrestricted; request services must set it explicitly after resolving + // authorization so a restricted-empty intersection remains restricted. + AuthResourcePathsUnrestricted *bool + AuthResourcePaths []string + ResourceType string + PivotOnly bool + CursorBatch int } type PopulatedField struct { Project string `json:"project"` + DatasetGeneration string `json:"dataset_generation,omitempty"` AuthResourcePath string `json:"auth_resource_path,omitempty"` ResourceType string `json:"resource_type"` Path string `json:"path"` @@ -75,35 +90,44 @@ type PopulatedField struct { // Read-side auth path discovery request type. type AuthResourcePathOptions struct { arangostore.ConnectionOptions - Project string - CursorBatch int + Project string + DatasetGeneration string + CursorBatch int } // Read-side reference discovery request and response types. type PopulatedReferenceOptions struct { arangostore.ConnectionOptions - Project string - AuthResourcePaths []string - FromType string - NodeType string - Mode string - CursorBatch int + Project string + // DatasetGeneration follows the same legacy-null contract as + // PopulatedFieldOptions. + DatasetGeneration string + // AuthResourcePathsUnrestricted has the same explicit-mode contract as + // PopulatedFieldOptions. + AuthResourcePathsUnrestricted *bool + AuthResourcePaths []string + FromType string + NodeType string + Mode string + CursorBatch int } type PopulatedReference struct { - FromType string `json:"from_type"` - Label string `json:"label"` - ToType string `json:"to_type"` - EdgeCount int64 `json:"edge_count"` + DatasetGeneration string `json:"dataset_generation,omitempty"` + FromType string `json:"from_type"` + Label string `json:"label"` + ToType string `json:"to_type"` + EdgeCount int64 `json:"edge_count"` } // Write-side field profiling state. type Profiler struct { - project string - authResourcePath string - resourceType string - shapeCache *ShapePlanCache - stats map[string]*fieldCatalogStats + project string + datasetGeneration string + authResourcePath string + resourceType string + shapeCache *ShapePlanCache + stats map[string]*fieldCatalogStats } type fieldCatalogStats struct { diff --git a/internal/catalog/write_profiler.go b/internal/catalog/write_profiler.go index bc2fbab..e1e99bf 100644 --- a/internal/catalog/write_profiler.go +++ b/internal/catalog/write_profiler.go @@ -1,6 +1,8 @@ package catalog import ( + "errors" + "fmt" "slices" "sort" "strings" @@ -13,13 +15,24 @@ func NewShapePlanCache() *ShapePlanCache { return &ShapePlanCache{plans: make(map[string]*shapePlan)} } +// NewProfiler constructs a profiler in the legacy catalog namespace. Keep +// this constructor for existing ingest callers: an empty generation produces +// the exact same catalog documents and keys as before generation support. func NewProfiler(project, authResourcePath, resourceType string, cache *ShapePlanCache) *Profiler { + return NewProfilerForGeneration(project, "", authResourcePath, resourceType, cache) +} + +// NewProfilerForGeneration constructs a profiler whose catalog documents are +// bound to one immutable dataset generation. A blank (or whitespace-only) +// generation intentionally selects the legacy namespace for compatibility. +func NewProfilerForGeneration(project, datasetGeneration, authResourcePath, resourceType string, cache *ShapePlanCache) *Profiler { return &Profiler{ - project: project, - authResourcePath: authResourcePath, - resourceType: resourceType, - shapeCache: cache, - stats: make(map[string]*fieldCatalogStats), + project: project, + datasetGeneration: NormalizeDatasetGeneration(datasetGeneration), + authResourcePath: authResourcePath, + resourceType: resourceType, + shapeCache: cache, + stats: make(map[string]*fieldCatalogStats), } } @@ -65,7 +78,55 @@ func (p *Profiler) ObservePayload(payload map[string]any, timings map[string]flo timings["field_profile"] += time.Since(observeStart).Seconds() } -func (p *Profiler) Merge(other *Profiler) { +// ErrProfilerIdentityMismatch reports an attempted merge between independently +// scoped catalog profilers. Combining those stats would let one project, +// generation, authorization path, or resource type claim observations from +// another scope. +var ErrProfilerIdentityMismatch = errors.New("catalog profiler identity mismatch") + +type profilerIdentity struct { + project string + datasetGeneration string + authResourcePath string + resourceType string +} + +func (p *Profiler) normalizedIdentity() profilerIdentity { + return profilerIdentity{ + project: p.project, + datasetGeneration: NormalizeDatasetGeneration(p.datasetGeneration), + authResourcePath: p.authResourcePath, + resourceType: p.resourceType, + } +} + +// Merge aggregates worker-local observations only when both profilers describe +// the same persisted catalog namespace. It validates every identity component +// before changing any statistics so a rejected merge is observationally a +// no-op for the destination profiler. +func (p *Profiler) Merge(other *Profiler) error { + if p == nil || other == nil { + return fmt.Errorf("%w: nil profiler", ErrProfilerIdentityMismatch) + } + identity := p.normalizedIdentity() + otherIdentity := other.normalizedIdentity() + if identity != otherIdentity { + return fmt.Errorf( + "%w: destination project=%q generation=%q auth_resource_path=%q resource_type=%q; source project=%q generation=%q auth_resource_path=%q resource_type=%q", + ErrProfilerIdentityMismatch, + identity.project, + identity.datasetGeneration, + identity.authResourcePath, + identity.resourceType, + otherIdentity.project, + otherIdentity.datasetGeneration, + otherIdentity.authResourcePath, + otherIdentity.resourceType, + ) + } + if p.stats == nil { + p.stats = make(map[string]*fieldCatalogStats) + } for path, otherStat := range other.stats { stat, ok := p.stats[path] if !ok { @@ -92,6 +153,7 @@ func (p *Profiler) Merge(other *Profiler) { stat.addPivotColumn(value) } } + return nil } func (p *Profiler) Documents() []FieldCatalogDocument { @@ -101,6 +163,7 @@ func (p *Profiler) Documents() []FieldCatalogDocument { paths = append(paths, path) } sort.Strings(paths) + datasetGeneration := NormalizeDatasetGeneration(p.datasetGeneration) for _, path := range paths { stat := p.stats[path] distinctValues := append([]string(nil), stat.distinctValues...) @@ -108,8 +171,9 @@ func (p *Profiler) Documents() []FieldCatalogDocument { slices.Sort(distinctValues) slices.Sort(pivotColumns) out = append(out, FieldCatalogDocument{ - Key: fieldCatalogKey(p.project, p.authResourcePath, p.resourceType, stat.path), + Key: fieldCatalogKeyForGeneration(p.project, datasetGeneration, p.authResourcePath, p.resourceType, stat.path), Project: p.project, + DatasetGeneration: datasetGeneration, AuthResourcePath: p.authResourcePath, ResourceType: p.resourceType, Path: stat.path, diff --git a/internal/catalog/write_profiler_test.go b/internal/catalog/write_profiler_test.go index d57ac99..7c2e38f 100644 --- a/internal/catalog/write_profiler_test.go +++ b/internal/catalog/write_profiler_test.go @@ -1,7 +1,11 @@ package catalog import ( + "encoding/json" + "errors" + "reflect" "slices" + "strings" "testing" "github.com/calypr/loom/internal/fhirschema" @@ -182,3 +186,151 @@ func TestFieldCatalogObservationPivotMetadata(t *testing.T) { t.Fatalf("unexpected value selector: %q", found.PivotValueSelect) } } + +func TestGenerationProfilerSeparatesCatalogDocumentsAndKeys(t *testing.T) { + cache := NewShapePlanCache() + payload := map[string]any{"id": "patient-1"} + timings := map[string]float64{} + + legacy := NewProfiler("P1", "scopeA", "Patient", cache) + generationA := NewProfilerForGeneration("P1", " generation/a ", "scopeA", "Patient", cache) + generationB := NewProfilerForGeneration("P1", "generation a", "scopeA", "Patient", cache) + canonicalGenerationA := NewProfilerForGeneration("P1", "generation/a", "scopeA", "Patient", cache) + for _, profiler := range []*Profiler{legacy, generationA, generationB, canonicalGenerationA} { + profiler.ObservePayload(payload, timings) + } + + legacyDocument := catalogDocumentForPath(t, legacy.Documents(), "id") + generationADocument := catalogDocumentForPath(t, generationA.Documents(), "id") + generationBDocument := catalogDocumentForPath(t, generationB.Documents(), "id") + canonicalGenerationADocument := catalogDocumentForPath(t, canonicalGenerationA.Documents(), "id") + + if got, want := legacyDocument.Key, fieldCatalogKey("P1", "scopeA", "Patient", "id"); got != want { + t.Fatalf("legacy catalog key = %q, want established layout %q", got, want) + } + if legacyDocument.DatasetGeneration != "" { + t.Fatalf("legacy document generation = %q, want empty legacy namespace", legacyDocument.DatasetGeneration) + } + if got, want := generationADocument.DatasetGeneration, "generation/a"; got != want { + t.Fatalf("generation document generation = %q, want normalized %q", got, want) + } + if got, want := generationADocument.Key, canonicalGenerationADocument.Key; got != want { + t.Fatalf("equivalent normalized generation produced different keys: %q != %q", got, want) + } + for _, key := range []string{generationADocument.Key, generationBDocument.Key} { + if !strings.HasPrefix(key, generationFieldCatalogKeyPrefix) { + t.Fatalf("generation catalog key %q does not use digest namespace %q", key, generationFieldCatalogKeyPrefix) + } + if got, want := len(key), len(generationFieldCatalogKeyPrefix)+64; got != want { + t.Fatalf("generation catalog key length = %d, want SHA-256 key length %d", got, want) + } + } + if generationADocument.Key == legacyDocument.Key || generationBDocument.Key == legacyDocument.Key || generationADocument.Key == generationBDocument.Key { + t.Fatalf("catalog keys must isolate legacy and each generation: legacy=%q generationA=%q generationB=%q", legacyDocument.Key, generationADocument.Key, generationBDocument.Key) + } + + // These generation values collide under sanitizeCollectionKey, which is why + // a direct sanitized suffix would not be a safe immutable namespace. + if got, want := sanitizeCollectionKey("generation/a"), sanitizeCollectionKey("generation a"); got != want { + t.Fatalf("test setup expected sanitized generation collision: %q != %q", got, want) + } + if generationADocument.Key == generationBDocument.Key { + t.Fatalf("digest keys collided for distinct generation identities") + } +} + +func TestLegacyProfilerConstructorAndKeyCompatibility(t *testing.T) { + cache := NewShapePlanCache() + payload := map[string]any{ + "id": "patient-1", + "active": true, + } + timings := map[string]float64{} + + legacy := NewProfiler(" Project One ", "scope A", "Patient", cache) + emptyGeneration := NewProfilerForGeneration(" Project One ", " \t ", "scope A", "Patient", cache) + legacy.ObservePayload(payload, timings) + emptyGeneration.ObservePayload(payload, timings) + + legacyDocuments := legacy.Documents() + emptyGenerationDocuments := emptyGeneration.Documents() + if !reflect.DeepEqual(legacyDocuments, emptyGenerationDocuments) { + t.Fatalf("legacy and empty-generation documents differ:\nlegacy=%+v\nempty=%+v", legacyDocuments, emptyGenerationDocuments) + } + for _, document := range legacyDocuments { + if got, want := document.Key, fieldCatalogKey(" Project One ", "scope A", "Patient", document.Path); got != want { + t.Fatalf("legacy key for %q = %q, want established layout %q", document.Path, got, want) + } + encoded, err := json.Marshal(document) + if err != nil { + t.Fatalf("marshal legacy document: %v", err) + } + if strings.Contains(string(encoded), `"dataset_generation"`) { + t.Fatalf("legacy document JSON unexpectedly changed namespace: %s", encoded) + } + } + if got, want := fieldCatalogKeyForGeneration("P1", " ", "scopeA", "Patient", "id"), fieldCatalogKey("P1", "scopeA", "Patient", "id"); got != want { + t.Fatalf("blank generation key = %q, want exact legacy key %q", got, want) + } +} + +func TestProfilerMergeRejectsIdentityMismatchBeforeMutatingStats(t *testing.T) { + identity := func(project, generation, authResourcePath, resourceType string) *Profiler { + return NewProfilerForGeneration(project, generation, authResourcePath, resourceType, NewShapePlanCache()) + } + cases := []struct { + name string + source *Profiler + }{ + {name: "project", source: identity("P2", "generation-a", "scopeA", "Patient")}, + {name: "generation", source: identity("P1", "generation-b", "scopeA", "Patient")}, + {name: "auth resource path", source: identity("P1", "generation-a", "scopeB", "Patient")}, + {name: "resource type", source: identity("P1", "generation-a", "scopeA", "Observation")}, + } + + for _, test := range cases { + t.Run(test.name, func(t *testing.T) { + destination := identity("P1", " generation-a ", "scopeA", "Patient") + destination.ObservePayload(map[string]any{"id": "left"}, map[string]float64{}) + test.source.ObservePayload(map[string]any{"id": "right"}, map[string]float64{}) + before := destination.Documents() + + err := destination.Merge(test.source) + if !errors.Is(err, ErrProfilerIdentityMismatch) { + t.Fatalf("Merge() error = %v, want ErrProfilerIdentityMismatch", err) + } + if after := destination.Documents(); !reflect.DeepEqual(after, before) { + t.Fatalf("rejected Merge() mutated destination:\nbefore=%+v\nafter=%+v", before, after) + } + }) + } +} + +func TestProfilerMergeNormalizesGenerationBeforeComparisonAndPersistence(t *testing.T) { + left := NewProfilerForGeneration("P1", " generation-a ", "scopeA", "Patient", NewShapePlanCache()) + right := NewProfilerForGeneration("P1", "generation-a", "scopeA", "Patient", NewShapePlanCache()) + left.ObservePayload(map[string]any{"id": "left"}, map[string]float64{}) + right.ObservePayload(map[string]any{"id": "right"}, map[string]float64{}) + + if err := left.Merge(right); err != nil { + t.Fatalf("Merge() normalized-equivalent generations: %v", err) + } + document := catalogDocumentForPath(t, left.Documents(), "id") + if got, want := document.DatasetGeneration, "generation-a"; got != want { + t.Fatalf("persisted generation = %q, want normalized %q", got, want) + } + if got, want := document.DocCount, int64(2); got != want { + t.Fatalf("merged doc count = %d, want %d", got, want) + } +} + +func catalogDocumentForPath(t *testing.T, documents []FieldCatalogDocument, path string) FieldCatalogDocument { + t.Helper() + for _, document := range documents { + if document.Path == path { + return document + } + } + t.Fatalf("catalog document path %q not found in %+v", path, documents) + return FieldCatalogDocument{} +} diff --git a/internal/dataframe/active_generation.go b/internal/dataframe/active_generation.go new file mode 100644 index 0000000..9b002ff --- /dev/null +++ b/internal/dataframe/active_generation.go @@ -0,0 +1,37 @@ +package dataframe + +import ( + "context" + "errors" + "fmt" + + "github.com/calypr/loom/internal/dataset" +) + +var ( + // ErrActiveGenerationConflict reports a caller-supplied generation that is + // not the one selected by the configured active-manifest resolver. Failing + // closed here prevents a catalog/compiled-query split across generations. + ErrActiveGenerationConflict = errors.New("requested dataset generation conflicts with active generation") +) + +// resolveActiveBuilder pins one execution request to the configured active +// READY manifest before any catalog or compiler work starts. Without a +// resolver the historical direct-Builder contract is unchanged: the builder's +// generation (or legacy null namespace) is used as supplied. +func (s *Service) resolveActiveBuilder(ctx context.Context, builder Builder) (Builder, error) { + if s == nil || s.activeManifestResolver == nil { + return builder, nil + } + manifest, err := dataset.ResolveReadyActiveManifest(ctx, s.activeManifestResolver, builder.Project) + if err != nil { + return Builder{}, fmt.Errorf("resolve active dataset generation: %w", err) + } + requested := normalizeDatasetGeneration(builder.DatasetGeneration) + active := manifest.Dataset.Generation + if requested != "" && requested != active { + return Builder{}, fmt.Errorf("%w: project %q requested %q but active is %q", ErrActiveGenerationConflict, builder.Project, requested, active) + } + builder.DatasetGeneration = active + return builder, nil +} diff --git a/internal/dataframe/active_generation_test.go b/internal/dataframe/active_generation_test.go new file mode 100644 index 0000000..ab751f8 --- /dev/null +++ b/internal/dataframe/active_generation_test.go @@ -0,0 +1,221 @@ +package dataframe + +import ( + "context" + "errors" + "strings" + "testing" + + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/dataset" +) + +type dataframeActiveManifestResolver struct { + manifest dataset.Manifest + err error + projects []string +} + +func (r *dataframeActiveManifestResolver) ResolveActiveManifest(_ context.Context, project string) (dataset.Manifest, error) { + r.projects = append(r.projects, project) + if r.err != nil { + return dataset.Manifest{}, r.err + } + return r.manifest.Clone(), nil +} + +type dataframeActiveResourceAccess struct{} + +func (dataframeActiveResourceAccess) GetAllowedResources(context.Context, string, string, string) ([]string, error) { + return []string{"/programs/example/projects/allowed"}, nil +} + +func dataframeReadyManifest(t *testing.T, project, generation string) dataset.Manifest { + t.Helper() + schema, err := dataset.NewSchemaIdentitySnapshot( + "urn:loom:dataframe-active-test", + "", + strings.Repeat("a", 64), + []string{"Patient", "Specimen"}, + ) + if err != nil { + t.Fatalf("NewSchemaIdentitySnapshot() error = %v", err) + } + ref, err := dataset.NewDatasetRef(project, generation) + if err != nil { + t.Fatalf("NewDatasetRef() error = %v", err) + } + manifest, err := dataset.NewManifest(ref, schema) + if err != nil { + t.Fatalf("NewManifest() error = %v", err) + } + for _, state := range []dataset.ManifestState{ + dataset.ManifestStateLoading, + dataset.ManifestStateAnalyzing, + dataset.ManifestStateReady, + } { + manifest, err = manifest.Transition(state) + if err != nil { + t.Fatalf("Transition(%s) error = %v", state, err) + } + } + return manifest +} + +func TestServiceActiveManifestPinsScopeCatalogAndCompilerGeneration(t *testing.T) { + const project = "P1" + const generation = "generation-a" + active := &dataframeActiveManifestResolver{manifest: dataframeReadyManifest(t, project, generation)} + var existingCalls []catalog.AuthResourcePathOptions + var fieldCalls []catalog.PopulatedFieldOptions + var referenceCalls []catalog.PopulatedReferenceOptions + + scopeResolver := authscope.NewScopeResolver(authscope.ScopeResolverConfig{ + ResourceAccess: dataframeActiveResourceAccess{}, + ListExistingAuthResourcePaths: func(_ context.Context, options catalog.AuthResourcePathOptions) ([]string, error) { + existingCalls = append(existingCalls, options) + return []string{"example-allowed"}, nil + }, + }) + svc := NewService(ServiceConfig{ + ActiveManifestResolver: active, + ScopeResolver: scopeResolver, + DiscoverFields: func(_ context.Context, options catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + fieldCalls = append(fieldCalls, options) + if options.PivotOnly { + return []catalog.PopulatedField{}, nil + } + switch options.ResourceType { + case "Patient": + return []catalog.PopulatedField{{Project: project, ResourceType: "Patient", Path: "gender", Kind: "scalar"}}, nil + case "Specimen": + return []catalog.PopulatedField{{Project: project, ResourceType: "Specimen", Path: "id", Kind: "scalar"}}, nil + default: + return []catalog.PopulatedField{}, nil + } + }, + DiscoverReferences: func(_ context.Context, options catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + referenceCalls = append(referenceCalls, options) + return []catalog.PopulatedReference{{FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 1}}, nil + }, + ExecuteRows: func(_ context.Context, _ ExecuteQueryOptions, query string, binds map[string]any, visit func(map[string]any) error) error { + if got := binds[datasetGenerationBindKey]; got != generation { + t.Fatalf("compiled dataset generation bind = %#v, want %q", got, generation) + } + if !strings.Contains(query, "root.dataset_generation == @dataset_generation") { + t.Fatalf("compiled query omitted generation scope:\n%s", query) + } + return visit(map[string]any{"_key": "patient-1", "gender": "female"}) + }, + }) + + ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{ + AuthorizationHeader: "Bearer header.payload.signature", + }) + result, err := svc.Run(ctx, RunRequest{Builder: Builder{ + Project: project, + RootResourceType: "Patient", + Fields: []FieldSelect{{Name: "gender", Select: "gender"}}, + Traversals: []TraversalStep{{ + Label: "subject_Patient", + ToResourceType: "Specimen", + Alias: "specimen", + Fields: []FieldSelect{{Name: "id", Select: "id"}}, + }}, + }, Limit: 1}) + if err != nil { + t.Fatalf("Run() error = %v", err) + } + if result.RowCount != 1 { + t.Fatalf("row count = %d, want 1", result.RowCount) + } + if len(active.projects) != 1 || active.projects[0] != project { + t.Fatalf("active resolver projects = %#v, want %q", active.projects, project) + } + if len(existingCalls) != 1 || existingCalls[0].Project != project || existingCalls[0].DatasetGeneration != generation { + t.Fatalf("scope existing-path calls = %#v, want %s/%s", existingCalls, project, generation) + } + for index, options := range fieldCalls { + if options.Project != project || options.DatasetGeneration != generation { + t.Fatalf("field catalog call %d = %+v, want %s/%s", index, options, project, generation) + } + } + for index, options := range referenceCalls { + if options.Project != project || options.DatasetGeneration != generation { + t.Fatalf("reference catalog call %d = %+v, want %s/%s", index, options, project, generation) + } + } +} + +func TestServiceActiveManifestKeepsRestrictedEmptyScopeWithinGeneration(t *testing.T) { + const project = "P1" + const generation = "generation-a" + scopeResolver := authscope.NewScopeResolver(authscope.ScopeResolverConfig{ + ResourceAccess: dataframeActiveResourceAccess{}, + ListExistingAuthResourcePaths: func(_ context.Context, options catalog.AuthResourcePathOptions) ([]string, error) { + if options.DatasetGeneration != generation { + t.Fatalf("scope generation = %q, want %q", options.DatasetGeneration, generation) + } + return []string{"example-unrelated"}, nil + }, + }) + assertRestricted := func(options catalog.PopulatedFieldOptions) { + if options.DatasetGeneration != generation { + t.Fatalf("field generation = %q, want %q", options.DatasetGeneration, generation) + } + if options.AuthResourcePathsUnrestricted == nil || *options.AuthResourcePathsUnrestricted || len(options.AuthResourcePaths) != 0 { + t.Fatalf("field restricted-empty options = %+v", options) + } + } + svc := NewService(ServiceConfig{ + ActiveManifestResolver: &dataframeActiveManifestResolver{manifest: dataframeReadyManifest(t, project, generation)}, + ScopeResolver: scopeResolver, + DiscoverFields: func(_ context.Context, options catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + assertRestricted(options) + return []catalog.PopulatedField{}, nil + }, + DiscoverReferences: func(_ context.Context, options catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + if options.DatasetGeneration != generation || options.AuthResourcePathsUnrestricted == nil || *options.AuthResourcePathsUnrestricted || len(options.AuthResourcePaths) != 0 { + t.Fatalf("reference restricted-empty options = %+v", options) + } + return []catalog.PopulatedReference{}, nil + }, + ExecuteRows: func(_ context.Context, _ ExecuteQueryOptions, _ string, binds map[string]any, _ func(map[string]any) error) error { + if got := binds[datasetGenerationBindKey]; got != generation { + t.Fatalf("compiled generation bind = %#v, want %q", got, generation) + } + if got, ok := binds["auth_resource_paths_unrestricted"].(bool); !ok || got { + t.Fatalf("compiled unrestricted bind = %#v, want false", binds["auth_resource_paths_unrestricted"]) + } + return nil + }, + }) + ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{AuthorizationHeader: "Bearer header.payload.signature"}) + if _, err := svc.Run(ctx, RunRequest{Builder: Builder{Project: project, RootResourceType: "Patient"}}); err != nil { + t.Fatalf("Run() error = %v", err) + } +} + +func TestServiceRejectsBuilderGenerationThatConflictsWithActiveManifest(t *testing.T) { + catalogCalled := false + svc := NewService(ServiceConfig{ + ActiveManifestResolver: &dataframeActiveManifestResolver{manifest: dataframeReadyManifest(t, "P1", "generation-a")}, + DiscoverFields: func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + catalogCalled = true + return nil, nil + }, + }) + + _, err := svc.Run(context.Background(), RunRequest{Builder: Builder{ + Project: "P1", + DatasetGeneration: "generation-b", + RootResourceType: "Patient", + }}) + if !errors.Is(err, ErrActiveGenerationConflict) { + t.Fatalf("Run() error = %v, want ErrActiveGenerationConflict", err) + } + if catalogCalled { + t.Fatal("catalog work occurred after active-generation conflict") + } +} diff --git a/internal/dataframe/aggregate_compile_test.go b/internal/dataframe/aggregate_compile_test.go new file mode 100644 index 0000000..a224508 --- /dev/null +++ b/internal/dataframe/aggregate_compile_test.go @@ -0,0 +1,53 @@ +package dataframe + +import ( + "strings" + "testing" +) + +func TestGenericExistsAggregateWithoutPredicateTestsSetNonEmptiness(t *testing.T) { + compiled, err := CompileRequest(Builder{ + Project: "P1", RootResourceType: "Specimen", + Traversals: []TraversalStep{{ + Label: "subject_Specimen", ToResourceType: "DocumentReference", Alias: "file", + Aggregates: []AggregateSelect{{Name: "has_file", Operation: "EXISTS"}}, + }}, + }, 1) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(compiled.Query, `"file__has_file": LENGTH(generic_file_set) > 0`) { + t.Fatalf("EXISTS aggregate did not compile as set non-emptiness:\n%s", compiled.Query) + } +} + +func TestSemanticPlanRejectsAggregateWithoutRequiredInput(t *testing.T) { + _, err := BuildSemanticPlan(Builder{ + Project: "P1", RootResourceType: "Specimen", + Aggregates: []AggregateSelect{{Name: "distinct", Operation: "COUNT_DISTINCT"}}, + }) + // COUNT_DISTINCT is accepted by the current public shape but requires an + // input before lowering; assert it never reaches a silent zero-value plan. + if err == nil { + t.Fatal("COUNT_DISTINCT without a selector unexpectedly reached semantic plan") + } +} + +func TestGenericMinAndMaxAggregatesLowerToTypedReductions(t *testing.T) { + compiled, err := CompileRequest(Builder{ + Project: "P1", RootResourceType: "Specimen", + Traversals: []TraversalStep{{ + Label: "subject_Specimen", ToResourceType: "DocumentReference", Alias: "file", + Aggregates: []AggregateSelect{ + {Name: "min_size", Operation: "MIN", Select: "content[].attachment.size"}, + {Name: "max_size", Operation: "MAX", Select: "content[].attachment.size"}, + }, + }}, + }, 1) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(compiled.Query, `"file__min_size": MIN(FLATTEN(`) || !strings.Contains(compiled.Query, `"file__max_size": MAX(FLATTEN(`) { + t.Fatalf("MIN/MAX did not compile through typed aggregate reductions:\n%s", compiled.Query) + } +} diff --git a/internal/dataframe/auth.go b/internal/dataframe/auth.go index 7d8655e..f3c791c 100644 --- a/internal/dataframe/auth.go +++ b/internal/dataframe/auth.go @@ -7,18 +7,31 @@ import ( "github.com/calypr/loom/internal/authscope" ) -func (s *Service) resolveAuthResourcePaths(ctx context.Context, principal *authscope.Principal, project string, requested []string) ([]string, error) { +// resolveReadScope returns both the effective paths and whether an empty path +// set may bypass scope checks. Callers must retain the mode through catalog +// discovery and compilation; returning paths alone is not safe for a +// restricted caller whose permitted dataset has no matching paths. +// resolveReadScopeForGeneration keeps authorization-path discovery aligned +// with the exact generation selected for catalog and dataframe reads. The +// empty generation retains the legacy null-generation behavior. +func (s *Service) resolveReadScopeForGeneration(ctx context.Context, principal *authscope.Principal, project, datasetGeneration string, requested []string) (authscope.ReadScope, error) { if s.scopeResolver != nil { - return s.scopeResolver.ResolveReadAuthResourcePaths(ctx, principal, project, requested) + return s.scopeResolver.ResolveReadScopeForGeneration(ctx, principal, project, datasetGeneration, requested) } if len(requested) == 0 { if principal == nil || len(principal.AuthResourcePaths) == 0 { - return nil, nil + return authscope.ReadScope{Mode: authscope.ReadScopeUnrestricted}, nil } - return append([]string(nil), principal.AuthResourcePaths...), nil + return authscope.ReadScope{ + AuthResourcePaths: append([]string(nil), principal.AuthResourcePaths...), + Mode: authscope.ReadScopeRestricted, + }, nil } if principal == nil || len(principal.AuthResourcePaths) == 0 { - return append([]string(nil), requested...), nil + return authscope.ReadScope{ + AuthResourcePaths: append([]string(nil), requested...), + Mode: authscope.ReadScopeRestricted, + }, nil } for _, path := range requested { found := false @@ -29,10 +42,13 @@ func (s *Service) resolveAuthResourcePaths(ctx context.Context, principal *auths } } if !found { - return nil, fmt.Errorf("authResourcePath %q is outside caller scope", path) + return authscope.ReadScope{}, fmt.Errorf("authResourcePath %q is outside caller scope", path) } } - return append([]string(nil), requested...), nil + return authscope.ReadScope{ + AuthResourcePaths: append([]string(nil), requested...), + Mode: authscope.ReadScopeRestricted, + }, nil } func authorizeProject(principal *authscope.Principal, project string, ignorePrincipalProjects bool) error { diff --git a/internal/dataframe/auth_scope.go b/internal/dataframe/auth_scope.go new file mode 100644 index 0000000..49bfc7b --- /dev/null +++ b/internal/dataframe/auth_scope.go @@ -0,0 +1,28 @@ +package dataframe + +import "github.com/calypr/loom/internal/authscope" + +// effectiveAuthScopeUnrestricted preserves the legacy direct-Builder contract +// while making resolved request scopes authoritative. In particular, a +// resolver-provided restricted empty path set returns false. +func effectiveAuthScopeUnrestricted(paths []string, mode authscope.ReadScopeMode) bool { + switch mode { + case authscope.ReadScopeUnrestricted: + return true + case authscope.ReadScopeRestricted: + return false + case "": + return len(paths) == 0 + default: + // An invalid internal mode must fail closed rather than bypass scope. + return false + } +} + +func builderAuthScopeUnrestricted(builder Builder) bool { + return effectiveAuthScopeUnrestricted(builder.AuthResourcePaths, builder.AuthScopeMode) +} + +func semanticAuthScopeUnrestricted(plan SemanticPlan) bool { + return effectiveAuthScopeUnrestricted(plan.AuthResourcePaths, plan.AuthScopeMode) +} diff --git a/internal/dataframe/auth_scope_test.go b/internal/dataframe/auth_scope_test.go new file mode 100644 index 0000000..83c91d4 --- /dev/null +++ b/internal/dataframe/auth_scope_test.go @@ -0,0 +1,110 @@ +package dataframe + +import ( + "context" + "strings" + "testing" + + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/catalog" +) + +type restrictedEmptyResourceAccess struct{} + +func (restrictedEmptyResourceAccess) GetAllowedResources(context.Context, string, string, string) ([]string, error) { + return []string{"/programs/example/projects/allowed"}, nil +} + +func restrictedEmptyScopeResolver() *authscope.ScopeResolver { + return authscope.NewScopeResolver(authscope.ScopeResolverConfig{ + ResourceAccess: restrictedEmptyResourceAccess{}, + ListExistingAuthResourcePaths: func(context.Context, catalog.AuthResourcePathOptions) ([]string, error) { + return []string{"example-different"}, nil + }, + }) +} + +func TestServiceRestrictedEmptyScopeStaysRestrictedInCatalogAndAQL(t *testing.T) { + catalogCalls := 0 + svc := NewService(ServiceConfig{ + ScopeResolver: restrictedEmptyScopeResolver(), + DiscoverReferences: func(_ context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + assertRestrictedEmptyReferenceOptions(t, opts) + return []catalog.PopulatedReference{}, nil + }, + DiscoverFields: func(_ context.Context, opts catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + catalogCalls++ + assertRestrictedEmptyFieldOptions(t, opts) + return []catalog.PopulatedField{}, nil + }, + ExecuteRows: func(_ context.Context, _ ExecuteQueryOptions, query string, bindVars map[string]any, _ func(map[string]any) error) error { + if got, ok := bindVars["auth_resource_paths_unrestricted"].(bool); !ok || got { + t.Fatalf("dataframe unrestricted bind = %#v, want false", bindVars["auth_resource_paths_unrestricted"]) + } + if !strings.Contains(query, "LET root_scope_allowed = @auth_resource_paths_unrestricted == true OR root.auth_resource_path IN @auth_resource_paths") || + !strings.Contains(query, "FILTER root_scope_allowed == @scope_allowed") { + t.Fatalf("dataframe query lost root auth scope:\n%s", query) + } + return nil + }, + }) + + ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{ + AuthorizationHeader: "Bearer header.payload.signature", + }) + result, err := svc.Run(ctx, RunRequest{Builder: Builder{ + Project: "P1", + RootResourceType: "Patient", + }}) + if err != nil { + t.Fatalf("Run() error = %v", err) + } + if result.RowCount != 0 { + t.Fatalf("result row count = %d, want no rows from the scoped executor", result.RowCount) + } + if catalogCalls == 0 { + t.Fatal("expected scope-aware catalog validation calls") + } +} + +func TestGenericPhysicalPlanRestrictedEmptyScopeBindsFalse(t *testing.T) { + plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, + Project: "P1", + AuthScopeMode: authscope.ReadScopeRestricted, + Root: SemanticNode{Alias: "root", ResourceType: "Patient"}, + }) + if err != nil { + t.Fatal(err) + } + if got, ok := plan.BindVars["auth_resource_paths_unrestricted"].(bool); !ok || got { + t.Fatalf("physical unrestricted bind = %#v, want false", plan.BindVars["auth_resource_paths_unrestricted"]) + } + rendered, err := RenderPhysicalPlan(plan) + if err != nil { + t.Fatal(err) + } + if got, ok := rendered.BindVars["auth_resource_paths_unrestricted"].(bool); !ok || got { + t.Fatalf("rendered physical unrestricted bind = %#v, want false", rendered.BindVars["auth_resource_paths_unrestricted"]) + } +} + +func assertRestrictedEmptyFieldOptions(t *testing.T, opts catalog.PopulatedFieldOptions) { + t.Helper() + if opts.AuthResourcePathsUnrestricted == nil || *opts.AuthResourcePathsUnrestricted { + t.Fatalf("field catalog scope mode = %#v, want explicit false", opts.AuthResourcePathsUnrestricted) + } + if len(opts.AuthResourcePaths) != 0 { + t.Fatalf("field catalog paths = %#v, want empty", opts.AuthResourcePaths) + } +} + +func assertRestrictedEmptyReferenceOptions(t *testing.T, opts catalog.PopulatedReferenceOptions) { + t.Helper() + if opts.AuthResourcePathsUnrestricted == nil || *opts.AuthResourcePathsUnrestricted { + t.Fatalf("reference catalog scope mode = %#v, want explicit false", opts.AuthResourcePathsUnrestricted) + } + if len(opts.AuthResourcePaths) != 0 { + t.Fatalf("reference catalog paths = %#v, want empty", opts.AuthResourcePaths) + } +} diff --git a/internal/dataframe/builder_types.go b/internal/dataframe/builder_types.go index 813060a..b29d204 100644 --- a/internal/dataframe/builder_types.go +++ b/internal/dataframe/builder_types.go @@ -1,11 +1,23 @@ package dataframe +import "github.com/calypr/loom/internal/authscope" + type Builder struct { - Project string - AuthResourcePaths []string + Project string + // DatasetGeneration is optional. An empty value deliberately targets only + // the legacy null generation namespace; it never means every generation. + DatasetGeneration string + AuthResourcePaths []string + // AuthScopeMode is set by a request-level authorization resolver. It is + // required to distinguish a restricted empty path set from an unrestricted + // one. The empty value preserves the legacy direct-Builder convention that + // no paths means unrestricted. + AuthScopeMode authscope.ReadScopeMode RootResourceType string + RowGrain RowGrain PlanHint *PlanHint Fields []FieldSelect + Filters []TypedFilter Pivots []PivotSelect Aggregates []AggregateSelect Slices []RepresentativeSlice @@ -13,16 +25,26 @@ type Builder struct { Sets []NamedSet DerivedFields []DerivedField RepresentativeSlices []RepresentativeSlice + // RequiredTraversalMatches is populated only by compiler lowering from + // TraversalStep.MatchMode. It keeps root-scoped relationship predicates + // separate from materialized traversal sets, so Compile can apply them + // before root SORT/LIMIT. + RequiredTraversalMatches []RequiredTraversalMatch } type TraversalStep struct { - Label string - ToResourceType string - Alias string - Fields []FieldSelect - Pivots []PivotSelect - Aggregates []AggregateSelect - Slices []RepresentativeSlice + Label string + ToResourceType string + Alias string + Fields []FieldSelect + Filters []TypedFilter + Pivots []PivotSelect + Aggregates []AggregateSelect + Slices []RepresentativeSlice + // MatchMode defaults to OPTIONAL. REQUIRED retains only root rows with a + // matching relationship route; it is lowered as a semi-join rather than a + // post-projection filter. + MatchMode TraversalMatchMode Traversals []TraversalStep Sets []NamedSet DerivedFields []DerivedField @@ -69,6 +91,15 @@ type Result struct { RowCount int } +// StreamResult describes rows delivered to a streaming caller. Columns are +// finalized only after iteration because flattened pivots can add bounded, +// data-dependent output keys. The streaming callback itself receives each +// flattened row as it is read from Arango. +type StreamResult struct { + Columns []string + RowCount int +} + func cloneStrings(in []string) []string { if in == nil { return nil diff --git a/internal/dataframe/compile.go b/internal/dataframe/compile.go index 9166f15..bc5c407 100644 --- a/internal/dataframe/compile.go +++ b/internal/dataframe/compile.go @@ -4,6 +4,7 @@ import "fmt" type CompiledQuery struct { Project string + DatasetGeneration string RootResourceType string AuthResourcePaths []string PlanMode string @@ -11,18 +12,65 @@ type CompiledQuery struct { NamedSetCount int FileSummaries bool StudyLookup bool - Query string - BindVars map[string]any - Columns []string - PivotFields []string - Limit int + OptimizationRules []string + // RowIdentity describes the stable resource identity behind each returned + // row. It is metadata for exporters and recipe consumers; the existing row + // object keeps its backwards-compatible _key column. + RowIdentity *RowIdentity + Query string + BindVars map[string]any + Columns []string + PivotFields []string + Limit int } func Compile(builder Builder, limit int) (CompiledQuery, error) { - if usesLoweredBuilder(builder) { - return compileLowered(builder, limit) + if !usesLoweredBuilder(builder) { + return CompiledQuery{}, fmt.Errorf("unsupported dataframe query shape: request was not lowered into the optimized lowered plan") } - return CompiledQuery{}, fmt.Errorf("unsupported dataframe query shape: request was not lowered into the optimized lowered plan") + // Compile is intentionally safe for callers that receive a pre-lowered + // builder (for example, persisted recipes or conformance fixtures). The + // renderer interpolates only a generated resource collection name; validate + // that boundary here rather than relying on a service caller to have done so. + if err := validateLoweredBuilder(builder); err != nil { + return CompiledQuery{}, err + } + return compileLowered(builder, limit) +} + +// CompileRequest is the public compiler entrypoint for a dataframe request. +// It preserves the validated semantic plan alongside the compatibility +// lowered Builder so generic navigation requests can execute through the typed +// physical renderer. Requests whose selections or shaping are not represented +// by the physical IR retain the established lowered renderer. +func CompileRequest(builder Builder, limit int) (CompiledQuery, error) { + semantic, err := BuildSemanticPlan(builder) + if err != nil { + return CompiledQuery{}, err + } + planned, err := lowerSemanticBuilder(builder, semantic) + if err != nil { + return CompiledQuery{}, err + } + return compileRequestPlans(semantic, planned, limit) +} + +// compileRequestPlans selects the typed execution path only when the semantic +// plan is wholly represented by the frozen generic navigation physical IR. +// The compatibility lowered renderer remains the explicit fallback for every +// richer request; it must never receive a partial physical plan that silently +// drops a user field, filter, pivot, aggregate, slice, or required match. +func compileRequestPlans(semantic SemanticPlan, planned Builder, limit int) (CompiledQuery, error) { + if !usesLoweredBuilder(planned) { + return CompiledQuery{}, fmt.Errorf("unsupported dataframe query shape: request was not lowered into the optimized lowered plan") + } + if err := validateLoweredBuilder(planned); err != nil { + return CompiledQuery{}, err + } + if planProfile(planned.PlanHint) == "generic_fhir_graph" && genericPhysicalPlanUnavailableReason(semantic.Root) == "" { + return compileGenericPhysicalExecution(semantic, planned, limit) + } + return Compile(planned, limit) } func planMode(hint *PlanHint) string { @@ -60,11 +108,26 @@ func planStudyLookup(hint *PlanHint) bool { return hint.StudyLookup } +func planRowIdentity(hint *PlanHint) *RowIdentity { + if hint == nil { + return nil + } + return cloneRowIdentity(hint.RowIdentity) +} + +func planAppliedRules(hint *PlanHint) []string { + if hint == nil || len(hint.AppliedRules) == 0 { + return nil + } + return append([]string(nil), hint.AppliedRules...) +} + type compiler struct { - builder Builder - bindVars map[string]any - columns []string - pivotFields []string - bindCount int - pivotExprs map[string]string + builder Builder + bindVars map[string]any + columns []string + pivotFields []string + bindCount int + pivotExprs map[string]string + genericSetRoutes map[string]storageRoute } diff --git a/internal/dataframe/compile_fields.go b/internal/dataframe/compile_fields.go index dca8fdd..cffbc3d 100644 --- a/internal/dataframe/compile_fields.go +++ b/internal/dataframe/compile_fields.go @@ -11,13 +11,16 @@ func (c *compiler) compileTraversal(parentVar string, parentIsArray bool, step T nodeVar := sanitizeColumnName(step.Alias) + "_nodes" var let string if parentIsArray { - let = fmt.Sprintf(" LET %s = UNIQUE(FLATTEN(FOR __parent IN %s FOR __node, __edge IN 1..1 INBOUND __parent fhir_edge FILTER __edge.project == @project FILTER @auth_resource_paths_unrestricted == true OR (__edge.auth_resource_path IN @auth_resource_paths AND __node.auth_resource_path IN @auth_resource_paths) FILTER __edge.label == @%s FILTER __node.resourceType == @%s RETURN [__node]))", nodeVar, parentVar, labelBind, toBind) + let = fmt.Sprintf(" LET %s = UNIQUE(FLATTEN(FOR __parent IN %s FOR __node, __edge IN 1..1 INBOUND __parent fhir_edge FILTER __edge.project == @project FILTER __node.project == @project FILTER __edge.%s == @%s FILTER __node.%s == @%s FILTER @auth_resource_paths_unrestricted == true OR (__edge.auth_resource_path IN @auth_resource_paths AND __node.auth_resource_path IN @auth_resource_paths) FILTER __edge.label == @%s FILTER __node.resourceType == @%s RETURN [__node]))", nodeVar, parentVar, datasetGenerationField, datasetGenerationBindKey, datasetGenerationField, datasetGenerationBindKey, labelBind, toBind) } else { - let = fmt.Sprintf(" LET %s = UNIQUE(FOR __node, __edge IN 1..1 INBOUND %s fhir_edge FILTER __edge.project == @project FILTER @auth_resource_paths_unrestricted == true OR (__edge.auth_resource_path IN @auth_resource_paths AND __node.auth_resource_path IN @auth_resource_paths) FILTER __edge.label == @%s FILTER __node.resourceType == @%s RETURN __node)", nodeVar, parentVar, labelBind, toBind) + let = fmt.Sprintf(" LET %s = UNIQUE(FOR __node, __edge IN 1..1 INBOUND %s fhir_edge FILTER __edge.project == @project FILTER __node.project == @project FILTER __edge.%s == @%s FILTER __node.%s == @%s FILTER @auth_resource_paths_unrestricted == true OR (__edge.auth_resource_path IN @auth_resource_paths AND __node.auth_resource_path IN @auth_resource_paths) FILTER __edge.label == @%s FILTER __node.resourceType == @%s RETURN __node)", nodeVar, parentVar, datasetGenerationField, datasetGenerationBindKey, datasetGenerationField, datasetGenerationBindKey, labelBind, toBind) } *lets = append(*lets, let) for _, field := range step.Fields { - sel, _ := ParseSelector(field.Select) + sel, err := ParseSelector(field.Select) + if err != nil { + return fmt.Errorf("traversal %q field %q selector: %w", step.Alias, field.Name, err) + } expr, err := c.compileTraversalFieldSelect(nodeVar, field, sel) if err != nil { return err @@ -27,8 +30,14 @@ func (c *compiler) compileTraversal(parentVar string, parentIsArray bool, step T c.columns = append(c.columns, colName) } for _, pivot := range step.Pivots { - keySel, _ := ParseSelector(pivot.ColumnSelect) - valueSel, _ := ParseSelector(pivot.ValueSelect) + keySel, err := ParseSelector(pivot.ColumnSelect) + if err != nil { + return fmt.Errorf("traversal %q pivot %q key selector: %w", step.Alias, pivot.Name, err) + } + valueSel, err := ParseSelector(pivot.ValueSelect) + if err != nil { + return fmt.Errorf("traversal %q pivot %q value selector: %w", step.Alias, pivot.Name, err) + } colName := sanitizeColumnName(step.Alias + "__" + pivot.Name) expr, err := c.compileTraversalPivot(nodeVar, keySel, valueSel, pivot.Columns) if err != nil { @@ -65,6 +74,14 @@ func (c *compiler) compileTraversal(parentVar string, parentIsArray bool, step T } func (c *compiler) compileRootFieldSelect(payloadVar string, field FieldSelect, sel Selector) (string, error) { + switch normalizeValueMode(field.ValueMode) { + case "ALL": + return c.compileSelectorArrayForSelects(payloadVar, append([]string{field.Select}, field.FallbackSelects...)), nil + case "DISTINCT": + return fmt.Sprintf("SORTED_UNIQUE(%s)", c.compileSelectorArrayForSelects(payloadVar, append([]string{field.Select}, field.FallbackSelects...))), nil + case "FIRST": + return c.compileFirstNonNullExpr(payloadVar, append([]string{field.Select}, field.FallbackSelects...)), nil + } if len(field.FallbackSelects) > 0 { return c.compileFirstNonNullExpr(payloadVar, append([]string{field.Select}, field.FallbackSelects...)), nil } @@ -79,6 +96,14 @@ func (c *compiler) compileRootField(payloadVar string, sel Selector) (string, er } func (c *compiler) compileTraversalFieldSelect(nodeVar string, field FieldSelect, sel Selector) (string, error) { + switch normalizeValueMode(field.ValueMode) { + case "FIRST": + tmp := DerivedField{Source: nodeVar, Operation: DerivedOpFirstNonNull, Select: field.Select, FallbackSelects: field.FallbackSelects} + return c.compileFirstNonNullField("", tmp, map[string]setMode{nodeVar: setModeNode}) + case "ALL": + tmp := DerivedField{Source: nodeVar, Operation: DerivedOpAll, Select: field.Select, FallbackSelects: field.FallbackSelects} + return c.compileAllField("", tmp, map[string]setMode{nodeVar: setModeNode}) + } if len(field.FallbackSelects) > 0 { tmp := DerivedField{ Source: nodeVar, @@ -91,7 +116,7 @@ func (c *compiler) compileTraversalFieldSelect(nodeVar string, field FieldSelect } func (c *compiler) compileTraversalField(nodeVar string, sel Selector) (string, error) { - return fmt.Sprintf("UNIQUE(FLATTEN(FOR __n IN %s RETURN %s))", nodeVar, compileSelectorArrayExpr("__n.payload", sel, c)), nil + return fmt.Sprintf("SORTED_UNIQUE(FLATTEN(FOR __n IN %s RETURN %s))", nodeVar, compileSelectorArrayExpr("__n.payload", sel, c)), nil } func (c *compiler) compileRootPivot(payloadVar string, keySel Selector, valueSel Selector, columns []string) (string, error) { @@ -177,7 +202,7 @@ func (c *compiler) compilePivotMapExpr(itemLoop string, payloadVar string, keySe RETURN { key: __key, values: __values } ) COLLECT __key = __pair.key INTO __group - LET __flat_values = UNIQUE(FLATTEN(__group[*].__pair.values)) + LET __flat_values = SORTED_UNIQUE(FLATTEN(__group[*].__pair.values)) FILTER LENGTH(__flat_values) > 0 RETURN { [__key]: FIRST(__flat_values) } )`, itemLoop, keyExpr, valueExpr, filterLine), nil diff --git a/internal/dataframe/compile_validation_test.go b/internal/dataframe/compile_validation_test.go new file mode 100644 index 0000000..f40fc43 --- /dev/null +++ b/internal/dataframe/compile_validation_test.go @@ -0,0 +1,75 @@ +package dataframe + +import ( + "strings" + "testing" +) + +func TestCompileRejectsMalformedSelectorsInManualLoweredBuilders(t *testing.T) { + _, err := Compile(Builder{ + Project: "P1", + RootResourceType: "Patient", + PlanHint: &PlanHint{Mode: "lowered", Profile: "test"}, + Fields: []FieldSelect{{Name: "bad", Select: "name[not-an-index]"}}, + }, 1) + if err == nil || !strings.Contains(err.Error(), "root field") { + t.Fatalf("expected malformed selector error, got %v", err) + } +} + +func TestCompileTraverseSetHonorsExplicitUniqueFlag(t *testing.T) { + compiled, err := Compile(Builder{ + Project: "P1", + RootResourceType: "Patient", + PlanHint: &PlanHint{Mode: "lowered", Profile: "test"}, + Sets: []NamedSet{{ + Name: "raw_children", Kind: SetKindTraverse, Label: "subject_Patient", ToResourceType: "Condition", Unique: false, + }}, + }, 1) + if err != nil { + t.Fatal(err) + } + if strings.Contains(compiled.Query, "LET raw_children = UNIQUE") { + t.Fatalf("unexpected deduplication for explicit non-unique set:\n%s", compiled.Query) + } +} + +func TestCompileRejectsUnknownOrUnsafeRootCollection(t *testing.T) { + _, err := Compile(Builder{ + Project: "P1", + RootResourceType: "Patient RETURN SLEEP(1)", + PlanHint: &PlanHint{Mode: "lowered", Profile: "test"}, + }, 1) + if err == nil || !strings.Contains(err.Error(), "not represented by the active generated FHIR schema") { + t.Fatalf("expected generated-schema root validation error, got %v", err) + } +} + +func TestCompileRejectsUnsafeInternalSortField(t *testing.T) { + _, err := Compile(Builder{ + Project: "P1", + RootResourceType: "Patient", + PlanHint: &PlanHint{Mode: "lowered", Profile: "test"}, + Sets: []NamedSet{{ + Name: "children", Kind: SetKindTraverse, Label: "subject_Patient", ToResourceType: "Condition", + SortField: "_key RETURN SLEEP(1)", + }}, + }, 1) + if err == nil || !strings.Contains(err.Error(), "unsafe sort field") { + t.Fatalf("expected sort-field validation error, got %v", err) + } +} + +func TestCompileRejectsRemovedRawAQLDerivedField(t *testing.T) { + _, err := Compile(Builder{ + Project: "P1", + RootResourceType: "Patient", + PlanHint: &PlanHint{Mode: "lowered", Profile: "test"}, + DerivedFields: []DerivedField{{ + Name: "unsafe", Operation: "RAW_EXPR", + }}, + }, 1) + if err == nil || !strings.Contains(err.Error(), "unsupported operation") { + t.Fatalf("expected removed raw AQL operation rejection, got %v", err) + } +} diff --git a/internal/dataframe/compiler_arango_integration_test.go b/internal/dataframe/compiler_arango_integration_test.go new file mode 100644 index 0000000..e0e3e41 --- /dev/null +++ b/internal/dataframe/compiler_arango_integration_test.go @@ -0,0 +1,323 @@ +package dataframe + +import ( + "context" + "fmt" + "os" + "reflect" + "sort" + "strings" + "testing" + + arangostore "github.com/calypr/loom/internal/store/arango" +) + +// TestGenericSpecimenPlanExplainsAndRunsAgainstArango is deliberately opt-in: +// it reads the locally loaded development FHIR database and never mutates it. +// Run with LOOM_COMPILER_ARANGO_INTEGRATION=1 after provisioning the documented +// local Arango/META fixture database. +func TestGenericSpecimenPlanExplainsAndRunsAgainstArango(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run compiler/Arango integration") + } + url := os.Getenv("LOOM_ARANGO_URL") + if url == "" { + url = "http://127.0.0.1:8529" + } + database := os.Getenv("LOOM_ARANGO_DATABASE") + if database == "" { + database = "fhir_proto" + } + project := os.Getenv("LOOM_ARANGO_PROJECT") + if project == "" { + project = "ARANGODB_PROTO" + } + + compiled, err := CompileRequest(Builder{ + Project: project, + RootResourceType: "Specimen", + Filters: []TypedFilter{{ + FieldRef: "Specimen.type_display", + Selector: "type.coding[].display", + FieldKind: FilterString, + Repeated: true, + Quantifier: QuantifierAny, + Operator: FilterExists, + }}, + Fields: []FieldSelect{ + {Name: "specimen_type", Select: "type.coding[].display"}, + }, + Traversals: []TraversalStep{{ + Label: "subject_Specimen", + ToResourceType: "DocumentReference", + Alias: "file", + Filters: []TypedFilter{{ + FieldRef: "DocumentReference.file_name", + Selector: "content[].attachment.title", + FieldKind: FilterString, + Repeated: true, + Quantifier: QuantifierAny, + Operator: FilterExists, + }}, + Aggregates: []AggregateSelect{{Name: "file_count", Operation: "COUNT"}}, + }}, + }, 5) + if err != nil { + t.Fatalf("CompileRequest() error = %v", err) + } + if compiled.PlanProfile != "generic_fhir_graph" { + t.Fatalf("plan profile = %q, want generic_fhir_graph", compiled.PlanProfile) + } + t.Logf("compiled generic AQL:\n%s", compiled.Query) + + opts := arangostore.ConnectionOptions{URL: url, Database: database} + explain, err := ExplainCompiledQuery(context.Background(), opts, compiled) + if err != nil { + t.Fatalf("ExplainCompiledQuery() error = %v", err) + } + if explain.Plan == nil { + t.Fatalf("explain returned no selected plan: %#v", explain) + } + if uses := arangostore.ExtractPlanIndexes(explain); len(uses) == 0 { + t.Fatalf("generic compiler plan used no reported indexes: %#v", explain.Plan) + } else { + t.Logf("EXPLAIN indexes: %#v", uses) + } + assessment := arangostore.AssessExplainResult(explain) + t.Logf("EXPLAIN assessment: plans=%#v fullCollectionScans=%#v optimizerRules=%#v warnings=%#v", assessment.Plans, assessment.FullCollectionScans, assessment.AppliedOptimizerRules, assessment.Warnings) + if !hasExplainIndex(assessment, "fhir_edge", []string{"_to"}) { + t.Fatalf("generic inbound traversal did not use fhir_edge's _to edge index: assessment=%#v", assessment) + } + + rows := 0 + err = ExecuteQueryRows(context.Background(), ExecuteQueryOptions{ + ConnectionOptions: opts, + BatchSize: 5, + }, compiled.Query, compiled.BindVars, func(map[string]any) error { + rows++ + return nil + }) + if err != nil { + t.Fatalf("ExecuteQueryRows() error = %v", err) + } + if rows == 0 { + t.Fatalf("generic Specimen plan returned no rows for project %q", project) + } +} + +// TestGenericRootPreviewUsesScopedSortIndexAgainstArango protects the index +// family that makes a generic, root-grain preview viable. The loader now +// provisions this index for every resource collection; Patient is used here +// because the checked-in META fixture already contains it. +func TestGenericRootPreviewUsesScopedSortIndexAgainstArango(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run compiler/Arango integration") + } + url, database, project := compilerArangoTarget() + compiled, err := CompileRequest(Builder{ + Project: project, + RootResourceType: "Patient", + }, 5) + if err != nil { + t.Fatalf("CompileRequest() error = %v", err) + } + if !strings.Contains(compiled.Query, "FOR root IN @@root_collection") { + t.Fatalf("root preview did not use the physical execution renderer:\n%s", compiled.Query) + } + explain, err := ExplainCompiledQuery(context.Background(), arangostore.ConnectionOptions{URL: url, Database: database}, compiled) + if err != nil { + t.Fatalf("ExplainCompiledQuery() error = %v", err) + } + assessment := arangostore.AssessExplainResult(explain) + if !hasExplainIndex(assessment, "Patient", []string{"project", "_key"}) { + t.Fatalf("root preview did not use the project/_key index; assessment=%#v", assessment) + } +} + +// TestGenericPhysicalExecutionHasLoweredResultParityAgainstArango compares +// the executable typed navigation renderer with the compatibility lowered +// renderer against one locally loaded fixture. Optional navigation must not +// change root membership or row shape, and both renderers must select the same +// stable root-key preview window. +func TestGenericPhysicalExecutionHasLoweredResultParityAgainstArango(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run compiler/Arango integration") + } + url, database, project := compilerArangoTarget() + builder := Builder{ + Project: project, + RootResourceType: "Patient", + Traversals: []TraversalStep{{ + Label: "subject_Patient", + ToResourceType: "Specimen", + Alias: "specimen", + }}, + } + physical, err := CompileRequest(builder, 25) + if err != nil { + t.Fatalf("CompileRequest() error = %v", err) + } + if !strings.Contains(physical.Query, "FOR root IN @@root_collection") || !strings.Contains(physical.Query, "LET __loom_physical_set_1") { + t.Fatalf("generic navigation did not execute through physical renderer:\n%s", physical.Query) + } + lowered, err := Lower(builder) + if err != nil { + t.Fatalf("Lower() error = %v", err) + } + legacy, err := Compile(lowered, 25) + if err != nil { + t.Fatalf("Compile(lowered) error = %v", err) + } + + opts := arangostore.ConnectionOptions{URL: url, Database: database} + physicalRows, err := executeCompiledRows(context.Background(), opts, physical) + if err != nil { + t.Fatalf("execute physical navigation: %v\nAQL:\n%s", err, physical.Query) + } + legacyRows, err := executeCompiledRows(context.Background(), opts, legacy) + if err != nil { + t.Fatalf("execute lowered navigation: %v\nAQL:\n%s", err, legacy.Query) + } + sortRowsByKey(physicalRows) + sortRowsByKey(legacyRows) + if difference := firstRowDifference(physicalRows, legacyRows); difference != "" { + t.Fatalf("physical/lowered navigation result mismatch: %s", difference) + } +} + +// TestRenderedGenericPhysicalNavigationExplainsAgainstArango verifies the +// typed navigation renderer against the real Arango parser without replacing +// the legacy dataframe renderer yet. It protects collection-bind handling, +// scoped inbound traversal syntax, and root-row-preserving LET subqueries. +// The navigation set is intentionally not projected yet, so Arango may prune +// it; this test verifies parseability and scoped-root index selection rather +// than requiring an unused traversal to execute. +func TestRenderedGenericPhysicalNavigationExplainsAgainstArango(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run compiler/Arango integration") + } + url, database, project := compilerArangoTarget() + physical, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, + Project: project, + Root: SemanticNode{ + Alias: "root", ResourceType: "Patient", + Children: []SemanticNode{{ + Alias: "specimen", ResourceType: "Specimen", EdgeLabel: "subject_Patient", + }}, + }, + }) + if err != nil { + t.Fatalf("BuildGenericPhysicalPlan() error = %v", err) + } + rendered, err := RenderPhysicalPlan(physical) + if err != nil { + t.Fatalf("RenderPhysicalPlan() error = %v", err) + } + explain, err := ExplainCompiledQuery(context.Background(), arangostore.ConnectionOptions{URL: url, Database: database}, CompiledQuery{ + Query: rendered.Query, + BindVars: rendered.BindVars, + }) + if err != nil { + t.Fatalf("Explain rendered physical navigation: %v\nAQL:\n%s", err, rendered.Query) + } + assessment := arangostore.AssessExplainResult(explain) + if len(assessment.FullCollectionScans) != 0 { + t.Fatalf("rendered physical navigation unexpectedly full-scanned a collection: assessment=%#v", assessment) + } + if !hasExplainIndex(assessment, "Patient", []string{"project", "_key"}) && !hasExplainIndex(assessment, "Patient", []string{"project", "auth_resource_path", "_key"}) { + t.Fatalf("rendered physical navigation did not use a scoped root index; assessment=%#v", assessment) + } +} + +func compilerArangoTarget() (url, database, project string) { + url = os.Getenv("LOOM_ARANGO_URL") + if url == "" { + url = "http://127.0.0.1:8529" + } + database = os.Getenv("LOOM_ARANGO_DATABASE") + if database == "" { + database = "fhir_proto" + } + project = os.Getenv("LOOM_ARANGO_PROJECT") + if project == "" { + project = "ARANGODB_PROTO" + } + return url, database, project +} + +func executeCompiledRows(ctx context.Context, opts arangostore.ConnectionOptions, compiled CompiledQuery) ([]map[string]any, error) { + rows := make([]map[string]any, 0) + err := ExecuteQueryRows(ctx, ExecuteQueryOptions{ConnectionOptions: opts, BatchSize: 25}, compiled.Query, compiled.BindVars, func(row map[string]any) error { + clone := make(map[string]any, len(row)) + for key, value := range row { + clone[key] = value + } + rows = append(rows, clone) + return nil + }) + return rows, err +} + +func sortRowsByKey(rows []map[string]any) { + sort.Slice(rows, func(i, j int) bool { + return fmt.Sprint(rows[i]["_key"]) < fmt.Sprint(rows[j]["_key"]) + }) +} + +func firstRowDifference(genericRows, specializedRows []map[string]any) string { + if len(genericRows) != len(specializedRows) { + return fmt.Sprintf("row count generic=%d specialized=%d", len(genericRows), len(specializedRows)) + } + for index := range genericRows { + generic := genericRows[index] + specialized := specializedRows[index] + if key := fmt.Sprint(generic["_key"]); key != fmt.Sprint(specialized["_key"]) { + return fmt.Sprintf("row %d key generic=%q specialized=%q", index, key, fmt.Sprint(specialized["_key"])) + } + keys := make([]string, 0, len(generic)+len(specialized)) + seen := map[string]bool{} + for key := range generic { + seen[key] = true + keys = append(keys, key) + } + for key := range specialized { + if !seen[key] { + keys = append(keys, key) + } + } + sort.Strings(keys) + for _, key := range keys { + if reflect.DeepEqual(generic[key], specialized[key]) { + continue + } + return fmt.Sprintf("row %q field %q generic=%s specialized=%s", fmt.Sprint(generic["_key"]), key, summarizeParityValue(generic[key]), summarizeParityValue(specialized[key])) + } + } + return "" +} + +func summarizeParityValue(value any) string { + rv := reflect.ValueOf(value) + if rv.IsValid() && (rv.Kind() == reflect.Array || rv.Kind() == reflect.Slice) { + limit := rv.Len() + if limit > 3 { + limit = 3 + } + prefix := make([]any, 0, limit) + for index := 0; index < limit; index++ { + prefix = append(prefix, rv.Index(index).Interface()) + } + return fmt.Sprintf("%T(len=%d, prefix=%#v)", value, rv.Len(), prefix) + } + return fmt.Sprintf("%#v", value) +} + +func hasExplainIndex(assessment arangostore.ExplainAssessment, collection string, fields []string) bool { + for _, index := range assessment.Indexes { + if index.Collection == collection && reflect.DeepEqual(index.Fields, fields) { + return true + } + } + return false +} diff --git a/internal/dataframe/compiler_explanation.go b/internal/dataframe/compiler_explanation.go new file mode 100644 index 0000000..87e8099 --- /dev/null +++ b/internal/dataframe/compiler_explanation.go @@ -0,0 +1,478 @@ +package dataframe + +import "strings" + +// CompilerExplanationVersion is incremented only when the public structure of +// CompilerExplanation changes incompatibly. +const CompilerExplanationVersion = 1 + +// CompilerExplanation is a pure, renderer-independent inspection result for a +// dataframe Builder. It captures the validated semantic request, normalized +// selection behavior, and safe metadata from the lowered and compiled plans. +// +// It deliberately does not expose a lowered Builder, rendered AQL, or bind +// variables. Those are renderer internals, and older lowered forms can contain +// raw expressions. The identifiers here are FHIR/schema semantics, stable +// compiler rule IDs, or compiler-generated physical-plan variables. +type CompilerExplanation struct { + Version int + SemanticPlan SemanticPlan + Selections []SelectionSemanticSpec + Lowered LoweredPlanMetadata + Compiled CompiledQueryMetadata + GenericPhysicalPlan GenericPhysicalPlanExplanation +} + +// LoweredPlanMetadata is the safe, stable portion of a lowered Builder. It +// intentionally omits named-set and derived-field internals so explain callers +// cannot couple to a renderer representation while that representation evolves. +type LoweredPlanMetadata struct { + PlanMode string + PlanProfile string + NamedSetCount int + FileSummaries bool + StudyLookup bool + RowIdentity *RowIdentity + OptimizationRules []string +} + +// CompiledQueryMetadata describes the public result shape of a successfully +// compiled request without exposing rendered AQL or bind values. +type CompiledQueryMetadata struct { + DatasetGeneration string + RootResourceType string + PlanMode string + PlanProfile string + NamedSetCount int + FileSummaries bool + StudyLookup bool + RowIdentity *RowIdentity + OptimizationRules []string + Columns []string + PivotFields []string + Limit int +} + +// GenericPhysicalPlanReason records why the current navigation-only generic +// physical-plan builder cannot faithfully represent a semantic request. +// Empty means the generic plan is available. +type GenericPhysicalPlanReason string + +const ( + GenericPhysicalPlanReasonSelections GenericPhysicalPlanReason = "SELECTIONS_NOT_SUPPORTED" + GenericPhysicalPlanReasonFilters GenericPhysicalPlanReason = "FILTERS_NOT_SUPPORTED" + GenericPhysicalPlanReasonShaping GenericPhysicalPlanReason = "SHAPING_NOT_SUPPORTED" + GenericPhysicalPlanReasonRelationshipMatch GenericPhysicalPlanReason = "RELATIONSHIP_MATCH_NOT_SUPPORTED" +) + +// GenericPhysicalPlanExplanation makes partial physical support explicit. A +// nil Plan always accompanies Available=false; callers must not infer a +// navigation plan that would silently omit fields, filters, or shaping. +type GenericPhysicalPlanExplanation struct { + Available bool + Reason GenericPhysicalPlanReason + Plan *PhysicalPlan +} + +// ExplainCompilerRequest validates, lowers, and compiles a Builder without +// performing dataset I/O. It returns an all-or-nothing inspection artifact: +// semantic, lowering, and compilation errors return the zero explanation. +// +// The generic physical-plan skeleton is intentionally optional. Requests that +// compile through the current renderer but include features the skeleton cannot +// yet represent still return successful compiled metadata with an explicit +// unavailable reason rather than a misleading partial PhysicalPlan. +func ExplainCompilerRequest(builder Builder, limit int) (CompilerExplanation, error) { + semantic, err := BuildSemanticPlan(builder) + if err != nil { + return CompilerExplanation{}, err + } + selections, err := NormalizeSelectionPlan(semantic) + if err != nil { + return CompilerExplanation{}, err + } + lowered, err := lowerSemanticBuilder(builder, semantic) + if err != nil { + return CompilerExplanation{}, err + } + compiled, err := compileRequestPlans(semantic, lowered, limit) + if err != nil { + return CompilerExplanation{}, err + } + physical, err := explainGenericPhysicalPlan(semantic, limit) + if err != nil { + return CompilerExplanation{}, err + } + + return CompilerExplanation{ + Version: CompilerExplanationVersion, + SemanticPlan: cloneCompilerSemanticPlan(semantic), + Selections: cloneCompilerSelectionSemantics(selections), + Lowered: loweredPlanMetadata(lowered), + Compiled: compiledQueryMetadata(compiled), + GenericPhysicalPlan: physical, + }, nil +} + +func loweredPlanMetadata(lowered Builder) LoweredPlanMetadata { + return LoweredPlanMetadata{ + PlanMode: planMode(lowered.PlanHint), + PlanProfile: planProfile(lowered.PlanHint), + NamedSetCount: planNamedSetCount(lowered.PlanHint), + FileSummaries: planFileSummaries(lowered.PlanHint), + StudyLookup: planStudyLookup(lowered.PlanHint), + RowIdentity: cloneRowIdentity(planRowIdentity(lowered.PlanHint)), + OptimizationRules: normalizeCompilerRules(planAppliedRules(lowered.PlanHint)), + } +} + +func compiledQueryMetadata(compiled CompiledQuery) CompiledQueryMetadata { + return CompiledQueryMetadata{ + DatasetGeneration: compiled.DatasetGeneration, + RootResourceType: compiled.RootResourceType, + PlanMode: compiled.PlanMode, + PlanProfile: compiled.PlanProfile, + NamedSetCount: compiled.NamedSetCount, + FileSummaries: compiled.FileSummaries, + StudyLookup: compiled.StudyLookup, + RowIdentity: cloneRowIdentity(compiled.RowIdentity), + OptimizationRules: normalizeCompilerRules(compiled.OptimizationRules), + Columns: cloneStrings(compiled.Columns), + PivotFields: cloneStrings(compiled.PivotFields), + Limit: compiled.Limit, + } +} + +func normalizeCompilerRules(rules []string) []string { + if len(rules) == 0 { + return nil + } + trimmed := make([]string, 0, len(rules)) + for _, rule := range rules { + if rule = strings.TrimSpace(rule); rule != "" { + trimmed = append(trimmed, rule) + } + } + if len(trimmed) == 0 { + return nil + } + return sortedUniqueStrings(trimmed) +} + +func explainGenericPhysicalPlan(semantic SemanticPlan, limit int) (GenericPhysicalPlanExplanation, error) { + if reason := genericPhysicalPlanUnavailableReason(semantic.Root); reason != "" { + return GenericPhysicalPlanExplanation{Reason: reason}, nil + } + plan, err := BuildGenericPhysicalPlan(semantic) + if err != nil { + return GenericPhysicalPlanExplanation{}, err + } + plan, err = withGenericPhysicalExecutionWindow(plan, limit) + if err != nil { + return GenericPhysicalPlanExplanation{}, err + } + planCopy := cloneCompilerPhysicalPlan(plan) + return GenericPhysicalPlanExplanation{Available: true, Plan: &planCopy}, nil +} + +func genericPhysicalPlanUnavailableReason(node SemanticNode) GenericPhysicalPlanReason { + if node.MatchMode.required() { + return GenericPhysicalPlanReasonRelationshipMatch + } + if len(node.Fields) != 0 { + return GenericPhysicalPlanReasonSelections + } + if len(node.Filters) != 0 { + return GenericPhysicalPlanReasonFilters + } + if len(node.Pivots) != 0 || len(node.Aggregates) != 0 || len(node.Slices) != 0 { + return GenericPhysicalPlanReasonShaping + } + for _, child := range node.Children { + if reason := genericPhysicalPlanUnavailableReason(child); reason != "" { + return reason + } + } + return "" +} + +func cloneCompilerSemanticPlan(plan SemanticPlan) SemanticPlan { + copy := plan + copy.AuthResourcePaths = cloneStrings(plan.AuthResourcePaths) + copy.RowIdentity = cloneRowIdentity(plan.RowIdentity) + copy.Root = cloneCompilerSemanticNode(plan.Root) + return copy +} + +func cloneCompilerSemanticNode(node SemanticNode) SemanticNode { + copy := node + copy.Fields = make([]SemanticField, len(node.Fields)) + for index, field := range node.Fields { + copy.Fields[index] = cloneCompilerSemanticField(field) + } + copy.Filters = cloneCompilerTypedFilters(node.Filters) + copy.Pivots = make([]SemanticPivot, len(node.Pivots)) + for index, pivot := range node.Pivots { + copy.Pivots[index] = cloneCompilerSemanticPivot(pivot) + } + copy.Aggregates = make([]SemanticAggregate, len(node.Aggregates)) + for index, aggregate := range node.Aggregates { + copy.Aggregates[index] = cloneCompilerSemanticAggregate(aggregate) + } + copy.Slices = make([]SemanticSlice, len(node.Slices)) + for index, slice := range node.Slices { + copy.Slices[index] = cloneCompilerSemanticSlice(slice) + } + copy.Children = make([]SemanticNode, len(node.Children)) + for index, child := range node.Children { + copy.Children[index] = cloneCompilerSemanticNode(child) + } + return copy +} + +func cloneCompilerSemanticField(field SemanticField) SemanticField { + copy := field + copy.Selector = cloneCompilerSelector(field.Selector) + copy.Fallbacks = make([]Selector, len(field.Fallbacks)) + for index, fallback := range field.Fallbacks { + copy.Fallbacks[index] = cloneCompilerSelector(fallback) + } + return copy +} + +func cloneCompilerSemanticPivot(pivot SemanticPivot) SemanticPivot { + copy := pivot + copy.ColumnSelector = cloneCompilerSelector(pivot.ColumnSelector) + copy.ValueSelector = cloneCompilerSelector(pivot.ValueSelector) + copy.Columns = cloneStrings(pivot.Columns) + return copy +} + +func cloneCompilerSemanticAggregate(aggregate SemanticAggregate) SemanticAggregate { + copy := aggregate + copy.Selector = cloneCompilerSelectorPointer(aggregate.Selector) + copy.Predicate = cloneCompilerSelectorPointer(aggregate.Predicate) + return copy +} + +func cloneCompilerSemanticSlice(slice SemanticSlice) SemanticSlice { + copy := slice + copy.Predicate = cloneCompilerSelectorPointer(slice.Predicate) + copy.Fields = make([]SemanticField, len(slice.Fields)) + for index, field := range slice.Fields { + copy.Fields[index] = cloneCompilerSemanticField(field) + } + return copy +} + +func cloneCompilerSelectionSemantics(in []SelectionSemanticSpec) []SelectionSemanticSpec { + if in == nil { + return nil + } + out := make([]SelectionSemanticSpec, len(in)) + for index, selection := range in { + copy := selection + copy.Selector = cloneCompilerSelector(selection.Selector) + copy.Fallbacks = make([]Selector, len(selection.Fallbacks)) + for fallbackIndex, fallback := range selection.Fallbacks { + copy.Fallbacks[fallbackIndex] = cloneCompilerSelector(fallback) + } + copy.RepeatedPaths = cloneStrings(selection.RepeatedPaths) + out[index] = copy + } + return out +} + +func cloneCompilerSelectorPointer(selector *Selector) *Selector { + if selector == nil { + return nil + } + copy := cloneCompilerSelector(*selector) + return © +} + +func cloneCompilerSelector(selector Selector) Selector { + copy := selector + copy.Steps = make([]SelectorStep, len(selector.Steps)) + for index, step := range selector.Steps { + stepCopy := step + if step.Index != nil { + indexCopy := *step.Index + stepCopy.Index = &indexCopy + } + copy.Steps[index] = stepCopy + } + if selector.Filter != nil { + filterCopy := *selector.Filter + copy.Filter = &filterCopy + } + return copy +} + +func cloneCompilerTypedFilters(filters []TypedFilter) []TypedFilter { + if filters == nil { + return nil + } + out := make([]TypedFilter, len(filters)) + for index, filter := range filters { + copy := filter + copy.Values = make([]FilterValue, len(filter.Values)) + for valueIndex, value := range filter.Values { + copy.Values[valueIndex] = cloneCompilerFilterValue(value) + } + out[index] = copy + } + return out +} + +func cloneCompilerFilterValue(value FilterValue) FilterValue { + copy := value + copy.String = cloneCompilerStringPointer(value.String) + if value.Code != nil { + codeCopy := *value.Code + copy.Code = &codeCopy + } + copy.Boolean = cloneCompilerBoolPointer(value.Boolean) + copy.Integer = cloneCompilerInt64Pointer(value.Integer) + copy.Decimal = cloneCompilerFloat64Pointer(value.Decimal) + copy.Date = cloneCompilerStringPointer(value.Date) + copy.DateTime = cloneCompilerStringPointer(value.DateTime) + return copy +} + +func cloneCompilerStringPointer(value *string) *string { + if value == nil { + return nil + } + copy := *value + return © +} + +func cloneCompilerBoolPointer(value *bool) *bool { + if value == nil { + return nil + } + copy := *value + return © +} + +func cloneCompilerInt64Pointer(value *int64) *int64 { + if value == nil { + return nil + } + copy := *value + return © +} + +func cloneCompilerFloat64Pointer(value *float64) *float64 { + if value == nil { + return nil + } + copy := *value + return © +} + +func cloneCompilerPhysicalPlan(plan PhysicalPlan) PhysicalPlan { + copy := plan + copy.BindVars = cloneCompilerBindVars(plan.BindVars) + copy.Operations = make([]PhysicalOperation, len(plan.Operations)) + for index, operation := range plan.Operations { + copy.Operations[index] = cloneCompilerPhysicalOperation(operation) + } + return copy +} + +func cloneCompilerBindVars(bindVars map[string]any) map[string]any { + if bindVars == nil { + return nil + } + copy := make(map[string]any, len(bindVars)) + for key, value := range bindVars { + copy[key] = cloneCompilerBindValue(value) + } + return copy +} + +func cloneCompilerBindValue(value any) any { + switch value := value.(type) { + case []string: + return cloneStrings(value) + case []any: + copy := make([]any, len(value)) + for index, item := range value { + copy[index] = cloneCompilerBindValue(item) + } + return copy + case map[string]any: + return cloneCompilerBindVars(value) + case map[string]string: + copy := make(map[string]string, len(value)) + for key, item := range value { + copy[key] = item + } + return copy + default: + return value + } +} + +func cloneCompilerPhysicalOperation(operation PhysicalOperation) PhysicalOperation { + copy := operation + if operation.RootScan != nil { + rootScanCopy := *operation.RootScan + copy.RootScan = &rootScanCopy + } + if operation.Traversal != nil { + traversalCopy := *operation.Traversal + copy.Traversal = &traversalCopy + } + if operation.Filter != nil { + filterCopy := *operation.Filter + filterCopy.Predicate = cloneCompilerPhysicalPredicate(operation.Filter.Predicate) + copy.Filter = &filterCopy + } + if operation.DerivedLet != nil { + derivedCopy := *operation.DerivedLet + derivedCopy.Inputs = make([]PhysicalValue, len(operation.DerivedLet.Inputs)) + for index, input := range operation.DerivedLet.Inputs { + derivedCopy.Inputs[index] = cloneCompilerPhysicalValue(input) + } + copy.DerivedLet = &derivedCopy + } + if operation.Sort != nil { + sortCopy := *operation.Sort + sortCopy.Value = cloneCompilerPhysicalValue(operation.Sort.Value) + copy.Sort = &sortCopy + } + if operation.Limit != nil { + limitCopy := *operation.Limit + copy.Limit = &limitCopy + } + if operation.Return != nil { + returnCopy := *operation.Return + returnCopy.Projections = make([]PhysicalProjection, len(operation.Return.Projections)) + for index, projection := range operation.Return.Projections { + projectionCopy := projection + projectionCopy.Value = cloneCompilerPhysicalValue(projection.Value) + returnCopy.Projections[index] = projectionCopy + } + copy.Return = &returnCopy + } + return copy +} + +func cloneCompilerPhysicalPredicate(predicate PhysicalPredicate) PhysicalPredicate { + copy := predicate + copy.Left = cloneCompilerPhysicalValue(predicate.Left) + if predicate.Right != nil { + rightCopy := cloneCompilerPhysicalValue(*predicate.Right) + copy.Right = &rightCopy + } + return copy +} + +func cloneCompilerPhysicalValue(value PhysicalValue) PhysicalValue { + copy := value + copy.Path = cloneStrings(value.Path) + return copy +} diff --git a/internal/dataframe/compiler_explanation_test.go b/internal/dataframe/compiler_explanation_test.go new file mode 100644 index 0000000..a89beed --- /dev/null +++ b/internal/dataframe/compiler_explanation_test.go @@ -0,0 +1,218 @@ +package dataframe + +import ( + "reflect" + "testing" +) + +func TestExplainCompilerRequestIncludesNavigationOnlyGenericPhysicalPlan(t *testing.T) { + explanation, err := ExplainCompilerRequest(Builder{ + Project: "P1", + AuthResourcePaths: []string{"/programs/p1"}, + RootResourceType: "Patient", + }, 25) + if err != nil { + t.Fatal(err) + } + if explanation.Version != CompilerExplanationVersion { + t.Fatalf("explanation version = %d", explanation.Version) + } + if explanation.SemanticPlan.RowIdentity == nil || explanation.SemanticPlan.RowIdentity.Grain != RowGrainPatient { + t.Fatalf("semantic row identity = %#v", explanation.SemanticPlan.RowIdentity) + } + if !explanation.GenericPhysicalPlan.Available || explanation.GenericPhysicalPlan.Reason != "" || explanation.GenericPhysicalPlan.Plan == nil { + t.Fatalf("generic physical plan availability = %#v", explanation.GenericPhysicalPlan) + } + if err := explanation.GenericPhysicalPlan.Plan.Validate(); err != nil { + t.Fatalf("explained generic physical plan does not validate: %v", err) + } + if got := explanation.GenericPhysicalPlan.Plan.BindVars["root_collection"]; got != "Patient" { + t.Fatalf("root collection = %#v", got) + } + operations := explanation.GenericPhysicalPlan.Plan.Operations + if len(operations) < 8 || operations[5].Kind != PhysicalSortOp || operations[6].Kind != PhysicalLimitOp || explanation.GenericPhysicalPlan.Plan.BindVars[genericPhysicalExecutionLimitBind] != 25 { + t.Fatalf("explained physical execution window = %#v / %#v", operations, explanation.GenericPhysicalPlan.Plan.BindVars) + } + if !reflect.DeepEqual(explanation.Compiled.Columns, []string{"_key"}) || explanation.Compiled.Limit != 25 { + t.Fatalf("compiled metadata = %#v", explanation.Compiled) + } +} + +func TestExplainCompilerRequestReportsSelectionPhysicalUnavailabilityAfterCompile(t *testing.T) { + explanation, err := ExplainCompilerRequest(Builder{ + Project: "P1", + RootResourceType: "Patient", + Fields: []FieldSelect{{ + Name: "gender", FieldRef: "Patient.gender", Select: "gender", + }}, + }, 5) + if err != nil { + t.Fatal(err) + } + if explanation.GenericPhysicalPlan.Available || explanation.GenericPhysicalPlan.Plan != nil { + t.Fatalf("selection request unexpectedly received generic physical plan: %#v", explanation.GenericPhysicalPlan) + } + if explanation.GenericPhysicalPlan.Reason != GenericPhysicalPlanReasonSelections { + t.Fatalf("physical reason = %q", explanation.GenericPhysicalPlan.Reason) + } + if !reflect.DeepEqual(explanation.Compiled.Columns, []string{"_key", "gender"}) { + t.Fatalf("compiled columns = %#v", explanation.Compiled.Columns) + } + if len(explanation.Selections) != 1 || explanation.Selections[0].Alias != "root.gender" || explanation.Selections[0].Projection != ProjectionScalar { + t.Fatalf("normalized selections = %#v", explanation.Selections) + } +} + +func TestExplainCompilerRequestCarriesFilterRowGrainAndOptimizerProvenance(t *testing.T) { + female := "female" + explanation, err := ExplainCompilerRequest(Builder{ + Project: "P1", + RootResourceType: "Patient", + RowGrain: RowGrainPatient, + Filters: []TypedFilter{{ + FieldRef: "Patient.gender", Selector: "gender", FieldKind: FilterString, Operator: FilterEquals, + Values: []FilterValue{{Kind: FilterString, String: &female}}, + }}, + }, 0) + if err != nil { + t.Fatal(err) + } + for _, identity := range []*RowIdentity{ + explanation.SemanticPlan.RowIdentity, + explanation.Lowered.RowIdentity, + explanation.Compiled.RowIdentity, + } { + if identity == nil || identity.Grain != RowGrainPatient || !reflect.DeepEqual(identity.Fields, []string{"project", "_key"}) { + t.Fatalf("row identity provenance = %#v", identity) + } + } + if explanation.Lowered.PlanProfile != "generic_fhir_graph" || explanation.Compiled.PlanProfile != "generic_fhir_graph" { + t.Fatalf("plan profile provenance = %#v / %#v", explanation.Lowered, explanation.Compiled) + } + if !reflect.DeepEqual(explanation.Lowered.OptimizationRules, []string{OptimizerRuleFilterPushdown}) || + !reflect.DeepEqual(explanation.Compiled.OptimizationRules, []string{OptimizerRuleFilterPushdown}) { + t.Fatalf("optimizer provenance = %#v / %#v", explanation.Lowered.OptimizationRules, explanation.Compiled.OptimizationRules) + } + if explanation.GenericPhysicalPlan.Available || explanation.GenericPhysicalPlan.Reason != GenericPhysicalPlanReasonFilters { + t.Fatalf("filter request physical availability = %#v", explanation.GenericPhysicalPlan) + } +} + +func TestExplainCompilerRequestReportsRequiredRelationshipPhysicalUnavailability(t *testing.T) { + explanation, err := ExplainCompilerRequest(Builder{ + Project: "P1", + RootResourceType: "Patient", + Traversals: []TraversalStep{{ + Label: "subject_Patient", ToResourceType: "Condition", Alias: "diagnosis", MatchMode: TraversalMatchRequired, + }}, + }, 5) + if err != nil { + t.Fatal(err) + } + if explanation.GenericPhysicalPlan.Available || explanation.GenericPhysicalPlan.Reason != GenericPhysicalPlanReasonRelationshipMatch || explanation.GenericPhysicalPlan.Plan != nil { + t.Fatalf("required relationship physical availability = %#v", explanation.GenericPhysicalPlan) + } + if !reflect.DeepEqual(explanation.Compiled.OptimizationRules, []string{OptimizerRuleRelationshipSemiJoin}) { + t.Fatalf("required relationship optimizer provenance = %#v", explanation.Compiled.OptimizationRules) + } +} + +func TestExplainCompilerRequestReturnsDeterministicDefensiveCopies(t *testing.T) { + female := "female" + builder := Builder{ + Project: "P1", + AuthResourcePaths: []string{"/programs/p1"}, + RootResourceType: "Patient", + Filters: []TypedFilter{{ + FieldRef: "Patient.gender", Selector: "gender", FieldKind: FilterString, Operator: FilterEquals, + Values: []FilterValue{{Kind: FilterString, String: &female}}, + }}, + Fields: []FieldSelect{ + {Name: "z_gender", FieldRef: "Patient.gender", Select: "gender"}, + {Name: "a_birth_date", FieldRef: "Patient.birth_date", Select: "birthDate"}, + }, + } + first, err := ExplainCompilerRequest(builder, 3) + if err != nil { + t.Fatal(err) + } + second, err := ExplainCompilerRequest(builder, 3) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(first, second) { + t.Fatalf("same request produced non-deterministic explanations:\nfirst=%#v\nsecond=%#v", first, second) + } + if got := []string{first.Selections[0].Alias, first.Selections[1].Alias}; !reflect.DeepEqual(got, []string{"root.a_birth_date", "root.z_gender"}) { + t.Fatalf("selection order = %#v", got) + } + + *first.SemanticPlan.Root.Filters[0].Values[0].String = "mutated" + first.SemanticPlan.AuthResourcePaths[0] = "mutated" + first.Selections[0].Selector.Steps[0].Field = "mutated" + first.Lowered.RowIdentity.Fields[0] = "mutated" + first.Compiled.Columns[0] = "mutated" + if *builder.Filters[0].Values[0].String != "female" || builder.AuthResourcePaths[0] != "/programs/p1" { + t.Fatalf("explanation mutation escaped into input builder: %#v", builder) + } + if second.SemanticPlan.Root.Fields[1].Selector.Steps[0].Field == "mutated" || + second.Compiled.Columns[0] != "_key" || + second.Lowered.RowIdentity.Fields[0] != "project" { + t.Fatalf("explanation mutation escaped into another result: %#v", second) + } + + rootOnly, err := ExplainCompilerRequest(Builder{Project: "P1", RootResourceType: "Patient", AuthResourcePaths: []string{"/programs/p1"}}, 1) + if err != nil { + t.Fatal(err) + } + rootOnly.GenericPhysicalPlan.Plan.BindVars["project"] = "mutated" + rootOnly.GenericPhysicalPlan.Plan.Operations[0].RootScan.Variable = "mutated" + freshRootOnly, err := ExplainCompilerRequest(Builder{Project: "P1", RootResourceType: "Patient", AuthResourcePaths: []string{"/programs/p1"}}, 1) + if err != nil { + t.Fatal(err) + } + if freshRootOnly.GenericPhysicalPlan.Plan.BindVars["project"] != "P1" || freshRootOnly.GenericPhysicalPlan.Plan.Operations[0].RootScan.Variable != "root" { + t.Fatalf("physical plan mutation escaped into a fresh result: %#v", freshRootOnly.GenericPhysicalPlan.Plan) + } +} + +func TestExplainCompilerRequestReturnsNoPartialResultOnInvalidInput(t *testing.T) { + tests := []struct { + name string + builder Builder + }{ + { + name: "semantic validation", + builder: Builder{ + Project: "P1", + RootResourceType: "Patient", + Fields: []FieldSelect{{Name: "bad", Select: "identifier[nope]"}}, + }, + }, + { + // Semantic aliases are valid FHIR graph identifiers, but these two + // distinct aliases collide in the current lowered AQL identifier + // scheme. This exercises the all-or-nothing lower/compile boundary. + name: "lowering validation", + builder: Builder{ + Project: "P1", + RootResourceType: "Specimen", + Traversals: []TraversalStep{ + {Label: "subject_Specimen", ToResourceType: "DocumentReference", Alias: "file-a"}, + {Label: "subject_Specimen", ToResourceType: "DocumentReference", Alias: "file_a"}, + }, + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + explanation, err := ExplainCompilerRequest(test.builder, 1) + if err == nil { + t.Fatal("invalid request unexpectedly explained") + } + if !reflect.DeepEqual(explanation, CompilerExplanation{}) { + t.Fatalf("invalid request returned partial explanation: %#v", explanation) + } + }) + } +} diff --git a/internal/dataframe/dataframe_test.go b/internal/dataframe/dataframe_test.go index e356dcd..01ca85c 100644 --- a/internal/dataframe/dataframe_test.go +++ b/internal/dataframe/dataframe_test.go @@ -35,7 +35,7 @@ func TestCompileRejectsNonLoweredBuilder(t *testing.T) { } } -func TestLowerGraphQLBuilderUsesStructuralLowering(t *testing.T) { +func TestLowerGraphQLBuilderUsesGenericCompilerForComplexPatientGraph(t *testing.T) { builder := Builder{ Project: "P1", RootResourceType: "Patient", @@ -65,12 +65,12 @@ func TestLowerGraphQLBuilderUsesStructuralLowering(t *testing.T) { } planned, err := lowerGraphQLBuilder(builder) if err != nil { - t.Fatalf("expected case-assay profile to match, got %v", err) + t.Fatalf("expected generic graph lowering, got %v", err) } if !usesLoweredBuilder(planned) { t.Fatal("expected planner to return lowered builder") } - if planned.PlanHint == nil || planned.PlanHint.Profile != "patient_case_assay_family" { + if planned.PlanHint == nil || planned.PlanHint.Profile != "generic_fhir_graph" { t.Fatalf("unexpected plan hint: %#v", planned.PlanHint) } if len(planned.DerivedFields) == 0 { @@ -79,14 +79,14 @@ func TestLowerGraphQLBuilderUsesStructuralLowering(t *testing.T) { if containsDerivedField(planned.DerivedFields, "recipe") { t.Fatalf("did not expect canned recipe field in lowered builder: %#v", planned.DerivedFields) } - for _, expectedSet := range []string{"root_patient_neighbor_set", "patient_condition_set", "patient_specimen_set", "specimen_group_set"} { + for _, expectedSet := range []string{"generic_root_subject_Patient_neighbors_set", "generic_condition_set", "generic_specimen_set", "generic_group_set"} { if !containsNamedSet(planned.Sets, expectedSet) { t.Fatalf("expected lowered set %q, got %#v", expectedSet, planned.Sets) } } } -func TestLowerGraphQLBuilderRejectsSimpleTraversal(t *testing.T) { +func TestLowerGraphQLBuilderUsesGenericPlanForSimpleTraversal(t *testing.T) { builder := Builder{ Project: "P1", RootResourceType: "Patient", @@ -94,13 +94,16 @@ func TestLowerGraphQLBuilderRejectsSimpleTraversal(t *testing.T) { {Label: "subject_Patient", ToResourceType: "Specimen", Alias: "specimen"}, }, } - _, err := lowerGraphQLBuilder(builder) - if err == nil || !strings.Contains(err.Error(), "unsupported dataframe query shape") { - t.Fatalf("expected unsupported lowering error, got %v", err) + planned, err := lowerGraphQLBuilder(builder) + if err != nil { + t.Fatalf("lowerGraphQLBuilder() error = %v", err) + } + if planned.PlanHint == nil || planned.PlanHint.Profile != "generic_fhir_graph" { + t.Fatalf("expected generic plan, got %#v", planned.PlanHint) } } -func TestLowerGraphQLBuilderMapsSingleDocumentReferenceSelectorToSummary(t *testing.T) { +func TestLowerGraphQLBuilderKeepsDocumentReferenceSelectorsInGenericFHIR(t *testing.T) { builder := Builder{ Project: "P1", RootResourceType: "Patient", @@ -124,13 +127,13 @@ func TestLowerGraphQLBuilderMapsSingleDocumentReferenceSelectorToSummary(t *test } planned, err := lowerGraphQLBuilder(builder) if err != nil { - t.Fatalf("expected supported structural lowering, got %v", err) + t.Fatalf("expected generic lowering, got %v", err) } - if !containsNamedSet(planned.Sets, "document_reference_summary_set") { - t.Fatalf("expected summary set, got %#v", planned.Sets) + if planned.PlanHint == nil || planned.PlanHint.Profile != "generic_fhir_graph" { + t.Fatalf("expected generic plan, got %#v", planned.PlanHint) } - if !containsDerivedFieldWithSelect(planned.DerivedFields, "specimen_file__data_category", "data_category") { - t.Fatalf("expected summary-backed derived field, got %#v", planned.DerivedFields) + if !containsDerivedFieldWithSelect(planned.DerivedFields, "specimen_file__data_category", `category[].coding[].display where system contains "data_category"`) { + t.Fatalf("expected raw FHIR selector, got %#v", planned.DerivedFields) } } @@ -158,11 +161,11 @@ func TestLowerGraphQLBuilderSupportsExpandedPatientRootFamily(t *testing.T) { t.Fatalf("expected expanded patient-root family to lower, got %v", err) } for _, expectedSet := range []string{ - "patient_subject_observation_set", - "patient_focus_observation_set", - "patient_imaging_study_set", - "patient_group_set", - "group_document_reference_set", + "generic_subject_observation_set", + "generic_focus_observation_set", + "generic_imaging_study_set", + "generic_patient_group_set", + "generic_group_file_set", } { if !containsNamedSet(planned.Sets, expectedSet) { t.Fatalf("expected lowered set %q, got %#v", expectedSet, planned.Sets) @@ -254,7 +257,7 @@ func TestLowerGraphQLBuilderPreservesUnrestrictedAuthScope(t *testing.T) { } } -func TestServiceRejectsUnsupportedSimpleQuery(t *testing.T) { +func TestServiceRunsGenericSimpleQuery(t *testing.T) { svc := NewService(ServiceConfig{ ConnectionOptions: arangostore.ConnectionOptions{}, DiscoverReferences: func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { @@ -277,7 +280,7 @@ func TestServiceRejectsUnsupportedSimpleQuery(t *testing.T) { Projects: []string{"P1"}, AuthResourcePaths: []string{"pathA"}, }) - _, err := svc.Run(ctx, RunRequest{ + result, err := svc.Run(ctx, RunRequest{ Builder: Builder{ Project: "P1", RootResourceType: "Patient", @@ -291,8 +294,11 @@ func TestServiceRejectsUnsupportedSimpleQuery(t *testing.T) { }}, }, }) - if err == nil || !strings.Contains(err.Error(), "unsupported dataframe query shape") { - t.Fatalf("expected unsupported lowering error, got %v", err) + if err != nil { + t.Fatalf("Run() error = %v", err) + } + if result.RowCount != 1 || !slices.Contains(result.Columns, "specimen__specimen_type") { + t.Fatalf("unexpected generic result: %#v", result) } } @@ -329,7 +335,7 @@ func TestServiceRunCaseAssayRecipe(t *testing.T) { }, nil }, ExecuteRows: func(ctx context.Context, opts ExecuteQueryOptions, query string, bindVars map[string]any, visit func(map[string]any) error) error { - if !strings.Contains(query, "LET root_patient_neighbor_set") || !strings.Contains(query, "LET patient_condition_set") || !strings.Contains(query, "LET specimen_group_set") { + if !strings.Contains(query, "LET generic_root_subject_Patient_neighbors_set") || !strings.Contains(query, "LET generic_condition_set") || !strings.Contains(query, "LET generic_group_set") { t.Fatalf("expected advanced planned query, got:\n%s", query) } if strings.Contains(query, `"recipe"`) { @@ -402,7 +408,7 @@ func containsDerivedFieldWithSelect(fields []DerivedField, wantName, wantSelect return false } -func TestServiceRejectsUnsupportedRootOnlyQuery(t *testing.T) { +func TestServiceRunsGenericRootOnlyQuery(t *testing.T) { svc := NewService(ServiceConfig{ ConnectionOptions: arangostore.ConnectionOptions{}, DiscoverReferences: func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { @@ -415,15 +421,18 @@ func TestServiceRejectsUnsupportedRootOnlyQuery(t *testing.T) { return visit(map[string]any{"_key": "p1", "gender": "female"}) }, }) - _, err := svc.Run(context.Background(), RunRequest{ + result, err := svc.Run(context.Background(), RunRequest{ Builder: Builder{ Project: "P1", RootResourceType: "Patient", Fields: []FieldSelect{{Name: "gender", Select: "gender"}}, }, }) - if err == nil || !strings.Contains(err.Error(), "unsupported dataframe query shape") { - t.Fatalf("expected unsupported lowering error, got %v", err) + if err != nil { + t.Fatalf("Run() error = %v", err) + } + if result.RowCount != 1 || !slices.Contains(result.Columns, "gender") { + t.Fatalf("unexpected generic result: %#v", result) } } @@ -445,55 +454,3 @@ func TestServiceRejectsUnauthorizedAuthPath(t *testing.T) { t.Fatal("expected auth path error") } } - -func TestLookupPlannerTraversalUsesSchemaDerivedMetadata(t *testing.T) { - cases := []struct { - fromType string - edgeLabel string - toType string - role traversalRole - }{ - {"Patient", "subject_Patient", "Condition", traversalRolePatientNeighborChild}, - {"Patient", "subject_Patient", "Specimen", traversalRolePatientNeighborChild}, - {"Patient", "focus_Patient", "Observation", traversalRolePatientDirectChild}, - {"Specimen", "subject_Specimen", "DocumentReference", traversalRoleSpecimenDocumentReference}, - {"Group", "subject_Group", "DocumentReference", traversalRoleGroupDocumentReference}, - } - for _, tc := range cases { - spec, ok := lookupPlannerTraversal(tc.fromType, tc.edgeLabel, tc.toType) - if !ok { - t.Fatalf("expected traversal %s %s %s", tc.fromType, tc.edgeLabel, tc.toType) - } - if spec.Role != tc.role { - t.Fatalf("unexpected role for %s %s %s: %q", tc.fromType, tc.edgeLabel, tc.toType, spec.Role) - } - if spec.Schema.FromType != tc.fromType || spec.Schema.EdgeLabel != tc.edgeLabel || spec.Schema.ToType != tc.toType { - t.Fatalf("unexpected schema spec: %#v", spec.Schema) - } - } -} - -func TestLookupPlannerTraversalRejectsUnsupportedTuple(t *testing.T) { - if _, ok := lookupPlannerTraversal("Patient", "subject_Patient", "Medication"); ok { - t.Fatal("expected unsupported tuple to miss") - } -} - -func TestDocumentReferenceSummaryFieldMapping(t *testing.T) { - got, ok := mapDocumentReferenceSelectorToSummaryField(`category[].coding[].display where system contains "workflow_type"`) - if !ok { - t.Fatal("expected workflow_type selector to map") - } - if got != "workflow_type" { - t.Fatalf("unexpected mapped field: %q", got) - } -} - -func TestRequiresResearchStudyHydration(t *testing.T) { - if requiresResearchStudyHydration("study.reference", "ResearchSubject.study_reference") { - t.Fatal("default generated study ref should not require hydration") - } - if !requiresResearchStudyHydration("study.display", "ResearchSubject.study_display") { - t.Fatal("study child selector should require hydration") - } -} diff --git a/internal/dataframe/dataset_generation.go b/internal/dataframe/dataset_generation.go new file mode 100644 index 0000000..d063304 --- /dev/null +++ b/internal/dataframe/dataset_generation.go @@ -0,0 +1,24 @@ +package dataframe + +import "strings" + +const ( + datasetGenerationBindKey = "dataset_generation" + datasetGenerationField = "dataset_generation" +) + +func normalizeDatasetGeneration(generation string) string { + return strings.TrimSpace(generation) +} + +// datasetGenerationBindValue makes the absent-generation case explicit for +// every AQL renderer. Binding nil and using equality yields +// `dataset_generation == null`, so legacy rows are isolated from all +// generation-qualified rows by default. +func datasetGenerationBindValue(generation string) any { + generation = normalizeDatasetGeneration(generation) + if generation == "" { + return nil + } + return generation +} diff --git a/internal/dataframe/dataset_generation_test.go b/internal/dataframe/dataset_generation_test.go new file mode 100644 index 0000000..150cc63 --- /dev/null +++ b/internal/dataframe/dataset_generation_test.go @@ -0,0 +1,216 @@ +package dataframe + +import ( + "context" + "strings" + "testing" + + "github.com/calypr/loom/internal/catalog" +) + +func TestDatasetGenerationCompilesRootTraversalAndRequiredMatch(t *testing.T) { + compiled, err := CompileRequest(Builder{ + Project: "P1", + DatasetGeneration: " generation-a ", + RootResourceType: "Patient", + Traversals: []TraversalStep{{ + Label: "subject_Patient", + ToResourceType: "Condition", + Alias: "diagnosis", + MatchMode: TraversalMatchRequired, + }}, + }, 5) + if err != nil { + t.Fatal(err) + } + if got := compiled.DatasetGeneration; got != "generation-a" { + t.Fatalf("compiled DatasetGeneration = %q, want normalized exact generation", got) + } + if got := compiled.BindVars[datasetGenerationBindKey]; got != "generation-a" { + t.Fatalf("compiled generation bind = %#v, want generation-a", got) + } + for _, want := range []string{ + "root.dataset_generation == @dataset_generation", + "__edge.dataset_generation == @dataset_generation", + "__node.dataset_generation == @dataset_generation", + "__match_edge_0_0.dataset_generation == @dataset_generation", + "__match_0_0.dataset_generation == @dataset_generation", + } { + if !strings.Contains(compiled.Query, want) { + t.Fatalf("compiled query is missing generation predicate %q:\n%s", want, compiled.Query) + } + } + + semantic, err := BuildSemanticPlan(Builder{Project: "P1", DatasetGeneration: " generation-a ", RootResourceType: "Patient"}) + if err != nil { + t.Fatal(err) + } + if got := semantic.DatasetGeneration; got != "generation-a" { + t.Fatalf("semantic DatasetGeneration = %q, want normalized exact generation", got) + } +} + +func TestDatasetGenerationAbsentCompilesLegacyNullNamespace(t *testing.T) { + compiled, err := CompileRequest(Builder{ + Project: "P1", + RootResourceType: "Specimen", + Traversals: []TraversalStep{{ + Label: "subject_Specimen", + ToResourceType: "DocumentReference", + Alias: "file", + }}, + }, 5) + if err != nil { + t.Fatal(err) + } + if got, present := compiled.BindVars[datasetGenerationBindKey]; !present || got != nil { + t.Fatalf("legacy compiled generation bind = %#v (present=%t), want explicit nil", got, present) + } + for _, want := range []string{ + "root.dataset_generation == @dataset_generation", + "edge_1.dataset_generation == @dataset_generation", + "node_1.dataset_generation == @dataset_generation", + } { + if !strings.Contains(compiled.Query, want) { + t.Fatalf("legacy query is missing null-generation predicate %q:\n%s", want, compiled.Query) + } + } +} + +func TestDatasetGenerationPhysicalPlanAndRendererFilterEveryGraphDocument(t *testing.T) { + semantic := SemanticPlan{ + Version: 1, + Project: "P1", + DatasetGeneration: "generation-a", + Root: SemanticNode{ + Alias: "root", ResourceType: "Patient", + Children: []SemanticNode{{ + Alias: "specimen", ResourceType: "Specimen", EdgeLabel: "subject_Patient", + }}, + }, + } + plan, err := BuildGenericPhysicalPlan(semantic) + if err != nil { + t.Fatal(err) + } + if got := plan.BindVars[datasetGenerationBindKey]; got != "generation-a" { + t.Fatalf("physical generation bind = %#v, want generation-a", got) + } + for _, variable := range []string{"root", "edge_1", "node_1"} { + if !hasDatasetGenerationFilter(plan, variable) { + t.Fatalf("physical plan is missing exact generation filter for %q: %#v", variable, plan.Operations) + } + } + if err := ValidateGenericPhysicalPlanScope(plan); err != nil { + t.Fatalf("generation-safe physical plan failed scope validation: %v", err) + } + + rendered, err := RenderPhysicalPlan(plan) + if err != nil { + t.Fatal(err) + } + if got := rendered.BindVars[datasetGenerationBindKey]; got != "generation-a" { + t.Fatalf("rendered generation bind = %#v, want generation-a", got) + } + for _, want := range []string{ + "FILTER root.dataset_generation == @dataset_generation", + "FILTER edge_1.dataset_generation == @dataset_generation", + "FILTER node_1.dataset_generation == @dataset_generation", + } { + if !strings.Contains(rendered.Query, want) { + t.Fatalf("rendered physical query missing %q:\n%s", want, rendered.Query) + } + } + + legacy := semantic + legacy.DatasetGeneration = "" + legacyPlan, err := BuildGenericPhysicalPlan(legacy) + if err != nil { + t.Fatal(err) + } + if got, present := legacyPlan.BindVars[datasetGenerationBindKey]; !present || got != nil { + t.Fatalf("legacy physical generation bind = %#v (present=%t), want explicit nil", got, present) + } +} + +func TestDatasetGenerationPhysicalScopeRejectsMissingTargetPredicate(t *testing.T) { + plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, + Project: "P1", + Root: SemanticNode{ + Alias: "root", ResourceType: "Patient", + Children: []SemanticNode{{Alias: "specimen", ResourceType: "Specimen", EdgeLabel: "subject_Patient"}}, + }, + }) + if err != nil { + t.Fatal(err) + } + for index, operation := range plan.Operations { + if operation.Kind == PhysicalFilterOp && isDatasetGenerationScopePredicate(operation.Filter.Predicate, "node_1") { + plan.Operations = append(plan.Operations[:index], plan.Operations[index+1:]...) + break + } + } + if err := ValidateGenericPhysicalPlanScope(plan); err == nil || !strings.Contains(err.Error(), "node_1.dataset_generation") { + t.Fatalf("missing target generation predicate error = %v", err) + } +} + +func TestServicePropagatesDatasetGenerationToEveryCatalogRead(t *testing.T) { + fieldOptions := make([]catalog.PopulatedFieldOptions, 0) + referenceOptions := make([]catalog.PopulatedReferenceOptions, 0) + service := NewService(ServiceConfig{ + DiscoverFields: func(_ context.Context, options catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + fieldOptions = append(fieldOptions, options) + return []catalog.PopulatedField{}, nil + }, + DiscoverReferences: func(_ context.Context, options catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + referenceOptions = append(referenceOptions, options) + return []catalog.PopulatedReference{{FromType: "Patient", Label: "subject_Patient", ToType: "Condition"}}, nil + }, + ExecuteRows: func(_ context.Context, _ ExecuteQueryOptions, query string, bindVars map[string]any, _ func(map[string]any) error) error { + if got := bindVars[datasetGenerationBindKey]; got != "generation-a" { + t.Fatalf("execution generation bind = %#v, want generation-a", got) + } + if !strings.Contains(query, "root.dataset_generation == @dataset_generation") { + t.Fatalf("execution query lost root generation predicate:\n%s", query) + } + return nil + }, + }) + _, err := service.Run(context.Background(), RunRequest{Builder: Builder{ + Project: "P1", + DatasetGeneration: " generation-a ", + RootResourceType: "Patient", + Traversals: []TraversalStep{{ + Label: "subject_Patient", + ToResourceType: "Condition", + Alias: "diagnosis", + }}, + }, Limit: 1}) + if err != nil { + t.Fatal(err) + } + if len(fieldOptions) == 0 || len(referenceOptions) == 0 { + t.Fatalf("catalog calls fields=%d references=%d, want both", len(fieldOptions), len(referenceOptions)) + } + for index, options := range fieldOptions { + if got := catalog.DatasetGenerationBindValue(options.DatasetGeneration); got != "generation-a" { + t.Fatalf("field catalog call %d generation bind = %#v, want generation-a", index, got) + } + } + for index, options := range referenceOptions { + if got := catalog.DatasetGenerationBindValue(options.DatasetGeneration); got != "generation-a" { + t.Fatalf("reference catalog call %d generation bind = %#v, want generation-a", index, got) + } + } +} + +func hasDatasetGenerationFilter(plan PhysicalPlan, variable string) bool { + for _, operation := range plan.Operations { + if operation.Kind == PhysicalFilterOp && isDatasetGenerationScopePredicate(operation.Filter.Predicate, variable) { + return true + } + } + return false +} diff --git a/internal/dataframe/document_reference_semantics.go b/internal/dataframe/document_reference_semantics.go deleted file mode 100644 index 3a1cedb..0000000 --- a/internal/dataframe/document_reference_semantics.go +++ /dev/null @@ -1,87 +0,0 @@ -package dataframe - -import ( - "strings" - - "github.com/calypr/loom/internal/fhirschema" -) - -type documentReferenceSummarySpec struct { - Selector fhirschema.FieldSelectorSpec - SummaryName string -} - -var documentReferenceSummarySpecs = []documentReferenceSummarySpec{ - {Selector: selector("identifier[]", whereContains("system", "file_id"), "value"), SummaryName: "file_id"}, - {Selector: selector("content[].attachment", nil, "title"), SummaryName: "file_name"}, - {Selector: selector("content[].attachment", nil, "url"), SummaryName: "file_url"}, - {Selector: selector("content[].attachment", nil, "size"), SummaryName: "file_size"}, - {Selector: selector("category[].coding[]", whereContains("system", "data_category"), "display"), SummaryName: "data_category"}, - {Selector: selector("category[].coding[]", whereContains("system", "data_type"), "display"), SummaryName: "data_type"}, - {Selector: selector("category[].coding[]", whereContains("system", "experimental_strategy"), "display"), SummaryName: "experimental_strategy"}, - {Selector: selector("category[].coding[]", whereContains("system", "workflow_type"), "display"), SummaryName: "workflow_type"}, - {Selector: selector("category[].coding[]", whereContains("system", "platform"), "display"), SummaryName: "platform"}, - {Selector: selector("category[].coding[]", whereContains("system", "access"), "display"), SummaryName: "access"}, - {Selector: selector("type.coding[]", nil, "display"), SummaryName: "data_format"}, -} - -func mapDocumentReferenceSelectorToSummaryField(selectorExpr string) (string, bool) { - parsed, err := fhirschema.ParseSelector(selectorExpr) - if err != nil { - return "", false - } - for _, spec := range documentReferenceSummarySpecs { - if fhirschema.CanonicalPath(spec.Selector) != parsed.CanonicalPath() { - continue - } - if !sameContainsPredicate(spec.Selector.Where, parsed.Filter) { - continue - } - return spec.SummaryName, true - } - return "", false -} - -func selectorNeedsDocumentReferenceSummary(selectorExpr string) bool { - _, ok := mapDocumentReferenceSelectorToSummaryField(selectorExpr) - return ok -} - -func requiresResearchStudyHydration(selectorExpr string, fieldRef string) bool { - if strings.TrimSpace(fieldRef) == "ResearchSubject.study_reference" { - return false - } - parsed, err := fhirschema.ParseSelector(selectorExpr) - if err != nil { - return false - } - return strings.HasPrefix(parsed.CanonicalPath(), "study.") -} - -func selector(sourcePath string, predicate *fhirschema.FieldPredicateSpec, valuePath string) fhirschema.FieldSelectorSpec { - return fhirschema.FieldSelectorSpec{ - SourcePath: strings.TrimSpace(sourcePath), - Where: predicate, - ValuePath: strings.TrimSpace(valuePath), - } -} - -func whereContains(path, value string) *fhirschema.FieldPredicateSpec { - return &fhirschema.FieldPredicateSpec{ - Path: path, - Op: fhirschema.PredicateContains, - Value: value, - } -} - -func sameContainsPredicate(expected *fhirschema.FieldPredicateSpec, actual *fhirschema.ContainsFilter) bool { - if expected == nil && actual == nil { - return true - } - if expected == nil || actual == nil { - return false - } - return strings.EqualFold(strings.TrimSpace(expected.Path), strings.TrimSpace(actual.Field)) && - strings.EqualFold(strings.TrimSpace(expected.Op), fhirschema.PredicateContains) && - strings.TrimSpace(expected.Value) == strings.TrimSpace(actual.Needle) -} diff --git a/internal/dataframe/execution.go b/internal/dataframe/execution.go index 720057f..88ceeb9 100644 --- a/internal/dataframe/execution.go +++ b/internal/dataframe/execution.go @@ -2,17 +2,53 @@ package dataframe import ( "context" + "fmt" + "sort" ) func (s *Service) runQuery(ctx context.Context, compiled CompiledQuery) (*Result, error) { rows := make([]map[string]any, 0, compiled.Limit) - rowCount := 0 + streamed, err := s.streamQuery(ctx, compiled, func(row map[string]any) error { + rows = append(rows, row) + return nil + }) + if err != nil { + return nil, err + } + return &Result{ + Columns: streamed.Columns, + Rows: rows, + RowCount: streamed.RowCount, + }, nil +} + +// Stream compiles the same catalog- and authorization-validated request used +// by Run, but delivers flattened rows as Arango yields them instead of +// retaining the complete dataframe in Loom memory. Each invocation receives a +// distinct top-level row map. +func (s *Service) Stream(ctx context.Context, req RunRequest, visit func(map[string]any) error) (StreamResult, error) { + if visit == nil { + return StreamResult{}, fmt.Errorf("row visitor is required") + } + compiled, err := s.compileRunRequest(ctx, req) + if err != nil { + return StreamResult{}, err + } + return s.streamQuery(ctx, compiled, visit) +} + +func (s *Service) streamQuery(ctx context.Context, compiled CompiledQuery, visit func(map[string]any) error) (StreamResult, error) { + if visit == nil { + return StreamResult{}, fmt.Errorf("row visitor is required") + } columns := materializedColumns(compiled.Columns, compiled.PivotFields) seenColumns := make(map[string]struct{}, len(columns)) for _, col := range columns { seenColumns[col] = struct{}{} } + extraColumns := map[string]struct{}{} + rowCount := 0 err := s.executeRows(ctx, ExecuteQueryOptions{ ConnectionOptions: s.connOpts, BatchSize: 1000, @@ -23,20 +59,28 @@ func (s *Service) runQuery(ctx context.Context, compiled CompiledQuery) (*Result continue } seenColumns[key] = struct{}{} - columns = append(columns, key) + extraColumns[key] = struct{}{} + } + if err := visit(flatRow); err != nil { + return err } - rows = append(rows, flatRow) rowCount++ return nil }) - if err != nil { - return nil, err + newColumns := make([]string, 0, len(extraColumns)) + for column := range extraColumns { + newColumns = append(newColumns, column) } - return &Result{ + sort.Strings(newColumns) + columns = append(columns, newColumns...) + result := StreamResult{ Columns: columns, - Rows: rows, RowCount: rowCount, - }, nil + } + if err != nil { + return result, err + } + return result, nil } func materializedColumns(columns []string, pivotFields []string) []string { @@ -68,7 +112,13 @@ func flattenPivotFields(row map[string]any, pivotFields []string) map[string]any continue } delete(row, field) - for key, item := range obj { + keys := make([]string, 0, len(obj)) + for key := range obj { + keys = append(keys, key) + } + sort.Strings(keys) + for _, key := range keys { + item := obj[key] row[sanitizeColumnName(field+"__"+key)] = item } } diff --git a/internal/dataframe/execution_test.go b/internal/dataframe/execution_test.go new file mode 100644 index 0000000..e42ae90 --- /dev/null +++ b/internal/dataframe/execution_test.go @@ -0,0 +1,131 @@ +package dataframe + +import ( + "context" + "reflect" + "testing" +) + +func TestFlattenPivotFieldsCreatesStableFlattenedKeys(t *testing.T) { + row := flattenPivotFields(map[string]any{ + "pivot": map[string]any{ + "zeta": "z", + "alpha": "a", + }, + "keep": "value", + }, []string{"pivot"}) + + if _, ok := row["pivot"]; ok { + t.Fatalf("pivot object was not removed: %#v", row) + } + want := map[string]any{ + "pivot__alpha": "a", + "pivot__zeta": "z", + "keep": "value", + } + if !reflect.DeepEqual(row, want) { + t.Fatalf("flattenPivotFields() = %#v, want %#v", row, want) + } +} + +func TestRunQueryAppendsDynamicColumnsInStableOrder(t *testing.T) { + svc := NewService(ServiceConfig{ + ExecuteRows: func(_ context.Context, _ ExecuteQueryOptions, _ string, _ map[string]any, visit func(map[string]any) error) error { + for _, row := range []map[string]any{ + {"_key": "first", "pivot": map[string]any{"zeta": "z", "alpha": "a"}}, + {"_key": "second", "pivot": map[string]any{"beta": "b"}}, + } { + if err := visit(row); err != nil { + return err + } + } + return nil + }, + }) + + result, err := svc.runQuery(context.Background(), CompiledQuery{ + Query: "RETURN []", + Columns: []string{"_key", "pivot"}, + PivotFields: []string{"pivot"}, + Limit: 2, + }) + if err != nil { + t.Fatalf("runQuery() error = %v", err) + } + wantColumns := []string{"_key", "pivot__alpha", "pivot__beta", "pivot__zeta"} + if !reflect.DeepEqual(result.Columns, wantColumns) { + t.Fatalf("Columns = %#v, want %#v", result.Columns, wantColumns) + } + if result.RowCount != 2 { + t.Fatalf("RowCount = %d, want 2", result.RowCount) + } +} + +func TestStreamQueryDeliversFlattenedRowsWithoutCollectingResultRows(t *testing.T) { + svc := NewService(ServiceConfig{ + ExecuteRows: func(_ context.Context, _ ExecuteQueryOptions, _ string, _ map[string]any, visit func(map[string]any) error) error { + for _, row := range []map[string]any{ + {"_key": "first", "pivot": map[string]any{"zeta": "z", "alpha": "a"}}, + {"_key": "second", "pivot": map[string]any{"beta": "b"}}, + } { + if err := visit(row); err != nil { + return err + } + } + return nil + }, + }) + + gotRows := []map[string]any{} + result, err := svc.streamQuery(context.Background(), CompiledQuery{ + Query: "RETURN []", + Columns: []string{"_key", "pivot"}, + PivotFields: []string{"pivot"}, + Limit: 2, + }, func(row map[string]any) error { + gotRows = append(gotRows, row) + return nil + }) + if err != nil { + t.Fatalf("streamQuery() error = %v", err) + } + if result.RowCount != 2 { + t.Fatalf("RowCount = %d, want 2", result.RowCount) + } + wantColumns := []string{"_key", "pivot__alpha", "pivot__beta", "pivot__zeta"} + if !reflect.DeepEqual(result.Columns, wantColumns) { + t.Fatalf("Columns = %#v, want %#v", result.Columns, wantColumns) + } + wantRows := []map[string]any{ + {"_key": "first", "pivot__alpha": "a", "pivot__zeta": "z"}, + {"_key": "second", "pivot__beta": "b"}, + } + if !reflect.DeepEqual(gotRows, wantRows) { + t.Fatalf("streamed rows = %#v, want %#v", gotRows, wantRows) + } +} + +func TestStreamQueryReturnsPartialProgressWhenVisitorStops(t *testing.T) { + svc := NewService(ServiceConfig{ + ExecuteRows: func(_ context.Context, _ ExecuteQueryOptions, _ string, _ map[string]any, visit func(map[string]any) error) error { + if err := visit(map[string]any{"_key": "first"}); err != nil { + return err + } + return visit(map[string]any{"_key": "second"}) + }, + }) + stop := assertError("stop") + result, err := svc.streamQuery(context.Background(), CompiledQuery{Query: "RETURN []", Columns: []string{"_key"}}, func(map[string]any) error { + return stop + }) + if err != stop { + t.Fatalf("streamQuery() error = %v, want visitor error %v", err, stop) + } + if result.RowCount != 0 { + t.Fatalf("RowCount = %d, want 0 because the visitor rejected the first row", result.RowCount) + } +} + +type assertError string + +func (e assertError) Error() string { return string(e) } diff --git a/internal/dataframe/explain.go b/internal/dataframe/explain.go new file mode 100644 index 0000000..aba4b5c --- /dev/null +++ b/internal/dataframe/explain.go @@ -0,0 +1,22 @@ +package dataframe + +import ( + "context" + + arangostore "github.com/calypr/loom/internal/store/arango" +) + +// ExplainCompiledQuery returns Arango's optimizer plan for a compiled query +// without executing the dataframe. Callers can use ExtractPlanIndexes and the +// result's estimated costs to evaluate optimizer passes. +func ExplainCompiledQuery(ctx context.Context, opts arangostore.ConnectionOptions, compiled CompiledQuery) (arangostore.ExplainResult, error) { + client, err := arangostore.Open(ctx, opts.URL, opts.Database) + if err != nil { + return arangostore.ExplainResult{}, err + } + defer client.Close(ctx) + return client.Explain(ctx, arangostore.ExplainRequest{ + Query: compiled.Query, + BindVars: compiled.BindVars, + }) +} diff --git a/internal/dataframe/explain_test.go b/internal/dataframe/explain_test.go new file mode 100644 index 0000000..993d904 --- /dev/null +++ b/internal/dataframe/explain_test.go @@ -0,0 +1,20 @@ +package dataframe + +import ( + "context" + "testing" + + arangostore "github.com/calypr/loom/internal/store/arango" +) + +func TestExplainCompiledQueryRequiresConnection(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + cancel() + _, err := ExplainCompiledQuery(ctx, arangostore.ConnectionOptions{ + URL: "http://127.0.0.1:8529", + Database: "fhir_proto", + }, CompiledQuery{}) + if err == nil { + t.Fatal("expected connection error") + } +} diff --git a/internal/dataframe/filter.go b/internal/dataframe/filter.go new file mode 100644 index 0000000..3feffd5 --- /dev/null +++ b/internal/dataframe/filter.go @@ -0,0 +1,248 @@ +package dataframe + +import ( + "errors" + "fmt" + "strings" + "time" + + "github.com/calypr/loom/internal/fhir" +) + +// FilterOperator is the closed set of operations accepted by the typed filter +// AST. Compilers must map these values to bound expressions rather than treat +// them as query fragments. +type FilterOperator string + +const ( + FilterEquals FilterOperator = "EQUALS" + FilterNotEquals FilterOperator = "NOT_EQUALS" + FilterIn FilterOperator = "IN" + FilterExists FilterOperator = "EXISTS" + FilterMissing FilterOperator = "MISSING" + FilterContains FilterOperator = "CONTAINS_TEXT" + FilterGreaterThan FilterOperator = "GT" + FilterGreaterEq FilterOperator = "GTE" + FilterLessThan FilterOperator = "LT" + FilterLessEq FilterOperator = "LTE" +) + +type FilterValueKind string + +const ( + FilterString FilterValueKind = "STRING" + FilterCode FilterValueKind = "CODE" + FilterBoolean FilterValueKind = "BOOLEAN" + FilterInteger FilterValueKind = "INTEGER" + FilterDecimal FilterValueKind = "DECIMAL" + FilterDate FilterValueKind = "DATE" + FilterDateTime FilterValueKind = "DATE_TIME" +) + +type ArrayQuantifier string + +const ( + QuantifierAny ArrayQuantifier = "ANY" + QuantifierAll ArrayQuantifier = "ALL" + QuantifierNone ArrayQuantifier = "NONE" +) + +// CodeValue preserves the terminology identity instead of filtering only on a +// human-readable display string. +type CodeValue struct { + System string `json:"system,omitempty"` + Code string `json:"code"` + Display string `json:"display,omitempty"` +} + +// FilterValue is a tagged value. Exactly the member selected by Kind must be +// populated. Pointer scalar fields preserve false, zero, and empty values. +type FilterValue struct { + Kind FilterValueKind `json:"kind"` + String *string `json:"string,omitempty"` + Code *CodeValue `json:"code,omitempty"` + Boolean *bool `json:"boolean,omitempty"` + Integer *int64 `json:"integer,omitempty"` + Decimal *float64 `json:"decimal,omitempty"` + Date *string `json:"date,omitempty"` + DateTime *string `json:"dateTime,omitempty"` +} + +// TypedFilter identifies a field through a stable reference. It deliberately +// contains no AQL or selector expression supplied by the user. +type TypedFilter struct { + FieldRef string `json:"fieldRef"` + // Selector is a resolved, canonical FHIR selector. Product callers should + // normally supply FieldRef and receive this selector from the semantic + // registry; the compiler requires it before physical lowering. + Selector string `json:"selector,omitempty"` + FieldKind FilterValueKind `json:"fieldKind"` + Repeated bool `json:"repeated,omitempty"` + Quantifier ArrayQuantifier `json:"quantifier,omitempty"` + Operator FilterOperator `json:"operator"` + Values []FilterValue `json:"values,omitempty"` +} + +func (f TypedFilter) Validate() error { + if strings.TrimSpace(f.FieldRef) == "" { + return errors.New("filter fieldRef is required") + } + if !f.FieldKind.Valid() { + return fmt.Errorf("unknown filter field kind %q", f.FieldKind) + } + if !f.Operator.Valid() { + return fmt.Errorf("unknown filter operator %q", f.Operator) + } + if f.Repeated { + if !f.Quantifier.Valid() { + return errors.New("repeated filter requires ANY, ALL, or NONE quantifier") + } + } else if f.Quantifier != "" { + return errors.New("array quantifier is only valid for repeated fields") + } + + want := 1 + if f.Operator == FilterExists || f.Operator == FilterMissing { + want = 0 + } else if f.Operator == FilterIn { + if len(f.Values) == 0 { + return errors.New("IN filter requires at least one value") + } + want = len(f.Values) + } + if len(f.Values) != want { + return fmt.Errorf("operator %s requires %d value(s), got %d", f.Operator, want, len(f.Values)) + } + if !OperatorSupportsKind(f.Operator, f.FieldKind) { + return fmt.Errorf("operator %s is not compatible with %s", f.Operator, f.FieldKind) + } + for i, value := range f.Values { + if err := value.Validate(); err != nil { + return fmt.Errorf("filter value %d: %w", i, err) + } + if value.Kind != f.FieldKind { + return fmt.Errorf("filter value %d kind %s does not match field kind %s", i, value.Kind, f.FieldKind) + } + if err := validateOrderedTemporalValue(f.Operator, value); err != nil { + return fmt.Errorf("filter value %d: %w", i, err) + } + } + return nil +} + +func (op FilterOperator) Valid() bool { + switch op { + case FilterEquals, FilterNotEquals, FilterIn, FilterExists, FilterMissing, + FilterContains, FilterGreaterThan, FilterGreaterEq, FilterLessThan, FilterLessEq: + return true + default: + return false + } +} + +func (kind FilterValueKind) Valid() bool { + switch kind { + case FilterString, FilterCode, FilterBoolean, FilterInteger, FilterDecimal, FilterDate, FilterDateTime: + return true + default: + return false + } +} + +func (q ArrayQuantifier) Valid() bool { + return q == QuantifierAny || q == QuantifierAll || q == QuantifierNone +} + +func OperatorSupportsKind(op FilterOperator, kind FilterValueKind) bool { + if !op.Valid() || !kind.Valid() { + return false + } + switch op { + case FilterExists, FilterMissing, FilterEquals, FilterNotEquals, FilterIn: + return true + case FilterContains: + return kind == FilterString + case FilterGreaterThan, FilterGreaterEq, FilterLessThan, FilterLessEq: + return kind == FilterInteger || kind == FilterDecimal || kind == FilterDate || kind == FilterDateTime + default: + return false + } +} + +func (v FilterValue) Validate() error { + if !v.Kind.Valid() { + return fmt.Errorf("unknown value kind %q", v.Kind) + } + populated := 0 + for _, present := range []bool{v.String != nil, v.Code != nil, v.Boolean != nil, v.Integer != nil, v.Decimal != nil, v.Date != nil, v.DateTime != nil} { + if present { + populated++ + } + } + if populated != 1 { + return fmt.Errorf("exactly one typed value member is required, got %d", populated) + } + switch v.Kind { + case FilterString: + if v.String == nil { + return errors.New("STRING requires string") + } + case FilterCode: + if v.Code == nil || strings.TrimSpace(v.Code.Code) == "" { + return errors.New("CODE requires a non-empty code") + } + case FilterBoolean: + if v.Boolean == nil { + return errors.New("BOOLEAN requires boolean") + } + case FilterInteger: + if v.Integer == nil { + return errors.New("INTEGER requires integer") + } + case FilterDecimal: + if v.Decimal == nil { + return errors.New("DECIMAL requires decimal") + } + case FilterDate: + if v.Date == nil { + return errors.New("DATE requires date") + } + if err := fhir.ValidateFhirDate(*v.Date); err != nil { + return fmt.Errorf("DATE must use a valid FHIR date: %w", err) + } + case FilterDateTime: + if v.DateTime == nil { + return errors.New("DATE_TIME requires dateTime") + } + if err := fhir.ValidateFhirDateTime(*v.DateTime); err != nil { + return fmt.Errorf("DATE_TIME must use a valid FHIR date-time: %w", err) + } + } + return nil +} + +// Ordered comparison has point-in-time semantics, unlike exact FHIR temporal +// matching which can legitimately use partial precision (for example, 2024). +// Require full values before emitting DATE_TIMESTAMP so offsets are normalized +// in AQL rather than compared lexically. +func validateOrderedTemporalValue(operator FilterOperator, value FilterValue) error { + switch operator { + case FilterGreaterThan, FilterGreaterEq, FilterLessThan, FilterLessEq: + default: + return nil + } + switch value.Kind { + case FilterDate: + if value.Date == nil || len(*value.Date) != len("2006-01-02") { + return errors.New("ordered DATE comparison requires full YYYY-MM-DD precision") + } + case FilterDateTime: + if value.DateTime == nil || !strings.Contains(*value.DateTime, "T") { + return errors.New("ordered DATE_TIME comparison requires a full RFC3339 timestamp") + } + if _, err := time.Parse(time.RFC3339Nano, *value.DateTime); err != nil { + return fmt.Errorf("ordered DATE_TIME comparison requires RFC3339 timestamp: %w", err) + } + } + return nil +} diff --git a/internal/dataframe/filter_compile.go b/internal/dataframe/filter_compile.go new file mode 100644 index 0000000..85c4d21 --- /dev/null +++ b/internal/dataframe/filter_compile.go @@ -0,0 +1,134 @@ +package dataframe + +import ( + "fmt" + "strings" +) + +func (c *compiler) compileTypedFilters(payloadVar string, filters []TypedFilter) (string, error) { + if len(filters) == 0 { + return "true", nil + } + parts := make([]string, 0, len(filters)) + for _, filter := range filters { + expr, err := c.compileTypedFilter(payloadVar, filter) + if err != nil { + return "", err + } + parts = append(parts, "("+expr+")") + } + return strings.Join(parts, " AND "), nil +} + +func (c *compiler) compileTypedFilter(payloadVar string, filter TypedFilter) (string, error) { + if err := filter.Validate(); err != nil { + return "", err + } + if strings.TrimSpace(filter.Selector) == "" { + return "", fmt.Errorf("filter %q requires a resolved selector", filter.FieldRef) + } + selector, err := ParseSelector(filter.Selector) + if err != nil { + return "", fmt.Errorf("filter %q selector: %w", filter.FieldRef, err) + } + values := compileSelectorArrayExpr(payloadVar, selector, c) + if filter.Operator == FilterExists { + return fmt.Sprintf("LENGTH(%s) > 0", values), nil + } + if filter.Operator == FilterMissing { + return fmt.Sprintf("LENGTH(%s) == 0", values), nil + } + + match, err := c.compileTypedFilterMatch("__value", filter) + if err != nil { + return "", err + } + quantifier := filter.Quantifier + if !filter.Repeated { + quantifier = QuantifierAny + } + switch quantifier { + case QuantifierAny: + return fmt.Sprintf("LENGTH(FOR __value IN %s FILTER %s LIMIT 1 RETURN 1) > 0", values, match), nil + case QuantifierNone: + return fmt.Sprintf("LENGTH(FOR __value IN %s FILTER %s LIMIT 1 RETURN 1) == 0", values, match), nil + case QuantifierAll: + return fmt.Sprintf("LENGTH(%s) > 0 AND LENGTH(FOR __value IN %s FILTER NOT (%s) LIMIT 1 RETURN 1) == 0", values, values, match), nil + default: + return "", fmt.Errorf("filter %q has unsupported quantifier %q", filter.FieldRef, quantifier) + } +} + +func (c *compiler) compileTypedFilterMatch(valueVar string, filter TypedFilter) (string, error) { + if filter.Operator == FilterIn { + values := make([]any, 0, len(filter.Values)) + for _, value := range filter.Values { + literal, err := filterLiteral(value) + if err != nil { + return "", err + } + values = append(values, literal) + } + bind := c.newBind("filter_in", values) + return fmt.Sprintf("POSITION(@%s, %s, true)", bind, valueVar), nil + } + if len(filter.Values) != 1 { + return "", fmt.Errorf("filter %q requires one value", filter.FieldRef) + } + literal, err := filterLiteral(filter.Values[0]) + if err != nil { + return "", err + } + bind := c.newBind("filter_value", literal) + left := valueVar + right := "@" + bind + if filter.FieldKind == FilterDate || filter.FieldKind == FilterDateTime { + switch filter.Operator { + case FilterGreaterThan, FilterGreaterEq, FilterLessThan, FilterLessEq: + left = "DATE_TIMESTAMP(" + valueVar + ")" + right = "DATE_TIMESTAMP(@" + bind + ")" + } + } + switch filter.Operator { + case FilterEquals: + return fmt.Sprintf("%s == @%s", left, bind), nil + case FilterNotEquals: + return fmt.Sprintf("%s != @%s", left, bind), nil + case FilterContains: + return fmt.Sprintf("CONTAINS(TO_STRING(%s), @%s)", valueVar, bind), nil + case FilterGreaterThan: + return fmt.Sprintf("%s > %s", left, right), nil + case FilterGreaterEq: + return fmt.Sprintf("%s >= %s", left, right), nil + case FilterLessThan: + return fmt.Sprintf("%s < %s", left, right), nil + case FilterLessEq: + return fmt.Sprintf("%s <= %s", left, right), nil + default: + return "", fmt.Errorf("filter %q uses unsupported operator %q", filter.FieldRef, filter.Operator) + } +} + +func filterLiteral(value FilterValue) (any, error) { + if err := value.Validate(); err != nil { + return nil, err + } + switch value.Kind { + case FilterString: + return *value.String, nil + case FilterCode: + return value.Code.Code, nil + case FilterBoolean: + return *value.Boolean, nil + case FilterInteger: + return *value.Integer, nil + case FilterDecimal: + return *value.Decimal, nil + case FilterDate: + return *value.Date, nil + case FilterDateTime: + return *value.DateTime, nil + default: + return nil, fmt.Errorf("unsupported filter value kind %q", value.Kind) + } +} diff --git a/internal/dataframe/filter_compile_test.go b/internal/dataframe/filter_compile_test.go new file mode 100644 index 0000000..eb481d5 --- /dev/null +++ b/internal/dataframe/filter_compile_test.go @@ -0,0 +1,102 @@ +package dataframe + +import ( + "strings" + "testing" +) + +func TestCompileTypedFilterUsesBindVariables(t *testing.T) { + value := "female" + c := &compiler{bindVars: map[string]any{}} + expr, err := c.compileTypedFilter("root.payload", TypedFilter{ + FieldRef: "Patient.gender", + Selector: "gender", + FieldKind: FilterString, + Operator: FilterEquals, + Values: []FilterValue{{Kind: FilterString, String: &value}}, + }) + if err != nil { + t.Fatal(err) + } + if strings.Contains(expr, value) || !strings.Contains(expr, "@__filter_value_0") { + t.Fatalf("filter expression does not use a bind variable: %s", expr) + } + if got := c.bindVars["__filter_value_0"]; got != value { + t.Fatalf("bind value = %#v, want %q", got, value) + } +} + +func TestCompileTypedFilterQuantifiers(t *testing.T) { + value := "BAM" + for _, quantifier := range []ArrayQuantifier{QuantifierAny, QuantifierAll, QuantifierNone} { + t.Run(string(quantifier), func(t *testing.T) { + c := &compiler{bindVars: map[string]any{}} + expr, err := c.compileTypedFilter("node.payload", TypedFilter{ + FieldRef: "DocumentReference.type", + Selector: "type.coding[].display", + FieldKind: FilterString, + Repeated: true, + Quantifier: quantifier, + Operator: FilterEquals, + Values: []FilterValue{{Kind: FilterString, String: &value}}, + }) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(expr, "FOR __value") { + t.Fatalf("unexpected quantifier expression: %s", expr) + } + }) + } +} + +func TestCompileTypedFilterNormalizesOrderedTemporalComparison(t *testing.T) { + date := "2025-01-01" + c := &compiler{bindVars: map[string]any{}} + expr, err := c.compileTypedFilter("root.payload", TypedFilter{ + FieldRef: "Patient.birth_date", Selector: "birthDate", FieldKind: FilterDate, + Operator: FilterGreaterEq, Values: []FilterValue{{Kind: FilterDate, Date: &date}}, + }) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(expr, "DATE_TIMESTAMP(__value)") || !strings.Contains(expr, "DATE_TIMESTAMP(@__filter_value_0)") { + t.Fatalf("ordered temporal filter did not normalize timestamps: %s", expr) + } +} + +func TestGenericLoweringPushesRootAndChildFiltersIntoAQL(t *testing.T) { + gender := "female" + bam := "BAM" + compiled, err := CompileRequest(Builder{ + Project: "P1", + RootResourceType: "Patient", + Filters: []TypedFilter{{ + FieldRef: "Patient.gender", Selector: "gender", FieldKind: FilterString, Operator: FilterEquals, + Values: []FilterValue{{Kind: FilterString, String: &gender}}, + }}, + Traversals: []TraversalStep{{ + Label: "subject_Patient", ToResourceType: "DocumentReference", Alias: "file", + Filters: []TypedFilter{{ + FieldRef: "DocumentReference.type", Selector: "type.coding[].display", FieldKind: FilterString, + Repeated: true, Quantifier: QuantifierAny, Operator: FilterEquals, + Values: []FilterValue{{Kind: FilterString, String: &bam}}, + }}, + }}, + }, 25) + if err != nil { + t.Fatal(err) + } + if compiled.PlanProfile != "generic_fhir_graph" { + t.Fatalf("expected generic filtered plan, got %q", compiled.PlanProfile) + } + if !containsOptimizerRule(compiled.OptimizationRules, OptimizerRuleFilterPushdown) { + t.Fatalf("expected filter-pushdown optimizer provenance, got %#v", compiled.OptimizationRules) + } + if strings.Count(compiled.Query, "FILTER (LENGTH(FOR __value") < 2 { + t.Fatalf("expected root and child pushed filters, got:\n%s", compiled.Query) + } + if len(compiled.BindVars) < 6 { + t.Fatalf("expected selector and value bind variables, got %#v", compiled.BindVars) + } +} diff --git a/internal/dataframe/filter_semantics.go b/internal/dataframe/filter_semantics.go new file mode 100644 index 0000000..c05882f --- /dev/null +++ b/internal/dataframe/filter_semantics.go @@ -0,0 +1,79 @@ +package dataframe + +import ( + "fmt" + "strings" + + "github.com/calypr/loom/internal/fhirschema" +) + +// ValidateTypedFilterForResource proves that a resolved filter selector has a +// compatible shape in the active generated FHIR schema. Runtime catalog +// validation remains responsible for whether that field is populated in the +// selected project; this function prevents a request from using a value type +// that cannot be represented by the generated resource definition. +func ValidateTypedFilterForResource(resourceType string, filter TypedFilter) error { + if err := filter.Validate(); err != nil { + return err + } + if strings.TrimSpace(filter.Selector) == "" { + return fmt.Errorf("filter %q requires a resolved selector", filter.FieldRef) + } + selector, err := ParseSelector(filter.Selector) + if err != nil { + return fmt.Errorf("filter %q selector: %w", filter.FieldRef, err) + } + if _, _, err := selectorCardinality(resourceType, selector); err != nil { + return fmt.Errorf("filter %q selector: %w", filter.FieldRef, err) + } + metadata, ok := fhirschema.ResolveTerminalScalarMetadata(resourceType, selector.CanonicalPath()) + if !ok { + return fmt.Errorf("filter selector %q is not represented by generated resource type %q", filter.Selector, resourceType) + } + if filter.Repeated != metadata.Repeated { + return fmt.Errorf("filter selector %q repeated=%t does not match generated cardinality repeated=%t", filter.Selector, filter.Repeated, metadata.Repeated) + } + if !filterKindMatchesGeneratedPrimitive(filter.FieldKind, metadata.Primitive, selector.CanonicalPath()) { + return fmt.Errorf("filter selector %q has generated primitive %q, incompatible with filter value kind %q", filter.Selector, metadata.Primitive, filter.FieldKind) + } + if filter.FieldKind == FilterCode { + for _, value := range filter.Values { + if value.Code == nil { + continue + } + // The current selector compiler safely matches the terminal code. It + // must not pretend an independently collected system/display belongs + // to that same Coding array member; paired Coding lowering is added + // only once represented explicitly in the physical expression IR. + if strings.TrimSpace(value.Code.System) != "" || strings.TrimSpace(value.Code.Display) != "" { + return fmt.Errorf("filter %q supplies code system/display, which requires paired Coding lowering not available in this compiler version", filter.FieldRef) + } + } + } + return nil +} + +func filterKindMatchesGeneratedPrimitive(kind FilterValueKind, primitive fhirschema.PrimitiveKind, canonicalPath string) bool { + switch primitive { + case fhirschema.PrimitiveString: + if kind == FilterString { + return true + } + // A code filter is safe only when the resolved generated selector ends + // in a code primitive. This remains deliberately conservative: fields + // such as Patient.gender are strings, not terminology codes. + return kind == FilterCode && (canonicalPath == "code" || strings.HasSuffix(canonicalPath, ".code")) + case fhirschema.PrimitiveBoolean: + return kind == FilterBoolean + case fhirschema.PrimitiveInteger: + return kind == FilterInteger + case fhirschema.PrimitiveDecimal: + return kind == FilterDecimal + case fhirschema.PrimitiveDate: + return kind == FilterDate + case fhirschema.PrimitiveDateTime: + return kind == FilterDateTime + default: + return false + } +} diff --git a/internal/dataframe/filter_semantics_test.go b/internal/dataframe/filter_semantics_test.go new file mode 100644 index 0000000..cbf79d4 --- /dev/null +++ b/internal/dataframe/filter_semantics_test.go @@ -0,0 +1,83 @@ +package dataframe + +import ( + "strings" + "testing" +) + +func TestValidateTypedFilterForResourceUsesGeneratedPrimitiveMetadata(t *testing.T) { + female := "female" + integer := int64(7) + + tests := []struct { + name string + resourceType string + filter TypedFilter + wantErr string + }{ + { + name: "string", resourceType: "Patient", + filter: TypedFilter{FieldRef: "Patient.gender", Selector: "gender", FieldKind: FilterString, Operator: FilterEquals, Values: []FilterValue{{Kind: FilterString, String: &female}}}, + }, + { + name: "integer", resourceType: "Observation", + filter: TypedFilter{FieldRef: "Observation.valueInteger", Selector: "valueInteger", FieldKind: FilterInteger, Operator: FilterGreaterThan, Values: []FilterValue{{Kind: FilterInteger, Integer: &integer}}}, + }, + { + name: "repeated scalar below repeated object", resourceType: "Observation", + filter: TypedFilter{FieldRef: "Observation.component_value_integer", Selector: "component[].valueInteger", FieldKind: FilterInteger, Repeated: true, Quantifier: QuantifierAny, Operator: FilterEquals, Values: []FilterValue{{Kind: FilterInteger, Integer: &integer}}}, + }, + { + name: "mismatched value kind", resourceType: "Patient", + filter: TypedFilter{FieldRef: "Patient.gender", Selector: "gender", FieldKind: FilterInteger, Operator: FilterEquals, Values: []FilterValue{{Kind: FilterInteger, Integer: &integer}}}, + wantErr: "incompatible", + }, + { + name: "mismatched repeated cardinality", resourceType: "Observation", + filter: TypedFilter{FieldRef: "Observation.component_value_integer", Selector: "component[].valueInteger", FieldKind: FilterInteger, Operator: FilterEquals, Values: []FilterValue{{Kind: FilterInteger, Integer: &integer}}}, + wantErr: "repeated", + }, + { + name: "implicit repeated navigation", resourceType: "Observation", + filter: TypedFilter{FieldRef: "Observation.component_value_integer", Selector: "component.valueInteger", FieldKind: FilterInteger, Operator: FilterEquals, Values: []FilterValue{{Kind: FilterInteger, Integer: &integer}}}, + wantErr: "without []", + }, + { + name: "generated date time format", resourceType: "Observation", + filter: TypedFilter{FieldRef: "Observation.value_date_time", Selector: "valueDateTime", FieldKind: FilterDateTime, Operator: FilterGreaterThan, Values: []FilterValue{{Kind: FilterDateTime, DateTime: stringPtr("2025-01-01T00:00:00Z")}}}, + }, + { + name: "generated date format", resourceType: "Patient", + filter: TypedFilter{FieldRef: "Patient.birth_date", Selector: "birthDate", FieldKind: FilterDate, Operator: FilterGreaterEq, Values: []FilterValue{{Kind: FilterDate, Date: stringPtr("2000-01-01")}}}, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + err := ValidateTypedFilterForResource(test.resourceType, test.filter) + if test.wantErr == "" { + if err != nil { + t.Fatal(err) + } + return + } + if err == nil || !strings.Contains(err.Error(), test.wantErr) { + t.Fatalf("error = %v, want substring %q", err, test.wantErr) + } + }) + } +} + +func TestValidateTypedFilterForResourceRejectsUnpairedCodingSystem(t *testing.T) { + code := "1234-5" + err := ValidateTypedFilterForResource("Observation", TypedFilter{ + FieldRef: "Observation.code_coding_code", Selector: "code.coding[].code", FieldKind: FilterCode, + Repeated: true, Quantifier: QuantifierAny, Operator: FilterEquals, + Values: []FilterValue{{Kind: FilterCode, Code: &CodeValue{Code: code, System: "http://loinc.org"}}}, + }) + if err == nil || !strings.Contains(err.Error(), "paired Coding") { + t.Fatalf("error = %v, want paired Coding rejection", err) + } +} + +func stringPtr(value string) *string { return &value } diff --git a/internal/dataframe/filter_test.go b/internal/dataframe/filter_test.go new file mode 100644 index 0000000..443329f --- /dev/null +++ b/internal/dataframe/filter_test.go @@ -0,0 +1,122 @@ +package dataframe + +import ( + "strings" + "testing" +) + +func TestTypedFilterValidation(t *testing.T) { + melanoma := "melanoma" + zero := int64(0) + tests := []struct { + name string + filter TypedFilter + wantErr string + }{ + { + name: "string equality", + filter: TypedFilter{FieldRef: "condition.code.display", FieldKind: FilterString, Operator: FilterEquals, + Values: []FilterValue{{Kind: FilterString, String: &melanoma}}}, + }, + { + name: "zero integer is present", + filter: TypedFilter{FieldRef: "observation.value", FieldKind: FilterInteger, Operator: FilterGreaterEq, + Values: []FilterValue{{Kind: FilterInteger, Integer: &zero}}}, + }, + { + name: "repeated requires quantifier", + filter: TypedFilter{FieldRef: "condition.code", FieldKind: FilterString, Repeated: true, Operator: FilterEquals, + Values: []FilterValue{{Kind: FilterString, String: &melanoma}}}, + wantErr: "requires ANY, ALL, or NONE", + }, + { + name: "scalar rejects quantifier", + filter: TypedFilter{FieldRef: "patient.gender", FieldKind: FilterString, Quantifier: QuantifierAny, Operator: FilterEquals, + Values: []FilterValue{{Kind: FilterString, String: &melanoma}}}, + wantErr: "only valid for repeated", + }, + { + name: "exists rejects a value", + filter: TypedFilter{FieldRef: "patient.birthDate", FieldKind: FilterDate, Operator: FilterExists, Values: []FilterValue{{Kind: FilterString, String: &melanoma}}}, + wantErr: "requires 0 value", + }, + { + name: "in requires values", + filter: TypedFilter{FieldRef: "patient.gender", FieldKind: FilterString, Operator: FilterIn}, + wantErr: "at least one value", + }, + { + name: "comparison rejects string", + filter: TypedFilter{FieldRef: "patient.gender", FieldKind: FilterString, Operator: FilterGreaterThan, + Values: []FilterValue{{Kind: FilterString, String: &melanoma}}}, + wantErr: "not compatible", + }, + { + name: "value kind must match field", + filter: TypedFilter{FieldRef: "observation.value", FieldKind: FilterDecimal, Operator: FilterEquals, + Values: []FilterValue{{Kind: FilterInteger, Integer: &zero}}}, + wantErr: "does not match field kind", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.filter.Validate() + if tt.wantErr == "" && err != nil { + t.Fatal(err) + } + if tt.wantErr != "" && (err == nil || !strings.Contains(err.Error(), tt.wantErr)) { + t.Fatalf("error = %v, want substring %q", err, tt.wantErr) + } + }) + } +} + +func TestFilterValueDateValidation(t *testing.T) { + validDate := "2026-07-11" + partialDate := "2026-07" + invalidDate := "07/11/2026" + validDateTime := "2026-07-11T12:30:00-07:00" + partialDateTime := "2026" + for _, value := range []FilterValue{ + {Kind: FilterDate, Date: &validDate}, + {Kind: FilterDate, Date: &partialDate}, + {Kind: FilterDateTime, DateTime: &validDateTime}, + {Kind: FilterDateTime, DateTime: &partialDateTime}, + } { + if err := value.Validate(); err != nil { + t.Fatal(err) + } + } + if err := (FilterValue{Kind: FilterDate, Date: &invalidDate}).Validate(); err == nil { + t.Fatal("expected invalid date to be rejected") + } +} + +func TestTypedFilterRejectsPartialTemporalOrderedComparison(t *testing.T) { + partialDate := "2026" + if err := (TypedFilter{ + FieldRef: "Patient.birth_date", FieldKind: FilterDate, Operator: FilterGreaterThan, + Values: []FilterValue{{Kind: FilterDate, Date: &partialDate}}, + }).Validate(); err == nil || !strings.Contains(err.Error(), "full YYYY-MM-DD") { + t.Fatalf("ordered partial date error = %v", err) + } +} + +func TestCodeValueRequiresTerminologyCode(t *testing.T) { + value := FilterValue{Kind: FilterCode, Code: &CodeValue{Display: "Melanoma"}} + if err := value.Validate(); err == nil { + t.Fatal("expected display-only code value to be rejected") + } +} + +func TestOperatorSupportsKind(t *testing.T) { + if !OperatorSupportsKind(FilterContains, FilterString) { + t.Fatal("CONTAINS_TEXT should support STRING") + } + if OperatorSupportsKind(FilterContains, FilterCode) { + t.Fatal("CONTAINS_TEXT must not treat CODE display as terminology identity") + } + if !OperatorSupportsKind(FilterLessEq, FilterDateTime) { + t.Fatal("LTE should support DATE_TIME") + } +} diff --git a/internal/dataframe/generic_lowering.go b/internal/dataframe/generic_lowering.go new file mode 100644 index 0000000..3005d79 --- /dev/null +++ b/internal/dataframe/generic_lowering.go @@ -0,0 +1,316 @@ +package dataframe + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/calypr/loom/internal/fhirschema" +) + +// lowerGenericGraphQLBuilder produces a correct, conservative plan for any +// root and populated traversal represented in the generated FHIR graph schema. +// +// The generic plan uses the compiler-owned fhir_edge storage route. Most +// populated relationships are generated builder routes that reach a referring +// child with an INBOUND traversal. The explicit ResearchSubject --study--> +// ResearchStudy contract is the currently proven forward exception. Generated +// traversal metadata validates FHIR semantics but does not by itself define a +// safe physical AQL direction, so every other forward/ANY route remains +// rejected until its edge-layout evidence is added to storage_route.go. +func lowerGenericGraphQLBuilder(builder Builder, request logicalRequest) (Builder, error) { + if !fhirschema.HasResource(request.Root.ResourceType) { + return Builder{}, unsupportedLoweringError(fmt.Sprintf("root resource type %q is not represented by the active generated FHIR schema", request.Root.ResourceType)) + } + requiredMatches, err := requiredTraversalMatches(request.Root) + if err != nil { + return Builder{}, unsupportedLoweringError(err.Error()) + } + + ctx := &loweringContext{ + request: request, + builder: Builder{ + Project: request.Project, + DatasetGeneration: request.DatasetGeneration, + AuthResourcePaths: request.AuthResourcePaths, + AuthScopeMode: request.AuthScopeMode, + RootResourceType: request.Root.ResourceType, + Fields: append([]FieldSelect(nil), request.Root.Fields...), + Filters: append([]TypedFilter(nil), request.Root.Filters...), + Pivots: append([]PivotSelect(nil), request.Root.Pivots...), + Aggregates: append([]AggregateSelect(nil), request.Root.Aggregates...), + Slices: append([]RepresentativeSlice(nil), request.Root.Slices...), + Sets: []NamedSet{}, + DerivedFields: []DerivedField{}, + RequiredTraversalMatches: requiredMatches, + }, + setsByName: map[string]struct{}{}, + modes: map[string]string{}, + genericSetsBySignature: map[string]string{}, + genericFilterSetsBySig: map[string]string{}, + genericAliasesBySetName: map[string]string{}, + } + + if err := ctx.lowerGenericChildren(request.Root, ""); err != nil { + return Builder{}, err + } + appliedRules := make([]string, 0, 3) + if requestHasTypedFilters(request.Root) { + appliedRules = append(appliedRules, OptimizerRuleFilterPushdown) + } + if ctx.genericTraversalShareCount > 0 { + appliedRules = append(appliedRules, OptimizerRuleTraversalSharing) + } + if len(requiredMatches) > 0 { + appliedRules = append(appliedRules, OptimizerRuleRelationshipSemiJoin) + } + if len(appliedRules) == 0 { + appliedRules = nil + } + ctx.builder.PlanHint = &PlanHint{ + Mode: "lowered", + Profile: "generic_fhir_graph", + NamedSetCount: len(ctx.builder.Sets), + AppliedRules: appliedRules, + } + return ctx.builder, nil +} + +func (ctx *loweringContext) lowerGenericChildren(parent logicalNode, parentSet string) error { + children, groups, groupOrder, err := ctx.prepareGenericChildren(parent, parentSet) + if err != nil { + return err + } + + // Materialize every shareable prefix before lowering the individual child + // selections. The shared set intentionally has no target-type predicate: + // its per-resource-type subsets are built below. This is the same physical + // shape as the Patient optimizer's root_patient_neighbor_set, but it is + // now available at every generic parent node. + for _, key := range groupOrder { + group := groups[key] + if !group.canSharePrefix() { + continue + } + baseName := ctx.nextGenericSharedTraversalSetName(parentSet, group.label) + group.baseSet = ctx.ensureSet(NamedSet{ + Name: baseName, + Kind: SetKindTraverse, + Source: parentSet, + Direction: group.route.namedSetDirection(), + Label: group.label, + // ToResourceType remains a generated-route validation anchor. The + // physical traversal deliberately includes every target type with + // this label; each child gets a typed filter subset below. + ToResourceType: children[group.indices[0]].node.ResourceType, + AllTargetTypes: true, + Unique: true, + }, "node") + ctx.genericTraversalShareCount += len(group.indices) - 1 + } + + // Preserve request order for derived fields and nested traversals. Prefix + // discovery may be grouped, but user-visible output ordering must not be. + for _, child := range children { + group := groups[child.groupKey] + setName := child.setName + if group.baseSet != "" { + var reused bool + setName, reused, err = ctx.ensureGenericFilteredSubset(group.baseSet, child.node) + if err != nil { + return err + } + if reused { + ctx.genericTraversalShareCount++ + } + } else { + setName, err = ctx.ensureGenericTraversalSet(parentSet, child.node, child.route, setName) + if err != nil { + return err + } + } + + ctx.lowerNodeSelections(child.node, setName) + if err := ctx.lowerGenericChildren(child.node, setName); err != nil { + return err + } + } + return nil +} + +type genericTraversalChild struct { + node logicalNode + route storageRoute + setName string + groupKey string +} + +type genericTraversalGroup struct { + label string + route storageRoute + indices []int + resourceTypes map[string]struct{} + baseSet string +} + +func (group genericTraversalGroup) canSharePrefix() bool { + return len(group.indices) > 1 && len(group.resourceTypes) > 1 +} + +func (ctx *loweringContext) prepareGenericChildren(parent logicalNode, parentSet string) ([]genericTraversalChild, map[string]*genericTraversalGroup, []string, error) { + children := make([]genericTraversalChild, 0, len(parent.Children)) + groups := make(map[string]*genericTraversalGroup, len(parent.Children)) + groupOrder := make([]string, 0, len(parent.Children)) + for _, child := range parent.Children { + setName, err := ctx.genericSetNameForAlias(child.Alias) + if err != nil { + return nil, nil, nil, err + } + route, err := resolveStorageRoute(parent.ResourceType, child.Label, child.ResourceType) + if err != nil { + return nil, nil, nil, unsupportedLoweringError(err.Error()) + } + key := genericSiblingTraversalKey(parentSet, child.Label, route) + group, exists := groups[key] + if !exists { + group = &genericTraversalGroup{ + label: child.Label, + route: route, + resourceTypes: map[string]struct{}{}, + } + groups[key] = group + groupOrder = append(groupOrder, key) + } + group.indices = append(group.indices, len(children)) + group.resourceTypes[child.ResourceType] = struct{}{} + children = append(children, genericTraversalChild{ + node: child, + route: route, + setName: setName, + groupKey: key, + }) + } + return children, groups, groupOrder, nil +} + +func (ctx *loweringContext) genericSetNameForAlias(alias string) (string, error) { + if strings.TrimSpace(alias) == "" { + return "", unsupportedLoweringError("generic lowering requires a traversal alias") + } + setName := "generic_" + sanitizeColumnName(alias) + "_set" + if priorAlias, exists := ctx.genericAliasesBySetName[setName]; exists && priorAlias != alias { + return "", unsupportedLoweringError(fmt.Sprintf("traversal aliases collide after identifier normalization: %q", alias)) + } + if _, exists := ctx.setsByName[setName]; exists { + return "", unsupportedLoweringError(fmt.Sprintf("traversal alias %q collides with an existing generic set after identifier normalization", alias)) + } + ctx.genericAliasesBySetName[setName] = alias + return setName, nil +} + +func (ctx *loweringContext) nextGenericSharedTraversalSetName(parentSet, label string) string { + parentName := "root" + if strings.TrimSpace(parentSet) != "" { + parentName = sanitizeColumnName(parentSet) + } + base := "generic_" + parentName + "_" + sanitizeColumnName(label) + "_neighbors_set" + name := base + for suffix := 2; ; suffix++ { + _, usedBySet := ctx.setsByName[name] + _, usedByAlias := ctx.genericAliasesBySetName[name] + if !usedBySet && !usedByAlias { + return name + } + name = fmt.Sprintf("%s_%d", base, suffix) + } +} + +func (ctx *loweringContext) ensureGenericTraversalSet(parentSet string, child logicalNode, route storageRoute, setName string) (string, error) { + signature, err := genericTraversalSignature(parentSet, child, route) + if err != nil { + return "", err + } + if sharedSet, exists := ctx.genericSetsBySignature[signature]; exists { + ctx.genericTraversalShareCount++ + return sharedSet, nil + } + ctx.ensureSet(NamedSet{ + Name: setName, + Kind: SetKindTraverse, + Source: parentSet, + Direction: route.namedSetDirection(), + Label: child.Label, + ToResourceType: child.ResourceType, + Filters: append([]TypedFilter(nil), child.Filters...), + Unique: true, + SortField: genericTraversalRequiresStableOrder(child), + }, "node") + ctx.genericSetsBySignature[signature] = setName + return setName, nil +} + +func (ctx *loweringContext) ensureGenericFilteredSubset(source string, child logicalNode) (string, bool, error) { + signature, err := genericFilteredSubsetSignature(source, child) + if err != nil { + return "", false, err + } + if sharedSet, exists := ctx.genericFilterSetsBySig[signature]; exists { + return sharedSet, true, nil + } + setName, err := ctx.genericSetNameForAlias(child.Alias) + if err != nil { + return "", false, err + } + // The shared base is deduplicated before this subset is evaluated. Sort the + // subset after it is typed and filtered so FIRST/ALL projections are stable + // and aliases observing the same subset see exactly the same order. + ctx.ensureSet(NamedSet{ + Name: setName, + Kind: SetKindFilter, + Source: source, + MatchResourceType: child.ResourceType, + Filters: append([]TypedFilter(nil), child.Filters...), + // The all-target base is already UNIQUE. Repeating it here would add a + // second hash-deduplication pass without changing the typed subset. + Unique: false, + SortField: "_key", + }, "node") + ctx.genericFilterSetsBySig[signature] = setName + return setName, false, nil +} + +func genericTraversalRequiresStableOrder(node logicalNode) string { + for _, field := range node.Fields { + switch normalizeValueMode(field.ValueMode) { + case "FIRST", "ALL", "AUTO": + return "_key" + } + } + if len(node.Slices) > 0 { + return "_key" + } + return "" +} + +func genericTraversalSignature(parentSet string, child logicalNode, route storageRoute) (string, error) { + filters, err := json.Marshal(child.Filters) + if err != nil { + return "", fmt.Errorf("serialize traversal filters for %s -> %s (%s): %w", child.ResourceType, child.Alias, child.Label, err) + } + return strings.Join([]string{parentSet, child.Label, child.ResourceType, route.namedSetDirection(), genericTraversalRequiresStableOrder(child), string(filters)}, "\x00"), nil +} + +func genericSiblingTraversalKey(parentSet, label string, route storageRoute) string { + return strings.Join([]string{parentSet, label, route.namedSetDirection()}, "\x00") +} + +func genericFilteredSubsetSignature(source string, child logicalNode) (string, error) { + filters, err := json.Marshal(child.Filters) + if err != nil { + return "", fmt.Errorf("serialize shared traversal filters for %s -> %s: %w", child.ResourceType, child.Alias, err) + } + // Shared generic subsets always sort by _key. This makes all selection + // modes deterministic and lets aliases with identical type/filter semantics + // reuse the same materialized subset. + return strings.Join([]string{source, child.ResourceType, "_key", string(filters)}, "\x00"), nil +} diff --git a/internal/dataframe/generic_lowering_test.go b/internal/dataframe/generic_lowering_test.go new file mode 100644 index 0000000..14ddc68 --- /dev/null +++ b/internal/dataframe/generic_lowering_test.go @@ -0,0 +1,111 @@ +package dataframe + +import ( + "strings" + "testing" + + "github.com/calypr/loom/internal/fhirschema" +) + +func TestLowerGraphQLBuilderFallsBackToGenericRootOnlyPlan(t *testing.T) { + planned, err := lowerGraphQLBuilder(Builder{ + Project: "P1", + RootResourceType: "Patient", + Fields: []FieldSelect{{Name: "gender", Select: "gender"}}, + }) + if err != nil { + t.Fatalf("lowerGraphQLBuilder() error = %v", err) + } + if planned.PlanHint == nil || planned.PlanHint.Profile != "generic_fhir_graph" { + t.Fatalf("expected generic plan hint, got %#v", planned.PlanHint) + } + compiled, err := Compile(planned, 25) + if err != nil { + t.Fatalf("Compile() error = %v", err) + } + if !strings.Contains(compiled.Query, "FOR root IN Patient") || !strings.Contains(compiled.Query, "root.payload.gender") { + t.Fatalf("unexpected generic root query:\n%s", compiled.Query) + } +} + +func TestLowerGraphQLBuilderFallsBackToGenericNonPatientTraversal(t *testing.T) { + planned, err := lowerGraphQLBuilder(Builder{ + Project: "P1", + RootResourceType: "Specimen", + Fields: []FieldSelect{{Name: "id", Select: "id"}}, + Traversals: []TraversalStep{{ + Label: "subject_Specimen", + ToResourceType: "DocumentReference", + Alias: "file", + Fields: []FieldSelect{{Name: "file_name", Select: "content[].attachment.title"}}, + }}, + }) + if err != nil { + t.Fatalf("lowerGraphQLBuilder() error = %v", err) + } + if planned.PlanHint == nil || planned.PlanHint.Profile != "generic_fhir_graph" { + t.Fatalf("expected generic plan hint, got %#v", planned.PlanHint) + } + if len(planned.Sets) != 1 || planned.Sets[0].Direction != "INBOUND" || planned.Sets[0].Source != "" { + t.Fatalf("unexpected generic set: %#v", planned.Sets) + } + compiled, err := Compile(planned, 25) + if err != nil { + t.Fatalf("Compile() error = %v", err) + } + if !strings.Contains(compiled.Query, "1..1 INBOUND root fhir_edge") || !strings.Contains(compiled.Query, "generic_file_set") { + t.Fatalf("unexpected generic traversal query:\n%s", compiled.Query) + } +} + +func TestGenericLoweringUsesInboundForNestedSchemaTraversal(t *testing.T) { + planned, err := lowerGraphQLBuilder(Builder{ + Project: "P1", + RootResourceType: "Patient", + Traversals: []TraversalStep{{ + Label: "subject_Patient", + ToResourceType: "Specimen", + Alias: "specimen", + Traversals: []TraversalStep{{ + Label: "subject_Specimen", + ToResourceType: "DocumentReference", + Alias: "file", + Fields: []FieldSelect{{Name: "id", Select: "id"}}, + }}, + }}, + }) + if err != nil { + t.Fatalf("lowerGraphQLBuilder() error = %v", err) + } + if planned.PlanHint == nil || planned.PlanHint.Profile != "generic_fhir_graph" { + t.Fatalf("ordinary Patient navigation must use generic lowering, got %#v", planned.PlanHint) + } + compiled, err := Compile(planned, 10) + if err != nil { + t.Fatal(err) + } + if strings.Count(compiled.Query, " INBOUND ") != 2 { + t.Fatalf("expected two generic INBOUND traversals, got:\n%s", compiled.Query) + } +} + +func TestGenericLoweringCompilesEveryGeneratedRootType(t *testing.T) { + for _, resourceType := range fhirschema.ResourceTypes() { + t.Run(resourceType, func(t *testing.T) { + planned, err := lowerGraphQLBuilder(Builder{Project: "P1", RootResourceType: resourceType}) + if err != nil { + t.Fatalf("lowerGraphQLBuilder() error = %v", err) + } + if planned.PlanHint == nil || planned.PlanHint.Profile != "generic_fhir_graph" { + t.Fatalf("expected generic plan, got %#v", planned.PlanHint) + } + compiled, err := Compile(planned, 1) + if err != nil { + t.Fatalf("Compile() error = %v", err) + } + if !strings.Contains(compiled.Query, "FOR root IN "+resourceType) { + t.Fatalf("query does not use expected root collection:\n%s", compiled.Query) + } + }) + } +} diff --git a/internal/dataframe/generic_physical_plan.go b/internal/dataframe/generic_physical_plan.go new file mode 100644 index 0000000..304c43f --- /dev/null +++ b/internal/dataframe/generic_physical_plan.go @@ -0,0 +1,183 @@ +package dataframe + +import ( + "fmt" + "strings" + + "github.com/calypr/loom/internal/fhirschema" +) + +// BuildGenericPhysicalPlan lowers only the navigation skeleton of an already +// validated semantic plan. Selection, user filtering, pivots, aggregation, and +// slicing remain intentionally unsupported until their physical operators are +// frozen. The returned plan is inspectable and renderer-independent. +func BuildGenericPhysicalPlan(semantic SemanticPlan) (PhysicalPlan, error) { + if strings.TrimSpace(semantic.Project) == "" { + return PhysicalPlan{}, fmt.Errorf("semantic plan project is required") + } + if err := ValidateSemanticGraph(semantic); err != nil { + return PhysicalPlan{}, err + } + if !fhirschema.ResourceExists(semantic.Root.ResourceType) { + return PhysicalPlan{}, fmt.Errorf("root resource type %q is not represented by the generated FHIR schema", semantic.Root.ResourceType) + } + if err := validateNavigationOnlyNode(semantic.Root); err != nil { + return PhysicalPlan{}, err + } + + physical := PhysicalPlan{ + Version: 1, + Source: PhysicalSource{ + SemanticNode: semantic.Root.Alias, + ResourceType: semantic.Root.ResourceType, + }, + BindVars: map[string]any{ + "root_collection": semantic.Root.ResourceType, + "project": semantic.Project, + datasetGenerationBindKey: datasetGenerationBindValue(semantic.DatasetGeneration), + "auth_resource_paths": append([]string(nil), semantic.AuthResourcePaths...), + "auth_resource_paths_unrestricted": semanticAuthScopeUnrestricted(semantic), + "scope_allowed": true, + }, + Operations: []PhysicalOperation{ + { + Kind: PhysicalRootScanOp, + Source: PhysicalSource{SemanticNode: semantic.Root.Alias, ResourceType: semantic.Root.ResourceType}, + RootScan: &PhysicalRootScan{Variable: "root", CollectionBindKey: "root_collection"}, + }, + }, + } + physical.Operations = appendProjectScope(physical.Operations, []string{"root"}, "", semantic.Root) + physical.Operations = appendDatasetGenerationScope(physical.Operations, []string{"root"}, "", semantic.Root) + physical.Operations = appendAuthScope(physical.Operations, []PhysicalValue{{Variable: "root", Path: []string{"auth_resource_path"}}}, "root_scope_allowed", semantic.Root) + + nextTraversal := 0 + var walk func(parent SemanticNode, parentVariable string) error + walk = func(parent SemanticNode, parentVariable string) error { + for _, child := range parent.Children { + route, err := resolveStorageRoute(parent.ResourceType, child.EdgeLabel, child.ResourceType) + if err != nil { + return err + } + nextTraversal++ + nodeVariable := fmt.Sprintf("node_%d", nextTraversal) + edgeVariable := fmt.Sprintf("edge_%d", nextTraversal) + labelBind := fmt.Sprintf("traversal_%d_label", nextTraversal) + typeBind := fmt.Sprintf("traversal_%d_target_type", nextTraversal) + edgeCollectionBind := fmt.Sprintf("traversal_%d_edge_collection", nextTraversal) + physical.BindVars[labelBind] = child.EdgeLabel + physical.BindVars[typeBind] = child.ResourceType + physical.BindVars[edgeCollectionBind] = "fhir_edge" + source := PhysicalSource{SemanticNode: child.Alias, ResourceType: child.ResourceType, Relationship: child.EdgeLabel} + physical.Operations = append(physical.Operations, PhysicalOperation{ + Kind: PhysicalTraversalOp, + Source: source, + Traversal: &PhysicalTraversal{ + SourceVariable: parentVariable, + TargetVariable: nodeVariable, + EdgeVariable: edgeVariable, + Direction: route.Direction, + EdgeCollectionBindKey: edgeCollectionBind, + EdgeLabelBindKey: labelBind, + TargetTypeBindKey: typeBind, + EdgeTargetTypeField: route.targetEdgeTypeField(), + }, + }) + // Edge metadata is not a substitute for the target resource's + // tenant boundary. Scope both documents before any subsequent + // traversal or return can observe the target node. + physical.Operations = appendProjectScope(physical.Operations, []string{edgeVariable, nodeVariable}, child.EdgeLabel, child) + physical.Operations = appendDatasetGenerationScope(physical.Operations, []string{edgeVariable, nodeVariable}, child.EdgeLabel, child) + physical.Operations = appendAuthScope(physical.Operations, []PhysicalValue{ + {Variable: edgeVariable, Path: []string{"auth_resource_path"}}, + {Variable: nodeVariable, Path: []string{"auth_resource_path"}}, + }, fmt.Sprintf("traversal_%d_scope_allowed", nextTraversal), child) + if err := walk(child, nodeVariable); err != nil { + return err + } + } + return nil + } + if err := walk(semantic.Root, "root"); err != nil { + return PhysicalPlan{}, err + } + physical.Operations = append(physical.Operations, PhysicalOperation{ + Kind: PhysicalReturnOp, + Source: PhysicalSource{SemanticNode: semantic.Root.Alias, ResourceType: semantic.Root.ResourceType, SemanticField: "_key"}, + Return: &PhysicalReturn{Projections: []PhysicalProjection{{Name: "_key", Value: PhysicalValue{Variable: "root", Path: []string{"_key"}}}}}, + }) + if err := physical.Validate(); err != nil { + return PhysicalPlan{}, fmt.Errorf("validate generic physical plan: %w", err) + } + if err := ValidateGenericPhysicalPlanScope(physical); err != nil { + return PhysicalPlan{}, fmt.Errorf("verify generic physical plan scope: %w", err) + } + return physical, nil +} + +func appendProjectScope(operations []PhysicalOperation, variables []string, relationship string, node SemanticNode) []PhysicalOperation { + right := PhysicalValue{BindKey: "project"} + for _, variable := range variables { + operations = append(operations, PhysicalOperation{ + Kind: PhysicalFilterOp, + Source: PhysicalSource{SemanticNode: node.Alias, ResourceType: node.ResourceType, Relationship: relationship, SemanticField: "project"}, + Filter: &PhysicalFilter{Predicate: PhysicalPredicate{ + Operator: "EQUALS", + Left: PhysicalValue{Variable: variable, Path: []string{"project"}}, + Right: &right, + }}, + }) + } + return operations +} + +// appendDatasetGenerationScope applies the same exact generation bind to +// every physical document participating in a scan/traversal. With a nil bind +// value this renders `dataset_generation == null`, deliberately isolating +// legacy documents from later generation-qualified loads. +func appendDatasetGenerationScope(operations []PhysicalOperation, variables []string, relationship string, node SemanticNode) []PhysicalOperation { + right := PhysicalValue{BindKey: datasetGenerationBindKey} + for _, variable := range variables { + operations = append(operations, PhysicalOperation{ + Kind: PhysicalFilterOp, + Source: PhysicalSource{SemanticNode: node.Alias, ResourceType: node.ResourceType, Relationship: relationship, SemanticField: datasetGenerationField}, + Filter: &PhysicalFilter{Predicate: PhysicalPredicate{ + Operator: "EQUALS", + Left: PhysicalValue{Variable: variable, Path: []string{datasetGenerationField}}, + Right: &right, + }}, + }) + } + return operations +} + +func appendAuthScope(operations []PhysicalOperation, scopedValues []PhysicalValue, resultVariable string, node SemanticNode) []PhysicalOperation { + inputs := append([]PhysicalValue(nil), scopedValues...) + inputs = append(inputs, PhysicalValue{BindKey: "auth_resource_paths"}, PhysicalValue{BindKey: "auth_resource_paths_unrestricted"}) + operations = append(operations, PhysicalOperation{ + Kind: PhysicalDerivedLetOp, + Source: PhysicalSource{SemanticNode: node.Alias, ResourceType: node.ResourceType, Relationship: node.EdgeLabel, SemanticField: "auth_resource_path"}, + DerivedLet: &PhysicalDerivedLet{Variable: resultVariable, Operator: "AUTH_RESOURCE_PATH_ALLOWED", Inputs: inputs}, + }) + right := PhysicalValue{BindKey: "scope_allowed"} + return append(operations, PhysicalOperation{ + Kind: PhysicalFilterOp, + Source: PhysicalSource{SemanticNode: node.Alias, ResourceType: node.ResourceType, Relationship: node.EdgeLabel, SemanticField: "auth_resource_path"}, + Filter: &PhysicalFilter{Predicate: PhysicalPredicate{Operator: "EQUALS", Left: PhysicalValue{Variable: resultVariable}, Right: &right}}, + }) +} + +func validateNavigationOnlyNode(node SemanticNode) error { + if node.MatchMode.required() { + return fmt.Errorf("semantic node %q requires a relationship match, which is not supported by the navigation-only physical plan", node.Alias) + } + if len(node.Fields) != 0 || len(node.Filters) != 0 || len(node.Pivots) != 0 || len(node.Aggregates) != 0 || len(node.Slices) != 0 { + return fmt.Errorf("semantic node %q contains selections or filters not supported by generic physical navigation", node.Alias) + } + for _, child := range node.Children { + if err := validateNavigationOnlyNode(child); err != nil { + return err + } + } + return nil +} diff --git a/internal/dataframe/generic_physical_plan_test.go b/internal/dataframe/generic_physical_plan_test.go new file mode 100644 index 0000000..5110c09 --- /dev/null +++ b/internal/dataframe/generic_physical_plan_test.go @@ -0,0 +1,92 @@ +package dataframe + +import ( + "strings" + "testing" +) + +func TestBuildGenericPhysicalPlanNavigationSkeleton(t *testing.T) { + semantic := SemanticPlan{ + Version: 1, + Project: "project-1", + AuthResourcePaths: []string{"/programs/p1"}, + Root: SemanticNode{ + Alias: "root", ResourceType: "Patient", + Children: []SemanticNode{{ + Alias: "specimen", ResourceType: "Specimen", EdgeLabel: "subject_Patient", + Children: []SemanticNode{{Alias: "file", ResourceType: "DocumentReference", EdgeLabel: "subject_Specimen"}}, + }}, + }, + } + plan, err := BuildGenericPhysicalPlan(semantic) + if err != nil { + t.Fatal(err) + } + if err := plan.Validate(); err != nil { + t.Fatalf("built plan does not validate: %v", err) + } + if plan.BindVars["root_collection"] != "Patient" || plan.BindVars["traversal_1_edge_collection"] != "fhir_edge" || plan.BindVars["traversal_1_label"] != "subject_Patient" || plan.BindVars["traversal_1_target_type"] != "Specimen" { + t.Fatalf("unexpected bound physical values: %#v", plan.BindVars) + } + if plan.BindVars["auth_resource_paths_unrestricted"] != false { + t.Fatalf("unexpected auth mode: %#v", plan.BindVars) + } + + traversals := 0 + authPredicates := 0 + for _, operation := range plan.Operations { + if operation.Traversal != nil { + traversals++ + if operation.Traversal.Direction != PhysicalInbound { + t.Fatalf("generic traversal direction = %q", operation.Traversal.Direction) + } + if operation.Traversal.EdgeTargetTypeField != "from_type" { + t.Fatalf("generic inbound traversal edge discriminator = %q", operation.Traversal.EdgeTargetTypeField) + } + if operation.Source.SemanticNode == "" || operation.Source.Relationship == "" { + t.Fatalf("traversal lost provenance: %#v", operation.Source) + } + } + if operation.DerivedLet != nil && operation.DerivedLet.Operator == "AUTH_RESOURCE_PATH_ALLOWED" { + authPredicates++ + } + } + if traversals != 2 || authPredicates != 3 { + t.Fatalf("traversals=%d auth predicates=%d operations=%#v", traversals, authPredicates, plan.Operations) + } + last := plan.Operations[len(plan.Operations)-1] + if last.Kind != PhysicalReturnOp || len(last.Return.Projections) != 1 || last.Return.Projections[0].Name != "_key" { + t.Fatalf("unexpected terminal return: %#v", last) + } +} + +func TestBuildGenericPhysicalPlanEmptyAuthScopeIsExplicit(t *testing.T) { + plan, err := BuildGenericPhysicalPlan(SemanticPlan{Version: 1, Project: "p", Root: SemanticNode{Alias: "root", ResourceType: "Observation"}}) + if err != nil { + t.Fatal(err) + } + if plan.BindVars["auth_resource_paths_unrestricted"] != true { + t.Fatalf("empty auth paths were not represented as unrestricted: %#v", plan.BindVars) + } +} + +func TestBuildGenericPhysicalPlanRejectsUnsupportedSemanticFeatures(t *testing.T) { + tests := []struct { + name string + root SemanticNode + want string + }{ + {"unknown root", SemanticNode{Alias: "root", ResourceType: "Unknown"}, "not represented"}, + {"root field", SemanticNode{Alias: "root", ResourceType: "Patient", Fields: []SemanticField{{Name: "gender"}}}, "not supported"}, + {"child filter", SemanticNode{Alias: "root", ResourceType: "Patient", Children: []SemanticNode{{Alias: "specimen", ResourceType: "Specimen", EdgeLabel: "subject_Patient", Filters: []TypedFilter{{FieldRef: "status"}}}}}, "not supported"}, + {"unknown traversal", SemanticNode{Alias: "root", ResourceType: "Patient", Children: []SemanticNode{{Alias: "medication", ResourceType: "Medication", EdgeLabel: "missing"}}}, "not represented"}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + _, err := BuildGenericPhysicalPlan(SemanticPlan{Version: 1, Project: "p", Root: test.root}) + if err == nil || !strings.Contains(err.Error(), test.want) { + t.Fatalf("error = %v; want substring %q", err, test.want) + } + }) + } +} diff --git a/internal/dataframe/grain.go b/internal/dataframe/grain.go new file mode 100644 index 0000000..9d63511 --- /dev/null +++ b/internal/dataframe/grain.go @@ -0,0 +1,221 @@ +package dataframe + +import ( + "fmt" + "strings" + + "github.com/calypr/loom/internal/fhirschema" +) + +// RowGrain identifies the resource represented by one output row. +type RowGrain string + +const ( + // RowGrainResource is the safe fallback for a generated FHIR resource that + // does not yet have a product-specific "one row per" label. It still has a + // stable root resource identity and is therefore safe to compile. + RowGrainResource RowGrain = "resource" + RowGrainPatient RowGrain = "patient" + RowGrainSpecimen RowGrain = "specimen" + RowGrainFile RowGrain = "file" + RowGrainDiagnosis RowGrain = "diagnosis" + RowGrainObservation RowGrain = "observation" + RowGrainStudyEnrollment RowGrain = "study_enrollment" +) + +func (g RowGrain) Validate() error { + switch g { + case RowGrainResource, RowGrainPatient, RowGrainSpecimen, RowGrainFile, RowGrainDiagnosis, + RowGrainObservation, RowGrainStudyEnrollment: + return nil + case "": + return fmt.Errorf("row grain is required") + default: + return fmt.Errorf("unsupported row grain %q", g) + } +} + +// InferRowGrain returns the product grain naturally represented by a generated +// FHIR root type. Valid schema resource types without a named product grain use +// RowGrainResource so every valid semantic request still carries a stable row +// identity. +func InferRowGrain(resourceType string) (RowGrain, bool) { + switch strings.TrimSpace(resourceType) { + case "Patient": + return RowGrainPatient, true + case "Specimen": + return RowGrainSpecimen, true + case "DocumentReference": + return RowGrainFile, true + case "Condition": + return RowGrainDiagnosis, true + case "Observation": + return RowGrainObservation, true + case "ResearchSubject": + return RowGrainStudyEnrollment, true + default: + if fhirschema.HasResource(resourceType) { + return RowGrainResource, true + } + return "", false + } +} + +// RootResourceForGrain returns the only root resource type currently capable +// of representing a named product grain without row expansion. The generic +// resource grain deliberately accepts any generated resource root. +func RootResourceForGrain(grain RowGrain) (string, bool) { + switch grain { + case RowGrainResource: + return "", true + case RowGrainPatient: + return "Patient", true + case RowGrainSpecimen: + return "Specimen", true + case RowGrainFile: + return "DocumentReference", true + case RowGrainDiagnosis: + return "Condition", true + case RowGrainObservation: + return "Observation", true + case RowGrainStudyEnrollment: + return "ResearchSubject", true + default: + return "", false + } +} + +// ValidateRootGrain prevents an API caller from asking for a named row grain +// while compiling rows rooted at a different resource. Cross-grain output will +// require an explicit future EXPLODE/root-rewrite operation; accepting it now +// would silently lie about the output identity. +func ValidateRootGrain(resourceType string, grain RowGrain) error { + if err := grain.Validate(); err != nil { + return err + } + if !fhirschema.HasResource(resourceType) { + return fmt.Errorf("root resource type %q is not represented by the active generated FHIR schema", resourceType) + } + expected, ok := RootResourceForGrain(grain) + if !ok { + return fmt.Errorf("unsupported row grain %q", grain) + } + if expected != "" && resourceType != expected { + return fmt.Errorf("row grain %q requires root resource type %q, got %q", grain, expected, resourceType) + } + return nil +} + +// DefaultRowIdentity uses the immutable project/key pair emitted by the graph +// loader. The grain remains explicit so downstream code cannot silently use a +// related resource as the output identity. +func DefaultRowIdentity(grain RowGrain) (RowIdentity, bool) { + if err := grain.Validate(); err != nil { + return RowIdentity{}, false + } + return RowIdentity{Grain: grain, Fields: []string{"project", "_key"}}, true +} + +// ProjectionMode defines how values at a selected path contribute to a row. +type ProjectionMode string + +const ( + ProjectionScalar ProjectionMode = "scalar" + ProjectionFirst ProjectionMode = "first" + ProjectionArray ProjectionMode = "array" + ProjectionDistinctArray ProjectionMode = "distinct_array" + ProjectionAggregate ProjectionMode = "aggregate" + ProjectionPivot ProjectionMode = "pivot" + ProjectionExplode ProjectionMode = "explode" +) + +func (m ProjectionMode) Validate() error { + switch m { + case ProjectionScalar, ProjectionFirst, ProjectionArray, + ProjectionDistinctArray, ProjectionAggregate, ProjectionPivot, + ProjectionExplode: + return nil + case "": + return fmt.Errorf("projection mode is required") + default: + return fmt.Errorf("unsupported projection mode %q", m) + } +} + +// ExpandsRows reports whether the projection deliberately changes row +// multiplicity instead of reducing values into the current row grain. +func (m ProjectionMode) ExpandsRows() bool { return m == ProjectionExplode } + +// Cardinality describes the formal multiplicity of a relationship or field. +// Observed data may refine UnknownObservedMany, but must not weaken a declared +// required, optional, or repeated relationship. +type Cardinality string + +const ( + CardinalityRequiredOne Cardinality = "required_one" + CardinalityOptionalOne Cardinality = "optional_one" + CardinalityMany Cardinality = "many" + CardinalityUnknownObservedMany Cardinality = "unknown_observed_many" +) + +func (c Cardinality) Validate() error { + switch c { + case CardinalityRequiredOne, CardinalityOptionalOne, CardinalityMany, + CardinalityUnknownObservedMany: + return nil + case "": + return fmt.Errorf("cardinality is required") + default: + return fmt.Errorf("unsupported cardinality %q", c) + } +} + +func (c Cardinality) AllowsMany() bool { + return c == CardinalityMany || c == CardinalityUnknownObservedMany +} + +func (c Cardinality) IsRequired() bool { return c == CardinalityRequiredOne } + +// ValidateProjection rejects implicit row expansion. Repeated values must be +// reduced explicitly or deliberately exploded into rows. +func ValidateProjection(cardinality Cardinality, mode ProjectionMode) error { + if err := cardinality.Validate(); err != nil { + return err + } + if err := mode.Validate(); err != nil { + return err + } + if cardinality.AllowsMany() && mode == ProjectionScalar { + return fmt.Errorf("scalar projection cannot represent %s cardinality", cardinality) + } + return nil +} + +// RowIdentity declares the stable fields that uniquely identify a row at a +// particular grain. Fields are ordered so callers can construct deterministic +// composite keys. +type RowIdentity struct { + Grain RowGrain + Fields []string +} + +func (i RowIdentity) Validate() error { + if err := i.Grain.Validate(); err != nil { + return err + } + if len(i.Fields) == 0 { + return fmt.Errorf("row identity requires at least one field") + } + seen := make(map[string]struct{}, len(i.Fields)) + for index, field := range i.Fields { + field = strings.TrimSpace(field) + if field == "" { + return fmt.Errorf("row identity field %d is empty", index) + } + if _, exists := seen[field]; exists { + return fmt.Errorf("row identity field %q is duplicated", field) + } + seen[field] = struct{}{} + } + return nil +} diff --git a/internal/dataframe/grain_test.go b/internal/dataframe/grain_test.go new file mode 100644 index 0000000..83b13e4 --- /dev/null +++ b/internal/dataframe/grain_test.go @@ -0,0 +1,133 @@ +package dataframe + +import "testing" + +func TestRowGrainValidate(t *testing.T) { + for _, grain := range []RowGrain{ + RowGrainResource, RowGrainPatient, RowGrainSpecimen, RowGrainFile, RowGrainDiagnosis, + RowGrainObservation, RowGrainStudyEnrollment, + } { + if err := grain.Validate(); err != nil { + t.Errorf("Validate(%q): %v", grain, err) + } + } + for _, grain := range []RowGrain{"", "encounter"} { + if err := grain.Validate(); err == nil { + t.Errorf("Validate(%q) unexpectedly succeeded", grain) + } + } +} + +func TestProjectionModeProperties(t *testing.T) { + modes := []ProjectionMode{ + ProjectionScalar, ProjectionFirst, ProjectionArray, + ProjectionDistinctArray, ProjectionAggregate, ProjectionPivot, + ProjectionExplode, + } + for _, mode := range modes { + if err := mode.Validate(); err != nil { + t.Errorf("Validate(%q): %v", mode, err) + } + if got := mode.ExpandsRows(); got != (mode == ProjectionExplode) { + t.Errorf("ExpandsRows(%q) = %v", mode, got) + } + } + if err := ProjectionMode("flatten").Validate(); err == nil { + t.Fatal("unknown projection mode unexpectedly succeeded") + } +} + +func TestCardinalityProperties(t *testing.T) { + tests := []struct { + cardinality Cardinality + many bool + required bool + }{ + {CardinalityRequiredOne, false, true}, + {CardinalityOptionalOne, false, false}, + {CardinalityMany, true, false}, + {CardinalityUnknownObservedMany, true, false}, + } + for _, test := range tests { + if err := test.cardinality.Validate(); err != nil { + t.Errorf("Validate(%q): %v", test.cardinality, err) + } + if got := test.cardinality.AllowsMany(); got != test.many { + t.Errorf("AllowsMany(%q) = %v", test.cardinality, got) + } + if got := test.cardinality.IsRequired(); got != test.required { + t.Errorf("IsRequired(%q) = %v", test.cardinality, got) + } + } +} + +func TestValidateProjection(t *testing.T) { + if err := ValidateProjection(CardinalityMany, ProjectionScalar); err == nil { + t.Fatal("many-to-scalar projection unexpectedly succeeded") + } + for _, mode := range []ProjectionMode{ + ProjectionFirst, ProjectionArray, ProjectionDistinctArray, + ProjectionAggregate, ProjectionPivot, ProjectionExplode, + } { + if err := ValidateProjection(CardinalityMany, mode); err != nil { + t.Errorf("many-to-%s projection: %v", mode, err) + } + } + if err := ValidateProjection(CardinalityRequiredOne, ProjectionScalar); err != nil { + t.Errorf("one-to-scalar projection: %v", err) + } +} + +func TestRowIdentityValidate(t *testing.T) { + valid := RowIdentity{Grain: RowGrainFile, Fields: []string{"project", "id"}} + if err := valid.Validate(); err != nil { + t.Fatalf("valid identity: %v", err) + } + + tests := []RowIdentity{ + {}, + {Grain: RowGrainFile}, + {Grain: RowGrainFile, Fields: []string{"id", " "}}, + {Grain: RowGrainFile, Fields: []string{"id", "id"}}, + } + for _, identity := range tests { + if err := identity.Validate(); err == nil { + t.Errorf("invalid identity %#v unexpectedly succeeded", identity) + } + } +} + +func TestInferRowGrainAndDefaultIdentity(t *testing.T) { + for resourceType, want := range map[string]RowGrain{ + "Patient": RowGrainPatient, + "Specimen": RowGrainSpecimen, + "DocumentReference": RowGrainFile, + "Condition": RowGrainDiagnosis, + "Observation": RowGrainObservation, + "ResearchSubject": RowGrainStudyEnrollment, + } { + grain, ok := InferRowGrain(resourceType) + if !ok || grain != want { + t.Fatalf("InferRowGrain(%q) = %q, %v; want %q, true", resourceType, grain, ok, want) + } + identity, ok := DefaultRowIdentity(grain) + if !ok || identity.Grain != grain || len(identity.Fields) != 2 { + t.Fatalf("DefaultRowIdentity(%q) = %#v, %v", grain, identity, ok) + } + } + if grain, ok := InferRowGrain("Organization"); !ok || grain != RowGrainResource { + t.Fatalf("Organization generic row grain = %q, %v; want %q, true", grain, ok, RowGrainResource) + } +} + +func TestValidateRootGrainRejectsImplicitCrossGrainOutput(t *testing.T) { + if err := ValidateRootGrain("Specimen", RowGrainSpecimen); err != nil { + t.Fatalf("matching named grain: %v", err) + } + if err := ValidateRootGrain("Organization", RowGrainResource); err != nil { + t.Fatalf("generic generated root: %v", err) + } + if err := ValidateRootGrain("Patient", RowGrainSpecimen); err == nil { + t.Fatal("cross-grain root unexpectedly accepted") + } +} diff --git a/internal/dataframe/lowered_compile.go b/internal/dataframe/lowered_compile.go index 076f8fa..d3bc38a 100644 --- a/internal/dataframe/lowered_compile.go +++ b/internal/dataframe/lowered_compile.go @@ -14,16 +14,22 @@ const ( ) func compileLowered(builder Builder, limit int) (CompiledQuery, error) { + genericSetRoutes, err := resolveGenericLoweredStorageRoutes(builder) + if err != nil { + return CompiledQuery{}, err + } c := &compiler{ builder: builder, bindVars: map[string]any{ "project": builder.Project, + datasetGenerationBindKey: datasetGenerationBindValue(builder.DatasetGeneration), "auth_resource_paths": builder.AuthResourcePaths, - "auth_resource_paths_unrestricted": len(builder.AuthResourcePaths) == 0, + "auth_resource_paths_unrestricted": builderAuthScopeUnrestricted(builder), }, - columns: []string{"_key"}, - pivotFields: []string{}, - pivotExprs: map[string]string{}, + columns: []string{"_key"}, + pivotFields: []string{}, + pivotExprs: map[string]string{}, + genericSetRoutes: genericSetRoutes, } if limit > 0 { c.bindVars["limit"] = limit @@ -41,9 +47,20 @@ func compileLowered(builder Builder, limit int) (CompiledQuery, error) { lets = append(lets, let) setModes[set.Name] = mode } + rootFilter, err := c.compileTypedFilters(rootVar+".payload", builder.Filters) + if err != nil { + return CompiledQuery{}, err + } + requiredMatchFilters, err := c.compileRequiredTraversalMatches(rootVar, builder.RequiredTraversalMatches) + if err != nil { + return CompiledQuery{}, err + } for _, field := range builder.Fields { - sel, _ := ParseSelector(field.Select) + sel, err := ParseSelector(field.Select) + if err != nil { + return CompiledQuery{}, fmt.Errorf("root field %q selector: %w", field.Name, err) + } expr, err := c.compileRootFieldSelect(rootVar+".payload", field, sel) if err != nil { return CompiledQuery{}, err @@ -52,8 +69,14 @@ func compileLowered(builder Builder, limit int) (CompiledQuery, error) { c.columns = append(c.columns, field.Name) } for _, pivot := range builder.Pivots { - keySel, _ := ParseSelector(pivot.ColumnSelect) - valueSel, _ := ParseSelector(pivot.ValueSelect) + keySel, err := ParseSelector(pivot.ColumnSelect) + if err != nil { + return CompiledQuery{}, fmt.Errorf("root pivot %q key selector: %w", pivot.Name, err) + } + valueSel, err := ParseSelector(pivot.ValueSelect) + if err != nil { + return CompiledQuery{}, fmt.Errorf("root pivot %q value selector: %w", pivot.Name, err) + } colName := sanitizeColumnName(pivot.Name) expr, err := c.compileRootPivot(rootVar+".payload", keySel, valueSel, pivot.Columns) if err != nil { @@ -115,7 +138,14 @@ func compileLowered(builder Builder, limit int) (CompiledQuery, error) { var sb strings.Builder sb.WriteString(fmt.Sprintf("FOR %s IN %s\n", rootVar, builder.RootResourceType)) sb.WriteString(fmt.Sprintf(" FILTER %s.project == @project\n", rootVar)) + sb.WriteString(fmt.Sprintf(" FILTER %s.%s == @%s\n", rootVar, datasetGenerationField, datasetGenerationBindKey)) sb.WriteString(fmt.Sprintf(" FILTER @auth_resource_paths_unrestricted == true OR %s.auth_resource_path IN @auth_resource_paths\n", rootVar)) + if rootFilter != "true" { + sb.WriteString(fmt.Sprintf(" FILTER %s\n", rootFilter)) + } + for _, matchFilter := range requiredMatchFilters { + sb.WriteString(fmt.Sprintf(" FILTER %s\n", matchFilter)) + } sb.WriteString(fmt.Sprintf(" SORT %s._key\n", rootVar)) if limit > 0 { sb.WriteString(" LIMIT @limit\n") @@ -133,6 +163,7 @@ func compileLowered(builder Builder, limit int) (CompiledQuery, error) { sb.WriteString("\n }\n") return CompiledQuery{ Project: builder.Project, + DatasetGeneration: normalizeDatasetGeneration(builder.DatasetGeneration), RootResourceType: builder.RootResourceType, AuthResourcePaths: append([]string(nil), builder.AuthResourcePaths...), PlanMode: planMode(builder.PlanHint), @@ -140,6 +171,8 @@ func compileLowered(builder Builder, limit int) (CompiledQuery, error) { NamedSetCount: planNamedSetCount(builder.PlanHint), FileSummaries: planFileSummaries(builder.PlanHint), StudyLookup: planStudyLookup(builder.PlanHint), + OptimizationRules: planAppliedRules(builder.PlanHint), + RowIdentity: planRowIdentity(builder.PlanHint), Query: sb.String(), BindVars: c.bindVars, Columns: append([]string(nil), c.columns...), @@ -161,12 +194,39 @@ func (c *compiler) compileNamedSet(rootVar string, set NamedSet, modes map[strin } labelBind := c.newBind(name+"_label", set.Label) var toFilter string - if set.ToResourceType != "" { + if set.ToResourceType != "" && !set.AllTargetTypes { toBind := c.newBind(name+"_to", set.ToResourceType) toFilter = fmt.Sprintf(" FILTER __node.resourceType == @%s", toBind) } - query := fmt.Sprintf(" LET %s = UNIQUE(%s)", name, c.compileTraverseSetSource(source, set.Source != "" && set.Source != "root", labelBind, toFilter)) - return query, setModeNode, nil + filters, err := c.compileTypedFilters("__node.payload", set.Filters) + if err != nil { + return "", "", fmt.Errorf("compile filters for set %q: %w", set.Name, err) + } + if filters != "true" { + toFilter += " FILTER " + filters + } + edgeTypeFilter := "" + // A shared sibling prefix intentionally spans several target resource + // types. Its ToResourceType is only a route-validation anchor, so an + // edge type predicate here would discard every sibling except that + // anchor. Typed subsets apply their resourceType filters afterwards. + if route, generic := c.genericSetRoutes[set.Name]; generic && !set.AllTargetTypes { + edgeTypeField := route.targetEdgeTypeField() + if edgeTypeField == "" { + return "", "", fmt.Errorf("compile generic traversal set %q: %w: route direction %q has no fhir_edge target type field", set.Name, ErrUnsupportedStorageRoute, route.Direction) + } + edgeTypeBind := c.newBind(name+"_edge_target_type", set.ToResourceType) + edgeTypeFilter = fmt.Sprintf(" FILTER __edge.%s == @%s", edgeTypeField, edgeTypeBind) + } + expr := c.compileTraverseSetSource(source, set.Source != "" && set.Source != "root", set.Direction, labelBind, edgeTypeFilter, toFilter) + setExpr := expr + if set.Unique { + setExpr = fmt.Sprintf("UNIQUE(%s)", setExpr) + } + if set.SortField != "" { + setExpr = fmt.Sprintf("(FOR __item IN %s SORT __item.%s RETURN __item)", setExpr, set.SortField) + } + return fmt.Sprintf(" LET %s = %s", name, setExpr), setModeNode, nil case SetKindFilter: source := sanitizeColumnName(set.Source) lines := []string{fmt.Sprintf("FOR __item IN %s", source)} @@ -174,15 +234,25 @@ func (c *compiler) compileNamedSet(rootVar string, set NamedSet, modes map[strin typeBind := c.newBind(name+"_match", set.MatchResourceType) lines = append(lines, fmt.Sprintf(" FILTER __item.resourceType == @%s", typeBind)) } - if set.SortField != "" { - lines = append(lines, fmt.Sprintf(" SORT __item.%s", set.SortField)) + filters, err := c.compileTypedFilters("__item.payload", set.Filters) + if err != nil { + return "", "", fmt.Errorf("compile filters for set %q: %w", set.Name, err) + } + if filters != "true" { + lines = append(lines, " FILTER "+filters) } lines = append(lines, " RETURN __item") - query := " LET " + name + " = (\n " + strings.Join(lines, "\n ") + "\n )" + setExpr := "(\n " + strings.Join(lines, "\n ") + "\n )" if set.Unique { - query = fmt.Sprintf(" LET %s = UNIQUE(%s)", name, strings.TrimPrefix(query, " LET "+name+" = ")) + setExpr = fmt.Sprintf("UNIQUE(%s)", setExpr) } - return query, modes[set.Source], nil + // UNIQUE is allowed to choose its own internal implementation order. + // Reapply the requested stable order after deduplication rather than + // assuming the order of the input subquery survives it. + if set.SortField != "" { + setExpr = fmt.Sprintf("(FOR __item IN %s SORT __item.%s RETURN __item)", setExpr, set.SortField) + } + return fmt.Sprintf(" LET %s = %s", name, setExpr), modes[set.Source], nil case SetKindUnion: parts := make([]string, 0, len(set.Sources)) mode := setModeNode @@ -293,7 +363,7 @@ func (c *compiler) compileDerivedPivotMapLets(rootVar string, fields []DerivedFi RETURN { key: __key, values: __values } ) COLLECT __key = __pair.key INTO __group - LET __flat_values = UNIQUE(FLATTEN(__group[*].__pair.values)) + LET __flat_values = SORTED_UNIQUE(FLATTEN(__group[*].__pair.values)) FILTER LENGTH(__flat_values) > 0 RETURN { [__key]: FIRST(__flat_values) } )`, group.letName, group.sourceExpr, keyExpr, valueExpr, filterLine) @@ -314,11 +384,15 @@ func (c *compiler) compilePivotMapProjection(mapVar string, columns []string) st )`, colsBind, mapVar, mapVar) } -func (c *compiler) compileTraverseSetSource(source string, sourceIsSet bool, labelBind string, toFilter string) string { +func (c *compiler) compileTraverseSetSource(source string, sourceIsSet bool, direction string, labelBind string, edgeTypeFilter string, toFilter string) string { + direction = strings.ToUpper(strings.TrimSpace(direction)) + if direction == "" { + direction = "INBOUND" + } if sourceIsSet { - return fmt.Sprintf("(FLATTEN(FOR __parent IN %s FOR __node, __edge IN 1..1 INBOUND __parent fhir_edge FILTER __edge.project == @project FILTER @auth_resource_paths_unrestricted == true OR (__edge.auth_resource_path IN @auth_resource_paths AND __node.auth_resource_path IN @auth_resource_paths) FILTER __edge.label == @%s%s RETURN [__node]))", source, labelBind, toFilter) + return fmt.Sprintf("(FLATTEN(FOR __parent IN %s FOR __node, __edge IN 1..1 %s __parent fhir_edge FILTER __edge.project == @project FILTER __node.project == @project FILTER __edge.%s == @%s FILTER __node.%s == @%s FILTER @auth_resource_paths_unrestricted == true OR (__edge.auth_resource_path IN @auth_resource_paths AND __node.auth_resource_path IN @auth_resource_paths) FILTER __edge.label == @%s%s%s RETURN [__node]))", source, direction, datasetGenerationField, datasetGenerationBindKey, datasetGenerationField, datasetGenerationBindKey, labelBind, edgeTypeFilter, toFilter) } - return fmt.Sprintf("(FOR __node, __edge IN 1..1 INBOUND %s fhir_edge FILTER __edge.project == @project FILTER @auth_resource_paths_unrestricted == true OR (__edge.auth_resource_path IN @auth_resource_paths AND __node.auth_resource_path IN @auth_resource_paths) FILTER __edge.label == @%s%s RETURN __node)", source, labelBind, toFilter) + return fmt.Sprintf("(FOR __node, __edge IN 1..1 %s %s fhir_edge FILTER __edge.project == @project FILTER __node.project == @project FILTER __edge.%s == @%s FILTER __node.%s == @%s FILTER @auth_resource_paths_unrestricted == true OR (__edge.auth_resource_path IN @auth_resource_paths AND __node.auth_resource_path IN @auth_resource_paths) FILTER __edge.label == @%s%s%s RETURN __node)", direction, source, datasetGenerationField, datasetGenerationBindKey, datasetGenerationField, datasetGenerationBindKey, labelBind, edgeTypeFilter, toFilter) } func (c *compiler) compileDerivedField(rootVar string, field DerivedField, modes map[string]setMode) (string, error) { @@ -328,8 +402,6 @@ func (c *compiler) compileDerivedField(rootVar string, field DerivedField, modes } } switch strings.ToUpper(strings.TrimSpace(field.Operation)) { - case DerivedOpRawExpr: - return field.RawExpr, nil case DerivedOpConst: return literalExpr(field.ConstValue), nil case DerivedOpRootField: @@ -349,12 +421,23 @@ func (c *compiler) compileDerivedField(rootVar string, field DerivedField, modes return "", err } return fmt.Sprintf("LENGTH(%s)", uniqueExpr), nil + case DerivedOpMin, DerivedOpMax: + values, err := c.compileAllField(rootVar, field, modes) + if err != nil { + return "", err + } + return fmt.Sprintf("%s(%s)", strings.ToUpper(strings.TrimSpace(field.Operation)), values), nil case DerivedOpCountWhere: return fmt.Sprintf("LENGTH(FOR __item IN %s FILTER %s RETURN 1)", sanitizeColumnName(field.Source), c.compilePredicateExpr("__item", modes[field.Source], field.Predicate, field.PredicatePath, field.PredicateEquals)), nil case DerivedOpAny: + if strings.TrimSpace(field.Predicate) == "" && strings.TrimSpace(field.PredicatePath) == "" { + return fmt.Sprintf("LENGTH(%s) > 0", sanitizeColumnName(field.Source)), nil + } return fmt.Sprintf("LENGTH(FOR __item IN %s FILTER %s LIMIT 1 RETURN 1) > 0", sanitizeColumnName(field.Source), c.compilePredicateExpr("__item", modes[field.Source], field.Predicate, field.PredicatePath, field.PredicateEquals)), nil case DerivedOpFirstNonNull: return c.compileFirstNonNullField(rootVar, field, modes) + case DerivedOpAll: + return c.compileAllField(rootVar, field, modes) case DerivedOpUnique: return c.compileUniqueField(rootVar, field, modes) case DerivedOpPivot: @@ -364,6 +447,19 @@ func (c *compiler) compileDerivedField(rootVar string, field DerivedField, modes } } +func (c *compiler) compileAllField(rootVar string, field DerivedField, modes map[string]setMode) (string, error) { + selects := append([]string{field.Select}, field.FallbackSelects...) + if field.Source == "root" || field.Source == "" { + return c.compileSelectorArrayForSelects(rootVar+".payload", selects), nil + } + setVar := sanitizeColumnName(field.Source) + mode := modes[field.Source] + return fmt.Sprintf(`FLATTEN( + FOR __item IN %s + RETURN %s + )`, setVar, c.compileSelectorArrayForSelects(setPayloadVar("__item", mode), selects)), nil +} + func (c *compiler) compileFirstNonNullField(rootVar string, field DerivedField, modes map[string]setMode) (string, error) { selects := append([]string{field.Select}, field.FallbackSelects...) if field.Source == "root" || field.Source == "" { @@ -382,11 +478,11 @@ func (c *compiler) compileFirstNonNullField(rootVar string, field DerivedField, func (c *compiler) compileUniqueField(rootVar string, field DerivedField, modes map[string]setMode) (string, error) { selects := append([]string{field.Select}, field.FallbackSelects...) if field.Source == "root" || field.Source == "" { - return fmt.Sprintf("UNIQUE(%s)", c.compileSelectorArrayForSelects(rootVar+".payload", selects)), nil + return fmt.Sprintf("SORTED_UNIQUE(%s)", c.compileSelectorArrayForSelects(rootVar+".payload", selects)), nil } setVar := sanitizeColumnName(field.Source) mode := modes[field.Source] - return fmt.Sprintf(`UNIQUE(FLATTEN( + return fmt.Sprintf(`SORTED_UNIQUE(FLATTEN( FOR __item IN %s RETURN %s ))`, setVar, c.compileSelectorArrayForSelects(setPayloadVar("__item", mode), selects)), nil @@ -457,7 +553,7 @@ func (c *compiler) compileRootAggregateExpr(payloadVar string, agg AggregateSele if err != nil { return "", err } - return fmt.Sprintf("LENGTH(UNIQUE(%s))", values), nil + return fmt.Sprintf("LENGTH(SORTED_UNIQUE(%s))", values), nil case "EXISTS": if strings.TrimSpace(agg.PredicatePath) != "" { return c.compileRootPredicateExpr(payloadVar, agg.PredicatePath, agg.PredicateEquals), nil @@ -478,7 +574,16 @@ func (c *compiler) compileRootAggregateExpr(payloadVar string, agg AggregateSele if err != nil { return "", err } - return fmt.Sprintf("UNIQUE(%s)", values), nil + return fmt.Sprintf("SORTED_UNIQUE(%s)", values), nil + case "MIN", "MAX": + if strings.TrimSpace(agg.Select) == "" { + return "", fmt.Errorf("aggregate %q requires fhirPath for %s", agg.Name, strings.ToUpper(strings.TrimSpace(agg.Operation))) + } + values, err := c.compileRootSelectorArray(payloadVar, agg.Select) + if err != nil { + return "", err + } + return fmt.Sprintf("%s(%s)", strings.ToUpper(strings.TrimSpace(agg.Operation)), values), nil default: return "", fmt.Errorf("unsupported aggregate operation %q", agg.Operation) } @@ -556,7 +661,7 @@ func (c *compiler) compileSetAggregateExpr(setVar string, agg AggregateSelect) ( if err != nil { return "", err } - return fmt.Sprintf("LENGTH(UNIQUE(FLATTEN(FOR __item IN %s RETURN %s)))", setVar, compileSelectorArrayExpr("__item.payload", sel, c)), nil + return fmt.Sprintf("LENGTH(SORTED_UNIQUE(FLATTEN(FOR __item IN %s RETURN %s)))", setVar, compileSelectorArrayExpr("__item.payload", sel, c)), nil case "EXISTS": if strings.TrimSpace(agg.PredicatePath) != "" { return fmt.Sprintf("LENGTH(FOR __item IN %s FILTER %s LIMIT 1 RETURN 1) > 0", setVar, c.compilePredicateExpr("__item", mode, "", agg.PredicatePath, agg.PredicateEquals)), nil @@ -577,7 +682,16 @@ func (c *compiler) compileSetAggregateExpr(setVar string, agg AggregateSelect) ( if err != nil { return "", err } - return fmt.Sprintf("UNIQUE(FLATTEN(FOR __item IN %s RETURN %s))", setVar, compileSelectorArrayExpr("__item.payload", sel, c)), nil + return fmt.Sprintf("SORTED_UNIQUE(FLATTEN(FOR __item IN %s RETURN %s))", setVar, compileSelectorArrayExpr("__item.payload", sel, c)), nil + case "MIN", "MAX": + if strings.TrimSpace(agg.Select) == "" { + return "", fmt.Errorf("aggregate %q requires fhirPath for %s", agg.Name, strings.ToUpper(strings.TrimSpace(agg.Operation))) + } + sel, err := ParseSelector(agg.Select) + if err != nil { + return "", err + } + return fmt.Sprintf("%s(FLATTEN(FOR __item IN %s RETURN %s))", strings.ToUpper(strings.TrimSpace(agg.Operation)), setVar, compileSelectorArrayExpr("__item.payload", sel, c)), nil default: return "", fmt.Errorf("unsupported aggregate operation %q", agg.Operation) } @@ -704,7 +818,16 @@ func compileStudyLookupSet(rootVar, researchSubjects string) string { ) LET __study_parts = __resolved_ref ? SPLIT(__resolved_ref, "/") : [] LET __study_id = LENGTH(__study_parts) == 2 ? __study_parts[1] : null - LET __study = __study_id ? DOCUMENT(CONCAT("ResearchStudy/", __study_id)) : null + LET __study = FIRST( + FOR __candidate IN ResearchStudy + FILTER __study_id != null + FILTER __candidate.project == @project + FILTER __candidate.dataset_generation == @dataset_generation + FILTER @auth_resource_paths_unrestricted == true OR __candidate.auth_resource_path IN @auth_resource_paths + FILTER __candidate.id == __study_id + LIMIT 1 + RETURN __candidate + ) FILTER __study != null RETURN __study.payload )`, researchSubjects, rootVar, rootVar) diff --git a/internal/dataframe/lowered_types.go b/internal/dataframe/lowered_types.go index 3455a45..6af8b35 100644 --- a/internal/dataframe/lowered_types.go +++ b/internal/dataframe/lowered_types.go @@ -3,6 +3,8 @@ package dataframe import ( "fmt" "strings" + + "github.com/calypr/loom/internal/fhirschema" ) const ( @@ -12,26 +14,39 @@ const ( SetKindClassifyDocumentReference = "CLASSIFY_DOCUMENT_REFERENCE" SetKindLookupStudy = "LOOKUP_STUDY" - DerivedOpRawExpr = "RAW_EXPR" DerivedOpConst = "CONST" DerivedOpRootField = "ROOT_FIELD" DerivedOpFirstNonNull = "FIRST_NON_NULL" + DerivedOpAll = "ALL" DerivedOpCount = "COUNT" DerivedOpCountDistinct = "COUNT_DISTINCT" DerivedOpCountWhere = "COUNT_WHERE" DerivedOpAny = "ANY" + DerivedOpMin = "MIN" + DerivedOpMax = "MAX" DerivedOpUnique = "UNIQUE" DerivedOpPivot = "PIVOT" ) type NamedSet struct { - Name string - Kind string - Source string - Sources []string - Label string - ToResourceType string + Name string + Kind string + Source string + Sources []string + // Direction is the physical Arango traversal direction for a TRAVERSE set. + // Empty preserves the current optimized-plan default (INBOUND). Generic + // lowering uses the proven INBOUND catalog contract until a direction- + // selection optimization has both catalog and edge-layout evidence. + Direction string + Label string + ToResourceType string + // AllTargetTypes is only used by generic sibling-prefix sharing. The + // ToResourceType above remains a generated-route validation anchor, while + // the physical traversal deliberately collects every target type for the + // shared edge label. Typed FILTER subsets consume that base set. + AllTargetTypes bool MatchResourceType string + Filters []TypedFilter Unique bool SortField string } @@ -49,7 +64,6 @@ type DerivedField struct { PivotFamily string PivotKeySelect string PivotValueSelect string - RawExpr string ConstValue any } @@ -65,6 +79,9 @@ type RepresentativeSlice struct { } func usesLoweredBuilder(builder Builder) bool { + if builder.PlanHint != nil && strings.TrimSpace(builder.PlanHint.Mode) != "" { + return true + } if len(builder.Sets) > 0 || len(builder.DerivedFields) > 0 || len(builder.RepresentativeSlices) > 0 { return true } @@ -77,6 +94,33 @@ func usesLoweredBuilder(builder Builder) bool { } func validateLoweredBuilder(builder Builder) error { + if !fhirschema.HasResource(builder.RootResourceType) { + return fmt.Errorf("root resource type %q is not represented by the active generated FHIR schema", builder.RootResourceType) + } + if builder.RowGrain != "" { + if err := ValidateRootGrain(builder.RootResourceType, builder.RowGrain); err != nil { + return err + } + } + if builder.PlanHint != nil && builder.PlanHint.RowIdentity != nil { + if err := builder.PlanHint.RowIdentity.Validate(); err != nil { + return fmt.Errorf("plan row identity: %w", err) + } + if builder.RowGrain != "" && builder.PlanHint.RowIdentity.Grain != builder.RowGrain { + return fmt.Errorf("plan row identity grain %q does not match builder row grain %q", builder.PlanHint.RowIdentity.Grain, builder.RowGrain) + } + } + for _, filter := range builder.Filters { + if err := ValidateTypedFilterForResource(builder.RootResourceType, filter); err != nil { + return fmt.Errorf("root filter %q: %w", filter.FieldRef, err) + } + } + if err := validateTraversalFilterSemantics(builder.RootResourceType, builder.Traversals); err != nil { + return err + } + if err := validateRequiredTraversalMatches(builder.RootResourceType, builder.RequiredTraversalMatches); err != nil { + return err + } seenSets := map[string]struct{}{} for _, set := range builder.Sets { if strings.TrimSpace(set.Name) == "" { @@ -86,15 +130,52 @@ func validateLoweredBuilder(builder Builder) error { return fmt.Errorf("set %q is duplicated", set.Name) } seenSets[set.Name] = struct{}{} + if set.SortField != "" && !isSafeAQLFieldIdentifier(set.SortField) { + return fmt.Errorf("set %q uses unsafe sort field %q", set.Name, set.SortField) + } switch strings.ToUpper(strings.TrimSpace(set.Kind)) { case SetKindTraverse: if set.Label == "" { return fmt.Errorf("set %q requires label", set.Name) } + if set.AllTargetTypes { + if builder.PlanHint == nil || builder.PlanHint.Profile != "generic_fhir_graph" { + return fmt.Errorf("set %q may collect all target types only in the generic FHIR graph profile", set.Name) + } + if strings.TrimSpace(set.ToResourceType) == "" { + return fmt.Errorf("set %q collecting all target types requires a generated-route validation anchor", set.Name) + } + if len(set.Filters) != 0 { + return fmt.Errorf("set %q collecting all target types must apply filters in typed subsets", set.Name) + } + } + switch strings.ToUpper(strings.TrimSpace(set.Direction)) { + case "", "INBOUND", "OUTBOUND", "ANY": + default: + return fmt.Errorf("set %q uses unsupported traversal direction %q", set.Name, set.Direction) + } + for _, filter := range set.Filters { + if err := ValidateTypedFilterForResource(set.ToResourceType, filter); err != nil { + return fmt.Errorf("set %q filter %q: %w", set.Name, filter.FieldRef, err) + } + } case SetKindFilter: if set.Source == "" { return fmt.Errorf("set %q requires source", set.Name) } + if strings.TrimSpace(set.MatchResourceType) == "" && len(set.Filters) > 0 { + return fmt.Errorf("set %q requires match resource type for typed filters", set.Name) + } + if set.MatchResourceType != "" { + if !fhirschema.HasResource(set.MatchResourceType) { + return fmt.Errorf("set %q match resource type %q is not represented by the active generated FHIR schema", set.Name, set.MatchResourceType) + } + for _, filter := range set.Filters { + if err := ValidateTypedFilterForResource(set.MatchResourceType, filter); err != nil { + return fmt.Errorf("set %q filter %q: %w", set.Name, filter.FieldRef, err) + } + } + } case SetKindUnion: if len(set.Sources) == 0 { return fmt.Errorf("set %q requires sources", set.Name) @@ -111,6 +192,9 @@ func validateLoweredBuilder(builder Builder) error { return fmt.Errorf("set %q uses unsupported kind %q", set.Name, set.Kind) } } + if err := validateGenericLoweredStorageRoutes(builder); err != nil { + return err + } seenDerived := map[string]struct{}{} for _, field := range builder.DerivedFields { @@ -122,10 +206,6 @@ func validateLoweredBuilder(builder Builder) error { } seenDerived[field.Name] = struct{}{} switch strings.ToUpper(strings.TrimSpace(field.Operation)) { - case DerivedOpRawExpr: - if strings.TrimSpace(field.RawExpr) == "" { - return fmt.Errorf("derived field %q requires rawExpr", field.Name) - } case DerivedOpConst: if field.ConstValue == nil { return fmt.Errorf("derived field %q requires const value", field.Name) @@ -134,7 +214,7 @@ func validateLoweredBuilder(builder Builder) error { if field.Select == "" { return fmt.Errorf("derived field %q requires select", field.Name) } - case DerivedOpFirstNonNull, DerivedOpUnique: + case DerivedOpFirstNonNull, DerivedOpAll, DerivedOpUnique: if field.Source == "" { return fmt.Errorf("derived field %q requires source", field.Name) } @@ -162,18 +242,21 @@ func validateLoweredBuilder(builder Builder) error { if _, err := ParseSelector(field.PivotValueSelect); err != nil { return fmt.Errorf("derived field %q invalid pivot value selector: %w", field.Name, err) } + if len(field.PivotColumns) == 0 { + return fmt.Errorf("derived field %q requires bounded pivot columns", field.Name) + } case DerivedOpCount: if field.Source == "" { return fmt.Errorf("derived field %q requires source", field.Name) } - case DerivedOpCountDistinct: + case DerivedOpCountDistinct, DerivedOpMin, DerivedOpMax: if field.Source == "" || strings.TrimSpace(field.Select) == "" { return fmt.Errorf("derived field %q requires source and select", field.Name) } if _, err := ParseSelector(field.Select); err != nil { return fmt.Errorf("derived field %q invalid select: %w", field.Name, err) } - case DerivedOpCountWhere, DerivedOpAny: + case DerivedOpCountWhere: if field.Source == "" { return fmt.Errorf("derived field %q requires source", field.Name) } @@ -185,6 +268,17 @@ func validateLoweredBuilder(builder Builder) error { return fmt.Errorf("derived field %q invalid predicatePath: %w", field.Name, err) } } + case DerivedOpAny: + if field.Source == "" { + return fmt.Errorf("derived field %q requires source", field.Name) + } + if strings.TrimSpace(field.Predicate) != "" || strings.TrimSpace(field.PredicatePath) != "" { + if strings.TrimSpace(field.PredicatePath) != "" { + if _, err := ParseSelector(field.PredicatePath); err != nil { + return fmt.Errorf("derived field %q invalid predicatePath: %w", field.Name, err) + } + } + } default: return fmt.Errorf("derived field %q uses unsupported operation %q", field.Name, field.Operation) } @@ -216,3 +310,26 @@ func validateLoweredBuilder(builder Builder) error { } return nil } + +func validateTraversalFilterSemantics(sourceResourceType string, traversals []TraversalStep) error { + for _, step := range traversals { + if err := step.MatchMode.Validate(); err != nil { + return fmt.Errorf("traversal %s -> %s (%s): %w", sourceResourceType, step.ToResourceType, step.Label, err) + } + if !fhirschema.HasResource(step.ToResourceType) { + return fmt.Errorf("traversal target resource type %q is not represented by the active generated FHIR schema", step.ToResourceType) + } + if _, err := resolveStorageRoute(sourceResourceType, step.Label, step.ToResourceType); err != nil { + return fmt.Errorf("traversal %s -> %s (%s): %w", sourceResourceType, step.ToResourceType, step.Label, err) + } + for _, filter := range step.Filters { + if err := ValidateTypedFilterForResource(step.ToResourceType, filter); err != nil { + return fmt.Errorf("traversal %s -> %s filter %q: %w", sourceResourceType, step.ToResourceType, filter.FieldRef, err) + } + } + if err := validateTraversalFilterSemantics(step.ToResourceType, step.Traversals); err != nil { + return err + } + } + return nil +} diff --git a/internal/dataframe/optimizer.go b/internal/dataframe/optimizer.go new file mode 100644 index 0000000..ea1ec9e --- /dev/null +++ b/internal/dataframe/optimizer.go @@ -0,0 +1,21 @@ +package dataframe + +// Stable optimizer-rule identifiers appear in compiler explain output and +// conformance evidence. They are deliberately independent of AQL text. +const ( + OptimizerRuleFilterPushdown = "push_down_typed_filters" + OptimizerRuleTraversalSharing = "share_identical_traversals" + // OptimizerRuleRelationshipSemiJoin records that REQUIRED relationship + // matches became root-scoped bounded existence predicates rather than + // post-projection filters. + OptimizerRuleRelationshipSemiJoin = "root_relationship_semi_join" +) + +func containsOptimizerRule(rules []string, want string) bool { + for _, rule := range rules { + if rule == want { + return true + } + } + return false +} diff --git a/internal/dataframe/optimizer_traversal_sharing_test.go b/internal/dataframe/optimizer_traversal_sharing_test.go new file mode 100644 index 0000000..2c900a2 --- /dev/null +++ b/internal/dataframe/optimizer_traversal_sharing_test.go @@ -0,0 +1,280 @@ +package dataframe + +import ( + "strings" + "testing" +) + +func TestGenericLoweringSharesIdenticalTraversalPrefixes(t *testing.T) { + planned, err := Lower(Builder{ + Project: "P1", RootResourceType: "Specimen", + Traversals: []TraversalStep{ + {Label: "subject_Specimen", ToResourceType: "DocumentReference", Alias: "file_primary", Fields: []FieldSelect{{Name: "title", Select: "content[].attachment.title"}}}, + {Label: "subject_Specimen", ToResourceType: "DocumentReference", Alias: "file_secondary", Fields: []FieldSelect{{Name: "url", Select: "content[].attachment.url"}}}, + }, + }) + if err != nil { + t.Fatal(err) + } + if len(planned.Sets) != 1 { + t.Fatalf("identical generic traversal sets = %#v, want one shared set", planned.Sets) + } + if len(planned.DerivedFields) != 2 || planned.DerivedFields[0].Source != planned.Sets[0].Name || planned.DerivedFields[1].Source != planned.Sets[0].Name { + t.Fatalf("derived fields did not reuse the shared set: %#v / %#v", planned.Sets, planned.DerivedFields) + } + if planned.PlanHint == nil || len(planned.PlanHint.AppliedRules) != 1 || planned.PlanHint.AppliedRules[0] != OptimizerRuleTraversalSharing { + t.Fatalf("applied optimizer rules = %#v", planned.PlanHint) + } + compiled, err := Compile(planned, 1) + if err != nil { + t.Fatal(err) + } + if len(compiled.OptimizationRules) != 1 || compiled.OptimizationRules[0] != OptimizerRuleTraversalSharing { + t.Fatalf("compiled optimizer rules = %#v", compiled.OptimizationRules) + } +} + +func TestGenericLoweringDoesNotShareTraversalsWithDifferentPredicates(t *testing.T) { + first := "first" + second := "second" + planned, err := Lower(Builder{ + Project: "P1", RootResourceType: "Specimen", + Traversals: []TraversalStep{ + { + Label: "subject_Specimen", ToResourceType: "DocumentReference", Alias: "first_file", + Filters: []TypedFilter{{FieldRef: "DocumentReference.title", Selector: "content[].attachment.title", FieldKind: FilterString, Repeated: true, Quantifier: QuantifierAny, Operator: FilterEquals, Values: []FilterValue{{Kind: FilterString, String: &first}}}}, + }, + { + Label: "subject_Specimen", ToResourceType: "DocumentReference", Alias: "second_file", + Filters: []TypedFilter{{FieldRef: "DocumentReference.title", Selector: "content[].attachment.title", FieldKind: FilterString, Repeated: true, Quantifier: QuantifierAny, Operator: FilterEquals, Values: []FilterValue{{Kind: FilterString, String: &second}}}}, + }, + }, + }) + if err != nil { + t.Fatal(err) + } + if len(planned.Sets) != 2 { + t.Fatalf("predicate-distinct traversal sets = %#v, want two sets", planned.Sets) + } + if planned.PlanHint == nil || len(planned.PlanHint.AppliedRules) != 1 || planned.PlanHint.AppliedRules[0] != OptimizerRuleFilterPushdown { + t.Fatalf("unexpected optimizer rules = %#v", planned.PlanHint) + } +} + +func TestGenericLoweringSharesSiblingPrefixAcrossTargetTypes(t *testing.T) { + conditionID := "condition-1" + specimenID := "specimen-1" + observationID := "observation-1" + planned, err := Lower(Builder{ + Project: "P1", RootResourceType: "Patient", + Traversals: []TraversalStep{ + { + Label: "subject_Patient", ToResourceType: "Condition", Alias: "condition", + Fields: []FieldSelect{{Name: "id", Select: "id", ValueMode: "ALL"}}, + Filters: []TypedFilter{{ + FieldRef: "Condition.id", Selector: "id", FieldKind: FilterString, Operator: FilterEquals, + Values: []FilterValue{{Kind: FilterString, String: &conditionID}}, + }}, + }, + { + Label: "subject_Patient", ToResourceType: "Specimen", Alias: "specimen", + Fields: []FieldSelect{{Name: "id", Select: "id", ValueMode: "ALL"}}, + Filters: []TypedFilter{{ + FieldRef: "Specimen.id", Selector: "id", FieldKind: FilterString, Operator: FilterEquals, + Values: []FilterValue{{Kind: FilterString, String: &specimenID}}, + }}, + }, + { + Label: "subject_Patient", ToResourceType: "Observation", Alias: "observation", + Fields: []FieldSelect{{Name: "id", Select: "id", ValueMode: "ALL"}}, + Filters: []TypedFilter{{ + FieldRef: "Observation.id", Selector: "id", FieldKind: FilterString, Operator: FilterEquals, + Values: []FilterValue{{Kind: FilterString, String: &observationID}}, + }}, + }, + }, + }) + if err != nil { + t.Fatal(err) + } + if planned.PlanHint == nil || planned.PlanHint.Profile != "generic_fhir_graph" { + t.Fatalf("expected generic plan, got %#v", planned.PlanHint) + } + if !containsOptimizerRule(planned.PlanHint.AppliedRules, OptimizerRuleTraversalSharing) || !containsOptimizerRule(planned.PlanHint.AppliedRules, OptimizerRuleFilterPushdown) { + t.Fatalf("expected sibling sharing and filter pushdown rules, got %#v", planned.PlanHint) + } + + base, ok := allTargetTraversal(planned.Sets) + if !ok { + t.Fatalf("missing shared sibling traversal: %#v", planned.Sets) + } + if base.Kind != SetKindTraverse || base.Direction != "INBOUND" || base.Label != "subject_Patient" || !base.AllTargetTypes || base.ToResourceType != "Condition" { + t.Fatalf("unexpected shared traversal = %#v", base) + } + if got := countNamedSetKind(planned.Sets, SetKindTraverse); got != 1 { + t.Fatalf("physical generic traversals = %d, want one shared prefix: %#v", got, planned.Sets) + } + + wantSubsets := map[string]string{ + "generic_condition_set": "Condition", + "generic_specimen_set": "Specimen", + "generic_observation_set": "Observation", + } + for name, resourceType := range wantSubsets { + subset, ok := namedSetByName(planned.Sets, name) + if !ok { + t.Fatalf("missing typed subset %q: %#v", name, planned.Sets) + } + if subset.Kind != SetKindFilter || subset.Source != base.Name || subset.MatchResourceType != resourceType || len(subset.Filters) != 1 || subset.Unique || subset.SortField != "_key" { + t.Fatalf("typed subset %q = %#v", name, subset) + } + } + for _, field := range planned.DerivedFields { + if _, ok := wantSubsets[field.Source]; !ok { + t.Fatalf("derived field %q unexpectedly escaped its typed sibling subset: %#v", field.Name, field) + } + } + + compiled, err := Compile(planned, 1) + if err != nil { + t.Fatal(err) + } + if got := strings.Count(compiled.Query, "1..1 INBOUND root fhir_edge"); got != 1 { + t.Fatalf("shared sibling query emitted %d root traversals, want one:\n%s", got, compiled.Query) + } + if strings.Contains(compiled.Query, base.Name+"_to") { + t.Fatalf("shared base accidentally retained its validation-anchor type predicate:\n%s", compiled.Query) + } + if got := strings.Count(compiled.Query, "FILTER __item.resourceType == @"); got != 3 { + t.Fatalf("typed sibling subsets = %d, want three:\n%s", got, compiled.Query) + } + if got := strings.Count(compiled.Query, "__edge.dataset_generation == @dataset_generation"); got != 1 { + t.Fatalf("shared traversal generation scope count = %d, want one:\n%s", got, compiled.Query) + } + if got := strings.Count(compiled.Query, "__edge.auth_resource_path IN @auth_resource_paths"); got != 1 { + t.Fatalf("shared traversal auth scope count = %d, want one:\n%s", got, compiled.Query) + } + for _, want := range []string{conditionID, specimenID, observationID} { + assertBindVarValue(t, compiled.BindVars, want) + } +} + +func TestGenericSiblingPrefixSharingRetainsRequiredMatch(t *testing.T) { + conditionID := "required-condition" + compiled, err := CompileRequest(Builder{ + Project: "P1", RootResourceType: "Patient", + Traversals: []TraversalStep{ + { + Label: "subject_Patient", ToResourceType: "Condition", Alias: "condition", MatchMode: TraversalMatchRequired, + Filters: []TypedFilter{{ + FieldRef: "Condition.id", Selector: "id", FieldKind: FilterString, Operator: FilterEquals, + Values: []FilterValue{{Kind: FilterString, String: &conditionID}}, + }}, + }, + {Label: "subject_Patient", ToResourceType: "Specimen", Alias: "specimen"}, + {Label: "subject_Patient", ToResourceType: "Observation", Alias: "observation"}, + }, + }, 5) + if err != nil { + t.Fatal(err) + } + if !containsOptimizerRule(compiled.OptimizationRules, OptimizerRuleTraversalSharing) || !containsOptimizerRule(compiled.OptimizationRules, OptimizerRuleRelationshipSemiJoin) { + t.Fatalf("missing shared-prefix/required-match provenance: %#v", compiled.OptimizationRules) + } + if !strings.Contains(compiled.Query, "LET generic_root_subject_Patient_neighbors_set") { + t.Fatalf("missing shared materialized sibling set:\n%s", compiled.Query) + } + if !strings.Contains(compiled.Query, "FOR __match_0_0, __match_edge_0_0 IN 1..1 INBOUND root fhir_edge") { + t.Fatalf("required sibling match was lost:\n%s", compiled.Query) + } + assertRootMatchPrecedesLimit(t, compiled.Query) +} + +func TestGenericSiblingPrefixSharingSupportsNestedChildRoutes(t *testing.T) { + gender := "female" + planned, err := Lower(Builder{ + Project: "P1", RootResourceType: "Patient", + Filters: []TypedFilter{{ + FieldRef: "Patient.gender", Selector: "gender", FieldKind: FilterString, Operator: FilterEquals, + Values: []FilterValue{{Kind: FilterString, String: &gender}}, + }}, + Traversals: []TraversalStep{ + {Label: "subject_Patient", ToResourceType: "Condition", Alias: "condition"}, + { + Label: "subject_Patient", ToResourceType: "Specimen", Alias: "specimen", + Traversals: []TraversalStep{{ + Label: "subject_Specimen", ToResourceType: "DocumentReference", Alias: "file", + Fields: []FieldSelect{{Name: "id", Select: "id", ValueMode: "ALL"}}, + }}, + }, + {Label: "subject_Patient", ToResourceType: "Observation", Alias: "observation"}, + }, + }) + if err != nil { + t.Fatal(err) + } + fileSet, ok := namedSetByName(planned.Sets, "generic_file_set") + if !ok || fileSet.Kind != SetKindTraverse || fileSet.Source != "generic_specimen_set" || fileSet.ToResourceType != "DocumentReference" { + t.Fatalf("nested route did not retain typed specimen parent: %#v", planned.Sets) + } + compiled, err := Compile(planned, 1) + if err != nil { + t.Fatalf("compile shared nested route: %v", err) + } + if got := strings.Count(compiled.Query, "1..1 INBOUND root fhir_edge"); got != 1 { + t.Fatalf("shared root prefix emitted %d root traversals, want one:\n%s", got, compiled.Query) + } + if !strings.Contains(compiled.Query, "FOR __parent IN generic_specimen_set FOR __node, __edge IN 1..1 INBOUND __parent fhir_edge") { + t.Fatalf("nested traversal did not use the typed subset parent:\n%s", compiled.Query) + } +} + +func namedSetByName(sets []NamedSet, name string) (NamedSet, bool) { + for _, set := range sets { + if set.Name == name { + return set, true + } + } + return NamedSet{}, false +} + +func countNamedSetKind(sets []NamedSet, kind string) int { + count := 0 + for _, set := range sets { + if set.Kind == kind { + count++ + } + } + return count +} + +func allTargetTraversal(sets []NamedSet) (NamedSet, bool) { + for _, set := range sets { + if set.Kind == SetKindTraverse && set.AllTargetTypes { + return set, true + } + } + return NamedSet{}, false +} + +func filterResourceTypes(sets []NamedSet, source string) map[string]struct{} { + types := map[string]struct{}{} + for _, set := range sets { + if set.Kind == SetKindFilter && set.Source == source && set.MatchResourceType != "" { + types[set.MatchResourceType] = struct{}{} + } + } + return types +} + +func sameStringSet(left, right map[string]struct{}) bool { + if len(left) != len(right) { + return false + } + for value := range left { + if _, ok := right[value]; !ok { + return false + } + } + return true +} diff --git a/internal/dataframe/physical_execution.go b/internal/dataframe/physical_execution.go new file mode 100644 index 0000000..efe6963 --- /dev/null +++ b/internal/dataframe/physical_execution.go @@ -0,0 +1,92 @@ +package dataframe + +import "fmt" + +const genericPhysicalExecutionLimitBind = "limit" + +// compileGenericPhysicalExecution is the executable bridge from the generic +// semantic graph to the typed physical renderer. Its caller has already +// established that the request is navigation-only, so the physical return +// shape (_key at the root row grain) is exactly the public dataframe shape. +func compileGenericPhysicalExecution(semantic SemanticPlan, lowered Builder, limit int) (CompiledQuery, error) { + physical, err := BuildGenericPhysicalPlan(semantic) + if err != nil { + return CompiledQuery{}, fmt.Errorf("build generic physical execution plan: %w", err) + } + physical, err = withGenericPhysicalExecutionWindow(physical, limit) + if err != nil { + return CompiledQuery{}, err + } + rendered, err := RenderPhysicalPlan(physical) + if err != nil { + return CompiledQuery{}, fmt.Errorf("render generic physical execution plan: %w", err) + } + + return CompiledQuery{ + Project: semantic.Project, + DatasetGeneration: normalizeDatasetGeneration(semantic.DatasetGeneration), + RootResourceType: semantic.Root.ResourceType, + AuthResourcePaths: cloneStrings(semantic.AuthResourcePaths), + PlanMode: planMode(lowered.PlanHint), + PlanProfile: planProfile(lowered.PlanHint), + NamedSetCount: planNamedSetCount(lowered.PlanHint), + FileSummaries: planFileSummaries(lowered.PlanHint), + StudyLookup: planStudyLookup(lowered.PlanHint), + OptimizationRules: planAppliedRules(lowered.PlanHint), + RowIdentity: planRowIdentity(lowered.PlanHint), + Query: rendered.Query, + BindVars: rendered.BindVars, + Columns: []string{"_key"}, + PivotFields: nil, + Limit: limit, + }, nil +} + +// withGenericPhysicalExecutionWindow inserts the deterministic root ordering +// and optional preview bound before any traversal LET subquery. This matches +// the established lowered renderer's row-grain semantics while ensuring an +// expensive optional navigation is evaluated only for selected root rows. +func withGenericPhysicalExecutionWindow(plan PhysicalPlan, limit int) (PhysicalPlan, error) { + if err := ValidateGenericPhysicalPlanScope(plan); err != nil { + return PhysicalPlan{}, fmt.Errorf("validate generic physical execution scope: %w", err) + } + if len(plan.Operations) == 0 || plan.Operations[0].Kind != PhysicalRootScanOp || plan.Operations[0].RootScan == nil { + return PhysicalPlan{}, fmt.Errorf("generic physical execution plan requires a root scan") + } + + // The generic scope verifier defines the root scope as every operation up + // to the first traversal or terminal return. BuildGenericPhysicalPlan has + // already proven that the whole prefix scopes the root correctly. + insertAt := physicalScopeWindowEnd(plan.Operations, 1) + if insertAt <= 1 || insertAt >= len(plan.Operations) { + return PhysicalPlan{}, fmt.Errorf("generic physical execution plan requires a scoped root followed by RETURN or traversal") + } + + out := cloneCompilerPhysicalPlan(plan) + root := out.Operations[0].RootScan.Variable + window := []PhysicalOperation{{ + Kind: PhysicalSortOp, + Source: PhysicalSource{SemanticNode: out.Source.SemanticNode, ResourceType: out.Source.ResourceType, SemanticField: "_key"}, + Sort: &PhysicalSort{Value: PhysicalValue{Variable: root, Path: []string{"_key"}}}, + }} + if limit > 0 { + if _, exists := out.BindVars[genericPhysicalExecutionLimitBind]; exists { + return PhysicalPlan{}, fmt.Errorf("generic physical execution limit bind %q is already defined", genericPhysicalExecutionLimitBind) + } + out.BindVars[genericPhysicalExecutionLimitBind] = limit + window = append(window, PhysicalOperation{ + Kind: PhysicalLimitOp, + Source: PhysicalSource{SemanticNode: out.Source.SemanticNode, ResourceType: out.Source.ResourceType}, + Limit: &PhysicalLimit{BindKey: genericPhysicalExecutionLimitBind}, + }) + } + operations := make([]PhysicalOperation, 0, len(out.Operations)+len(window)) + operations = append(operations, out.Operations[:insertAt]...) + operations = append(operations, window...) + operations = append(operations, out.Operations[insertAt:]...) + out.Operations = operations + if err := ValidateGenericPhysicalPlanScope(out); err != nil { + return PhysicalPlan{}, fmt.Errorf("validate generic physical execution window: %w", err) + } + return out, nil +} diff --git a/internal/dataframe/physical_execution_test.go b/internal/dataframe/physical_execution_test.go new file mode 100644 index 0000000..504e945 --- /dev/null +++ b/internal/dataframe/physical_execution_test.go @@ -0,0 +1,139 @@ +package dataframe + +import ( + "reflect" + "strings" + "testing" +) + +func TestCompileRequestUsesPhysicalExecutionForNavigationOnlyGenericPlan(t *testing.T) { + builder := Builder{ + Project: "P1", + DatasetGeneration: "generation-a", + AuthResourcePaths: []string{"/programs/p1"}, + RootResourceType: "Specimen", + Traversals: []TraversalStep{{ + Label: "subject_Specimen", + ToResourceType: "DocumentReference", + Alias: "file", + }}, + } + physical, err := CompileRequest(builder, 7) + if err != nil { + t.Fatalf("CompileRequest() error = %v", err) + } + if got := physical.BindVars["@root_collection"]; got != "Specimen" { + t.Fatalf("physical root collection bind = %#v", got) + } + if got := physical.BindVars["@traversal_1_edge_collection"]; got != "fhir_edge" { + t.Fatalf("physical edge collection bind = %#v", got) + } + for _, want := range []string{ + "FOR root IN @@root_collection", + "SORT root._key", + "LIMIT @limit", + "FOR node_1, edge_1 IN 1..1 INBOUND root @@traversal_1_edge_collection", + "RETURN { [@__loom_physical_projection_0_name]: root._key }", + } { + if !strings.Contains(physical.Query, want) { + t.Fatalf("physical execution query missing %q:\n%s", want, physical.Query) + } + } + if got, want := strings.Index(physical.Query, "LIMIT @limit"), strings.Index(physical.Query, "LET __loom_physical_set_1"); got < 0 || want < 0 || got > want { + t.Fatalf("root limit must occur before optional navigation materialization:\n%s", physical.Query) + } + if strings.Contains(physical.Query, "FOR root IN Specimen") || strings.Contains(physical.Query, "generic_file_set") { + t.Fatalf("navigation-only request unexpectedly used lowered string renderer:\n%s", physical.Query) + } + + lowered, err := Lower(builder) + if err != nil { + t.Fatalf("Lower() error = %v", err) + } + legacy, err := Compile(lowered, 7) + if err != nil { + t.Fatalf("Compile(lowered) error = %v", err) + } + if physical.Query == legacy.Query { + t.Fatalf("physical execution path did not render a distinct typed plan:\n%s", physical.Query) + } + assertPhysicalExecutionMetadataParity(t, physical, legacy) +} + +func TestCompileRequestFallsBackForGenericSelectionUntilPhysicalProjectionExists(t *testing.T) { + compiled, err := CompileRequest(Builder{ + Project: "P1", + RootResourceType: "Specimen", + Fields: []FieldSelect{{Name: "id", Select: "id"}}, + }, 3) + if err != nil { + t.Fatalf("CompileRequest() error = %v", err) + } + if !strings.Contains(compiled.Query, "FOR root IN Specimen") || !strings.Contains(compiled.Query, "root.payload.id") { + t.Fatalf("selection request did not use the full lowered fallback:\n%s", compiled.Query) + } + if strings.Contains(compiled.Query, "@@root_collection") { + t.Fatalf("selection request was incorrectly routed through the navigation-only physical renderer:\n%s", compiled.Query) + } +} + +func TestGenericPhysicalExecutionWindowIsTypedAndOptional(t *testing.T) { + semantic, err := BuildSemanticPlan(Builder{Project: "P1", RootResourceType: "Patient"}) + if err != nil { + t.Fatal(err) + } + plan, err := BuildGenericPhysicalPlan(semantic) + if err != nil { + t.Fatal(err) + } + plan, err = withGenericPhysicalExecutionWindow(plan, 2) + if err != nil { + t.Fatal(err) + } + if len(plan.Operations) < 8 || plan.Operations[5].Kind != PhysicalSortOp || plan.Operations[6].Kind != PhysicalLimitOp { + t.Fatalf("typed execution window = %#v", plan.Operations) + } + if got := plan.BindVars[genericPhysicalExecutionLimitBind]; got != 2 { + t.Fatalf("typed limit bind = %#v", got) + } + if err := plan.Validate(); err != nil { + t.Fatalf("windowed physical plan did not validate: %v", err) + } + + withoutLimit, err := withGenericPhysicalExecutionWindow(buildPhysicalPlanForTest(t, semantic), 0) + if err != nil { + t.Fatal(err) + } + if len(withoutLimit.Operations) < 7 || withoutLimit.Operations[5].Kind != PhysicalSortOp || withoutLimit.Operations[6].Kind == PhysicalLimitOp { + t.Fatalf("unbounded physical execution window = %#v", withoutLimit.Operations) + } +} + +func buildPhysicalPlanForTest(t *testing.T, semantic SemanticPlan) PhysicalPlan { + t.Helper() + plan, err := BuildGenericPhysicalPlan(semantic) + if err != nil { + t.Fatal(err) + } + return plan +} + +func assertPhysicalExecutionMetadataParity(t *testing.T, physical, lowered CompiledQuery) { + t.Helper() + if physical.Project != lowered.Project || + physical.DatasetGeneration != lowered.DatasetGeneration || + physical.RootResourceType != lowered.RootResourceType || + physical.PlanMode != lowered.PlanMode || + physical.PlanProfile != lowered.PlanProfile || + physical.NamedSetCount != lowered.NamedSetCount || + physical.FileSummaries != lowered.FileSummaries || + physical.StudyLookup != lowered.StudyLookup || + physical.Limit != lowered.Limit || + !reflect.DeepEqual(physical.AuthResourcePaths, lowered.AuthResourcePaths) || + !reflect.DeepEqual(physical.OptimizationRules, lowered.OptimizationRules) || + !reflect.DeepEqual(physical.RowIdentity, lowered.RowIdentity) || + !reflect.DeepEqual(physical.Columns, lowered.Columns) || + !reflect.DeepEqual(physical.PivotFields, lowered.PivotFields) { + t.Fatalf("physical metadata does not match lowered renderer:\nphysical=%#v\nlowered=%#v", physical, lowered) + } +} diff --git a/internal/dataframe/physical_plan.go b/internal/dataframe/physical_plan.go new file mode 100644 index 0000000..d61e9c5 --- /dev/null +++ b/internal/dataframe/physical_plan.go @@ -0,0 +1,345 @@ +package dataframe + +import ( + "fmt" + "regexp" + "strings" +) + +// PhysicalPlan is the renderer-independent AQL operation graph produced after +// semantic planning. Operations are ordered because AQL variables have lexical +// scope: an operation may reference only variables introduced before it. +type PhysicalPlan struct { + Version int + Source PhysicalSource + BindVars map[string]any + Operations []PhysicalOperation +} + +// PhysicalSource retains semantic provenance through physical optimization so +// explain output and compiler errors can point back to user intent. +type PhysicalSource struct { + RecipeID string + TemplateID string + SemanticNode string + SemanticField string + ResourceType string + Relationship string +} + +type PhysicalOperationKind string + +const ( + PhysicalRootScanOp PhysicalOperationKind = "ROOT_SCAN" + PhysicalTraversalOp PhysicalOperationKind = "TRAVERSAL" + PhysicalFilterOp PhysicalOperationKind = "FILTER" + PhysicalDerivedLetOp PhysicalOperationKind = "DERIVED_LET" + // PhysicalSortOp and PhysicalLimitOp describe the root execution window. + // They are intentionally typed so preview ordering and bounds cannot be + // smuggled into an AQL string by a caller. + PhysicalSortOp PhysicalOperationKind = "SORT" + PhysicalLimitOp PhysicalOperationKind = "LIMIT" + PhysicalReturnOp PhysicalOperationKind = "RETURN" +) + +// PhysicalOperation is a tagged union. Exactly one payload matching Kind must +// be set. Source can be more specific than the plan-level provenance. +type PhysicalOperation struct { + Kind PhysicalOperationKind + Source PhysicalSource + RootScan *PhysicalRootScan + Traversal *PhysicalTraversal + Filter *PhysicalFilter + DerivedLet *PhysicalDerivedLet + Sort *PhysicalSort + Limit *PhysicalLimit + Return *PhysicalReturn +} + +type PhysicalRootScan struct { + Variable string + CollectionBindKey string +} + +type PhysicalTraversalDirection string + +const ( + PhysicalOutbound PhysicalTraversalDirection = "OUTBOUND" + PhysicalInbound PhysicalTraversalDirection = "INBOUND" + PhysicalAny PhysicalTraversalDirection = "ANY" +) + +type PhysicalTraversal struct { + SourceVariable string + TargetVariable string + EdgeVariable string + Direction PhysicalTraversalDirection + EdgeCollectionBindKey string + EdgeLabelBindKey string + TargetTypeBindKey string + // EdgeTargetTypeField is a compiler-owned fhir_edge discriminator used + // alongside TargetTypeBindKey. For a parent-to-child INBOUND route it is + // from_type; for a proven forward OUTBOUND route it is to_type. The node + // resourceType check remains independently mandatory. + EdgeTargetTypeField string +} + +// PhysicalValue is either a variable/path reference or a bind variable. A +// renderer must never interpret Path segments as AQL source text. +type PhysicalValue struct { + Variable string + Path []string + BindKey string +} + +type PhysicalPredicate struct { + Operator string + Left PhysicalValue + Right *PhysicalValue +} + +type PhysicalFilter struct { + Predicate PhysicalPredicate +} + +// PhysicalDerivedLet names a derived value. Operator is a compiler-owned +// symbolic operation (for example UNIQUE or LENGTH), never raw AQL. +type PhysicalDerivedLet struct { + Variable string + Operator string + Inputs []PhysicalValue +} + +// PhysicalSort is the deliberately small ordering primitive currently needed +// by generic root-grain previews. Additional sort keys and directions should +// be added only with a corresponding semantic ordering contract. +type PhysicalSort struct { + Value PhysicalValue +} + +// PhysicalLimit references a positive integer bind value. Keeping the value +// in BindVars retains the same parameterized execution boundary as filters. +type PhysicalLimit struct { + BindKey string +} + +type PhysicalProjection struct { + Name string + Value PhysicalValue +} + +type PhysicalReturn struct { + Projections []PhysicalProjection +} + +var ( + physicalVariablePattern = regexp.MustCompile(`^[A-Za-z_][A-Za-z0-9_]*$`) + physicalBindKeyPattern = regexp.MustCompile(`^[A-Za-z][A-Za-z0-9_]*$`) + physicalPathPartPattern = regexp.MustCompile(`^[A-Za-z_][A-Za-z0-9_]*$`) +) + +// Validate enforces the frozen physical-plan invariants without rendering AQL. +func (p PhysicalPlan) Validate() error { + if p.Version <= 0 { + return fmt.Errorf("physical plan version must be positive") + } + for key := range p.BindVars { + if !physicalBindKeyPattern.MatchString(key) { + return fmt.Errorf("unsafe bind key %q", key) + } + } + defined := map[string]bool{} + rootScans := 0 + returns := 0 + for i, operation := range p.Operations { + if returns > 0 { + return fmt.Errorf("operation %d appears after RETURN", i) + } + if err := operation.validatePayload(); err != nil { + return fmt.Errorf("operation %d (%s): %w", i, operation.Kind, err) + } + switch operation.Kind { + case PhysicalRootScanOp: + rootScans++ + if rootScans > 1 { + return fmt.Errorf("operation %d: physical plan has multiple root scans", i) + } + if err := requireBind(p.BindVars, operation.RootScan.CollectionBindKey); err != nil { + return fmt.Errorf("operation %d: %w", i, err) + } + if err := definePhysicalVariable(defined, operation.RootScan.Variable); err != nil { + return fmt.Errorf("operation %d: %w", i, err) + } + case PhysicalTraversalOp: + traversal := operation.Traversal + if !defined[traversal.SourceVariable] { + return fmt.Errorf("operation %d: traversal source variable %q is out of scope", i, traversal.SourceVariable) + } + if traversal.Direction != PhysicalOutbound && traversal.Direction != PhysicalInbound && traversal.Direction != PhysicalAny { + return fmt.Errorf("operation %d: invalid traversal direction %q", i, traversal.Direction) + } + if traversal.EdgeTargetTypeField != "" && !physicalPathPartPattern.MatchString(traversal.EdgeTargetTypeField) { + return fmt.Errorf("operation %d: unsafe traversal edge type field %q", i, traversal.EdgeTargetTypeField) + } + for _, key := range []string{traversal.EdgeCollectionBindKey, traversal.EdgeLabelBindKey, traversal.TargetTypeBindKey} { + if key != "" { + if err := requireBind(p.BindVars, key); err != nil { + return fmt.Errorf("operation %d: %w", i, err) + } + } + } + if err := definePhysicalVariable(defined, traversal.TargetVariable); err != nil { + return fmt.Errorf("operation %d: %w", i, err) + } + if traversal.EdgeVariable != "" { + if err := definePhysicalVariable(defined, traversal.EdgeVariable); err != nil { + return fmt.Errorf("operation %d: %w", i, err) + } + } + case PhysicalFilterOp: + if err := validatePhysicalPredicate(operation.Filter.Predicate, defined, p.BindVars); err != nil { + return fmt.Errorf("operation %d: %w", i, err) + } + case PhysicalDerivedLetOp: + derived := operation.DerivedLet + if strings.TrimSpace(derived.Operator) == "" { + return fmt.Errorf("operation %d: derived LET operator is required", i) + } + for _, input := range derived.Inputs { + if err := validatePhysicalValue(input, defined, p.BindVars); err != nil { + return fmt.Errorf("operation %d: %w", i, err) + } + } + if err := definePhysicalVariable(defined, derived.Variable); err != nil { + return fmt.Errorf("operation %d: %w", i, err) + } + case PhysicalSortOp: + if err := validatePhysicalValue(operation.Sort.Value, defined, p.BindVars); err != nil { + return fmt.Errorf("operation %d: %w", i, err) + } + case PhysicalLimitOp: + if err := requireBind(p.BindVars, operation.Limit.BindKey); err != nil { + return fmt.Errorf("operation %d: %w", i, err) + } + limit, ok := p.BindVars[operation.Limit.BindKey].(int) + if !ok || limit <= 0 { + return fmt.Errorf("operation %d: limit bind %q must be a positive int", i, operation.Limit.BindKey) + } + case PhysicalReturnOp: + returns++ + seenNames := map[string]bool{} + for _, projection := range operation.Return.Projections { + if strings.TrimSpace(projection.Name) == "" || seenNames[projection.Name] { + return fmt.Errorf("operation %d: return projection name %q is empty or duplicated", i, projection.Name) + } + seenNames[projection.Name] = true + if err := validatePhysicalValue(projection.Value, defined, p.BindVars); err != nil { + return fmt.Errorf("operation %d projection %q: %w", i, projection.Name, err) + } + } + } + } + if rootScans != 1 { + return fmt.Errorf("physical plan requires exactly one root scan") + } + if returns != 1 { + return fmt.Errorf("physical plan requires exactly one RETURN") + } + return nil +} + +func (operation PhysicalOperation) validatePayload() error { + payloads := 0 + if operation.RootScan != nil { + payloads++ + } + if operation.Traversal != nil { + payloads++ + } + if operation.Filter != nil { + payloads++ + } + if operation.DerivedLet != nil { + payloads++ + } + if operation.Sort != nil { + payloads++ + } + if operation.Limit != nil { + payloads++ + } + if operation.Return != nil { + payloads++ + } + if payloads != 1 { + return fmt.Errorf("operation must contain exactly one payload") + } + valid := (operation.Kind == PhysicalRootScanOp && operation.RootScan != nil) || + (operation.Kind == PhysicalTraversalOp && operation.Traversal != nil) || + (operation.Kind == PhysicalFilterOp && operation.Filter != nil) || + (operation.Kind == PhysicalDerivedLetOp && operation.DerivedLet != nil) || + (operation.Kind == PhysicalSortOp && operation.Sort != nil) || + (operation.Kind == PhysicalLimitOp && operation.Limit != nil) || + (operation.Kind == PhysicalReturnOp && operation.Return != nil) + if !valid { + return fmt.Errorf("payload does not match operation kind") + } + return nil +} + +func definePhysicalVariable(defined map[string]bool, variable string) error { + if !physicalVariablePattern.MatchString(variable) { + return fmt.Errorf("unsafe variable name %q", variable) + } + if defined[variable] { + return fmt.Errorf("variable %q is already defined", variable) + } + defined[variable] = true + return nil +} + +func requireBind(bindVars map[string]any, key string) error { + if !physicalBindKeyPattern.MatchString(key) { + return fmt.Errorf("unsafe bind key %q", key) + } + if _, ok := bindVars[key]; !ok { + return fmt.Errorf("bind key %q is not defined", key) + } + return nil +} + +func validatePhysicalPredicate(predicate PhysicalPredicate, defined map[string]bool, bindVars map[string]any) error { + if strings.TrimSpace(predicate.Operator) == "" { + return fmt.Errorf("filter operator is required") + } + if err := validatePhysicalValue(predicate.Left, defined, bindVars); err != nil { + return err + } + if predicate.Right != nil { + return validatePhysicalValue(*predicate.Right, defined, bindVars) + } + return nil +} + +func validatePhysicalValue(value PhysicalValue, defined map[string]bool, bindVars map[string]any) error { + hasVariable := value.Variable != "" + hasBind := value.BindKey != "" + if hasVariable == hasBind { + return fmt.Errorf("physical value must reference exactly one variable or bind key") + } + if hasBind { + if len(value.Path) != 0 { + return fmt.Errorf("bind value %q cannot have a path", value.BindKey) + } + return requireBind(bindVars, value.BindKey) + } + if !defined[value.Variable] { + return fmt.Errorf("variable %q is out of scope", value.Variable) + } + for _, part := range value.Path { + if !physicalPathPartPattern.MatchString(part) { + return fmt.Errorf("unsafe path segment %q", part) + } + } + return nil +} diff --git a/internal/dataframe/physical_plan_test.go b/internal/dataframe/physical_plan_test.go new file mode 100644 index 0000000..0a7ffbb --- /dev/null +++ b/internal/dataframe/physical_plan_test.go @@ -0,0 +1,100 @@ +package dataframe + +import ( + "strings" + "testing" +) + +func validPhysicalPlan() PhysicalPlan { + label := PhysicalValue{BindKey: "edge_label"} + return PhysicalPlan{ + Version: 1, + Source: PhysicalSource{RecipeID: "file_manifest", TemplateID: "file-manifest-v1", SemanticNode: "root", ResourceType: "Patient"}, + BindVars: map[string]any{"root_collection": "Patient", "edge_collection": "fhir_edge", "edge_label": "subject_Patient", "target_type": "Specimen"}, + Operations: []PhysicalOperation{ + {Kind: PhysicalRootScanOp, Source: PhysicalSource{SemanticNode: "root", ResourceType: "Patient"}, RootScan: &PhysicalRootScan{Variable: "root", CollectionBindKey: "root_collection"}}, + {Kind: PhysicalFilterOp, Source: PhysicalSource{SemanticField: "project"}, Filter: &PhysicalFilter{Predicate: PhysicalPredicate{Operator: "EQUALS", Left: PhysicalValue{Variable: "root", Path: []string{"project"}}, Right: &label}}}, + {Kind: PhysicalTraversalOp, Source: PhysicalSource{SemanticNode: "specimen", Relationship: "subject_Patient"}, Traversal: &PhysicalTraversal{SourceVariable: "root", TargetVariable: "specimen", EdgeVariable: "edge", Direction: PhysicalOutbound, EdgeCollectionBindKey: "edge_collection", EdgeLabelBindKey: "edge_label", TargetTypeBindKey: "target_type"}}, + {Kind: PhysicalDerivedLetOp, Source: PhysicalSource{SemanticField: "specimen_count"}, DerivedLet: &PhysicalDerivedLet{Variable: "specimen_count", Operator: "LENGTH", Inputs: []PhysicalValue{{Variable: "specimen"}}}}, + {Kind: PhysicalReturnOp, Return: &PhysicalReturn{Projections: []PhysicalProjection{{Name: "_key", Value: PhysicalValue{Variable: "root", Path: []string{"_key"}}}, {Name: "specimen_count", Value: PhysicalValue{Variable: "specimen_count"}}}}}, + }, + } +} + +func TestPhysicalPlanValidateGenericOperationGraph(t *testing.T) { + plan := validPhysicalPlan() + if err := plan.Validate(); err != nil { + t.Fatal(err) + } + if plan.Operations[1].Source.SemanticField != "project" || plan.Operations[2].Source.Relationship != "subject_Patient" { + t.Fatalf("semantic provenance was not retained: %#v", plan.Operations) + } +} + +func TestPhysicalPlanValidateRejectsOutOfScopeAndOrdering(t *testing.T) { + tests := []struct { + name string + mutate func(*PhysicalPlan) + want string + }{ + {"traversal before source", func(p *PhysicalPlan) { p.Operations[0], p.Operations[2] = p.Operations[2], p.Operations[0] }, "source variable"}, + {"derived input before definition", func(p *PhysicalPlan) { p.Operations[3].DerivedLet.Inputs[0].Variable = "later" }, "out of scope"}, + {"operation after return", func(p *PhysicalPlan) { + p.Operations = append(p.Operations, PhysicalOperation{Kind: PhysicalFilterOp, Filter: &PhysicalFilter{Predicate: PhysicalPredicate{Operator: "EXISTS", Left: PhysicalValue{Variable: "root"}}}}) + }, "after RETURN"}, + {"duplicate variable", func(p *PhysicalPlan) { p.Operations[2].Traversal.TargetVariable = "root" }, "already defined"}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + plan := validPhysicalPlan() + test.mutate(&plan) + if err := plan.Validate(); err == nil || !strings.Contains(err.Error(), test.want) { + t.Fatalf("Validate() error = %v; want substring %q", err, test.want) + } + }) + } +} + +func TestPhysicalPlanValidateRejectsUnsafeOrMissingBindKeys(t *testing.T) { + tests := []struct { + name string + mutate func(*PhysicalPlan) + want string + }{ + {"unsafe map key", func(p *PhysicalPlan) { p.BindVars["bad-key"] = 1 }, "unsafe bind key"}, + {"AQL marker", func(p *PhysicalPlan) { p.Operations[0].RootScan.CollectionBindKey = "@root_collection" }, "unsafe bind key"}, + {"missing key", func(p *PhysicalPlan) { delete(p.BindVars, "target_type") }, "is not defined"}, + {"unsafe path", func(p *PhysicalPlan) { p.Operations[4].Return.Projections[0].Value.Path = []string{"payload.name"} }, "unsafe path segment"}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + plan := validPhysicalPlan() + test.mutate(&plan) + if err := plan.Validate(); err == nil || !strings.Contains(err.Error(), test.want) { + t.Fatalf("Validate() error = %v; want substring %q", err, test.want) + } + }) + } +} + +func TestPhysicalPlanValidateTaggedOperationAndReturnShape(t *testing.T) { + tests := []struct { + name string + mutate func(*PhysicalPlan) + want string + }{ + {"mismatched payload", func(p *PhysicalPlan) { p.Operations[1].Kind = PhysicalDerivedLetOp }, "does not match"}, + {"multiple payloads", func(p *PhysicalPlan) { p.Operations[1].DerivedLet = &PhysicalDerivedLet{} }, "exactly one payload"}, + {"duplicate projection", func(p *PhysicalPlan) { p.Operations[4].Return.Projections[1].Name = "_key" }, "duplicated"}, + {"missing return", func(p *PhysicalPlan) { p.Operations = p.Operations[:4] }, "exactly one RETURN"}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + plan := validPhysicalPlan() + test.mutate(&plan) + if err := plan.Validate(); err == nil || !strings.Contains(err.Error(), test.want) { + t.Fatalf("Validate() error = %v; want substring %q", err, test.want) + } + }) + } +} diff --git a/internal/dataframe/physical_render.go b/internal/dataframe/physical_render.go new file mode 100644 index 0000000..3112b12 --- /dev/null +++ b/internal/dataframe/physical_render.go @@ -0,0 +1,639 @@ +package dataframe + +import ( + "fmt" + "strings" +) + +// RenderedPhysicalPlan is an executable AQL representation of a validated +// PhysicalPlan. BindVars is independent of the input plan and uses Arango's +// required "@name" key form for collection bind variables referenced as +// "@@name" in Query. +// +// This renderer covers the frozen generic navigation subset emitted by +// BuildGenericPhysicalPlan. CompileRequest and the dataframe service use it +// for that subset; richer semantic requests retain the compatibility lowered +// renderer until their typed physical operators are frozen. +type RenderedPhysicalPlan struct { + Query string + BindVars map[string]any +} + +// RenderPhysicalPlan renders the frozen navigation-only physical-plan subset +// to deterministic AQL. It validates the full plan before rendering and keeps +// data and metadata values out of the generated AQL source. +func RenderPhysicalPlan(plan PhysicalPlan) (RenderedPhysicalPlan, error) { + if err := plan.Validate(); err != nil { + return RenderedPhysicalPlan{}, fmt.Errorf("validate physical plan: %w", err) + } + + collectionKeys, err := collectionBindKeys(plan) + if err != nil { + return RenderedPhysicalPlan{}, err + } + if err := validateRenderablePhysicalPlan(plan, collectionKeys); err != nil { + return RenderedPhysicalPlan{}, err + } + // This renderer deliberately supports only BuildGenericPhysicalPlan's + // navigation contract. Validate its required project/auth windows again at + // the executable boundary so a manually assembled plan cannot render an + // unscoped resource scan. + if err := ValidateGenericPhysicalPlanScope(plan); err != nil { + return RenderedPhysicalPlan{}, fmt.Errorf("verify renderable generic physical plan scope: %w", err) + } + layout, err := buildNavigationRenderLayout(plan) + if err != nil { + return RenderedPhysicalPlan{}, err + } + + renderer := physicalPlanRenderer{ + bindVars: runtimePhysicalBindVars(plan.BindVars, collectionKeys), + collectionKeys: collectionKeys, + setVariables: map[string]string{}, + reservedVars: physicalPlanVariableNames(plan), + } + lines := make([]string, 0, len(plan.Operations)+1) + lines = append(lines, fmt.Sprintf("FOR %s IN @@%s", layout.root.Variable, layout.root.CollectionBindKey)) + for index, operation := range layout.rootScope { + line, err := renderer.renderScopeOperation(operation, " ") + if err != nil { + return RenderedPhysicalPlan{}, fmt.Errorf("render root scope operation %d (%s): %w", index, operation.Kind, err) + } + lines = append(lines, line...) + } + for index, operation := range layout.rootWindow { + line, err := renderer.renderRootWindowOperation(operation, " ") + if err != nil { + return RenderedPhysicalPlan{}, fmt.Errorf("render root execution window operation %d (%s): %w", index, operation.Kind, err) + } + lines = append(lines, line...) + } + for index, traversal := range layout.traversals { + line, err := renderer.renderTraversalSet(traversal, layout.root.Variable, index+1) + if err != nil { + return RenderedPhysicalPlan{}, fmt.Errorf("render traversal %d: %w", index+1, err) + } + lines = append(lines, line...) + } + returnExpression, err := renderer.renderReturn(layout.returnOp) + if err != nil { + return RenderedPhysicalPlan{}, fmt.Errorf("render RETURN: %w", err) + } + lines = append(lines, "RETURN "+returnExpression) + return RenderedPhysicalPlan{ + Query: strings.Join(lines, "\n") + "\n", + BindVars: renderer.bindVars, + }, nil +} + +func (r *physicalPlanRenderer) renderRootWindowOperation(operation PhysicalOperation, indent string) ([]string, error) { + switch operation.Kind { + case PhysicalSortOp: + value, err := r.renderValue(operation.Sort.Value) + if err != nil { + return nil, err + } + return []string{indent + "SORT " + value}, nil + case PhysicalLimitOp: + if _, collectionBinding := r.collectionKeys[operation.Limit.BindKey]; collectionBinding { + return nil, fmt.Errorf("limit bind key %q cannot be a collection bind", operation.Limit.BindKey) + } + return []string{indent + "LIMIT @" + operation.Limit.BindKey}, nil + default: + return nil, fmt.Errorf("root execution window cannot contain physical operation %q", operation.Kind) + } +} + +type physicalPlanRenderer struct { + bindVars map[string]any + collectionKeys map[string]struct{} + setVariables map[string]string + reservedVars map[string]struct{} +} + +func (r *physicalPlanRenderer) renderScopeOperation(operation PhysicalOperation, indent string) ([]string, error) { + switch operation.Kind { + case PhysicalFilterOp: + expression, err := r.renderPredicate(operation.Filter.Predicate) + if err != nil { + return nil, err + } + return []string{indent + "FILTER " + expression}, nil + case PhysicalDerivedLetOp: + expression, err := r.renderDerivedLet(*operation.DerivedLet) + if err != nil { + return nil, err + } + return []string{fmt.Sprintf("%sLET %s = %s", indent, operation.DerivedLet.Variable, expression)}, nil + default: + return nil, fmt.Errorf("navigation scope cannot contain physical operation %q", operation.Kind) + } +} + +// physicalNavigationRenderLayout is the intentionally narrow executable shape +// produced by BuildGenericPhysicalPlan. Traversals are retained as sets rather +// than emitted as top-level loops so the root scan remains the row grain. +type physicalNavigationRenderLayout struct { + root PhysicalRootScan + rootScope []PhysicalOperation + rootWindow []PhysicalOperation + traversals []physicalNavigationTraversal + returnOp PhysicalReturn +} + +type physicalNavigationTraversal struct { + traversal PhysicalTraversal + scope []PhysicalOperation +} + +func buildNavigationRenderLayout(plan PhysicalPlan) (physicalNavigationRenderLayout, error) { + if len(plan.Operations) < 6 { + return physicalNavigationRenderLayout{}, fmt.Errorf("generic navigation renderer requires ROOT_SCAN, scope operations, and RETURN") + } + if plan.Operations[0].Kind != PhysicalRootScanOp { + return physicalNavigationRenderLayout{}, fmt.Errorf("generic navigation renderer requires ROOT_SCAN as the first operation") + } + last := len(plan.Operations) - 1 + if plan.Operations[last].Kind != PhysicalReturnOp { + return physicalNavigationRenderLayout{}, fmt.Errorf("generic navigation renderer requires RETURN as the final operation") + } + + layout := physicalNavigationRenderLayout{ + root: *plan.Operations[0].RootScan, + rootScope: append([]PhysicalOperation(nil), plan.Operations[1:5]...), + returnOp: *plan.Operations[last].Return, + } + rootScopeVariable, err := validateGenericNavigationScopeBlock(layout.rootScope, layout.root.Variable, "", layout.root.Variable) + if err != nil { + return physicalNavigationRenderLayout{}, fmt.Errorf("root navigation scope: %w", err) + } + + index := 5 + if index < last && plan.Operations[index].Kind == PhysicalSortOp { + if err := validateGenericNavigationRootSort(plan.Operations[index], layout.root.Variable); err != nil { + return physicalNavigationRenderLayout{}, fmt.Errorf("root execution window at operation %d: %w", index, err) + } + layout.rootWindow = append(layout.rootWindow, plan.Operations[index]) + index++ + if index < last && plan.Operations[index].Kind == PhysicalLimitOp { + if err := validateGenericNavigationRootLimit(plan.Operations[index]); err != nil { + return physicalNavigationRenderLayout{}, fmt.Errorf("root execution window at operation %d: %w", index, err) + } + layout.rootWindow = append(layout.rootWindow, plan.Operations[index]) + index++ + } + } else if index < last && plan.Operations[index].Kind == PhysicalLimitOp { + return physicalNavigationRenderLayout{}, fmt.Errorf("root execution window at operation %d: LIMIT requires deterministic root SORT", index) + } + for index < last { + operation := plan.Operations[index] + if operation.Kind != PhysicalTraversalOp { + return physicalNavigationRenderLayout{}, fmt.Errorf("generic navigation renderer expected TRAVERSAL at operation %d, got %s", index, operation.Kind) + } + const traversalScopeLength = 6 // edge + target project/generation, then auth LET/filter + if index+traversalScopeLength >= last { + return physicalNavigationRenderLayout{}, fmt.Errorf("traversal at operation %d is missing its project/auth scope block", index) + } + traversal := *operation.Traversal + if err := validateGenericNavigationTraversal(plan, traversal); err != nil { + return physicalNavigationRenderLayout{}, fmt.Errorf("traversal at operation %d: %w", index, err) + } + scope := append([]PhysicalOperation(nil), plan.Operations[index+1:index+1+traversalScopeLength]...) + if _, err := validateGenericNavigationScopeBlock(scope, traversal.TargetVariable, traversal.EdgeVariable, traversal.TargetVariable); err != nil { + return physicalNavigationRenderLayout{}, fmt.Errorf("traversal at operation %d scope: %w", index, err) + } + layout.traversals = append(layout.traversals, physicalNavigationTraversal{traversal: traversal, scope: scope}) + index += 1 + traversalScopeLength + } + if err := validateNavigationReturnScope(layout.returnOp, layout.root.Variable, rootScopeVariable); err != nil { + return physicalNavigationRenderLayout{}, err + } + return layout, nil +} + +func validateGenericNavigationTraversal(plan PhysicalPlan, traversal PhysicalTraversal) error { + if traversal.Direction != PhysicalInbound && traversal.Direction != PhysicalOutbound { + return fmt.Errorf("generic navigation traversal direction must be INBOUND or OUTBOUND, got %q", traversal.Direction) + } + wantEdgeTypeField := "from_type" + if traversal.Direction == PhysicalOutbound { + wantEdgeTypeField = "to_type" + } + if traversal.EdgeTargetTypeField != wantEdgeTypeField { + return fmt.Errorf("generic navigation traversal %s must constrain edge.%s, got %q", traversal.Direction, wantEdgeTypeField, traversal.EdgeTargetTypeField) + } + if traversal.EdgeVariable == "" || traversal.EdgeLabelBindKey == "" || traversal.TargetTypeBindKey == "" { + return fmt.Errorf("generic navigation traversal requires edge variable, edge label bind, and target type bind") + } + collection, ok := plan.BindVars[traversal.EdgeCollectionBindKey].(string) + if !ok || collection != "fhir_edge" { + return fmt.Errorf("generic navigation traversal must use fhir_edge through its collection bind") + } + return nil +} + +func validateGenericNavigationRootSort(operation PhysicalOperation, rootVariable string) error { + if operation.Sort == nil || !sameRenderPhysicalValue(operation.Sort.Value, PhysicalValue{Variable: rootVariable, Path: []string{"_key"}}) { + return fmt.Errorf("SORT must order the root variable %s._key", rootVariable) + } + return nil +} + +func validateGenericNavigationRootLimit(operation PhysicalOperation) error { + if operation.Limit == nil || operation.Limit.BindKey != genericPhysicalExecutionLimitBind { + return fmt.Errorf("LIMIT must use @%s", genericPhysicalExecutionLimitBind) + } + return nil +} + +// validateGenericNavigationScopeBlock accepts the exact generation-safe scope +// operations emitted by appendProjectScope, appendDatasetGenerationScope, and +// appendAuthScope. The standalone +// scope verifier is intentionally more flexible; rendering is stricter so it +// can relocate the whole block safely into a LET subquery. +func validateGenericNavigationScopeBlock(operations []PhysicalOperation, resourceVariable, edgeVariable, targetVariable string) (string, error) { + expectedProjectVariables := []string{resourceVariable} + expectedGenerationVariables := []string{resourceVariable} + if edgeVariable != "" { + expectedProjectVariables = []string{edgeVariable, targetVariable} + expectedGenerationVariables = []string{edgeVariable, targetVariable} + } + expectedLength := len(expectedProjectVariables) + len(expectedGenerationVariables) + 2 + if len(operations) != expectedLength || operations[0].Kind != PhysicalFilterOp { + return "", fmt.Errorf("requires project filters for every graph document, dataset_generation filters, LET AUTH_RESOURCE_PATH_ALLOWED, FILTER scope_allowed in order") + } + for index, variable := range expectedProjectVariables { + operation := operations[index] + if operation.Kind != PhysicalFilterOp || !matchesPhysicalEquality(operation.Filter.Predicate, PhysicalValue{Variable: variable, Path: []string{"project"}}, PhysicalValue{BindKey: "project"}) { + return "", fmt.Errorf("project scope must be %s.project == @project", variable) + } + } + for index, variable := range expectedGenerationVariables { + operation := operations[len(expectedProjectVariables)+index] + if operation.Kind != PhysicalFilterOp || !matchesPhysicalEquality(operation.Filter.Predicate, PhysicalValue{Variable: variable, Path: []string{datasetGenerationField}}, PhysicalValue{BindKey: datasetGenerationBindKey}) { + return "", fmt.Errorf("dataset generation scope must be %s.%s == @%s", variable, datasetGenerationField, datasetGenerationBindKey) + } + } + authLetIndex := len(expectedProjectVariables) + len(expectedGenerationVariables) + authFilterIndex := authLetIndex + 1 + + if operations[authLetIndex].Kind != PhysicalDerivedLetOp || operations[authLetIndex].DerivedLet == nil { + return "", fmt.Errorf("scope block requires AUTH_RESOURCE_PATH_ALLOWED LET after dataset generation scope") + } + derived := operations[authLetIndex].DerivedLet + if strings.ToUpper(strings.TrimSpace(derived.Operator)) != "AUTH_RESOURCE_PATH_ALLOWED" { + return "", fmt.Errorf("scope LET must use AUTH_RESOURCE_PATH_ALLOWED") + } + expectedInputs := []PhysicalValue{{Variable: resourceVariable, Path: []string{"auth_resource_path"}}} + if edgeVariable != "" { + expectedInputs = []PhysicalValue{ + {Variable: edgeVariable, Path: []string{"auth_resource_path"}}, + {Variable: targetVariable, Path: []string{"auth_resource_path"}}, + } + } + expectedInputs = append(expectedInputs, PhysicalValue{BindKey: "auth_resource_paths"}, PhysicalValue{BindKey: "auth_resource_paths_unrestricted"}) + if len(derived.Inputs) != len(expectedInputs) { + return "", fmt.Errorf("AUTH_RESOURCE_PATH_ALLOWED requires the exact generic auth scope inputs") + } + for index := range expectedInputs { + if !sameRenderPhysicalValue(derived.Inputs[index], expectedInputs[index]) { + return "", fmt.Errorf("AUTH_RESOURCE_PATH_ALLOWED input %d is not the required generic scope value", index) + } + } + if operations[authFilterIndex].Kind != PhysicalFilterOp || !matchesPhysicalEquality(operations[authFilterIndex].Filter.Predicate, PhysicalValue{Variable: derived.Variable}, PhysicalValue{BindKey: "scope_allowed"}) { + return "", fmt.Errorf("auth scope must be %s == @scope_allowed", derived.Variable) + } + return derived.Variable, nil +} + +func matchesPhysicalEquality(predicate PhysicalPredicate, left, right PhysicalValue) bool { + return strings.ToUpper(strings.TrimSpace(predicate.Operator)) == "EQUALS" && + predicate.Right != nil && + sameRenderPhysicalValue(predicate.Left, left) && + sameRenderPhysicalValue(*predicate.Right, right) +} + +func sameRenderPhysicalValue(left, right PhysicalValue) bool { + if left.Variable != right.Variable || left.BindKey != right.BindKey || len(left.Path) != len(right.Path) { + return false + } + for index := range left.Path { + if left.Path[index] != right.Path[index] { + return false + } + } + return true +} + +func validateNavigationReturnScope(returnOp PhysicalReturn, rootVariable, rootScopeVariable string) error { + for _, projection := range returnOp.Projections { + if projection.Value.BindKey != "" { + continue + } + if projection.Value.Variable != rootVariable && projection.Value.Variable != rootScopeVariable { + return fmt.Errorf("RETURN projection %q references %q, but traversal variables are local to LET subqueries", projection.Name, projection.Value.Variable) + } + } + return nil +} + +func (r *physicalPlanRenderer) renderTraversalSet(block physicalNavigationTraversal, rootVariable string, traversalIndex int) ([]string, error) { + traversal := block.traversal + setVariable := r.newInternalVariable(fmt.Sprintf("set_%d", traversalIndex)) + parentVariable := traversal.SourceVariable + traversalIndent := " " + lines := []string{fmt.Sprintf(" LET %s = (", setVariable)} + if traversal.SourceVariable != rootVariable { + parentSet, ok := r.setVariables[traversal.SourceVariable] + if !ok { + return nil, fmt.Errorf("source variable %q has no previously rendered parent set", traversal.SourceVariable) + } + parentVariable = r.newInternalVariable(fmt.Sprintf("parent_%d", traversalIndex)) + lines = append(lines, fmt.Sprintf(" FOR %s IN %s", parentVariable, parentSet)) + traversalIndent = " " + } + lines = append(lines, + fmt.Sprintf("%sFOR %s, %s IN 1..1 %s %s @@%s", traversalIndent, traversal.TargetVariable, traversal.EdgeVariable, traversal.Direction, parentVariable, traversal.EdgeCollectionBindKey), + fmt.Sprintf("%s FILTER %s.label == @%s", traversalIndent, traversal.EdgeVariable, traversal.EdgeLabelBindKey), + fmt.Sprintf("%s FILTER %s.%s == @%s", traversalIndent, traversal.EdgeVariable, traversal.EdgeTargetTypeField, traversal.TargetTypeBindKey), + fmt.Sprintf("%s FILTER %s.resourceType == @%s", traversalIndent, traversal.TargetVariable, traversal.TargetTypeBindKey), + ) + for scopeIndex, operation := range block.scope { + line, err := r.renderScopeOperation(operation, traversalIndent+" ") + if err != nil { + return nil, fmt.Errorf("render traversal scope operation %d: %w", scopeIndex, err) + } + lines = append(lines, line...) + } + lines = append(lines, traversalIndent+" RETURN "+traversal.TargetVariable, " )") + r.setVariables[traversal.TargetVariable] = setVariable + return lines, nil +} + +func physicalPlanVariableNames(plan PhysicalPlan) map[string]struct{} { + variables := map[string]struct{}{} + for _, operation := range plan.Operations { + switch operation.Kind { + case PhysicalRootScanOp: + variables[operation.RootScan.Variable] = struct{}{} + case PhysicalTraversalOp: + variables[operation.Traversal.SourceVariable] = struct{}{} + variables[operation.Traversal.TargetVariable] = struct{}{} + if operation.Traversal.EdgeVariable != "" { + variables[operation.Traversal.EdgeVariable] = struct{}{} + } + case PhysicalDerivedLetOp: + variables[operation.DerivedLet.Variable] = struct{}{} + } + } + return variables +} + +func (r *physicalPlanRenderer) newInternalVariable(suffix string) string { + base := "__loom_physical_" + suffix + variable := base + for counter := 1; ; counter++ { + if _, exists := r.reservedVars[variable]; !exists { + r.reservedVars[variable] = struct{}{} + return variable + } + variable = fmt.Sprintf("%s_%d", base, counter) + } +} + +func (r *physicalPlanRenderer) renderPredicate(predicate PhysicalPredicate) (string, error) { + if strings.ToUpper(strings.TrimSpace(predicate.Operator)) != "EQUALS" { + return "", fmt.Errorf("unsupported physical filter operator %q", predicate.Operator) + } + if predicate.Right == nil { + return "", fmt.Errorf("EQUALS filter requires a right value") + } + left, err := r.renderValue(predicate.Left) + if err != nil { + return "", err + } + right, err := r.renderValue(*predicate.Right) + if err != nil { + return "", err + } + return left + " == " + right, nil +} + +func (r *physicalPlanRenderer) renderDerivedLet(derived PhysicalDerivedLet) (string, error) { + if strings.ToUpper(strings.TrimSpace(derived.Operator)) != "AUTH_RESOURCE_PATH_ALLOWED" { + return "", fmt.Errorf("unsupported physical derived LET operator %q", derived.Operator) + } + if len(derived.Inputs) < 3 { + return "", fmt.Errorf("AUTH_RESOURCE_PATH_ALLOWED requires one or more scope values plus paths and unrestricted inputs") + } + + paths := derived.Inputs[len(derived.Inputs)-2] + unrestricted := derived.Inputs[len(derived.Inputs)-1] + if paths.BindKey == "" || paths.Variable != "" || unrestricted.BindKey == "" || unrestricted.Variable != "" { + return "", fmt.Errorf("AUTH_RESOURCE_PATH_ALLOWED requires paths and unrestricted bind inputs") + } + pathsExpression, err := r.renderValue(paths) + if err != nil { + return "", err + } + unrestrictedExpression, err := r.renderValue(unrestricted) + if err != nil { + return "", err + } + + scopeChecks := make([]string, 0, len(derived.Inputs)-2) + for _, input := range derived.Inputs[:len(derived.Inputs)-2] { + if input.Variable == "" || input.BindKey != "" { + return "", fmt.Errorf("AUTH_RESOURCE_PATH_ALLOWED scope inputs must be variable paths") + } + scopeValue, err := r.renderValue(input) + if err != nil { + return "", err + } + scopeChecks = append(scopeChecks, scopeValue+" IN "+pathsExpression) + } + + scopeExpression := strings.Join(scopeChecks, " AND ") + if len(scopeChecks) > 1 { + scopeExpression = "(" + scopeExpression + ")" + } + return unrestrictedExpression + " == true OR " + scopeExpression, nil +} + +func (r *physicalPlanRenderer) renderReturn(returnOp PhysicalReturn) (string, error) { + if len(returnOp.Projections) == 0 { + return "{}", nil + } + projections := make([]string, 0, len(returnOp.Projections)) + for index, projection := range returnOp.Projections { + nameBindKey := r.newInternalBindKey(fmt.Sprintf("projection_%d_name", index)) + r.bindVars[nameBindKey] = projection.Name + value, err := r.renderValue(projection.Value) + if err != nil { + return "", err + } + projections = append(projections, fmt.Sprintf("[@%s]: %s", nameBindKey, value)) + } + return "{ " + strings.Join(projections, ", ") + " }", nil +} + +func (r *physicalPlanRenderer) renderValue(value PhysicalValue) (string, error) { + if value.BindKey != "" { + if _, collectionBinding := r.collectionKeys[value.BindKey]; collectionBinding { + return "", fmt.Errorf("bind key %q cannot be used as both a collection and scalar bind", value.BindKey) + } + return "@" + value.BindKey, nil + } + if value.Variable == "" { + return "", fmt.Errorf("physical value has no variable or bind key") + } + if len(value.Path) == 0 { + return value.Variable, nil + } + return value.Variable + "." + strings.Join(value.Path, "."), nil +} + +func (r *physicalPlanRenderer) newInternalBindKey(suffix string) string { + base := "__loom_physical_" + suffix + key := base + for counter := 1; ; counter++ { + if _, exists := r.bindVars[key]; !exists { + return key + } + key = fmt.Sprintf("%s_%d", base, counter) + } +} + +func collectionBindKeys(plan PhysicalPlan) (map[string]struct{}, error) { + keys := map[string]struct{}{} + for index, operation := range plan.Operations { + switch operation.Kind { + case PhysicalRootScanOp: + keys[operation.RootScan.CollectionBindKey] = struct{}{} + case PhysicalTraversalOp: + if operation.Traversal.EdgeCollectionBindKey == "" { + return nil, fmt.Errorf("render operation %d (TRAVERSAL): edge collection bind key is required", index) + } + keys[operation.Traversal.EdgeCollectionBindKey] = struct{}{} + } + } + for key := range keys { + value, ok := plan.BindVars[key] + if !ok { + return nil, fmt.Errorf("collection bind key %q is not defined", key) + } + collection, ok := value.(string) + if !ok || strings.TrimSpace(collection) == "" { + return nil, fmt.Errorf("collection bind key %q must have a non-empty string value", key) + } + } + return keys, nil +} + +func validateRenderablePhysicalPlan(plan PhysicalPlan, collectionKeys map[string]struct{}) error { + for index, operation := range plan.Operations { + if err := validateRenderableOperation(operation, collectionKeys); err != nil { + return fmt.Errorf("render operation %d (%s): %w", index, operation.Kind, err) + } + } + return nil +} + +func validateRenderableOperation(operation PhysicalOperation, collectionKeys map[string]struct{}) error { + valueIsCollection := func(value PhysicalValue) error { + if _, isCollection := collectionKeys[value.BindKey]; isCollection { + return fmt.Errorf("bind key %q cannot be used as both a collection and scalar bind", value.BindKey) + } + return nil + } + checkValue := func(value PhysicalValue) error { + if err := valueIsCollection(value); err != nil { + return err + } + return nil + } + + switch operation.Kind { + case PhysicalRootScanOp: + return nil + case PhysicalTraversalOp: + traversal := operation.Traversal + if traversal.EdgeVariable == "" { + return fmt.Errorf("TRAVERSAL requires an edge variable for edge-label and project scope checks") + } + if traversal.EdgeLabelBindKey == "" || traversal.TargetTypeBindKey == "" { + return fmt.Errorf("TRAVERSAL requires edge label and target resource type bind keys") + } + return nil + case PhysicalFilterOp: + if strings.ToUpper(strings.TrimSpace(operation.Filter.Predicate.Operator)) != "EQUALS" { + return fmt.Errorf("unsupported physical filter operator %q", operation.Filter.Predicate.Operator) + } + if operation.Filter.Predicate.Right == nil { + return fmt.Errorf("EQUALS filter requires a right value") + } + if err := checkValue(operation.Filter.Predicate.Left); err != nil { + return err + } + return checkValue(*operation.Filter.Predicate.Right) + case PhysicalDerivedLetOp: + if strings.ToUpper(strings.TrimSpace(operation.DerivedLet.Operator)) != "AUTH_RESOURCE_PATH_ALLOWED" { + return fmt.Errorf("unsupported physical derived LET operator %q", operation.DerivedLet.Operator) + } + for _, input := range operation.DerivedLet.Inputs { + if err := checkValue(input); err != nil { + return err + } + } + return nil + case PhysicalSortOp: + return checkValue(operation.Sort.Value) + case PhysicalLimitOp: + if _, isCollection := collectionKeys[operation.Limit.BindKey]; isCollection { + return fmt.Errorf("bind key %q cannot be used as both a collection and scalar bind", operation.Limit.BindKey) + } + return nil + case PhysicalReturnOp: + for _, projection := range operation.Return.Projections { + if err := checkValue(projection.Value); err != nil { + return err + } + } + return nil + default: + return fmt.Errorf("unsupported physical operation %q", operation.Kind) + } +} + +func runtimePhysicalBindVars(bindVars map[string]any, collectionKeys map[string]struct{}) map[string]any { + out := make(map[string]any, len(bindVars)) + for key, value := range bindVars { + if _, collectionBinding := collectionKeys[key]; collectionBinding { + out["@"+key] = clonePhysicalBindValue(value) + continue + } + out[key] = clonePhysicalBindValue(value) + } + return out +} + +func clonePhysicalBindValue(value any) any { + switch typed := value.(type) { + case []string: + return append([]string(nil), typed...) + case []any: + out := make([]any, len(typed)) + for index, item := range typed { + out[index] = clonePhysicalBindValue(item) + } + return out + case map[string]any: + out := make(map[string]any, len(typed)) + for key, item := range typed { + out[key] = clonePhysicalBindValue(item) + } + return out + default: + return value + } +} diff --git a/internal/dataframe/physical_render_test.go b/internal/dataframe/physical_render_test.go new file mode 100644 index 0000000..90ffce6 --- /dev/null +++ b/internal/dataframe/physical_render_test.go @@ -0,0 +1,297 @@ +package dataframe + +import ( + "reflect" + "strings" + "testing" +) + +func TestRenderPhysicalPlanGenericNavigation(t *testing.T) { + plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, + Project: "project-1", + AuthResourcePaths: []string{"/programs/p1"}, + Root: SemanticNode{ + Alias: "root", + ResourceType: "Patient", + Children: []SemanticNode{{ + Alias: "specimen", + ResourceType: "Specimen", + EdgeLabel: "subject_Patient", + }}, + }, + }) + if err != nil { + t.Fatal(err) + } + + rendered, err := RenderPhysicalPlan(plan) + if err != nil { + t.Fatalf("RenderPhysicalPlan() error = %v", err) + } + for _, want := range []string{ + "FOR root IN @@root_collection", + " FILTER root.project == @project", + " LET root_scope_allowed = @auth_resource_paths_unrestricted == true OR root.auth_resource_path IN @auth_resource_paths", + " FILTER root_scope_allowed == @scope_allowed", + " LET __loom_physical_set_1 = (", + " FOR node_1, edge_1 IN 1..1 INBOUND root @@traversal_1_edge_collection", + " FILTER edge_1.label == @traversal_1_label", + " FILTER edge_1.from_type == @traversal_1_target_type", + " FILTER node_1.resourceType == @traversal_1_target_type", + " FILTER edge_1.project == @project", + " FILTER node_1.project == @project", + " LET traversal_1_scope_allowed = @auth_resource_paths_unrestricted == true OR (edge_1.auth_resource_path IN @auth_resource_paths AND node_1.auth_resource_path IN @auth_resource_paths)", + " FILTER traversal_1_scope_allowed == @scope_allowed", + " RETURN node_1", + "RETURN { [@__loom_physical_projection_0_name]: root._key }", + } { + if !strings.Contains(rendered.Query, want) { + t.Fatalf("rendered query missing %q:\n%s", want, rendered.Query) + } + } + if got := rendered.BindVars["@root_collection"]; got != "Patient" { + t.Fatalf("root collection bind = %#v", got) + } + if got := rendered.BindVars["@traversal_1_edge_collection"]; got != "fhir_edge" { + t.Fatalf("edge collection bind = %#v", got) + } + if _, present := rendered.BindVars["root_collection"]; present { + t.Fatalf("runtime binds retained unprefixed root collection: %#v", rendered.BindVars) + } + if _, present := rendered.BindVars["traversal_1_edge_collection"]; present { + t.Fatalf("runtime binds retained unprefixed edge collection: %#v", rendered.BindVars) + } + if got := rendered.BindVars["project"]; got != "project-1" { + t.Fatalf("normal bind was not retained: %#v", got) + } + if got := rendered.BindVars["__loom_physical_projection_0_name"]; got != "_key" { + t.Fatalf("projection name was not bound: %#v", got) + } +} + +func TestRenderPhysicalPlanTraversalSetsPreserveRootRowGrain(t *testing.T) { + plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, + Project: "project-1", + AuthResourcePaths: []string{"/programs/p1"}, + Root: SemanticNode{ + Alias: "root", ResourceType: "Patient", + Children: []SemanticNode{{ + Alias: "specimen", ResourceType: "Specimen", EdgeLabel: "subject_Patient", + Children: []SemanticNode{{ + Alias: "file", ResourceType: "DocumentReference", EdgeLabel: "subject_Specimen", + }}, + }}, + }, + }) + if err != nil { + t.Fatal(err) + } + rendered, err := RenderPhysicalPlan(plan) + if err != nil { + t.Fatal(err) + } + + setOne := strings.Index(rendered.Query, "\n LET __loom_physical_set_1 = (") + firstTraversal := strings.Index(rendered.Query, "\n FOR node_1, edge_1 IN 1..1 INBOUND root @@traversal_1_edge_collection") + setTwo := strings.Index(rendered.Query, "\n LET __loom_physical_set_2 = (") + parentLoop := strings.Index(rendered.Query, "\n FOR __loom_physical_parent_2 IN __loom_physical_set_1") + secondTraversal := strings.Index(rendered.Query, "\n FOR node_2, edge_2 IN 1..1 INBOUND __loom_physical_parent_2 @@traversal_2_edge_collection") + outerReturn := strings.LastIndex(rendered.Query, "\nRETURN { [@__loom_physical_projection_0_name]: root._key }") + if setOne < 0 || firstTraversal < setOne || setTwo < firstTraversal || parentLoop < setTwo || secondTraversal < parentLoop || outerReturn < secondTraversal { + t.Fatalf("nested traversal sets did not preserve outer root shape:\n%s", rendered.Query) + } + if strings.Contains(rendered.Query, "\nFOR node_1") || strings.Contains(rendered.Query, "\nFOR node_2") { + t.Fatalf("a traversal escaped its LET subquery and can multiply root rows:\n%s", rendered.Query) + } + if strings.Count(rendered.Query, "RETURN { [@__loom_physical_projection_0_name]: root._key }") != 1 { + t.Fatalf("expected exactly one outer root RETURN:\n%s", rendered.Query) + } +} + +func TestRenderPhysicalPlanIsDeterministicAndCopiesBindVars(t *testing.T) { + plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, + Project: "project-1", + AuthResourcePaths: []string{"/programs/p1"}, + Root: SemanticNode{Alias: "root", ResourceType: "Patient"}, + }) + if err != nil { + t.Fatal(err) + } + first, err := RenderPhysicalPlan(plan) + if err != nil { + t.Fatal(err) + } + second, err := RenderPhysicalPlan(plan) + if err != nil { + t.Fatal(err) + } + if first.Query != second.Query || !reflect.DeepEqual(first.BindVars, second.BindVars) { + t.Fatalf("renders are not deterministic:\nfirst=%#v\nsecond=%#v", first, second) + } + if strings.Contains(first.Query, "LET __loom_physical_set_") { + t.Fatalf("root-only navigation should not require a child traversal set:\n%s", first.Query) + } + + first.BindVars["project"] = "changed" + first.BindVars["auth_resource_paths"].([]string)[0] = "/changed" + if plan.BindVars["project"] != "project-1" { + t.Fatalf("runtime bind map mutated plan: %#v", plan.BindVars) + } + if got := plan.BindVars["auth_resource_paths"].([]string)[0]; got != "/programs/p1" { + t.Fatalf("runtime bind slice mutated plan: %#v", plan.BindVars) + } +} + +func TestRenderPhysicalPlanRejectsUnsupportedOrAmbiguousOperations(t *testing.T) { + newPlan := func(t *testing.T) PhysicalPlan { + t.Helper() + plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, + Project: "project-1", + Root: SemanticNode{Alias: "root", ResourceType: "Patient"}, + }) + if err != nil { + t.Fatal(err) + } + return plan + } + + tests := []struct { + name string + mutate func(*PhysicalPlan) + want string + }{ + { + name: "invalid physical plan", + mutate: func(plan *PhysicalPlan) { + plan.Version = 0 + }, + want: "validate physical plan", + }, + { + name: "unsupported filter operator", + mutate: func(plan *PhysicalPlan) { + returnIndex := len(plan.Operations) - 1 + unsupported := PhysicalOperation{ + Kind: PhysicalFilterOp, + Filter: &PhysicalFilter{Predicate: PhysicalPredicate{ + Operator: "NOT_EQUALS", + Left: PhysicalValue{Variable: "root", Path: []string{"_key"}}, + Right: &PhysicalValue{BindKey: "project"}, + }}, + } + plan.Operations = append(plan.Operations[:returnIndex], append([]PhysicalOperation{unsupported}, plan.Operations[returnIndex:]...)...) + }, + want: "unsupported physical filter operator", + }, + { + name: "unsupported derived operator", + mutate: func(plan *PhysicalPlan) { + returnIndex := len(plan.Operations) - 1 + unsupported := PhysicalOperation{ + Kind: PhysicalDerivedLetOp, + DerivedLet: &PhysicalDerivedLet{Variable: "unsupported_value", Operator: "LENGTH", Inputs: []PhysicalValue{{Variable: "root"}}}, + } + plan.Operations = append(plan.Operations[:returnIndex], append([]PhysicalOperation{unsupported}, plan.Operations[returnIndex:]...)...) + }, + want: "unsupported physical derived LET operator", + }, + { + name: "collection key used as scalar bind", + mutate: func(plan *PhysicalPlan) { + value := PhysicalValue{BindKey: "root_collection"} + plan.Operations[1].Filter.Predicate.Right = &value + }, + want: "both a collection and scalar bind", + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + plan := newPlan(t) + test.mutate(&plan) + _, err := RenderPhysicalPlan(plan) + if err == nil || !strings.Contains(err.Error(), test.want) { + t.Fatalf("RenderPhysicalPlan() error = %v; want substring %q", err, test.want) + } + }) + } +} + +func TestRenderPhysicalPlanRejectsMissingGenericScope(t *testing.T) { + plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, + Project: "project-1", + Root: SemanticNode{Alias: "root", ResourceType: "Patient"}, + }) + if err != nil { + t.Fatal(err) + } + plan.Operations = append(plan.Operations[:1], plan.Operations[2:]...) + + _, err = RenderPhysicalPlan(plan) + if err == nil || !strings.Contains(err.Error(), "generic physical plan scope") { + t.Fatalf("RenderPhysicalPlan() error = %v, want scope validation failure", err) + } +} + +func TestRenderPhysicalPlanRejectsMisboundGenericEdgeTypeDiscriminator(t *testing.T) { + plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, + Project: "project-1", + Root: SemanticNode{ + Alias: "root", ResourceType: "Patient", + Children: []SemanticNode{{ + Alias: "specimen", ResourceType: "Specimen", EdgeLabel: "subject_Patient", + }}, + }, + }) + if err != nil { + t.Fatal(err) + } + for index := range plan.Operations { + if plan.Operations[index].Traversal != nil { + plan.Operations[index].Traversal.EdgeTargetTypeField = "to_type" + break + } + } + _, err = RenderPhysicalPlan(plan) + if err == nil || !strings.Contains(err.Error(), "must constrain edge.from_type") { + t.Fatalf("RenderPhysicalPlan() error = %v, want inbound edge discriminator rejection", err) + } +} + +func TestRenderPhysicalPlanKeepsCollectionAndProjectionValuesOutOfAQL(t *testing.T) { + plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, + Project: "project-1", + Root: SemanticNode{Alias: "root", ResourceType: "Patient"}, + }) + if err != nil { + t.Fatal(err) + } + maliciousCollection := "Patient; RETURN {injected: true}" + maliciousProjection := "x]: true } RETURN {injected: true} //" + plan.BindVars["root_collection"] = maliciousCollection + for index := range plan.Operations { + if plan.Operations[index].Return != nil { + plan.Operations[index].Return.Projections[0].Name = maliciousProjection + } + } + + rendered, err := RenderPhysicalPlan(plan) + if err != nil { + t.Fatal(err) + } + if strings.Contains(rendered.Query, maliciousCollection) || strings.Contains(rendered.Query, maliciousProjection) { + t.Fatalf("data value was interpolated into AQL:\n%s", rendered.Query) + } + if got := rendered.BindVars["@root_collection"]; got != maliciousCollection { + t.Fatalf("collection value was not carried as a collection bind: %#v", got) + } + if got := rendered.BindVars["__loom_physical_projection_0_name"]; got != maliciousProjection { + t.Fatalf("projection name was not carried as a scalar bind: %#v", got) + } +} diff --git a/internal/dataframe/physical_scope.go b/internal/dataframe/physical_scope.go new file mode 100644 index 0000000..559529a --- /dev/null +++ b/internal/dataframe/physical_scope.go @@ -0,0 +1,281 @@ +package dataframe + +import "fmt" + +const ( + physicalScopeProjectBind = "project" + physicalScopeAllowedBind = "scope_allowed" + physicalScopeAuthPathsBind = "auth_resource_paths" + physicalScopeAuthPathsUnrestrictedBind = "auth_resource_paths_unrestricted" + physicalScopeAuthPathField = "auth_resource_path" + physicalScopeProjectField = "project" + physicalScopeDatasetGenerationBind = datasetGenerationBindKey + physicalScopeDatasetGenerationField = datasetGenerationField +) + +// ValidateGenericPhysicalPlanScope proves the authorization and project-scope +// contract of the navigation-only physical plan built by +// BuildGenericPhysicalPlan. It deliberately validates the physical operation +// graph rather than rendered AQL, so a renderer cannot accidentally hide a +// missing or reordered scope operation. +// +// This is intentionally narrower than PhysicalPlan.Validate: arbitrary +// physical plans may have a different scope strategy, while the generic FHIR +// navigation plan must use the exact project and authorization primitives +// checked here. It also requires an exact dataset-generation predicate for +// each scanned graph document, including the legacy null-generation case. +func ValidateGenericPhysicalPlanScope(plan PhysicalPlan) error { + if err := plan.Validate(); err != nil { + return fmt.Errorf("validate physical plan before verifying generic scope: %w", err) + } + + for operationIndex, operation := range plan.Operations { + resource, ok := physicalScopeResourceForOperation(operation) + if !ok { + continue + } + windowEnd := physicalScopeWindowEnd(plan.Operations, operationIndex+1) + if err := validatePhysicalScopeWindow(plan.Operations, operationIndex, windowEnd, resource); err != nil { + return err + } + } + return nil +} + +type physicalScopeResource struct { + description string + projectVariables []string + datasetGenVariables []string + authPaths []PhysicalValue +} + +func physicalScopeResourceForOperation(operation PhysicalOperation) (physicalScopeResource, bool) { + switch operation.Kind { + case PhysicalRootScanOp: + return physicalScopeResource{ + description: "root scan", + projectVariables: []string{operation.RootScan.Variable}, + datasetGenVariables: []string{operation.RootScan.Variable}, + authPaths: []PhysicalValue{{ + Variable: operation.RootScan.Variable, + Path: []string{physicalScopeAuthPathField}, + }}, + }, true + case PhysicalTraversalOp: + return physicalScopeResource{ + description: fmt.Sprintf("traversal to %q", operation.Traversal.TargetVariable), + projectVariables: []string{operation.Traversal.EdgeVariable, operation.Traversal.TargetVariable}, + datasetGenVariables: []string{operation.Traversal.EdgeVariable, operation.Traversal.TargetVariable}, + authPaths: []PhysicalValue{ + {Variable: operation.Traversal.EdgeVariable, Path: []string{physicalScopeAuthPathField}}, + {Variable: operation.Traversal.TargetVariable, Path: []string{physicalScopeAuthPathField}}, + }, + }, true + default: + return physicalScopeResource{}, false + } +} + +// physicalScopeWindowEnd returns the first subsequent operation that can +// create another resource or terminate the plan. Scope must be established +// before either happens; otherwise a traversal can observe an unscoped row. +func physicalScopeWindowEnd(operations []PhysicalOperation, start int) int { + for index := start; index < len(operations); index++ { + switch operations[index].Kind { + case PhysicalRootScanOp, PhysicalTraversalOp, PhysicalReturnOp: + return index + } + } + return len(operations) +} + +func validatePhysicalScopeWindow(operations []PhysicalOperation, resourceIndex, windowEnd int, resource physicalScopeResource) error { + projectIndex, err := findProjectScopeFilters(operations, resourceIndex+1, windowEnd, resource) + if err != nil { + return fmt.Errorf("%s at operation %d: %w", resource.description, resourceIndex, err) + } + + generationIndex, err := findDatasetGenerationScopeFilters(operations, projectIndex+1, windowEnd, resource) + if err != nil { + return err + } + + authIndex, authVariable, err := findAuthScopeLet(operations, generationIndex+1, windowEnd, resource) + if err != nil { + return fmt.Errorf("%s at operation %d: %w", resource.description, resourceIndex, err) + } + + if err := findAuthScopeEquality(operations, authIndex+1, windowEnd, authVariable); err != nil { + return fmt.Errorf("%s at operation %d: %w", resource.description, resourceIndex, err) + } + return nil +} + +func findDatasetGenerationScopeFilters(operations []PhysicalOperation, start, end int, resource physicalScopeResource) (int, error) { + lastIndex := start - 1 + for _, variable := range resource.datasetGenVariables { + found := false + for index := lastIndex + 1; index < end; index++ { + operation := operations[index] + if operation.Kind == PhysicalDerivedLetOp && operation.DerivedLet.Operator == "AUTH_RESOURCE_PATH_ALLOWED" { + return 0, fmt.Errorf("AUTH_RESOURCE_PATH_ALLOWED LET at operation %d appears before dataset generation scope filter %s.%s == @%s", index, variable, physicalScopeDatasetGenerationField, physicalScopeDatasetGenerationBind) + } + if operation.Kind != PhysicalFilterOp { + continue + } + predicate := operation.Filter.Predicate + if predicate.Left.Variable != variable || !physicalPathEquals(predicate.Left.Path, []string{physicalScopeDatasetGenerationField}) { + continue + } + if isDatasetGenerationScopePredicate(predicate, variable) { + found = true + lastIndex = index + break + } + return 0, fmt.Errorf("dataset generation scope filter at operation %d must be %s.%s == @%s", index, variable, physicalScopeDatasetGenerationField, physicalScopeDatasetGenerationBind) + } + if !found { + return 0, fmt.Errorf("missing dataset generation scope filter %s.%s == @%s before the next resource operation", variable, physicalScopeDatasetGenerationField, physicalScopeDatasetGenerationBind) + } + } + return lastIndex, nil +} + +func findProjectScopeFilters(operations []PhysicalOperation, start, end int, resource physicalScopeResource) (int, error) { + lastIndex := start - 1 + for _, variable := range resource.projectVariables { + found := false + for index := lastIndex + 1; index < end; index++ { + operation := operations[index] + if operation.Kind == PhysicalDerivedLetOp && operation.DerivedLet.Operator == "AUTH_RESOURCE_PATH_ALLOWED" { + return 0, fmt.Errorf("AUTH_RESOURCE_PATH_ALLOWED LET at operation %d appears before project scope filter %s.project == @%s", index, variable, physicalScopeProjectBind) + } + if operation.Kind != PhysicalFilterOp { + continue + } + predicate := operation.Filter.Predicate + if predicate.Left.Variable != variable || !physicalPathEquals(predicate.Left.Path, []string{physicalScopeProjectField}) { + continue + } + if isProjectScopePredicate(predicate, variable) { + found = true + lastIndex = index + break + } + return 0, fmt.Errorf("project scope filter at operation %d must be %s.project == @%s", index, variable, physicalScopeProjectBind) + } + if !found { + return 0, fmt.Errorf("missing project scope filter %s.project == @%s before the next resource operation", variable, physicalScopeProjectBind) + } + } + return lastIndex, nil +} + +func findAuthScopeLet(operations []PhysicalOperation, start, end int, resource physicalScopeResource) (int, string, error) { + for index := start; index < end; index++ { + operation := operations[index] + if operation.Kind == PhysicalFilterOp && isScopeAllowedFilter(operation.Filter.Predicate) { + return 0, "", fmt.Errorf("auth scope equality at operation %d appears before AUTH_RESOURCE_PATH_ALLOWED LET", index) + } + if operation.Kind != PhysicalDerivedLetOp || operation.DerivedLet.Operator != "AUTH_RESOURCE_PATH_ALLOWED" { + continue + } + if err := validateAuthScopeInputs(operation.DerivedLet.Inputs, resource.authPaths); err != nil { + return 0, "", fmt.Errorf("AUTH_RESOURCE_PATH_ALLOWED LET at operation %d: %w", index, err) + } + return index, operation.DerivedLet.Variable, nil + } + return 0, "", fmt.Errorf("missing AUTH_RESOURCE_PATH_ALLOWED LET before the next resource operation") +} + +func findAuthScopeEquality(operations []PhysicalOperation, start, end int, authVariable string) error { + for index := start; index < end; index++ { + operation := operations[index] + if operation.Kind != PhysicalFilterOp { + continue + } + predicate := operation.Filter.Predicate + if predicate.Left.Variable != authVariable || len(predicate.Left.Path) != 0 { + continue + } + if isScopeAllowedPredicate(predicate, authVariable) { + return nil + } + return fmt.Errorf("auth scope equality at operation %d must be %s == @%s", index, authVariable, physicalScopeAllowedBind) + } + return fmt.Errorf("missing auth scope equality %s == @%s before the next resource operation", authVariable, physicalScopeAllowedBind) +} + +func isProjectScopePredicate(predicate PhysicalPredicate, variable string) bool { + return predicate.Operator == "EQUALS" && + predicate.Left.Variable == variable && + physicalPathEquals(predicate.Left.Path, []string{physicalScopeProjectField}) && + predicate.Right != nil && + predicate.Right.BindKey == physicalScopeProjectBind && + predicate.Right.Variable == "" && + len(predicate.Right.Path) == 0 +} + +func isScopeAllowedFilter(predicate PhysicalPredicate) bool { + return predicate.Operator == "EQUALS" && predicate.Right != nil && predicate.Right.BindKey == physicalScopeAllowedBind && predicate.Right.Variable == "" && len(predicate.Right.Path) == 0 +} + +func isScopeAllowedPredicate(predicate PhysicalPredicate, variable string) bool { + return isScopeAllowedFilter(predicate) && predicate.Left.Variable == variable && len(predicate.Left.Path) == 0 +} + +func isDatasetGenerationScopePredicate(predicate PhysicalPredicate, variable string) bool { + return predicate.Operator == "EQUALS" && + predicate.Left.Variable == variable && + physicalPathEquals(predicate.Left.Path, []string{physicalScopeDatasetGenerationField}) && + predicate.Right != nil && + predicate.Right.BindKey == physicalScopeDatasetGenerationBind && + predicate.Right.Variable == "" && + len(predicate.Right.Path) == 0 +} + +func validateAuthScopeInputs(inputs, expectedPaths []PhysicalValue) error { + for _, expected := range expectedPaths { + if !containsPhysicalValue(inputs, expected) { + return fmt.Errorf("must include %s", formatPhysicalValue(expected)) + } + } + for _, bindKey := range []string{physicalScopeAuthPathsBind, physicalScopeAuthPathsUnrestrictedBind} { + expected := PhysicalValue{BindKey: bindKey} + if !containsPhysicalValue(inputs, expected) { + return fmt.Errorf("must include @%s", bindKey) + } + } + return nil +} + +func containsPhysicalValue(values []PhysicalValue, expected PhysicalValue) bool { + for _, value := range values { + if value.Variable == expected.Variable && value.BindKey == expected.BindKey && physicalPathEquals(value.Path, expected.Path) { + return true + } + } + return false +} + +func physicalPathEquals(left, right []string) bool { + if len(left) != len(right) { + return false + } + for index := range left { + if left[index] != right[index] { + return false + } + } + return true +} + +func formatPhysicalValue(value PhysicalValue) string { + if value.BindKey != "" { + return "@" + value.BindKey + } + if len(value.Path) == 0 { + return value.Variable + } + return value.Variable + "." + value.Path[0] +} diff --git a/internal/dataframe/physical_scope_test.go b/internal/dataframe/physical_scope_test.go new file mode 100644 index 0000000..06bf18f --- /dev/null +++ b/internal/dataframe/physical_scope_test.go @@ -0,0 +1,165 @@ +package dataframe + +import ( + "strings" + "testing" +) + +func TestValidateGenericPhysicalPlanScope(t *testing.T) { + plan := genericScopePhysicalPlan(t) + if err := ValidateGenericPhysicalPlanScope(plan); err != nil { + t.Fatalf("ValidateGenericPhysicalPlanScope() error = %v", err) + } +} + +func TestValidateGenericPhysicalPlanScopeRejectsMissingMisboundAndReorderedScope(t *testing.T) { + tests := []struct { + name string + mutate func(t *testing.T, plan *PhysicalPlan) + want string + }{ + { + name: "missing root project filter", + mutate: func(t *testing.T, plan *PhysicalPlan) { + removePhysicalOperation(plan, findProjectFilter(t, *plan, "root")) + }, + want: "project scope filter root.project == @project", + }, + { + name: "misbound root project filter", + mutate: func(t *testing.T, plan *PhysicalPlan) { + index := findProjectFilter(t, *plan, "root") + plan.Operations[index].Filter.Predicate.Right = &PhysicalValue{BindKey: physicalScopeAllowedBind} + }, + want: "project scope filter at operation", + }, + { + name: "missing traversal target project filter", + mutate: func(t *testing.T, plan *PhysicalPlan) { + removePhysicalOperation(plan, findProjectFilter(t, *plan, "node_1")) + }, + want: "project scope filter node_1.project == @project", + }, + { + name: "project scope reordered after auth let", + mutate: func(t *testing.T, plan *PhysicalPlan) { + projectIndex := findProjectFilter(t, *plan, "root") + authIndex := findTestAuthScopeLet(t, *plan, "root_scope_allowed") + plan.Operations[projectIndex], plan.Operations[authIndex] = plan.Operations[authIndex], plan.Operations[projectIndex] + }, + want: "AUTH_RESOURCE_PATH_ALLOWED LET", + }, + { + name: "missing root auth scope", + mutate: func(t *testing.T, plan *PhysicalPlan) { + authLet := findTestAuthScopeLet(t, *plan, "root_scope_allowed") + authEquality := findTestAuthScopeEquality(t, *plan, "root_scope_allowed") + removePhysicalOperation(plan, authEquality) + removePhysicalOperation(plan, authLet) + }, + want: "missing AUTH_RESOURCE_PATH_ALLOWED LET", + }, + { + name: "misbound root auth allowed marker", + mutate: func(t *testing.T, plan *PhysicalPlan) { + index := findTestAuthScopeEquality(t, *plan, "root_scope_allowed") + plan.Operations[index].Filter.Predicate.Right = &PhysicalValue{BindKey: physicalScopeProjectBind} + }, + want: "auth scope equality", + }, + { + name: "traversal auth scope omits target path", + mutate: func(t *testing.T, plan *PhysicalPlan) { + index := findTestAuthScopeLet(t, *plan, "traversal_1_scope_allowed") + inputs := plan.Operations[index].DerivedLet.Inputs + filtered := inputs[:0] + for _, input := range inputs { + if input.Variable == "node_1" && physicalPathEquals(input.Path, []string{physicalScopeAuthPathField}) { + continue + } + filtered = append(filtered, input) + } + plan.Operations[index].DerivedLet.Inputs = filtered + }, + want: "must include node_1.auth_resource_path", + }, + { + name: "auth equality reordered before its let", + mutate: func(t *testing.T, plan *PhysicalPlan) { + authLet := findTestAuthScopeLet(t, *plan, "root_scope_allowed") + authEquality := findTestAuthScopeEquality(t, *plan, "root_scope_allowed") + plan.Operations[authLet], plan.Operations[authEquality] = plan.Operations[authEquality], plan.Operations[authLet] + }, + want: "validate physical plan before verifying generic scope", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + plan := genericScopePhysicalPlan(t) + test.mutate(t, &plan) + if err := ValidateGenericPhysicalPlanScope(plan); err == nil || !strings.Contains(err.Error(), test.want) { + t.Fatalf("ValidateGenericPhysicalPlanScope() error = %v; want substring %q", err, test.want) + } + }) + } +} + +func genericScopePhysicalPlan(t *testing.T) PhysicalPlan { + t.Helper() + plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, + Project: "project-1", + AuthResourcePaths: []string{"/programs/p1"}, + Root: SemanticNode{ + Alias: "root", ResourceType: "Patient", + Children: []SemanticNode{{ + Alias: "specimen", ResourceType: "Specimen", EdgeLabel: "subject_Patient", + Children: []SemanticNode{{ + Alias: "file", ResourceType: "DocumentReference", EdgeLabel: "subject_Specimen", + }}, + }}, + }, + }) + if err != nil { + t.Fatalf("BuildGenericPhysicalPlan() error = %v", err) + } + return plan +} + +func findProjectFilter(t *testing.T, plan PhysicalPlan, variable string) int { + t.Helper() + for index, operation := range plan.Operations { + if operation.Kind == PhysicalFilterOp && isProjectScopePredicate(operation.Filter.Predicate, variable) { + return index + } + } + t.Fatalf("project scope filter for %q not found", variable) + return 0 +} + +func findTestAuthScopeLet(t *testing.T, plan PhysicalPlan, variable string) int { + t.Helper() + for index, operation := range plan.Operations { + if operation.Kind == PhysicalDerivedLetOp && operation.DerivedLet.Operator == "AUTH_RESOURCE_PATH_ALLOWED" && operation.DerivedLet.Variable == variable { + return index + } + } + t.Fatalf("auth scope LET %q not found", variable) + return 0 +} + +func findTestAuthScopeEquality(t *testing.T, plan PhysicalPlan, variable string) int { + t.Helper() + for index, operation := range plan.Operations { + if operation.Kind == PhysicalFilterOp && isScopeAllowedPredicate(operation.Filter.Predicate, variable) { + return index + } + } + t.Fatalf("auth scope equality for %q not found", variable) + return 0 +} + +func removePhysicalOperation(plan *PhysicalPlan, index int) { + plan.Operations = append(plan.Operations[:index], plan.Operations[index+1:]...) +} diff --git a/internal/dataframe/pivots.go b/internal/dataframe/pivots.go index 37a845d..38cb96a 100644 --- a/internal/dataframe/pivots.go +++ b/internal/dataframe/pivots.go @@ -2,6 +2,7 @@ package dataframe import ( "context" + "fmt" "github.com/calypr/loom/internal/catalog" "github.com/calypr/loom/internal/fhirschema" @@ -9,64 +10,91 @@ import ( func (s *Service) expandPivotColumns(ctx context.Context, builder Builder) (Builder, error) { pivots, err := s.discoverFields(ctx, catalog.PopulatedFieldOptions{ - ConnectionOptions: s.connOpts, - Project: builder.Project, - AuthResourcePaths: builder.AuthResourcePaths, - ResourceType: builder.RootResourceType, - PivotOnly: true, + ConnectionOptions: s.connOpts, + Project: builder.Project, + DatasetGeneration: builder.DatasetGeneration, + AuthResourcePathsUnrestricted: catalog.ExplicitAuthResourcePathsUnrestricted(builderAuthScopeUnrestricted(builder)), + AuthResourcePaths: builder.AuthResourcePaths, + ResourceType: builder.RootResourceType, + PivotOnly: true, }) if err != nil { return Builder{}, err } - builder.Pivots = fillPivotColumns(builder.Pivots, pivots) + resolved, err := fillPivotColumns(builder.Pivots, pivots) + if err != nil { + return Builder{}, err + } + builder.Pivots = resolved for i := range builder.Traversals { - if err := s.expandTraversalPivotColumns(ctx, builder.Project, builder.AuthResourcePaths, &builder.Traversals[i]); err != nil { + if err := s.expandTraversalPivotColumns(ctx, builder.Project, builder.DatasetGeneration, builder.AuthResourcePaths, builderAuthScopeUnrestricted(builder), &builder.Traversals[i]); err != nil { return Builder{}, err } } return builder, nil } -func (s *Service) expandTraversalPivotColumns(ctx context.Context, project string, authResourcePaths []string, step *TraversalStep) error { +func (s *Service) expandTraversalPivotColumns(ctx context.Context, project, datasetGeneration string, authResourcePaths []string, authResourcePathsUnrestricted bool, step *TraversalStep) error { pivots, err := s.discoverFields(ctx, catalog.PopulatedFieldOptions{ - ConnectionOptions: s.connOpts, - Project: project, - AuthResourcePaths: authResourcePaths, - ResourceType: step.ToResourceType, - PivotOnly: true, + ConnectionOptions: s.connOpts, + Project: project, + DatasetGeneration: datasetGeneration, + AuthResourcePathsUnrestricted: catalog.ExplicitAuthResourcePathsUnrestricted(authResourcePathsUnrestricted), + AuthResourcePaths: authResourcePaths, + ResourceType: step.ToResourceType, + PivotOnly: true, }) if err != nil { return err } - step.Pivots = fillPivotColumns(step.Pivots, pivots) + resolved, err := fillPivotColumns(step.Pivots, pivots) + if err != nil { + return err + } + step.Pivots = resolved for i := range step.Traversals { - if err := s.expandTraversalPivotColumns(ctx, project, authResourcePaths, &step.Traversals[i]); err != nil { + if err := s.expandTraversalPivotColumns(ctx, project, datasetGeneration, authResourcePaths, authResourcePathsUnrestricted, &step.Traversals[i]); err != nil { return err } } return nil } -func fillPivotColumns(in []PivotSelect, discovered []catalog.PopulatedField) []PivotSelect { +// fillPivotColumns resolves an omitted user column list to the bounded, +// scope-aware catalog values computed at ingest time. Rendering an empty list +// would materialize every observed pivot key and is not a safe fallback. +func fillPivotColumns(in []PivotSelect, discovered []catalog.PopulatedField) ([]PivotSelect, error) { if len(in) == 0 { - return []PivotSelect{} + return []PivotSelect{}, nil } out := make([]PivotSelect, 0, len(in)) resourceType := resourceTypeFromDiscovered(discovered) for _, pivot := range in { + columnSel, err := ParseSelector(pivot.ColumnSelect) + if err != nil { + return nil, fmt.Errorf("pivot %q column selector: %w", pivot.Name, err) + } + valueSel, err := ParseSelector(pivot.ValueSelect) + if err != nil { + return nil, fmt.Errorf("pivot %q value selector: %w", pivot.Name, err) + } + spec, err := fhirschema.ValidatePivotSelectors(resourceType, selectorSpecFromSelector(columnSel), selectorSpecFromSelector(valueSel)) + if err != nil { + return nil, fmt.Errorf("pivot %q: %w", pivot.Name, err) + } if pivot.PivotFamily == "" { - columnSel, colErr := ParseSelector(pivot.ColumnSelect) - valueSel, valErr := ParseSelector(pivot.ValueSelect) - if colErr == nil && valErr == nil { - spec, err := fhirschema.ValidatePivotSelectors(resourceType, selectorSpecFromSelector(columnSel), selectorSpecFromSelector(valueSel)) - if err == nil { - pivot.PivotFamily = spec.Family - } + pivot.PivotFamily = spec.Family + } + if len(pivot.Columns) == 0 { + match := findFieldByPath(discovered, spec.CatalogRootPath) + if match == nil || len(match.PivotColumns) == 0 { + return nil, fmt.Errorf("pivot %q has no bounded catalog columns", pivot.Name) } + pivot.Columns = cloneStrings(match.PivotColumns) } out = append(out, pivot) } - return out + return out, nil } func resourceTypeFromDiscovered(fields []catalog.PopulatedField) string { diff --git a/internal/dataframe/pivots_test.go b/internal/dataframe/pivots_test.go new file mode 100644 index 0000000..85e8bcc --- /dev/null +++ b/internal/dataframe/pivots_test.go @@ -0,0 +1,46 @@ +package dataframe + +import ( + "reflect" + "strings" + "testing" + + "github.com/calypr/loom/internal/catalog" +) + +func TestFillPivotColumnsUsesBoundedCatalogValues(t *testing.T) { + resolved, err := fillPivotColumns([]PivotSelect{{ + Name: "lab_values", ColumnSelect: "code.coding[].display", ValueSelect: "valueQuantity.value", + }}, []catalog.PopulatedField{{ + ResourceType: "Observation", Path: "code", PivotCandidate: true, + PivotColumns: []string{"Hemoglobin", "Platelets"}, + }}) + if err != nil { + t.Fatal(err) + } + if len(resolved) != 1 || !reflect.DeepEqual(resolved[0].Columns, []string{"Hemoglobin", "Platelets"}) { + t.Fatalf("resolved pivots = %#v", resolved) + } + if resolved[0].PivotFamily == "" { + t.Fatalf("expected generated pivot family, got %#v", resolved[0]) + } +} + +func TestFillPivotColumnsRejectsUnboundedDiscovery(t *testing.T) { + _, err := fillPivotColumns([]PivotSelect{{ + Name: "lab_values", ColumnSelect: "code.coding[].display", ValueSelect: "valueQuantity.value", + }}, []catalog.PopulatedField{{ResourceType: "Observation", Path: "code", PivotCandidate: true}}) + if err == nil || !strings.Contains(err.Error(), "bounded catalog columns") { + t.Fatalf("error = %v, want bounded catalog column error", err) + } +} + +func TestBuildSemanticPlanRejectsUnresolvedPivotDiscovery(t *testing.T) { + _, err := BuildSemanticPlan(Builder{ + Project: "P1", RootResourceType: "Observation", + Pivots: []PivotSelect{{Name: "lab_values", ColumnSelect: "code.coding[].display", ValueSelect: "valueQuantity.value"}}, + }) + if err == nil || !strings.Contains(err.Error(), "bounded columns") { + t.Fatalf("error = %v, want bounded pivot error", err) + } +} diff --git a/internal/dataframe/planner.go b/internal/dataframe/planner.go index eac3a72..9c05161 100644 --- a/internal/dataframe/planner.go +++ b/internal/dataframe/planner.go @@ -3,6 +3,8 @@ package dataframe import ( "fmt" "strings" + + "github.com/calypr/loom/internal/authscope" ) type PlanHint struct { @@ -11,11 +13,22 @@ type PlanHint struct { NamedSetCount int ClassifiedFileSummaries bool StudyLookup bool + // RowIdentity is copied from the semantic plan so the physical renderer, + // compiler explain output, and downstream exporters agree on what one row + // represents. It is not an optimizer hint despite living here temporarily + // during the Builder-to-physical-plan migration. + RowIdentity *RowIdentity + // AppliedRules records stable optimizer rule identifiers that changed the + // physical shape. It is carried into CompiledQuery for explain, golden, and + // performance comparisons. + AppliedRules []string } type logicalRequest struct { Project string + DatasetGeneration string AuthResourcePaths []string + AuthScopeMode authscope.ReadScopeMode Root logicalNode } @@ -23,7 +36,9 @@ type logicalNode struct { ResourceType string Alias string Label string + MatchMode TraversalMatchMode Fields []FieldSelect + Filters []TypedFilter Pivots []PivotSelect Aggregates []AggregateSelect Slices []RepresentativeSlice @@ -31,30 +46,27 @@ type logicalNode struct { } type loweringContext struct { - request logicalRequest - builder Builder - setsByName map[string]struct{} - modes map[string]string - rootNeighborSet string - patientTypeSets map[string]string - specimenGroupSet string - patientDocumentReferenceSet string - specimenDocumentRefSet string - groupDocumentRefSet string - documentReferenceUnionSet string - documentReferenceSummarySet string - classifyDocumentReferences bool - studyLookupSet string + request logicalRequest + builder Builder + setsByName map[string]struct{} + modes map[string]string + genericSetsBySignature map[string]string + genericFilterSetsBySig map[string]string + genericAliasesBySetName map[string]string + genericTraversalShareCount int } func buildLogicalRequest(builder Builder) logicalRequest { return logicalRequest{ Project: builder.Project, + DatasetGeneration: normalizeDatasetGeneration(builder.DatasetGeneration), AuthResourcePaths: cloneStrings(builder.AuthResourcePaths), + AuthScopeMode: builder.AuthScopeMode, Root: logicalNode{ ResourceType: builder.RootResourceType, Alias: "root", Fields: append([]FieldSelect(nil), builder.Fields...), + Filters: append([]TypedFilter(nil), builder.Filters...), Pivots: append([]PivotSelect(nil), builder.Pivots...), Aggregates: append([]AggregateSelect(nil), builder.Aggregates...), Slices: append([]RepresentativeSlice(nil), builder.Slices...), @@ -73,7 +85,9 @@ func logicalNodesFromTraversal(in []TraversalStep) []logicalNode { ResourceType: step.ToResourceType, Alias: step.Alias, Label: step.Label, + MatchMode: step.MatchMode, Fields: append([]FieldSelect(nil), step.Fields...), + Filters: append([]TypedFilter(nil), step.Filters...), Pivots: append([]PivotSelect(nil), step.Pivots...), Aggregates: append([]AggregateSelect(nil), step.Aggregates...), Slices: append([]RepresentativeSlice(nil), step.Slices...), @@ -84,188 +98,84 @@ func logicalNodesFromTraversal(in []TraversalStep) []logicalNode { } func lowerGraphQLBuilder(builder Builder) (Builder, error) { - request := buildLogicalRequest(builder) - if request.Root.ResourceType != "Patient" { - return Builder{}, unsupportedLoweringError("optimized lowering currently supports only Patient-root dataframe requests") - } - if !supportsSemanticLoweringFamily(request.Root, request.Root.ResourceType) { - return Builder{}, unsupportedLoweringError("one or more traversals are outside the supported optimized FHIR traversal family") - } - if !shouldUseStructuralLowering(request.Root) { - return Builder{}, unsupportedLoweringError("request does not use a supported optimized dataframe shape; add supported traversals, aggregates, slices, or pivots") - } - - ctx := &loweringContext{ - request: request, - builder: Builder{ - Project: request.Project, - AuthResourcePaths: request.AuthResourcePaths, - RootResourceType: request.Root.ResourceType, - Fields: append([]FieldSelect(nil), request.Root.Fields...), - Pivots: append([]PivotSelect(nil), request.Root.Pivots...), - Aggregates: append([]AggregateSelect(nil), request.Root.Aggregates...), - Slices: append([]RepresentativeSlice(nil), request.Root.Slices...), - Sets: []NamedSet{}, - DerivedFields: []DerivedField{}, - }, - setsByName: map[string]struct{}{}, - modes: map[string]string{}, - patientTypeSets: map[string]string{}, - } - - ctx.classifyDocumentReferences = requestUsesDocumentReferenceSummary(request.Root) - if !ctx.lowerPatientRoot(request.Root) { - return Builder{}, unsupportedLoweringError("request matches the optimized family, but required semantic lowering rules are not implemented yet") - } - - ctx.builder.PlanHint = &PlanHint{ - Mode: "lowered", - Profile: "patient_case_assay_family", - NamedSetCount: len(ctx.builder.Sets), - ClassifiedFileSummaries: ctx.documentReferenceSummarySet != "", - StudyLookup: ctx.studyLookupSet != "", - } - return ctx.builder, nil -} - -func unsupportedLoweringError(msg string) error { - return fmt.Errorf("unsupported dataframe query shape: %s", msg) + return lowerGenericGraphQLBuilder(builder, buildLogicalRequest(builder)) } -func supportsSemanticLoweringFamily(node logicalNode, sourceType string) bool { +func requestHasTypedFilters(node logicalNode) bool { + if len(node.Filters) > 0 { + return true + } for _, child := range node.Children { - if _, ok := lookupPlannerTraversal(sourceType, child.Label, child.ResourceType); !ok { - return false - } - if !supportsSemanticLoweringFamily(child, child.ResourceType) { - return false + if requestHasTypedFilters(child) { + return true } } - return true + return false } -func (ctx *loweringContext) lowerPatientRoot(root logicalNode) bool { - useRootNeighbors := shouldUseRootNeighborSet(root.Children, root.ResourceType) - if useRootNeighbors { - ctx.rootNeighborSet = ctx.ensureSet(NamedSet{ - Name: "root_patient_neighbor_set", - Kind: SetKindTraverse, - Label: "subject_Patient", - Unique: true, - }, "node") - } - - for _, child := range root.Children { - spec, ok := lookupPlannerTraversal(root.ResourceType, child.Label, child.ResourceType) - if !ok { - return false - } - switch spec.Role { - case traversalRolePatientNeighborChild: - sourceSet := ctx.ensurePatientChildSet(spec, useRootNeighbors) - if child.ResourceType == "ResearchSubject" && requestNeedsStudyHydration(child) { - ctx.ensureStudyLookupSet(sourceSet) - } - if child.ResourceType == "Specimen" { - if !ctx.lowerSpecimenNode(child, sourceSet) { - return false - } - } else if child.ResourceType == "Group" { - if !ctx.lowerGroupNode(child, sourceSet) { - return false - } - } else { - ctx.lowerNodeSelections(child, sourceSet, false) - } - case traversalRolePatientDocumentReference: - sourceSet := ctx.ensurePatientDocumentReferenceSet(useRootNeighbors) - ctx.lowerDocumentReferenceNode(child, sourceSet) - case traversalRolePatientDirectChild: - sourceSet := ctx.ensureDirectTraversalSet(spec, "") - if child.ResourceType == "Group" { - if !ctx.lowerGroupNode(child, sourceSet) { - return false - } - } else { - ctx.lowerNodeSelections(child, sourceSet, false) - } - default: - return false +func requestHasRequiredTraversalMatch(node logicalNode) bool { + for _, child := range node.Children { + if child.MatchMode.required() || requestHasRequiredTraversalMatch(child) { + return true } } - - if ctx.classifyDocumentReferences { - ctx.ensureDocumentReferenceSummarySet() - } - return true + return false } -func (ctx *loweringContext) lowerSpecimenNode(node logicalNode, specimenSet string) bool { - ctx.lowerNodeSelections(node, specimenSet, false) - for _, child := range node.Children { - spec, ok := lookupPlannerTraversal(node.ResourceType, child.Label, child.ResourceType) - if !ok { - return false - } - switch spec.Role { - case traversalRoleSpecimenGroup: - groupSet := ctx.ensureSpecimenGroupSet(specimenSet) - if !ctx.lowerGroupNode(child, groupSet) { - return false - } - case traversalRoleSpecimenDocumentReference: - docSet := ctx.ensureSpecimenDocumentReferenceSet(specimenSet) - ctx.lowerDocumentReferenceNode(child, docSet) - default: - return false - } +// Lower converts the public dataframe request into a validated physical-plan +// builder. It is the compiler boundary used by conformance tooling and by the +// service layer; callers should not construct named sets directly. +func Lower(builder Builder) (Builder, error) { + semantic, err := BuildSemanticPlan(builder) + if err != nil { + return Builder{}, err } - return true + return lowerSemanticBuilder(builder, semantic) } -func (ctx *loweringContext) lowerGroupNode(node logicalNode, groupSet string) bool { - ctx.lowerNodeSelections(node, groupSet, false) - for _, child := range node.Children { - spec, ok := lookupPlannerTraversal(node.ResourceType, child.Label, child.ResourceType) - if !ok { - return false - } - if spec.Role != traversalRoleGroupDocumentReference { - return false - } - docSet := ctx.ensureGroupDocumentReferenceSet(groupSet) - ctx.lowerDocumentReferenceNode(child, docSet) - } - return true +// lowerSemanticBuilder performs the representation-specific half of Lower +// after its caller has already built the semantic request. Keeping that seam +// explicit lets CompileRequest, the service path, and compiler explain all +// choose the typed physical renderer without parsing selectors twice. +func lowerSemanticBuilder(builder Builder, semantic SemanticPlan) (Builder, error) { + planned, err := lowerGraphQLBuilder(builder) + if err != nil { + return Builder{}, err + } + planned.RowGrain = semantic.RowIdentity.Grain + if planned.PlanHint == nil { + return Builder{}, fmt.Errorf("compiler lowering produced no physical plan hint") + } + planned.PlanHint.RowIdentity = cloneRowIdentity(semantic.RowIdentity) + return planned, nil } -func (ctx *loweringContext) lowerDocumentReferenceNode(node logicalNode, routeSet string) { - useSummary := ctx.classifyDocumentReferences && hasSingleDocumentReferenceAlias(ctx.request.Root) - sourceSet := routeSet - if useSummary { - sourceSet = ctx.ensureDocumentReferenceSummarySet() - } - ctx.lowerNodeSelections(node, sourceSet, useSummary) +func unsupportedLoweringError(msg string) error { + return fmt.Errorf("unsupported dataframe query shape: %s", msg) } -func (ctx *loweringContext) lowerNodeSelections(node logicalNode, sourceSet string, useDocumentSummary bool) { +// lowerNodeSelections implements the canonical selection contract for every +// FHIR root and traversal. AUTO on a repeated relationship is deterministic +// FIRST; callers that need arrays must request ALL or DISTINCT explicitly. +func (ctx *loweringContext) lowerNodeSelections(node logicalNode, sourceSet string) { for _, field := range node.Fields { selectExpr := field.Select fallbacks := append([]string(nil), field.FallbackSelects...) - if useDocumentSummary { - if mapped, ok := mapDocumentReferenceSelectorToSummaryField(field.Select); ok { - selectExpr = mapped - } - for i := range fallbacks { - if mapped, ok := mapDocumentReferenceSelectorToSummaryField(fallbacks[i]); ok { - fallbacks[i] = mapped - } - } + operation := DerivedOpUnique + switch normalizeValueMode(field.ValueMode) { + case "FIRST": + operation = DerivedOpFirstNonNull + case "ALL": + operation = DerivedOpAll + case "DISTINCT": + operation = DerivedOpUnique + case "AUTO": + operation = DerivedOpFirstNonNull } ctx.builder.DerivedFields = append(ctx.builder.DerivedFields, DerivedField{ Name: sanitizeColumnName(node.Alias + "__" + field.Name), Source: sourceSet, - Operation: DerivedOpUnique, + Operation: operation, Select: selectExpr, FallbackSelects: fallbacks, }) @@ -273,14 +183,6 @@ func (ctx *loweringContext) lowerNodeSelections(node logicalNode, sourceSet stri for _, pivot := range node.Pivots { keySelect := pivot.ColumnSelect valueSelect := pivot.ValueSelect - if useDocumentSummary { - if mapped, ok := mapDocumentReferenceSelectorToSummaryField(keySelect); ok { - keySelect = mapped - } - if mapped, ok := mapDocumentReferenceSelectorToSummaryField(valueSelect); ok { - valueSelect = mapped - } - } ctx.builder.DerivedFields = append(ctx.builder.DerivedFields, DerivedField{ Name: sanitizeColumnName(node.Alias + "__" + pivot.Name), Source: sourceSet, @@ -299,14 +201,6 @@ func (ctx *loweringContext) lowerNodeSelections(node logicalNode, sourceSet stri PredicatePath: agg.PredicatePath, PredicateEquals: agg.PredicateEquals, } - if useDocumentSummary { - if mapped, ok := mapDocumentReferenceSelectorToSummaryField(field.Select); ok { - field.Select = mapped - } - if mapped, ok := mapDocumentReferenceSelectorToSummaryField(field.PredicatePath); ok { - field.PredicatePath = mapped - } - } switch strings.ToUpper(strings.TrimSpace(agg.Operation)) { case "COUNT": if strings.TrimSpace(field.PredicatePath) != "" || strings.TrimSpace(field.Predicate) != "" { @@ -320,6 +214,10 @@ func (ctx *loweringContext) lowerNodeSelections(node logicalNode, sourceSet stri field.Operation = DerivedOpAny case "DISTINCT_VALUES": field.Operation = DerivedOpUnique + case "MIN": + field.Operation = DerivedOpMin + case "MAX": + field.Operation = DerivedOpMax default: continue } @@ -334,25 +232,19 @@ func (ctx *loweringContext) lowerNodeSelections(node logicalNode, sourceSet stri Limit: slice.Limit, Fields: append([]FieldSelect(nil), slice.Fields...), } - if useDocumentSummary { - if mapped, ok := mapDocumentReferenceSelectorToSummaryField(projected.PredicatePath); ok { - projected.PredicatePath = mapped - } - for i := range projected.Fields { - if mapped, ok := mapDocumentReferenceSelectorToSummaryField(projected.Fields[i].Select); ok { - projected.Fields[i].Select = mapped - } - for j := range projected.Fields[i].FallbackSelects { - if mapped, ok := mapDocumentReferenceSelectorToSummaryField(projected.Fields[i].FallbackSelects[j]); ok { - projected.Fields[i].FallbackSelects[j] = mapped - } - } - } - } ctx.builder.RepresentativeSlices = append(ctx.builder.RepresentativeSlices, projected) } } +func normalizeValueMode(mode string) string { + switch strings.ToUpper(strings.TrimSpace(mode)) { + case "FIRST", "ALL", "DISTINCT": + return strings.ToUpper(strings.TrimSpace(mode)) + default: + return "AUTO" + } +} + func (ctx *loweringContext) ensureSet(set NamedSet, mode string) string { if _, ok := ctx.setsByName[set.Name]; ok { return set.Name @@ -362,278 +254,3 @@ func (ctx *loweringContext) ensureSet(set NamedSet, mode string) string { ctx.modes[set.Name] = mode return set.Name } - -func (ctx *loweringContext) ensurePatientChildSet(spec plannerTraversal, useRootNeighbors bool) string { - if name, ok := ctx.patientTypeSets[spec.Schema.ToType]; ok { - return name - } - setName := spec.SetName - if strings.TrimSpace(setName) == "" { - setName = "patient_" + sanitizeColumnName(strings.ToLower(spec.Schema.ToType)) + "_set" - } - set := NamedSet{ - Name: setName, - Kind: SetKindFilter, - Source: ctx.rootNeighborSet, - MatchResourceType: spec.Schema.ToType, - SortField: "_key", - } - if !useRootNeighbors { - set = NamedSet{ - Name: setName, - Kind: SetKindTraverse, - Label: spec.Schema.EdgeLabel, - ToResourceType: spec.Schema.ToType, - Unique: true, - } - } - ctx.patientTypeSets[spec.Schema.ToType] = ctx.ensureSet(set, "node") - return ctx.patientTypeSets[spec.Schema.ToType] -} - -func (ctx *loweringContext) ensureSpecimenGroupSet(specimenSet string) string { - if ctx.specimenGroupSet != "" { - return ctx.specimenGroupSet - } - ctx.specimenGroupSet = ctx.ensureSet(NamedSet{ - Name: "specimen_group_set", - Kind: SetKindTraverse, - Source: specimenSet, - Label: "member_entity_Specimen", - ToResourceType: "Group", - Unique: true, - }, "node") - return ctx.specimenGroupSet -} - -func (ctx *loweringContext) ensurePatientDocumentReferenceSet(useRootNeighbors bool) string { - if ctx.patientDocumentReferenceSet != "" { - return ctx.patientDocumentReferenceSet - } - set := NamedSet{ - Name: "patient_document_reference_set", - Kind: SetKindFilter, - Source: ctx.rootNeighborSet, - MatchResourceType: "DocumentReference", - } - if !useRootNeighbors { - set = NamedSet{ - Name: "patient_document_reference_set", - Kind: SetKindTraverse, - Label: "subject_Patient", - ToResourceType: "DocumentReference", - Unique: true, - } - } - ctx.patientDocumentReferenceSet = ctx.ensureSet(set, "node") - return ctx.patientDocumentReferenceSet -} - -func (ctx *loweringContext) ensureSpecimenDocumentReferenceSet(specimenSet string) string { - if ctx.specimenDocumentRefSet != "" { - return ctx.specimenDocumentRefSet - } - ctx.specimenDocumentRefSet = ctx.ensureSet(NamedSet{ - Name: "specimen_document_reference_set", - Kind: SetKindTraverse, - Source: specimenSet, - Label: "subject_Specimen", - ToResourceType: "DocumentReference", - Unique: true, - }, "node") - return ctx.specimenDocumentRefSet -} - -func (ctx *loweringContext) ensureGroupDocumentReferenceSet(groupSet string) string { - if ctx.groupDocumentRefSet != "" { - return ctx.groupDocumentRefSet - } - ctx.groupDocumentRefSet = ctx.ensureSet(NamedSet{ - Name: "group_document_reference_set", - Kind: SetKindTraverse, - Source: groupSet, - Label: "subject_Group", - ToResourceType: "DocumentReference", - Unique: true, - }, "node") - return ctx.groupDocumentRefSet -} - -func (ctx *loweringContext) ensureDocumentReferenceUnionSet() string { - if ctx.documentReferenceUnionSet != "" { - return ctx.documentReferenceUnionSet - } - sources := []string{} - for _, name := range []string{ctx.patientDocumentReferenceSet, ctx.specimenDocumentRefSet, ctx.groupDocumentRefSet} { - if name != "" { - sources = append(sources, name) - } - } - if len(sources) == 0 { - return "" - } - if len(sources) == 1 { - ctx.documentReferenceUnionSet = sources[0] - return ctx.documentReferenceUnionSet - } - ctx.documentReferenceUnionSet = ctx.ensureSet(NamedSet{ - Name: "document_reference_union_set", - Kind: SetKindUnion, - Sources: sources, - }, "node") - return ctx.documentReferenceUnionSet -} - -func (ctx *loweringContext) ensureDocumentReferenceSummarySet() string { - if ctx.documentReferenceSummarySet != "" { - return ctx.documentReferenceSummarySet - } - source := ctx.ensureDocumentReferenceUnionSet() - if source == "" { - return "" - } - ctx.documentReferenceSummarySet = ctx.ensureSet(NamedSet{ - Name: "document_reference_summary_set", - Kind: SetKindClassifyDocumentReference, - Source: source, - }, "object") - return ctx.documentReferenceSummarySet -} - -func (ctx *loweringContext) ensureStudyLookupSet(researchSubjectSet string) string { - if ctx.studyLookupSet != "" { - return ctx.studyLookupSet - } - ctx.studyLookupSet = ctx.ensureSet(NamedSet{ - Name: "research_subject_study_lookup_set", - Kind: SetKindLookupStudy, - Source: researchSubjectSet, - }, "object") - return ctx.studyLookupSet -} - -func (ctx *loweringContext) ensureDirectTraversalSet(spec plannerTraversal, sourceSet string) string { - mode := "node" - set := NamedSet{ - Name: spec.SetName, - Kind: SetKindTraverse, - Label: spec.Schema.EdgeLabel, - ToResourceType: spec.Schema.ToType, - Unique: true, - } - if sourceSet != "" { - set.Source = sourceSet - } - return ctx.ensureSet(set, mode) -} - -func shouldUseRootNeighborSet(children []logicalNode, rootType string) bool { - count := 0 - for _, child := range children { - spec, ok := lookupPlannerTraversal(rootType, child.Label, child.ResourceType) - if ok && spec.SharedRootNeighborEligible { - count++ - } - } - return count > 1 -} - -func shouldUseStructuralLowering(root logicalNode) bool { - if len(root.Children) > 1 { - return true - } - if requestUsesDocumentReferenceSummary(root) { - return true - } - var hasNested bool - var walk func(node logicalNode) - walk = func(node logicalNode) { - if len(node.Children) > 0 { - hasNested = true - } - for _, child := range node.Children { - walk(child) - } - } - for _, child := range root.Children { - walk(child) - } - return hasNested -} - -func requestUsesDocumentReferenceSummary(root logicalNode) bool { - nodes := collectDocumentReferenceNodes(root) - for _, node := range nodes { - for _, field := range node.Fields { - if selectorNeedsDocumentReferenceSummary(field.Select) { - return true - } - for _, fallback := range field.FallbackSelects { - if selectorNeedsDocumentReferenceSummary(fallback) { - return true - } - } - } - for _, agg := range node.Aggregates { - if selectorNeedsDocumentReferenceSummary(agg.Select) { - return true - } - if selectorNeedsDocumentReferenceSummary(agg.PredicatePath) { - return true - } - } - for _, slice := range node.Slices { - if selectorNeedsDocumentReferenceSummary(slice.PredicatePath) { - return true - } - for _, field := range slice.Fields { - if selectorNeedsDocumentReferenceSummary(field.Select) { - return true - } - for _, fallback := range field.FallbackSelects { - if selectorNeedsDocumentReferenceSummary(fallback) { - return true - } - } - } - } - } - return false -} - -func collectDocumentReferenceNodes(root logicalNode) []logicalNode { - var out []logicalNode - var walk func(node logicalNode) - walk = func(node logicalNode) { - if node.ResourceType == "DocumentReference" { - out = append(out, node) - } - for _, child := range node.Children { - walk(child) - } - } - for _, child := range root.Children { - walk(child) - } - return out -} - -func hasSingleDocumentReferenceAlias(root logicalNode) bool { - return len(collectDocumentReferenceNodes(root)) == 1 -} - -func requestNeedsStudyHydration(node logicalNode) bool { - for _, field := range node.Fields { - if requiresResearchStudyHydration(field.Select, field.FieldRef) { - return true - } - } - for _, slice := range node.Slices { - for _, field := range slice.Fields { - if requiresResearchStudyHydration(field.Select, field.FieldRef) { - return true - } - } - } - return false -} diff --git a/internal/dataframe/relationship_match.go b/internal/dataframe/relationship_match.go new file mode 100644 index 0000000..2c791d2 --- /dev/null +++ b/internal/dataframe/relationship_match.go @@ -0,0 +1,132 @@ +package dataframe + +import ( + "fmt" + "strings" + + "github.com/calypr/loom/internal/fhirschema" +) + +// TraversalMatchMode controls whether a relationship contributes values to a +// dataframe row only, or must exist for that root row to be included at all. +// +// OPTIONAL is the legacy behavior: a missing child yields an empty child +// projection but does not remove the root row. REQUIRED is intentionally +// opt-in and lowers to a root-scoped semi-join. The empty value is OPTIONAL so +// existing Builder callers retain their current behavior. +type TraversalMatchMode string + +const ( + TraversalMatchOptional TraversalMatchMode = "OPTIONAL" + TraversalMatchRequired TraversalMatchMode = "REQUIRED" +) + +func (m TraversalMatchMode) Validate() error { + switch m { + case "", TraversalMatchOptional, TraversalMatchRequired: + return nil + default: + return fmt.Errorf("unsupported traversal match mode %q", m) + } +} + +func (m TraversalMatchMode) required() bool { + return m == TraversalMatchRequired +} + +// RequiredTraversalMatch is the lowered representation of one existential +// relationship route. It is compiler-owned, not a GraphQL input: Lower builds +// it from TraversalStep.MatchMode and Compile renders it before root sorting +// and limiting. Every step in Steps must match for the root row to survive. +type RequiredTraversalMatch struct { + Steps []TraversalMatchStep +} + +// TraversalMatchStep retains only the information necessary to evaluate a +// relationship existence predicate. Alias and selection shape do not affect +// the semi-join, while typed filters do. +type TraversalMatchStep struct { + Alias string + Label string + ToResourceType string + Filters []TypedFilter +} + +func requiredTraversalMatches(root logicalNode) ([]RequiredTraversalMatch, error) { + matches := make([]RequiredTraversalMatch, 0) + var walk func(parent logicalNode, route []TraversalMatchStep) error + walk = func(parent logicalNode, route []TraversalMatchStep) error { + for _, child := range parent.Children { + if err := child.MatchMode.Validate(); err != nil { + return fmt.Errorf("traversal %s -> %s (%s): %w", parent.ResourceType, child.ResourceType, child.Label, err) + } + if _, err := resolveStorageRoute(parent.ResourceType, child.Label, child.ResourceType); err != nil { + return fmt.Errorf("traversal %s -> %s (%s): %w", parent.ResourceType, child.ResourceType, child.Label, err) + } + + next := appendTraversalMatchStep(route, TraversalMatchStep{ + Alias: child.Alias, + Label: child.Label, + ToResourceType: child.ResourceType, + Filters: append([]TypedFilter(nil), child.Filters...), + }) + if child.MatchMode.required() { + matches = append(matches, RequiredTraversalMatch{Steps: cloneTraversalMatchSteps(next)}) + } + if err := walk(child, next); err != nil { + return err + } + } + return nil + } + if err := walk(root, nil); err != nil { + return nil, err + } + return matches, nil +} + +func validateRequiredTraversalMatches(rootResourceType string, matches []RequiredTraversalMatch) error { + for matchIndex, match := range matches { + if len(match.Steps) == 0 { + return fmt.Errorf("required traversal match %d has no route steps", matchIndex) + } + fromResourceType := rootResourceType + for stepIndex, step := range match.Steps { + if strings.TrimSpace(step.Label) == "" { + return fmt.Errorf("required traversal match %d step %d has no edge label", matchIndex, stepIndex) + } + if !fhirschema.HasResource(step.ToResourceType) { + return fmt.Errorf("required traversal match %d step %d target resource type %q is not represented by the active generated FHIR schema", matchIndex, stepIndex, step.ToResourceType) + } + if _, err := resolveStorageRoute(fromResourceType, step.Label, step.ToResourceType); err != nil { + return fmt.Errorf("required traversal match %d step %d %s -> %s (%s): %w", matchIndex, stepIndex, fromResourceType, step.ToResourceType, step.Label, err) + } + for _, filter := range step.Filters { + if err := ValidateTypedFilterForResource(step.ToResourceType, filter); err != nil { + return fmt.Errorf("required traversal match %d step %d filter %q: %w", matchIndex, stepIndex, filter.FieldRef, err) + } + } + fromResourceType = step.ToResourceType + } + } + return nil +} + +func appendTraversalMatchStep(route []TraversalMatchStep, step TraversalMatchStep) []TraversalMatchStep { + next := make([]TraversalMatchStep, len(route), len(route)+1) + copy(next, route) + next = append(next, step) + return next +} + +func cloneTraversalMatchSteps(in []TraversalMatchStep) []TraversalMatchStep { + if len(in) == 0 { + return nil + } + out := make([]TraversalMatchStep, len(in)) + for i, step := range in { + out[i] = step + out[i].Filters = append([]TypedFilter(nil), step.Filters...) + } + return out +} diff --git a/internal/dataframe/relationship_match_arango_integration_test.go b/internal/dataframe/relationship_match_arango_integration_test.go new file mode 100644 index 0000000..f6acb5d --- /dev/null +++ b/internal/dataframe/relationship_match_arango_integration_test.go @@ -0,0 +1,51 @@ +package dataframe + +import ( + "context" + "os" + "testing" + + arangostore "github.com/calypr/loom/internal/store/arango" +) + +// TestRequiredTraversalMatchExplainsAndRunsAgainstArango verifies that the +// root-correlated bounded subquery is accepted by the real Arango parser and +// executes against the locally loaded META fixture. It remains opt-in because +// it reads a developer's local database. +func TestRequiredTraversalMatchExplainsAndRunsAgainstArango(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run compiler/Arango integration") + } + url, database, project := compilerArangoTarget() + compiled, err := CompileRequest(Builder{ + Project: project, + RootResourceType: "Specimen", + Traversals: []TraversalStep{{ + Label: "subject_Specimen", + ToResourceType: "DocumentReference", + Alias: "file", + MatchMode: TraversalMatchRequired, + Filters: []TypedFilter{{ + FieldRef: "DocumentReference.file_name", + Selector: "content[].attachment.title", + FieldKind: FilterString, + Repeated: true, + Quantifier: QuantifierAny, + Operator: FilterExists, + }}, + }}, + }, 5) + if err != nil { + t.Fatalf("CompileRequest() error = %v", err) + } + if _, err := ExplainCompiledQuery(context.Background(), arangostore.ConnectionOptions{URL: url, Database: database}, compiled); err != nil { + t.Fatalf("ExplainCompiledQuery() error = %v\nAQL:\n%s", err, compiled.Query) + } + rows, err := executeCompiledRows(context.Background(), arangostore.ConnectionOptions{URL: url, Database: database}, compiled) + if err != nil { + t.Fatalf("execute required relationship match: %v\nAQL:\n%s", err, compiled.Query) + } + if len(rows) == 0 { + t.Fatalf("required relationship match returned no rows for project %q", project) + } +} diff --git a/internal/dataframe/relationship_match_compile.go b/internal/dataframe/relationship_match_compile.go new file mode 100644 index 0000000..a6b4057 --- /dev/null +++ b/internal/dataframe/relationship_match_compile.go @@ -0,0 +1,67 @@ +package dataframe + +import ( + "fmt" + "strings" +) + +// compileRequiredTraversalMatch emits a bounded root-correlated existence +// subquery. Each step is rechecked against the compiler-owned stored-edge +// route contract, so a manually assembled lowered Builder cannot turn an +// unproven schema-valid forward FHIR reference into an incorrect semi-join. +func (c *compiler) compileRequiredTraversalMatch(rootVar string, matchIndex int, match RequiredTraversalMatch) (string, error) { + if len(match.Steps) == 0 { + return "", fmt.Errorf("required traversal match %d has no route steps", matchIndex) + } + + lines := make([]string, 0, len(match.Steps)*6+2) + parentVar := rootVar + parentResourceType := c.builder.RootResourceType + for stepIndex, step := range match.Steps { + route, err := resolveStorageRoute(parentResourceType, step.Label, step.ToResourceType) + if err != nil { + return "", fmt.Errorf("compile required traversal match %d step %d: %w", matchIndex, stepIndex, err) + } + nodeVar := fmt.Sprintf("__match_%d_%d", matchIndex, stepIndex) + edgeVar := fmt.Sprintf("__match_edge_%d_%d", matchIndex, stepIndex) + labelBind := c.newBind(fmt.Sprintf("match_%d_%d_label", matchIndex, stepIndex), step.Label) + toBind := c.newBind(fmt.Sprintf("match_%d_%d_to", matchIndex, stepIndex), step.ToResourceType) + edgeTypeField := route.targetEdgeTypeField() + if edgeTypeField == "" { + return "", fmt.Errorf("compile required traversal match %d step %d: %w: route direction %q has no fhir_edge target type field", matchIndex, stepIndex, ErrUnsupportedStorageRoute, route.Direction) + } + edgeTypeBind := c.newBind(fmt.Sprintf("match_%d_%d_edge_target_type", matchIndex, stepIndex), step.ToResourceType) + lines = append(lines, fmt.Sprintf("FOR %s, %s IN 1..1 %s %s fhir_edge", nodeVar, edgeVar, route.Direction, parentVar)) + lines = append(lines, fmt.Sprintf(" FILTER %s.project == @project", edgeVar)) + lines = append(lines, fmt.Sprintf(" FILTER %s.project == @project", nodeVar)) + lines = append(lines, fmt.Sprintf(" FILTER %s.%s == @%s", edgeVar, datasetGenerationField, datasetGenerationBindKey)) + lines = append(lines, fmt.Sprintf(" FILTER %s.%s == @%s", nodeVar, datasetGenerationField, datasetGenerationBindKey)) + lines = append(lines, fmt.Sprintf(" FILTER @auth_resource_paths_unrestricted == true OR (%s.auth_resource_path IN @auth_resource_paths AND %s.auth_resource_path IN @auth_resource_paths)", edgeVar, nodeVar)) + lines = append(lines, fmt.Sprintf(" FILTER %s.label == @%s", edgeVar, labelBind)) + lines = append(lines, fmt.Sprintf(" FILTER %s.%s == @%s", edgeVar, edgeTypeField, edgeTypeBind)) + lines = append(lines, fmt.Sprintf(" FILTER %s.resourceType == @%s", nodeVar, toBind)) + filters, err := c.compileTypedFilters(nodeVar+".payload", step.Filters) + if err != nil { + return "", fmt.Errorf("compile required traversal match %d step %d filters: %w", matchIndex, stepIndex, err) + } + if filters != "true" { + lines = append(lines, " FILTER ("+filters+")") + } + parentVar = nodeVar + parentResourceType = step.ToResourceType + } + lines = append(lines, " LIMIT 1", " RETURN 1") + return "LENGTH(\n " + strings.Join(lines, "\n ") + "\n ) > 0", nil +} + +func (c *compiler) compileRequiredTraversalMatches(rootVar string, matches []RequiredTraversalMatch) ([]string, error) { + filters := make([]string, 0, len(matches)) + for matchIndex, match := range matches { + expr, err := c.compileRequiredTraversalMatch(rootVar, matchIndex, match) + if err != nil { + return nil, err + } + filters = append(filters, expr) + } + return filters, nil +} diff --git a/internal/dataframe/relationship_match_test.go b/internal/dataframe/relationship_match_test.go new file mode 100644 index 0000000..6b72f32 --- /dev/null +++ b/internal/dataframe/relationship_match_test.go @@ -0,0 +1,214 @@ +package dataframe + +import ( + "strings" + "testing" +) + +func TestOptionalTraversalMatchPreservesRootMembershipAndPostLimitMaterialization(t *testing.T) { + compiled, err := CompileRequest(Builder{ + Project: "P1", + RootResourceType: "Specimen", + Traversals: []TraversalStep{{ + Label: "subject_Specimen", + ToResourceType: "DocumentReference", + Alias: "file", + }}, + }, 5) + if err != nil { + t.Fatal(err) + } + if strings.Contains(compiled.Query, "__match_") || containsOptimizerRule(compiled.OptimizationRules, OptimizerRuleRelationshipSemiJoin) { + t.Fatalf("optional traversal unexpectedly changed root membership:\n%s\nrules=%#v", compiled.Query, compiled.OptimizationRules) + } + if !strings.Contains(compiled.Query, "FOR root IN @@root_collection") { + t.Fatalf("navigation-only generic request did not use the typed physical renderer:\n%s", compiled.Query) + } + if got, want := strings.Index(compiled.Query, "LIMIT @limit"), strings.Index(compiled.Query, "LET __loom_physical_set_1"); got < 0 || want < 0 || got > want { + t.Fatalf("optional traversal should materialize after the root execution window:\n%s", compiled.Query) + } +} + +func TestRequiredDirectTraversalCompilesTypedChildFilterAsRootSemiJoin(t *testing.T) { + melanoma := "melanoma" + builder := Builder{ + Project: "P1", + RootResourceType: "Patient", + Traversals: []TraversalStep{{ + Label: "subject_Patient", + ToResourceType: "Condition", + Alias: "diagnosis", + MatchMode: TraversalMatchRequired, + Filters: []TypedFilter{{ + FieldRef: "Condition.id", + Selector: "id", + FieldKind: FilterString, + Operator: FilterEquals, + Values: []FilterValue{{Kind: FilterString, String: &melanoma}}, + }}, + }}, + } + semantic, err := BuildSemanticPlan(builder) + if err != nil { + t.Fatal(err) + } + if len(semantic.Root.Children) != 1 || semantic.Root.Children[0].MatchMode != TraversalMatchRequired { + t.Fatalf("semantic required match mode was not preserved: %#v", semantic.Root.Children) + } + planned, err := Lower(builder) + if err != nil { + t.Fatal(err) + } + if len(planned.RequiredTraversalMatches) != 1 || len(planned.RequiredTraversalMatches[0].Steps) != 1 { + t.Fatalf("lowered required matches = %#v", planned.RequiredTraversalMatches) + } + compiled, err := Compile(planned, 5) + if err != nil { + t.Fatal(err) + } + if compiled.PlanProfile != "generic_fhir_graph" { + t.Fatalf("required match must use generic lowerer, got %q", compiled.PlanProfile) + } + if !containsOptimizerRule(compiled.OptimizationRules, OptimizerRuleRelationshipSemiJoin) { + t.Fatalf("missing semi-join provenance: %#v", compiled.OptimizationRules) + } + for _, want := range []string{ + "FOR __match_0_0, __match_edge_0_0 IN 1..1 INBOUND root fhir_edge", + "__match_edge_0_0.project == @project", + "__match_edge_0_0.auth_resource_path IN @auth_resource_paths", + "__match_0_0.auth_resource_path IN @auth_resource_paths", + "__match_0_0.resourceType == @__match_0_0_to_", + "__match_0_0.payload", + "LIMIT 1", + } { + if !strings.Contains(compiled.Query, want) { + t.Fatalf("required semi-join missing %q:\n%s", want, compiled.Query) + } + } + assertBindVarValue(t, compiled.BindVars, "subject_Patient") + assertBindVarValue(t, compiled.BindVars, "Condition") + assertBindVarValue(t, compiled.BindVars, melanoma) + assertRootMatchPrecedesLimit(t, compiled.Query) +} + +func TestRequiredNestedTraversalCompilesOneBoundedRoute(t *testing.T) { + fileID := "melanoma-report" + compiled, err := CompileRequest(Builder{ + Project: "P1", + RootResourceType: "Patient", + Traversals: []TraversalStep{{ + Label: "subject_Patient", + ToResourceType: "Specimen", + Alias: "specimen", + Traversals: []TraversalStep{{ + Label: "subject_Specimen", + ToResourceType: "DocumentReference", + Alias: "file", + MatchMode: TraversalMatchRequired, + Filters: []TypedFilter{{ + FieldRef: "DocumentReference.id", + Selector: "id", + FieldKind: FilterString, + Operator: FilterEquals, + Values: []FilterValue{{Kind: FilterString, String: &fileID}}, + }}, + }}, + }}, + }, 5) + if err != nil { + t.Fatal(err) + } + first := "FOR __match_0_0, __match_edge_0_0 IN 1..1 INBOUND root fhir_edge" + second := "FOR __match_0_1, __match_edge_0_1 IN 1..1 INBOUND __match_0_0 fhir_edge" + if !strings.Contains(compiled.Query, first) || !strings.Contains(compiled.Query, second) { + t.Fatalf("required nested route was not compiled as one correlated semi-join:\n%s", compiled.Query) + } + if strings.Index(compiled.Query, first) > strings.Index(compiled.Query, second) { + t.Fatalf("nested route order is reversed:\n%s", compiled.Query) + } + assertBindVarValue(t, compiled.BindVars, "subject_Specimen") + assertBindVarValue(t, compiled.BindVars, "DocumentReference") + assertBindVarValue(t, compiled.BindVars, fileID) + assertRootMatchPrecedesLimit(t, compiled.Query) +} + +func TestRequiredTraversalRejectsUnsafeOrUnknownRoute(t *testing.T) { + tests := []struct { + name string + step TraversalStep + want string + }{ + { + name: "unknown route", + step: TraversalStep{Label: "not_a_generated_route", ToResourceType: "Condition", Alias: "diagnosis", MatchMode: TraversalMatchRequired}, + want: "not represented by the active generated FHIR schema", + }, + { + name: "unsafe route label", + step: TraversalStep{Label: "subject_Patient RETURN SLEEP(1)", ToResourceType: "Condition", Alias: "diagnosis", MatchMode: TraversalMatchRequired}, + want: "not represented by the active generated FHIR schema", + }, + { + name: "unknown match mode", + step: TraversalStep{Label: "subject_Patient", ToResourceType: "Condition", Alias: "diagnosis", MatchMode: TraversalMatchMode("MUST_MATCH")}, + want: "unsupported traversal match mode", + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + _, err := CompileRequest(Builder{Project: "P1", RootResourceType: "Patient", Traversals: []TraversalStep{test.step}}, 1) + if err == nil || !strings.Contains(err.Error(), test.want) { + t.Fatalf("CompileRequest() error = %v, want %q", err, test.want) + } + }) + } + t.Run("manual lowered unsafe route", func(t *testing.T) { + _, err := Compile(Builder{ + Project: "P1", + RootResourceType: "Patient", + PlanHint: &PlanHint{Mode: "lowered", Profile: "test"}, + RequiredTraversalMatches: []RequiredTraversalMatch{{ + Steps: []TraversalMatchStep{{Label: "subject_Patient RETURN SLEEP(1)", ToResourceType: "Condition"}}, + }}, + }, 1) + if err == nil || !strings.Contains(err.Error(), "not represented by the active generated FHIR schema") { + t.Fatalf("Compile() error = %v", err) + } + }) +} + +func TestNavigationOnlyPhysicalPlanRejectsRequiredRelationshipMatch(t *testing.T) { + _, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, + Project: "P1", + Root: SemanticNode{ + Alias: "root", ResourceType: "Patient", + Children: []SemanticNode{{ + Alias: "diagnosis", ResourceType: "Condition", EdgeLabel: "subject_Patient", MatchMode: TraversalMatchRequired, + }}, + }, + }) + if err == nil || !strings.Contains(err.Error(), "requires a relationship match") { + t.Fatalf("BuildGenericPhysicalPlan() error = %v", err) + } +} + +func assertRootMatchPrecedesLimit(t *testing.T, query string) { + t.Helper() + match := strings.Index(query, "FOR __match_0_0") + sort := strings.Index(query, "SORT root._key") + limit := strings.Index(query, "LIMIT @limit") + if match < 0 || sort < 0 || limit < 0 || match > sort || match > limit || sort > limit { + t.Fatalf("required match must be a root predicate before SORT/LIMIT:\n%s", query) + } +} + +func assertBindVarValue(t *testing.T, bindVars map[string]any, want any) { + t.Helper() + for _, got := range bindVars { + if got == want { + return + } + } + t.Fatalf("bind variables do not contain %#v: %#v", want, bindVars) +} diff --git a/internal/dataframe/selection_semantics.go b/internal/dataframe/selection_semantics.go new file mode 100644 index 0000000..f70239b --- /dev/null +++ b/internal/dataframe/selection_semantics.go @@ -0,0 +1,178 @@ +package dataframe + +import ( + "fmt" + "sort" + "strings" + + "github.com/calypr/loom/internal/fhirschema" +) + +// SelectionSemanticSpec is the compiler-ready meaning of one field selection. +// It deliberately contains selectors and schema facts, not rendered AQL. +type SelectionSemanticSpec struct { + Alias string + NodeAlias string + ResourceType string + FieldRef string + Selector Selector + Fallbacks []Selector + Cardinality Cardinality + Projection ProjectionMode + LegacyAuto bool + RepeatedPaths []string +} + +// NormalizeSelectionPlan resolves every semantic field against the active +// generated FHIR metadata and returns stable alias-sorted selections. +func NormalizeSelectionPlan(plan SemanticPlan) ([]SelectionSemanticSpec, error) { + out := make([]SelectionSemanticSpec, 0) + nodeAliases := map[string]struct{}{} + selectionAliases := map[string]struct{}{} + var walk func(SemanticNode) error + walk = func(node SemanticNode) error { + if strings.TrimSpace(node.Alias) == "" { + return fmt.Errorf("semantic node for %s has no alias", node.ResourceType) + } + if _, exists := nodeAliases[node.Alias]; exists { + return fmt.Errorf("semantic node alias %q is duplicated", node.Alias) + } + nodeAliases[node.Alias] = struct{}{} + for index, field := range node.Fields { + spec, err := ResolveSemanticField(node.ResourceType, node.Alias, index, field) + if err != nil { + return err + } + if _, exists := selectionAliases[spec.Alias]; exists { + return fmt.Errorf("selection alias %q is duplicated", spec.Alias) + } + selectionAliases[spec.Alias] = struct{}{} + out = append(out, spec) + } + for _, child := range node.Children { + if err := walk(child); err != nil { + return err + } + } + return nil + } + if err := walk(plan.Root); err != nil { + return nil, err + } + sort.Slice(out, func(i, j int) bool { return out[i].Alias < out[j].Alias }) + return out, nil +} + +// ResolveSemanticField resolves a single field and all fallback selectors. +func ResolveSemanticField(resourceType, nodeAlias string, index int, field SemanticField) (SelectionSemanticSpec, error) { + if !fhirschema.HasResource(resourceType) { + return SelectionSemanticSpec{}, fmt.Errorf("field %q: resource type %q is not in the active FHIR schema", field.Name, resourceType) + } + repeated, paths, err := selectorCardinality(resourceType, field.Selector) + if err != nil { + return SelectionSemanticSpec{}, fmt.Errorf("field %q: %w", field.Name, err) + } + for fallbackIndex, fallback := range field.Fallbacks { + fallbackRepeated, fallbackPaths, err := selectorCardinality(resourceType, fallback) + if err != nil { + return SelectionSemanticSpec{}, fmt.Errorf("field %q fallback %d: %w", field.Name, fallbackIndex, err) + } + repeated = repeated || fallbackRepeated + paths = append(paths, fallbackPaths...) + } + paths = sortedUniqueStrings(paths) + cardinality := CardinalityOptionalOne + if repeated { + cardinality = CardinalityMany + } + projection, legacyAuto, err := projectionForValueMode(field.ValueMode, cardinality) + if err != nil { + return SelectionSemanticSpec{}, fmt.Errorf("field %q: %w", field.Name, err) + } + if err := ValidateProjection(cardinality, projection); err != nil { + return SelectionSemanticSpec{}, fmt.Errorf("field %q: %w", field.Name, err) + } + name := strings.TrimSpace(field.Name) + if name == "" { + name = fmt.Sprintf("field_%d", index+1) + } + return SelectionSemanticSpec{ + Alias: nodeAlias + "." + name, NodeAlias: nodeAlias, + ResourceType: resourceType, FieldRef: field.FieldRef, + Selector: field.Selector, Fallbacks: append([]Selector(nil), field.Fallbacks...), + Cardinality: cardinality, Projection: projection, LegacyAuto: legacyAuto, + RepeatedPaths: paths, + }, nil +} + +func projectionForValueMode(valueMode string, cardinality Cardinality) (ProjectionMode, bool, error) { + switch strings.ToUpper(strings.TrimSpace(valueMode)) { + case "", "AUTO": + if cardinality.AllowsMany() { + // Legacy AUTO selected FIRST for an array-bearing selector. Preserve + // that behavior as an explicit semantic decision, not compiler magic. + return ProjectionFirst, true, nil + } + return ProjectionScalar, true, nil + case "FIRST": + return ProjectionFirst, false, nil + case "ALL": + return ProjectionArray, false, nil + case "DISTINCT": + return ProjectionDistinctArray, false, nil + default: + return "", false, fmt.Errorf("unsupported value mode %q", valueMode) + } +} + +func isKnownValueMode(valueMode string) bool { + switch strings.ToUpper(strings.TrimSpace(valueMode)) { + case "", "AUTO", "FIRST", "ALL", "DISTINCT": + return true + default: + return false + } +} + +func selectorCardinality(resourceType string, selector Selector) (bool, []string, error) { + if len(selector.Steps) == 0 { + return false, nil, fmt.Errorf("selector is required") + } + metadataParts := make([]string, 0, len(selector.Steps)) + repeatedPaths := make([]string, 0) + for _, step := range selector.Steps { + part := step.Field + probeParts := append(append([]string(nil), metadataParts...), part) + probe := strings.Join(probeParts, ".") + semantics, ok := fhirschema.ResolveFieldSemantics(resourceType, probe) + if !ok { + return false, nil, fmt.Errorf("selector path %q is not in the active FHIR schema", selector.CanonicalPath()) + } + if semantics.Kind == fhirschema.FieldKindArray { + if !step.Iterate && step.Index == nil { + return false, nil, fmt.Errorf("selector path %q crosses repeated field %q without [] or an explicit index", selector.CanonicalPath(), strings.Join(probeParts, ".")) + } + metadataParts = append(metadataParts, part+"[]") + if step.Index == nil { + repeatedPaths = append(repeatedPaths, strings.Join(metadataParts, ".")) + } + } else { + metadataParts = append(metadataParts, part) + } + } + return len(repeatedPaths) > 0, repeatedPaths, nil +} + +func sortedUniqueStrings(values []string) []string { + seen := make(map[string]struct{}, len(values)) + out := make([]string, 0, len(values)) + for _, value := range values { + if _, exists := seen[value]; exists { + continue + } + seen[value] = struct{}{} + out = append(out, value) + } + sort.Strings(out) + return out +} diff --git a/internal/dataframe/selection_semantics_test.go b/internal/dataframe/selection_semantics_test.go new file mode 100644 index 0000000..bf9d629 --- /dev/null +++ b/internal/dataframe/selection_semantics_test.go @@ -0,0 +1,90 @@ +package dataframe + +import "testing" + +func TestResolveSemanticFieldScalarAuto(t *testing.T) { + selector, _ := ParseSelector("gender") + got, err := ResolveSemanticField("Patient", "root", 0, SemanticField{Name: "gender", Selector: selector}) + if err != nil { + t.Fatalf("ResolveSemanticField: %v", err) + } + if got.Cardinality != CardinalityOptionalOne || got.Projection != ProjectionScalar || !got.LegacyAuto { + t.Fatalf("unexpected scalar semantics: %#v", got) + } +} + +func TestResolveSemanticFieldDetectsRepeatedAncestor(t *testing.T) { + selector, _ := ParseSelector("name[].family") + got, err := ResolveSemanticField("Patient", "root", 0, SemanticField{Name: "family", Selector: selector}) + if err != nil { + t.Fatalf("ResolveSemanticField: %v", err) + } + if got.Cardinality != CardinalityMany || got.Projection != ProjectionFirst || !got.LegacyAuto { + t.Fatalf("unexpected repeated AUTO semantics: %#v", got) + } + if len(got.RepeatedPaths) != 1 || got.RepeatedPaths[0] != "name[]" { + t.Fatalf("unexpected repeated paths: %#v", got.RepeatedPaths) + } +} + +func TestResolveSemanticFieldValueModes(t *testing.T) { + selector, _ := ParseSelector("identifier[].value") + tests := []struct { + mode string + want ProjectionMode + }{ + {"FIRST", ProjectionFirst}, + {"ALL", ProjectionArray}, + {"DISTINCT", ProjectionDistinctArray}, + } + for _, test := range tests { + got, err := ResolveSemanticField("Patient", "root", 0, SemanticField{Name: "id", Selector: selector, ValueMode: test.mode}) + if err != nil { + t.Errorf("mode %s: %v", test.mode, err) + continue + } + if got.Projection != test.want || got.LegacyAuto { + t.Errorf("mode %s = %#v", test.mode, got) + } + } +} + +func TestResolveSemanticFieldRejectsInvalidSemantics(t *testing.T) { + valid, _ := ParseSelector("gender") + missing, _ := ParseSelector("notAField") + implicitArray, _ := ParseSelector("name.family") + tests := []struct { + name string + resourceType string + field SemanticField + }{ + {"unknown resource", "Imaginary", SemanticField{Name: "x", Selector: valid}}, + {"unknown path", "Patient", SemanticField{Name: "x", Selector: missing}}, + {"invalid value mode", "Patient", SemanticField{Name: "x", Selector: valid, ValueMode: "SCALAR"}}, + {"implicit array traversal", "Patient", SemanticField{Name: "x", Selector: implicitArray}}, + {"empty selector", "Patient", SemanticField{Name: "x"}}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + if _, err := ResolveSemanticField(test.resourceType, "root", 0, test.field); err == nil { + t.Fatal("invalid selection unexpectedly succeeded") + } + }) + } +} + +func TestNormalizeSelectionPlanStableAliases(t *testing.T) { + gender, _ := ParseSelector("gender") + id, _ := ParseSelector("identifier[].value") + plan := SemanticPlan{Root: SemanticNode{ + Alias: "root", ResourceType: "Patient", + Fields: []SemanticField{{Name: "z", Selector: gender}, {Selector: id}}, + }} + got, err := NormalizeSelectionPlan(plan) + if err != nil { + t.Fatalf("NormalizeSelectionPlan: %v", err) + } + if len(got) != 2 || got[0].Alias != "root.field_2" || got[1].Alias != "root.z" { + t.Fatalf("unexpected stable aliases: %#v", got) + } +} diff --git a/internal/dataframe/selectors.go b/internal/dataframe/selectors.go index ec39f48..e5928de 100644 --- a/internal/dataframe/selectors.go +++ b/internal/dataframe/selectors.go @@ -40,6 +40,24 @@ func sanitizeColumnName(in string) string { return b.String() } +func isSafeAQLFieldIdentifier(in string) bool { + if in == "" { + return false + } + for index, r := range in { + if index == 0 { + if (r < 'a' || r > 'z') && (r < 'A' || r > 'Z') && r != '_' { + return false + } + continue + } + if (r < 'a' || r > 'z') && (r < 'A' || r > 'Z') && (r < '0' || r > '9') && r != '_' { + return false + } + } + return true +} + func quoteKey(key string) string { data, _ := json.Marshal(key) return string(data) diff --git a/internal/dataframe/semantic_plan.go b/internal/dataframe/semantic_plan.go new file mode 100644 index 0000000..1084cd8 --- /dev/null +++ b/internal/dataframe/semantic_plan.go @@ -0,0 +1,431 @@ +package dataframe + +import ( + "fmt" + "strings" + + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/fhirschema" +) + +// SemanticPlan is the validated, backend-independent meaning of a dataframe +// request. It deliberately contains no AQL variable names, named-set choices, +// or optimizer decisions. Physical lowering is free to choose those details +// while preserving this plan's row and selection semantics. +// +// It is currently constructed from Builder so the existing GraphQL contract +// can remain stable while the compiler moves away from string-oriented lowering. +type SemanticPlan struct { + Version int + Project string + DatasetGeneration string + AuthResourcePaths []string + // AuthScopeMode is copied from Builder so physical plans retain the + // restricted-empty distinction after semantic lowering. + AuthScopeMode authscope.ReadScopeMode + RowIdentity *RowIdentity + Root SemanticNode +} + +// SemanticNode represents one FHIR resource reached at a stable alias. The +// root alias is always "root". Child nodes are relationship traversals from +// this node; a child selection is represented as an array, aggregate, pivot, +// or representative slice unless a later row-grain plan explicitly explodes +// it into rows. +type SemanticNode struct { + Alias string + ResourceType string + EdgeLabel string + MatchMode TraversalMatchMode + Fields []SemanticField + Filters []TypedFilter + Pivots []SemanticPivot + Aggregates []SemanticAggregate + Slices []SemanticSlice + Children []SemanticNode +} + +type SemanticField struct { + Name string + FieldRef string + Selector Selector + Fallbacks []Selector + ValueMode string +} + +type SemanticPivot struct { + Name string + FieldRef string + ColumnSelector Selector + ValueSelector Selector + Columns []string + Family string +} + +type SemanticAggregate struct { + Name string + Operation string + FieldRef string + Selector *Selector + PredicateField string + Predicate *Selector + PredicateEquals string + ValueMode string +} + +type SemanticSlice struct { + Name string + Limit int + PredicateField string + Predicate *Selector + PredicateEquals string + Fields []SemanticField +} + +// BuildSemanticPlan parses the selector-bearing portions of Builder exactly +// once and preserves the user's requested traversal shape. Catalog and +// authorization validation remain the responsibility of Service.validateBuilder +// because they require a request context and an observed dataset. +func BuildSemanticPlan(builder Builder) (SemanticPlan, error) { + if strings.TrimSpace(builder.Project) == "" { + return SemanticPlan{}, fmt.Errorf("project is required") + } + if strings.TrimSpace(builder.RootResourceType) == "" { + return SemanticPlan{}, fmt.Errorf("rootResourceType is required") + } + if !fhirschema.HasResource(builder.RootResourceType) { + return SemanticPlan{}, fmt.Errorf("root resource type %q is not represented by the active generated FHIR schema", builder.RootResourceType) + } + + root, err := semanticNodeFromBuilder("root", builder.RootResourceType, "", "", builder.Fields, builder.Filters, builder.Pivots, builder.Aggregates, builder.Slices, builder.Traversals) + if err != nil { + return SemanticPlan{}, err + } + plan := SemanticPlan{ + Version: 1, + Project: builder.Project, + DatasetGeneration: normalizeDatasetGeneration(builder.DatasetGeneration), + AuthResourcePaths: cloneStrings(builder.AuthResourcePaths), + AuthScopeMode: builder.AuthScopeMode, + Root: root, + } + grain := builder.RowGrain + if grain == "" { + var known bool + grain, known = InferRowGrain(builder.RootResourceType) + if !known { + return SemanticPlan{}, fmt.Errorf("no row grain is available for root resource type %q", builder.RootResourceType) + } + } + if err := ValidateRootGrain(builder.RootResourceType, grain); err != nil { + return SemanticPlan{}, err + } + identity, ok := DefaultRowIdentity(grain) + if !ok { + return SemanticPlan{}, fmt.Errorf("invalid row grain %q", grain) + } + plan.RowIdentity = &identity + if err := ValidateSemanticGraph(plan); err != nil { + return SemanticPlan{}, err + } + if _, err := NormalizeSelectionPlan(plan); err != nil { + return SemanticPlan{}, err + } + return plan, nil +} + +func semanticNodeFromBuilder(alias, resourceType, edgeLabel string, matchMode TraversalMatchMode, fields []FieldSelect, filters []TypedFilter, pivots []PivotSelect, aggregates []AggregateSelect, slices []RepresentativeSlice, traversals []TraversalStep) (SemanticNode, error) { + node := SemanticNode{ + Alias: alias, + ResourceType: resourceType, + EdgeLabel: edgeLabel, + MatchMode: matchMode, + Fields: make([]SemanticField, 0, len(fields)), + Filters: append([]TypedFilter(nil), filters...), + Pivots: make([]SemanticPivot, 0, len(pivots)), + Aggregates: make([]SemanticAggregate, 0, len(aggregates)), + Slices: make([]SemanticSlice, 0, len(slices)), + Children: make([]SemanticNode, 0, len(traversals)), + } + for _, filter := range node.Filters { + if err := ValidateTypedFilterForResource(resourceType, filter); err != nil { + return SemanticNode{}, fmt.Errorf("filter %q: %w", filter.FieldRef, err) + } + } + + seenFields := map[string]struct{}{} + for _, field := range fields { + if strings.TrimSpace(field.Name) == "" { + return SemanticNode{}, fmt.Errorf("field selections require name and select") + } + if _, exists := seenFields[field.Name]; exists { + return SemanticNode{}, fmt.Errorf("field name %q is duplicated", field.Name) + } + seenFields[field.Name] = struct{}{} + selector, err := ParseSelector(field.Select) + if err != nil { + return SemanticNode{}, fmt.Errorf("field %q: %w", field.Name, err) + } + fallbacks := make([]Selector, 0, len(field.FallbackSelects)) + for _, fallback := range field.FallbackSelects { + parsed, err := ParseSelector(fallback) + if err != nil { + return SemanticNode{}, fmt.Errorf("field %q fallback: %w", field.Name, err) + } + fallbacks = append(fallbacks, parsed) + } + node.Fields = append(node.Fields, SemanticField{ + Name: field.Name, + FieldRef: field.FieldRef, + Selector: selector, + Fallbacks: fallbacks, + ValueMode: field.ValueMode, + }) + } + + seenPivots := map[string]struct{}{} + for _, pivot := range pivots { + if strings.TrimSpace(pivot.Name) == "" { + return SemanticNode{}, fmt.Errorf("pivot selections require name") + } + if _, exists := seenPivots[pivot.Name]; exists { + return SemanticNode{}, fmt.Errorf("pivot name %q is duplicated", pivot.Name) + } + seenPivots[pivot.Name] = struct{}{} + if len(pivot.Columns) == 0 { + return SemanticNode{}, fmt.Errorf("pivot %q requires bounded columns resolved from the field catalog before compilation", pivot.Name) + } + column, err := ParseSelector(pivot.ColumnSelect) + if err != nil { + return SemanticNode{}, fmt.Errorf("pivot %q column selector: %w", pivot.Name, err) + } + value, err := ParseSelector(pivot.ValueSelect) + if err != nil { + return SemanticNode{}, fmt.Errorf("pivot %q value selector: %w", pivot.Name, err) + } + if err := validateSemanticSelector(resourceType, column); err != nil { + return SemanticNode{}, fmt.Errorf("pivot %q column selector: %w", pivot.Name, err) + } + if err := validateSemanticSelector(resourceType, value); err != nil { + return SemanticNode{}, fmt.Errorf("pivot %q value selector: %w", pivot.Name, err) + } + pivotSpec, err := fhirschema.ValidatePivotSelectors(resourceType, selectorSpecFromSelector(column), selectorSpecFromSelector(value)) + if err != nil { + return SemanticNode{}, fmt.Errorf("pivot %q: %w", pivot.Name, err) + } + if pivot.PivotFamily != "" && pivot.PivotFamily != pivotSpec.Family { + return SemanticNode{}, fmt.Errorf("pivot %q family %q conflicts with generated family %q", pivot.Name, pivot.PivotFamily, pivotSpec.Family) + } + node.Pivots = append(node.Pivots, SemanticPivot{ + Name: pivot.Name, + FieldRef: pivot.FieldRef, + ColumnSelector: column, + ValueSelector: value, + Columns: cloneStrings(pivot.Columns), + Family: pivotSpec.Family, + }) + } + + seenAggregates := map[string]struct{}{} + for _, aggregate := range aggregates { + if strings.TrimSpace(aggregate.Name) == "" { + return SemanticNode{}, fmt.Errorf("aggregate selections require name") + } + if _, exists := seenAggregates[aggregate.Name]; exists { + return SemanticNode{}, fmt.Errorf("aggregate name %q is duplicated", aggregate.Name) + } + seenAggregates[aggregate.Name] = struct{}{} + operation := strings.ToUpper(strings.TrimSpace(aggregate.Operation)) + if _, err := normalizeAggregateFunction(operation); err != nil { + return SemanticNode{}, fmt.Errorf("aggregate %q: %w", aggregate.Name, err) + } + if !isKnownValueMode(aggregate.ValueMode) { + return SemanticNode{}, fmt.Errorf("aggregate %q uses unsupported value mode %q", aggregate.Name, aggregate.ValueMode) + } + semanticAggregate := SemanticAggregate{ + Name: aggregate.Name, + Operation: operation, + FieldRef: aggregate.FieldRef, + PredicateField: aggregate.PredicateFieldRef, + PredicateEquals: aggregate.PredicateEquals, + ValueMode: aggregate.ValueMode, + } + if strings.TrimSpace(aggregate.Select) != "" { + selector, err := ParseSelector(aggregate.Select) + if err != nil { + return SemanticNode{}, fmt.Errorf("aggregate %q selector: %w", aggregate.Name, err) + } + if err := validateSemanticSelector(resourceType, selector); err != nil { + return SemanticNode{}, fmt.Errorf("aggregate %q selector: %w", aggregate.Name, err) + } + semanticAggregate.Selector = &selector + } + if strings.TrimSpace(aggregate.PredicatePath) != "" { + predicate, err := ParseSelector(aggregate.PredicatePath) + if err != nil { + return SemanticNode{}, fmt.Errorf("aggregate %q predicate: %w", aggregate.Name, err) + } + if err := validateSemanticSelector(resourceType, predicate); err != nil { + return SemanticNode{}, fmt.Errorf("aggregate %q predicate: %w", aggregate.Name, err) + } + semanticAggregate.Predicate = &predicate + } + if aggregateOperationRequiresSelector(operation) && semanticAggregate.Selector == nil { + return SemanticNode{}, fmt.Errorf("aggregate %q operation %s requires a selector", aggregate.Name, operation) + } + node.Aggregates = append(node.Aggregates, semanticAggregate) + } + + seenSlices := map[string]struct{}{} + for _, slice := range slices { + if strings.TrimSpace(slice.Name) == "" { + return SemanticNode{}, fmt.Errorf("representative slices require name") + } + if _, exists := seenSlices[slice.Name]; exists { + return SemanticNode{}, fmt.Errorf("representative slice name %q is duplicated", slice.Name) + } + seenSlices[slice.Name] = struct{}{} + if slice.Limit <= 0 { + return SemanticNode{}, fmt.Errorf("representative slice %q requires positive limit", slice.Name) + } + semanticSlice := SemanticSlice{ + Name: slice.Name, + Limit: slice.Limit, + PredicateField: slice.PredicateFieldRef, + PredicateEquals: slice.PredicateEquals, + Fields: make([]SemanticField, 0, len(slice.Fields)), + } + if strings.TrimSpace(slice.PredicatePath) != "" { + predicate, err := ParseSelector(slice.PredicatePath) + if err != nil { + return SemanticNode{}, fmt.Errorf("representative slice %q predicate: %w", slice.Name, err) + } + if err := validateSemanticSelector(resourceType, predicate); err != nil { + return SemanticNode{}, fmt.Errorf("representative slice %q predicate: %w", slice.Name, err) + } + semanticSlice.Predicate = &predicate + } + seenSliceFields := map[string]struct{}{} + for _, field := range slice.Fields { + if strings.TrimSpace(field.Name) == "" { + return SemanticNode{}, fmt.Errorf("representative slice %q requires field name", slice.Name) + } + if _, exists := seenSliceFields[field.Name]; exists { + return SemanticNode{}, fmt.Errorf("representative slice %q field name %q is duplicated", slice.Name, field.Name) + } + seenSliceFields[field.Name] = struct{}{} + selector, err := ParseSelector(field.Select) + if err != nil { + return SemanticNode{}, fmt.Errorf("representative slice %q field %q: %w", slice.Name, field.Name, err) + } + if err := validateSemanticSelector(resourceType, selector); err != nil { + return SemanticNode{}, fmt.Errorf("representative slice %q field %q: %w", slice.Name, field.Name, err) + } + fallbacks := make([]Selector, 0, len(field.FallbackSelects)) + for _, fallback := range field.FallbackSelects { + parsed, err := ParseSelector(fallback) + if err != nil { + return SemanticNode{}, fmt.Errorf("representative slice %q field %q fallback: %w", slice.Name, field.Name, err) + } + if err := validateSemanticSelector(resourceType, parsed); err != nil { + return SemanticNode{}, fmt.Errorf("representative slice %q field %q fallback: %w", slice.Name, field.Name, err) + } + fallbacks = append(fallbacks, parsed) + } + if !isKnownValueMode(field.ValueMode) { + return SemanticNode{}, fmt.Errorf("representative slice %q field %q uses unsupported value mode %q", slice.Name, field.Name, field.ValueMode) + } + semanticSlice.Fields = append(semanticSlice.Fields, SemanticField{ + Name: field.Name, + FieldRef: field.FieldRef, + Selector: selector, + Fallbacks: fallbacks, + ValueMode: field.ValueMode, + }) + } + node.Slices = append(node.Slices, semanticSlice) + } + + for _, traversal := range traversals { + child, err := semanticNodeFromBuilder(traversal.Alias, traversal.ToResourceType, traversal.Label, traversal.MatchMode, traversal.Fields, traversal.Filters, traversal.Pivots, traversal.Aggregates, traversal.Slices, traversal.Traversals) + if err != nil { + return SemanticNode{}, err + } + node.Children = append(node.Children, child) + } + return node, nil +} + +func validateSemanticSelector(resourceType string, selector Selector) error { + _, _, err := selectorCardinality(resourceType, selector) + return err +} + +func aggregateOperationRequiresSelector(operation string) bool { + switch operation { + case "COUNT_DISTINCT", "DISTINCT_VALUES", "MIN", "MAX": + return true + default: + return false + } +} + +// Explain returns a compact stable summary suitable for diagnostics and tests. +// It intentionally does not expose physical AQL decisions. +func (p SemanticPlan) Explain() SemanticPlanExplanation { + explanation := SemanticPlanExplanation{ + Version: p.Version, + RootResourceType: p.Root.ResourceType, + DatasetGeneration: p.DatasetGeneration, + RowIdentity: cloneRowIdentity(p.RowIdentity), + Nodes: make([]SemanticNodeExplanation, 0), + } + var walk func(SemanticNode, string) + walk = func(node SemanticNode, parentAlias string) { + explanation.Nodes = append(explanation.Nodes, SemanticNodeExplanation{ + Alias: node.Alias, + ParentAlias: parentAlias, + ResourceType: node.ResourceType, + EdgeLabel: node.EdgeLabel, + MatchMode: node.MatchMode, + FieldCount: len(node.Fields), + PivotCount: len(node.Pivots), + AggregateCount: len(node.Aggregates), + SliceCount: len(node.Slices), + }) + for _, child := range node.Children { + walk(child, node.Alias) + } + } + walk(p.Root, "") + return explanation +} + +type SemanticPlanExplanation struct { + Version int + RootResourceType string + DatasetGeneration string + RowIdentity *RowIdentity + Nodes []SemanticNodeExplanation +} + +func cloneRowIdentity(identity *RowIdentity) *RowIdentity { + if identity == nil { + return nil + } + copy := *identity + copy.Fields = cloneStrings(identity.Fields) + return © +} + +type SemanticNodeExplanation struct { + Alias string + ParentAlias string + ResourceType string + EdgeLabel string + MatchMode TraversalMatchMode + FieldCount int + PivotCount int + AggregateCount int + SliceCount int +} diff --git a/internal/dataframe/semantic_plan_test.go b/internal/dataframe/semantic_plan_test.go new file mode 100644 index 0000000..5f2eeaa --- /dev/null +++ b/internal/dataframe/semantic_plan_test.go @@ -0,0 +1,97 @@ +package dataframe + +import "testing" + +func TestBuildSemanticPlanPreservesNestedFHIRSelections(t *testing.T) { + plan, err := BuildSemanticPlan(Builder{ + Project: "P1", + AuthResourcePaths: []string{"pathA"}, + RootResourceType: "Patient", + Fields: []FieldSelect{{ + Name: "case_id", + FieldRef: "Patient.identifier_value", + Select: `identifier[].value where system contains "case_id"`, + FallbackSelects: []string{"id"}, + ValueMode: "FIRST", + }}, + Traversals: []TraversalStep{{ + Label: "subject_Patient", + ToResourceType: "Observation", + Alias: "observation", + Pivots: []PivotSelect{{ + Name: "values", + ColumnSelect: "code.coding[].display", + ValueSelect: "valueQuantity.value", + Columns: []string{"Hemoglobin"}, + }}, + Aggregates: []AggregateSelect{{Name: "count", Operation: "COUNT"}}, + Traversals: []TraversalStep{{ + Label: "subject_Observation", + ToResourceType: "DocumentReference", + Alias: "document_reference", + }}, + }}, + }) + if err != nil { + t.Fatalf("BuildSemanticPlan() error = %v", err) + } + if plan.Version != 1 || plan.Root.ResourceType != "Patient" { + t.Fatalf("unexpected plan root: %#v", plan) + } + if plan.RowIdentity == nil || plan.RowIdentity.Grain != RowGrainPatient { + t.Fatalf("expected inferred Patient row identity, got %#v", plan.RowIdentity) + } + if len(plan.Root.Fields) != 1 || plan.Root.Fields[0].Selector.CanonicalPath() != "identifier[].value" { + t.Fatalf("root field not parsed: %#v", plan.Root.Fields) + } + if len(plan.Root.Children) != 1 || plan.Root.Children[0].Alias != "observation" { + t.Fatalf("child not preserved: %#v", plan.Root.Children) + } + if len(plan.Root.Children[0].Pivots) != 1 || plan.Root.Children[0].Pivots[0].ColumnSelector.CanonicalPath() != "code.coding[].display" { + t.Fatalf("pivot not parsed: %#v", plan.Root.Children[0].Pivots) + } + got := plan.Explain() + if len(got.Nodes) != 3 || got.Nodes[1].ParentAlias != "root" || got.Nodes[2].ParentAlias != "observation" { + t.Fatalf("unexpected explanation: %#v", got) + } +} + +func TestBuildSemanticPlanRejectsBadSelector(t *testing.T) { + _, err := BuildSemanticPlan(Builder{ + Project: "P1", + RootResourceType: "Patient", + Fields: []FieldSelect{{Name: "bad", Select: "identifier[nope]"}}, + }) + if err == nil { + t.Fatal("expected bad selector error") + } +} + +func TestBuildSemanticPlanUsesGenericIdentityForGeneratedNonProductRoot(t *testing.T) { + plan, err := BuildSemanticPlan(Builder{Project: "P1", RootResourceType: "Organization"}) + if err != nil { + t.Fatal(err) + } + if plan.RowIdentity == nil || plan.RowIdentity.Grain != RowGrainResource { + t.Fatalf("generic root identity = %#v", plan.RowIdentity) + } +} + +func TestBuildSemanticPlanRejectsCrossGrainRootBeforeLowering(t *testing.T) { + _, err := BuildSemanticPlan(Builder{ + Project: "P1", RootResourceType: "Patient", RowGrain: RowGrainSpecimen, + }) + if err == nil { + t.Fatal("cross-grain semantic plan unexpectedly succeeded") + } +} + +func TestCompileRequestCarriesStableRowIdentity(t *testing.T) { + compiled, err := CompileRequest(Builder{Project: "P1", RootResourceType: "Specimen"}, 1) + if err != nil { + t.Fatal(err) + } + if compiled.RowIdentity == nil || compiled.RowIdentity.Grain != RowGrainSpecimen { + t.Fatalf("compiled identity = %#v", compiled.RowIdentity) + } +} diff --git a/internal/dataframe/semantic_validation.go b/internal/dataframe/semantic_validation.go new file mode 100644 index 0000000..424e8c2 --- /dev/null +++ b/internal/dataframe/semantic_validation.go @@ -0,0 +1,102 @@ +package dataframe + +import ( + "fmt" + "strings" + + "github.com/calypr/loom/internal/fhirschema" +) + +// MaxSemanticTraversalDepth is the maximum number of relationship edges below +// a semantic-plan root. Keeping this small bounds compiler work and graph-query +// fanout until a cost model can safely authorize deeper plans. +const MaxSemanticTraversalDepth = 4 + +// ValidateSemanticGraph checks the schema and structural safety of an already +// constructed semantic plan. It performs no observed-data or authorization +// checks and does not mutate the plan. +func ValidateSemanticGraph(plan SemanticPlan) error { + if strings.TrimSpace(plan.Root.ResourceType) == "" { + return fmt.Errorf("semantic graph root resource type is required") + } + if plan.Root.Alias != "root" { + return fmt.Errorf("semantic graph root alias must be %q, got %q", "root", plan.Root.Alias) + } + if strings.TrimSpace(plan.Root.EdgeLabel) != "" { + return fmt.Errorf("semantic graph root must not declare edge label %q", plan.Root.EdgeLabel) + } + if plan.Root.MatchMode != "" { + return fmt.Errorf("semantic graph root must not declare traversal match mode %q", plan.Root.MatchMode) + } + if !fhirschema.HasResource(plan.Root.ResourceType) { + return fmt.Errorf("semantic graph root resource type %q is not represented by the active generated FHIR schema", plan.Root.ResourceType) + } + + state := semanticValidationState{ + aliases: map[string]string{}, + } + return state.validateChildren(plan.Root, 0, []string{plan.Root.ResourceType}, map[string]bool{}) +} + +type semanticValidationState struct { + aliases map[string]string +} + +func (s *semanticValidationState) validateChildren(parent SemanticNode, depth int, path []string, edgesOnPath map[string]bool) error { + for index, child := range parent.Children { + childDepth := depth + 1 + location := fmt.Sprintf("%s.children[%d]", strings.Join(path, " -> "), index) + if childDepth > MaxSemanticTraversalDepth { + return fmt.Errorf("semantic traversal depth %d exceeds maximum %d at %s", childDepth, MaxSemanticTraversalDepth, location) + } + alias := strings.TrimSpace(child.Alias) + if alias == "" { + return fmt.Errorf("semantic traversal alias is required at %s", location) + } + if alias == "root" { + return fmt.Errorf("semantic traversal alias %q is reserved for the root at %s", alias, location) + } + if prior, exists := s.aliases[alias]; exists { + return fmt.Errorf("semantic traversal alias %q is not unique: used at %s and %s", alias, prior, location) + } + s.aliases[alias] = location + if err := child.MatchMode.Validate(); err != nil { + return fmt.Errorf("semantic traversal %s -> %s (%s) at %s: %w", parent.ResourceType, child.ResourceType, child.EdgeLabel, location, err) + } + + if !fhirschema.HasResource(child.ResourceType) { + return fmt.Errorf("semantic traversal target resource type %q is not represented by the active generated FHIR schema at %s", child.ResourceType, location) + } + if strings.TrimSpace(child.EdgeLabel) == "" { + return fmt.Errorf("semantic traversal edge label is required for %s -> %s at %s", parent.ResourceType, child.ResourceType, location) + } + if _, err := resolveStorageRoute(parent.ResourceType, child.EdgeLabel, child.ResourceType); err != nil { + return fmt.Errorf("semantic traversal %s -> %s (%s) at %s: %w", parent.ResourceType, child.ResourceType, child.EdgeLabel, location, err) + } + + edge := fmt.Sprintf("%s -[%s]-> %s", parent.ResourceType, child.EdgeLabel, child.ResourceType) + edgeKey := parent.ResourceType + "\x00" + child.EdgeLabel + "\x00" + child.ResourceType + // A single self-reference (for example, Patient.link.other) is a + // normal, finite FHIR relationship and must remain compilable. A route + // that repeats the same relationship within one requested path is the + // cycle that can accidentally multiply graph work; reject that while the + // depth cap protects paths made of distinct relationships. + if edgesOnPath[edgeKey] { + return fmt.Errorf("semantic traversal cycle detected at %s: %s", location, strings.Join(append(path, edge), " -> ")) + } + nextEdges := cloneTraversalPathSet(edgesOnPath) + nextEdges[edgeKey] = true + if err := s.validateChildren(child, childDepth, append(path, edge), nextEdges); err != nil { + return err + } + } + return nil +} + +func cloneTraversalPathSet(in map[string]bool) map[string]bool { + out := make(map[string]bool, len(in)+1) + for key, value := range in { + out[key] = value + } + return out +} diff --git a/internal/dataframe/semantic_validation_test.go b/internal/dataframe/semantic_validation_test.go new file mode 100644 index 0000000..ccfa449 --- /dev/null +++ b/internal/dataframe/semantic_validation_test.go @@ -0,0 +1,96 @@ +package dataframe + +import ( + "strings" + "testing" +) + +func TestValidateSemanticGraphAcceptsGeneratedAcyclicGraph(t *testing.T) { + plan := semanticValidationPlan(SemanticNode{ + Alias: "specimen", ResourceType: "Specimen", EdgeLabel: "subject_Patient", + Children: []SemanticNode{{ + Alias: "file", ResourceType: "DocumentReference", EdgeLabel: "subject_Specimen", + }}, + }) + if err := ValidateSemanticGraph(plan); err != nil { + t.Fatal(err) + } +} + +func TestValidateSemanticGraphRejectsDuplicateAlias(t *testing.T) { + plan := semanticValidationPlan( + SemanticNode{Alias: "related", ResourceType: "Specimen", EdgeLabel: "subject_Patient"}, + SemanticNode{Alias: "related", ResourceType: "Condition", EdgeLabel: "subject_Patient"}, + ) + assertSemanticValidationError(t, plan, "alias \"related\" is not unique") +} + +func TestValidateSemanticGraphRejectsUnknownRootAndTraversal(t *testing.T) { + unknownRoot := SemanticPlan{Root: SemanticNode{Alias: "root", ResourceType: "InventedResource"}} + assertSemanticValidationError(t, unknownRoot, "root resource type \"InventedResource\"") + + unknownTraversal := semanticValidationPlan(SemanticNode{ + Alias: "specimen", ResourceType: "Specimen", EdgeLabel: "invented_edge", + }) + assertSemanticValidationError(t, unknownTraversal, "is not represented by the active generated FHIR schema") +} + +func TestValidateSemanticGraphRejectsSelfCycle(t *testing.T) { + plan := SemanticPlan{Root: SemanticNode{ + Alias: "root", ResourceType: "Patient", + Children: []SemanticNode{{ + Alias: "linked", ResourceType: "Patient", EdgeLabel: "link_other_Patient", + Children: []SemanticNode{{Alias: "linked_again", ResourceType: "Patient", EdgeLabel: "link_other_Patient"}}, + }}, + }} + assertSemanticValidationError(t, plan, "cycle detected") +} + +func TestValidateSemanticGraphAllowsOneHopSelfReference(t *testing.T) { + plan := SemanticPlan{Root: SemanticNode{ + Alias: "root", ResourceType: "Patient", + Children: []SemanticNode{{Alias: "linked", ResourceType: "Patient", EdgeLabel: "link_other_Patient"}}, + }} + if err := ValidateSemanticGraph(plan); err != nil { + t.Fatalf("one-hop self reference should remain a valid finite query: %v", err) + } +} + +func TestValidateSemanticGraphEnforcesDepthCap(t *testing.T) { + plan := SemanticPlan{Root: SemanticNode{ + Alias: "root", ResourceType: "Patient", + Children: []SemanticNode{{ + Alias: "specimen", ResourceType: "Specimen", EdgeLabel: "subject_Patient", + Children: []SemanticNode{{ + Alias: "file", ResourceType: "DocumentReference", EdgeLabel: "subject_Specimen", + Children: []SemanticNode{{ + Alias: "procedure", ResourceType: "Procedure", EdgeLabel: "report_DocumentReference", + Children: []SemanticNode{{ + Alias: "another_specimen", ResourceType: "Specimen", EdgeLabel: "collection_procedure", + Children: []SemanticNode{{ + Alias: "too_deep", ResourceType: "Practitioner", EdgeLabel: "irrelevant_at_depth_guard", + }}, + }}, + }}, + }}, + }}, + }} + assertSemanticValidationError(t, plan, "exceeds maximum 4") +} + +func TestValidateSemanticGraphRejectsMalformedRoot(t *testing.T) { + assertSemanticValidationError(t, SemanticPlan{Root: SemanticNode{Alias: "patient", ResourceType: "Patient"}}, "root alias must be") + assertSemanticValidationError(t, SemanticPlan{Root: SemanticNode{Alias: "root", ResourceType: "Patient", EdgeLabel: "subject"}}, "must not declare edge label") +} + +func semanticValidationPlan(children ...SemanticNode) SemanticPlan { + return SemanticPlan{Root: SemanticNode{Alias: "root", ResourceType: "Patient", Children: children}} +} + +func assertSemanticValidationError(t *testing.T, plan SemanticPlan, contains string) { + t.Helper() + err := ValidateSemanticGraph(plan) + if err == nil || !strings.Contains(err.Error(), contains) { + t.Fatalf("error = %v, want substring %q", err, contains) + } +} diff --git a/internal/dataframe/service.go b/internal/dataframe/service.go index fbed4f4..f5398b5 100644 --- a/internal/dataframe/service.go +++ b/internal/dataframe/service.go @@ -6,6 +6,7 @@ import ( "github.com/calypr/loom/internal/authscope" "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/dataset" arangostore "github.com/calypr/loom/internal/store/arango" ) @@ -17,20 +18,26 @@ type ServiceConfig struct { DiscoverFields func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) ExecuteRows func(context.Context, ExecuteQueryOptions, string, map[string]any, func(map[string]any) error) error ScopeResolver *authscope.ScopeResolver + // ActiveManifestResolver is optional. When configured, every Run/Stream + // selects one READY active generation before resolving scope, catalog facts, + // lowering, or AQL. A Builder's explicit generation must agree with it. + ActiveManifestResolver dataset.ActiveManifestResolver } type Service struct { - connOpts arangostore.ConnectionOptions - discoverReferences func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) - discoverFields func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) - executeRows func(context.Context, ExecuteQueryOptions, string, map[string]any, func(map[string]any) error) error - scopeResolver *authscope.ScopeResolver + connOpts arangostore.ConnectionOptions + discoverReferences func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) + discoverFields func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) + executeRows func(context.Context, ExecuteQueryOptions, string, map[string]any, func(map[string]any) error) error + scopeResolver *authscope.ScopeResolver + activeManifestResolver dataset.ActiveManifestResolver } func NewService(cfg ServiceConfig) *Service { svc := &Service{ - connOpts: cfg.ConnectionOptions, - scopeResolver: cfg.ScopeResolver, + connOpts: cfg.ConnectionOptions, + scopeResolver: cfg.ScopeResolver, + activeManifestResolver: cfg.ActiveManifestResolver, } if cfg.DiscoverReferences != nil { svc.discoverReferences = cfg.DiscoverReferences @@ -51,19 +58,30 @@ func NewService(cfg ServiceConfig) *Service { } func (s *Service) Run(ctx context.Context, req RunRequest) (*Result, error) { - spec, err := s.prepareSpec(ctx, req.Builder) + compiled, err := s.compileRunRequest(ctx, req) if err != nil { return nil, err } + return s.runQuery(ctx, compiled) +} + +func (s *Service) compileRunRequest(ctx context.Context, req RunRequest) (CompiledQuery, error) { + spec, err := s.prepareSpec(ctx, req.Builder) + if err != nil { + return CompiledQuery{}, err + } limit := req.Limit if limit <= 0 { limit = defaultRowLimit } - compiled, err := Compile(spec, limit) + // Keep the validated logical request through the compiler boundary. Calling + // Compile on a pre-lowered Builder would force every service execution down + // the legacy string renderer and bypass the typed physical-plan path. + compiled, err := CompileRequest(spec, limit) if err != nil { - return nil, err + return CompiledQuery{}, err } - return s.runQuery(ctx, compiled) + return compiled, nil } func (s *Service) prepareSpec(ctx context.Context, builder Builder) (Builder, error) { @@ -75,15 +93,34 @@ func (s *Service) prepareSpec(ctx context.Context, builder Builder) (Builder, er } principal, _ := authscope.PrincipalFromContext(ctx) - resolvedPaths, err := s.resolveAuthResourcePaths(ctx, principal, builder.Project, builder.AuthResourcePaths) - if err != nil { + if err := authorizeProject(principal, builder.Project, s.scopeResolver != nil); err != nil { return Builder{}, err } - if err := authorizeProject(principal, builder.Project, s.scopeResolver != nil); err != nil { + resolvedBuilder, err := s.resolveActiveBuilder(ctx, builder) + if err != nil { return Builder{}, err } + builder = resolvedBuilder + var scope authscope.ReadScope + // A dataframebuilder service can hand an already-resolved scope to a + // dataframe service configured without its own resolver. Preserve that + // explicit mode rather than reinterpreting a restricted empty list through + // the legacy no-paths-means-unrestricted rule. + if s.scopeResolver == nil && builder.AuthScopeMode != "" { + scope = authscope.ReadScope{ + AuthResourcePaths: cloneStrings(builder.AuthResourcePaths), + Mode: builder.AuthScopeMode, + } + } else { + var err error + scope, err = s.resolveReadScopeForGeneration(ctx, principal, builder.Project, builder.DatasetGeneration, builder.AuthResourcePaths) + if err != nil { + return Builder{}, err + } + } - builder.AuthResourcePaths = resolvedPaths + builder.AuthResourcePaths = cloneStrings(scope.AuthResourcePaths) + builder.AuthScopeMode = scope.Mode if err := s.validateBuilder(ctx, builder); err != nil { return Builder{}, err } @@ -91,12 +128,5 @@ func (s *Service) prepareSpec(ctx context.Context, builder Builder) (Builder, er if err != nil { return Builder{}, err } - planned, err := lowerGraphQLBuilder(expanded) - if err != nil { - return Builder{}, err - } - if err := validateLoweredBuilder(planned); err != nil { - return Builder{}, err - } - return planned, nil + return expanded, nil } diff --git a/internal/dataframe/shaping.go b/internal/dataframe/shaping.go new file mode 100644 index 0000000..d56b5c7 --- /dev/null +++ b/internal/dataframe/shaping.go @@ -0,0 +1,200 @@ +package dataframe + +import ( + "fmt" + "strings" +) + +// AggregateFunction identifies a stable, backend-independent reduction. +type AggregateFunction string + +const ( + AggregateCount AggregateFunction = "count" + AggregateCountDistinct AggregateFunction = "count_distinct" + AggregateExists AggregateFunction = "exists" + AggregateDistinctValues AggregateFunction = "distinct_values" + AggregateMin AggregateFunction = "min" + AggregateMax AggregateFunction = "max" +) + +func (f AggregateFunction) Validate() error { + switch f { + case AggregateCount, AggregateCountDistinct, AggregateExists, + AggregateDistinctValues, AggregateMin, AggregateMax: + return nil + case "": + return fmt.Errorf("aggregate function is required") + default: + return fmt.Errorf("unsupported aggregate function %q", f) + } +} + +// NullPolicy defines how missing or null input values participate in shaping. +type NullPolicy string + +const ( + NullIgnore NullPolicy = "ignore" + NullInclude NullPolicy = "include" + NullReject NullPolicy = "reject" +) + +func (p NullPolicy) Validate() error { + switch p { + case NullIgnore, NullInclude, NullReject: + return nil + case "": + return fmt.Errorf("null policy is required") + default: + return fmt.Errorf("unsupported null policy %q", p) + } +} + +// AggregateConfig describes an aggregate without binding it to AQL syntax. +// Input is an opaque semantic expression identifier owned by the future IR. +type AggregateConfig struct { + Function AggregateFunction + Input string + NullPolicy NullPolicy +} + +func (c AggregateConfig) Validate() error { + if err := c.Function.Validate(); err != nil { + return err + } + if err := c.NullPolicy.Validate(); err != nil { + return err + } + if c.Function != AggregateCount && strings.TrimSpace(c.Input) == "" { + return fmt.Errorf("aggregate %s requires an input", c.Function) + } + return nil +} + +// DuplicatePolicy defines how multiple values for the same pivot key are +// handled. First and last require deterministic ordering from the caller. +type DuplicatePolicy string + +const ( + DuplicateReject DuplicatePolicy = "reject" + DuplicateFirst DuplicatePolicy = "first" + DuplicateLast DuplicatePolicy = "last" + DuplicateArray DuplicatePolicy = "array" + DuplicateDistinctArray DuplicatePolicy = "distinct_array" +) + +func (p DuplicatePolicy) Validate() error { + switch p { + case DuplicateReject, DuplicateFirst, DuplicateLast, DuplicateArray, + DuplicateDistinctArray: + return nil + case "": + return fmt.Errorf("duplicate policy is required") + default: + return fmt.Errorf("unsupported duplicate policy %q", p) + } +} + +// PivotCardinalityPolicy controls which pivot columns may be materialized. +// Discovery is always bounded; an unbounded discovery policy is intentionally +// absent from this contract. +type PivotCardinalityPolicy string + +const ( + PivotRequestedColumns PivotCardinalityPolicy = "requested_columns" + PivotBoundedDiscovery PivotCardinalityPolicy = "bounded_discovery" +) + +func (p PivotCardinalityPolicy) Validate() error { + switch p { + case PivotRequestedColumns, PivotBoundedDiscovery: + return nil + case "": + return fmt.Errorf("pivot cardinality policy is required") + default: + return fmt.Errorf("unsupported pivot cardinality policy %q", p) + } +} + +// SparsePivotPolicy defines the value emitted when a requested pivot key has +// no matching input. +type SparsePivotPolicy string + +const ( + SparsePivotNull SparsePivotPolicy = "null" + SparsePivotOmit SparsePivotPolicy = "omit" +) + +func (p SparsePivotPolicy) Validate() error { + switch p { + case SparsePivotNull, SparsePivotOmit: + return nil + case "": + return fmt.Errorf("sparse pivot policy is required") + default: + return fmt.Errorf("unsupported sparse pivot policy %q", p) + } +} + +// PivotConfig describes pivot semantics independently of physical lowering. +// Key and Value are opaque semantic expression identifiers owned by the IR. +type PivotConfig struct { + Key string + Value string + DuplicatePolicy DuplicatePolicy + NullPolicy NullPolicy + CardinalityPolicy PivotCardinalityPolicy + SparsePolicy SparsePivotPolicy + RequestedColumns []string + MaxColumns int +} + +func (c PivotConfig) Validate() error { + if strings.TrimSpace(c.Key) == "" { + return fmt.Errorf("pivot key is required") + } + if strings.TrimSpace(c.Value) == "" { + return fmt.Errorf("pivot value is required") + } + if err := c.DuplicatePolicy.Validate(); err != nil { + return err + } + if err := c.NullPolicy.Validate(); err != nil { + return err + } + if err := c.CardinalityPolicy.Validate(); err != nil { + return err + } + if err := c.SparsePolicy.Validate(); err != nil { + return err + } + + seen := make(map[string]struct{}, len(c.RequestedColumns)) + for index, column := range c.RequestedColumns { + column = strings.TrimSpace(column) + if column == "" { + return fmt.Errorf("requested pivot column %d is empty", index) + } + if _, exists := seen[column]; exists { + return fmt.Errorf("requested pivot column %q is duplicated", column) + } + seen[column] = struct{}{} + } + + switch c.CardinalityPolicy { + case PivotRequestedColumns: + if len(c.RequestedColumns) == 0 { + return fmt.Errorf("requested-columns pivot requires at least one column") + } + if c.MaxColumns < 0 { + return fmt.Errorf("pivot max columns cannot be negative") + } + if c.MaxColumns > 0 && len(c.RequestedColumns) > c.MaxColumns { + return fmt.Errorf("requested pivot columns %d exceed maximum %d", len(c.RequestedColumns), c.MaxColumns) + } + case PivotBoundedDiscovery: + if c.MaxColumns <= 0 { + return fmt.Errorf("bounded pivot discovery requires a positive maximum") + } + } + return nil +} diff --git a/internal/dataframe/shaping_plan.go b/internal/dataframe/shaping_plan.go new file mode 100644 index 0000000..d69c69f --- /dev/null +++ b/internal/dataframe/shaping_plan.go @@ -0,0 +1,202 @@ +package dataframe + +import ( + "fmt" + "sort" + "strings" + + "github.com/calypr/loom/internal/fhirschema" +) + +// ShapingDefaults makes policies absent from the legacy Builder contract +// explicit at the boundary to the semantic compiler. +type ShapingDefaults struct { + NullPolicy NullPolicy + PivotDuplicatePolicy DuplicatePolicy + SparsePivotPolicy SparsePivotPolicy + MaxDiscoveredPivotCols int +} + +func (d ShapingDefaults) Validate() error { + if err := d.NullPolicy.Validate(); err != nil { + return err + } + if err := d.PivotDuplicatePolicy.Validate(); err != nil { + return err + } + if err := d.SparsePivotPolicy.Validate(); err != nil { + return err + } + if d.MaxDiscoveredPivotCols <= 0 { + return fmt.Errorf("maximum discovered pivot columns must be positive") + } + return nil +} + +// ShapingSource records the semantic node and, for non-root nodes, the +// generated FHIR relationship that supplies aggregate or pivot values. +type ShapingSource struct { + ParentAlias string + TargetAlias string + ResourceType string + Relationship *fhirschema.CompilerTraversal +} + +type AggregateSemanticSpec struct { + Alias string + Source ShapingSource + Config AggregateConfig + Selector *Selector + Predicate *Selector + PredicateEquals string +} + +type PivotSemanticSpec struct { + Alias string + Source ShapingSource + Config PivotConfig + ColumnSelector Selector + ValueSelector Selector + Family string +} + +type ShapingPlan struct { + Aggregates []AggregateSemanticSpec + Pivots []PivotSemanticSpec +} + +// NormalizeShapingPlan validates shaping requests and returns deterministic, +// alias-sorted specs. It contains no AQL expressions or physical-plan choices. +func NormalizeShapingPlan(plan SemanticPlan, defaults ShapingDefaults) (ShapingPlan, error) { + if err := defaults.Validate(); err != nil { + return ShapingPlan{}, fmt.Errorf("shaping defaults: %w", err) + } + out := ShapingPlan{ + Aggregates: make([]AggregateSemanticSpec, 0), + Pivots: make([]PivotSemanticSpec, 0), + } + aliases := map[string]struct{}{} + var walk func(SemanticNode, string, string) error + walk = func(node SemanticNode, parentAlias, parentType string) error { + if strings.TrimSpace(node.Alias) == "" { + return fmt.Errorf("semantic node for %s has no alias", node.ResourceType) + } + if _, exists := aliases[node.Alias]; exists { + return fmt.Errorf("semantic node alias %q is duplicated", node.Alias) + } + aliases[node.Alias] = struct{}{} + source := ShapingSource{ParentAlias: parentAlias, TargetAlias: node.Alias, ResourceType: node.ResourceType} + if parentAlias != "" { + relationship, found, err := fhirschema.ResolveCompilerTraversal(parentType, node.EdgeLabel, node.ResourceType) + if err != nil { + return fmt.Errorf("relationship %s -[%s]-> %s: %w", parentType, node.EdgeLabel, node.ResourceType, err) + } + if !found { + return fmt.Errorf("unknown relationship %s -[%s]-> %s", parentType, node.EdgeLabel, node.ResourceType) + } + source.Relationship = &relationship + } + + for index, aggregate := range node.Aggregates { + spec, err := normalizeAggregateSpec(node.Alias, index, source, aggregate, defaults.NullPolicy) + if err != nil { + return err + } + out.Aggregates = append(out.Aggregates, spec) + } + for index, pivot := range node.Pivots { + spec, err := normalizePivotSpec(node.Alias, index, source, pivot, defaults) + if err != nil { + return err + } + out.Pivots = append(out.Pivots, spec) + } + for _, child := range node.Children { + if err := walk(child, node.Alias, node.ResourceType); err != nil { + return err + } + } + return nil + } + if err := walk(plan.Root, "", ""); err != nil { + return ShapingPlan{}, err + } + sort.Slice(out.Aggregates, func(i, j int) bool { return out.Aggregates[i].Alias < out.Aggregates[j].Alias }) + sort.Slice(out.Pivots, func(i, j int) bool { return out.Pivots[i].Alias < out.Pivots[j].Alias }) + return out, nil +} + +func normalizeAggregateSpec(nodeAlias string, index int, source ShapingSource, in SemanticAggregate, nulls NullPolicy) (AggregateSemanticSpec, error) { + name := stableShapeName(in.Name, "aggregate", index) + function, err := normalizeAggregateFunction(in.Operation) + if err != nil { + return AggregateSemanticSpec{}, fmt.Errorf("aggregate %q: %w", name, err) + } + input := "" + if in.Selector != nil { + input = in.Selector.CanonicalPath() + } else if in.Predicate != nil { + input = in.Predicate.CanonicalPath() + } else if function == AggregateExists { + input = "node:" + source.TargetAlias + } + config := AggregateConfig{Function: function, Input: input, NullPolicy: nulls} + if err := config.Validate(); err != nil { + return AggregateSemanticSpec{}, fmt.Errorf("aggregate %q: %w", name, err) + } + return AggregateSemanticSpec{ + Alias: nodeAlias + "." + name, Source: source, Config: config, + Selector: in.Selector, Predicate: in.Predicate, PredicateEquals: in.PredicateEquals, + }, nil +} + +func normalizePivotSpec(nodeAlias string, index int, source ShapingSource, in SemanticPivot, defaults ShapingDefaults) (PivotSemanticSpec, error) { + name := stableShapeName(in.Name, "pivot", index) + columns := cloneStrings(in.Columns) + cardinality := PivotRequestedColumns + maxColumns := len(columns) + if len(columns) == 0 { + cardinality = PivotBoundedDiscovery + maxColumns = defaults.MaxDiscoveredPivotCols + } + config := PivotConfig{ + Key: in.ColumnSelector.CanonicalPath(), Value: in.ValueSelector.CanonicalPath(), + DuplicatePolicy: defaults.PivotDuplicatePolicy, NullPolicy: defaults.NullPolicy, + CardinalityPolicy: cardinality, SparsePolicy: defaults.SparsePivotPolicy, + RequestedColumns: columns, MaxColumns: maxColumns, + } + if err := config.Validate(); err != nil { + return PivotSemanticSpec{}, fmt.Errorf("pivot %q: %w", name, err) + } + return PivotSemanticSpec{ + Alias: nodeAlias + "." + name, Source: source, Config: config, + ColumnSelector: in.ColumnSelector, ValueSelector: in.ValueSelector, Family: in.Family, + }, nil +} + +func normalizeAggregateFunction(operation string) (AggregateFunction, error) { + switch strings.ToUpper(strings.TrimSpace(operation)) { + case "COUNT": + return AggregateCount, nil + case "COUNT_DISTINCT": + return AggregateCountDistinct, nil + case "EXISTS": + return AggregateExists, nil + case "DISTINCT_VALUES": + return AggregateDistinctValues, nil + case "MIN": + return AggregateMin, nil + case "MAX": + return AggregateMax, nil + default: + return "", fmt.Errorf("unsupported operation %q", operation) + } +} + +func stableShapeName(name, kind string, index int) string { + name = strings.TrimSpace(name) + if name != "" { + return name + } + return fmt.Sprintf("%s_%d", kind, index+1) +} diff --git a/internal/dataframe/shaping_plan_test.go b/internal/dataframe/shaping_plan_test.go new file mode 100644 index 0000000..a20a3e6 --- /dev/null +++ b/internal/dataframe/shaping_plan_test.go @@ -0,0 +1,74 @@ +package dataframe + +import "testing" + +func TestNormalizeShapingPlanDeterministicSpecs(t *testing.T) { + selector, _ := ParseSelector("code.coding[].code") + value, _ := ParseSelector("valueQuantity.value") + plan := SemanticPlan{Root: SemanticNode{ + Alias: "root", ResourceType: "Observation", + Aggregates: []SemanticAggregate{ + {Name: "values", Operation: "DISTINCT_VALUES", Selector: &value}, + {Name: "", Operation: "COUNT"}, + }, + Pivots: []SemanticPivot{{ + Name: "labs", ColumnSelector: selector, ValueSelector: value, + Columns: []string{"weight", "height"}, Family: "observation", + }}, + }} + got, err := NormalizeShapingPlan(plan, testShapingDefaults()) + if err != nil { + t.Fatalf("NormalizeShapingPlan: %v", err) + } + if len(got.Aggregates) != 2 || got.Aggregates[0].Alias != "root.aggregate_2" || got.Aggregates[1].Alias != "root.values" { + t.Fatalf("unexpected deterministic aggregates: %#v", got.Aggregates) + } + if len(got.Pivots) != 1 || got.Pivots[0].Alias != "root.labs" { + t.Fatalf("unexpected pivots: %#v", got.Pivots) + } + if got.Pivots[0].Config.CardinalityPolicy != PivotRequestedColumns || got.Pivots[0].Config.MaxColumns != 2 { + t.Fatalf("unexpected pivot cardinality: %#v", got.Pivots[0].Config) + } +} + +func TestNormalizeShapingPlanUsesBoundedDiscovery(t *testing.T) { + key, _ := ParseSelector("code") + value, _ := ParseSelector("value") + plan := SemanticPlan{Root: SemanticNode{Alias: "root", ResourceType: "Observation", Pivots: []SemanticPivot{{ColumnSelector: key, ValueSelector: value}}}} + got, err := NormalizeShapingPlan(plan, testShapingDefaults()) + if err != nil { + t.Fatalf("NormalizeShapingPlan: %v", err) + } + if got.Pivots[0].Config.CardinalityPolicy != PivotBoundedDiscovery || got.Pivots[0].Config.MaxColumns != 64 { + t.Fatalf("unexpected discovery policy: %#v", got.Pivots[0].Config) + } +} + +func TestNormalizeShapingPlanRejectsBadRequests(t *testing.T) { + validDefaults := testShapingDefaults() + tests := []struct { + name string + plan SemanticPlan + defs ShapingDefaults + }{ + {"invalid defaults", SemanticPlan{Root: SemanticNode{Alias: "root", ResourceType: "Patient"}}, ShapingDefaults{}}, + {"missing node alias", SemanticPlan{Root: SemanticNode{ResourceType: "Patient"}}, validDefaults}, + {"duplicate node alias", SemanticPlan{Root: SemanticNode{Alias: "root", ResourceType: "Patient", Children: []SemanticNode{{Alias: "root", ResourceType: "Specimen", EdgeLabel: "subject"}}}}, validDefaults}, + {"unknown relationship", SemanticPlan{Root: SemanticNode{Alias: "root", ResourceType: "Patient", Children: []SemanticNode{{Alias: "child", ResourceType: "Specimen", EdgeLabel: "not-a-real-edge"}}}}, validDefaults}, + {"unsupported aggregate", SemanticPlan{Root: SemanticNode{Alias: "root", ResourceType: "Patient", Aggregates: []SemanticAggregate{{Operation: "MEDIAN"}}}}, validDefaults}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + if _, err := NormalizeShapingPlan(test.plan, test.defs); err == nil { + t.Fatal("invalid shaping request unexpectedly succeeded") + } + }) + } +} + +func testShapingDefaults() ShapingDefaults { + return ShapingDefaults{ + NullPolicy: NullIgnore, PivotDuplicatePolicy: DuplicateDistinctArray, + SparsePivotPolicy: SparsePivotNull, MaxDiscoveredPivotCols: 64, + } +} diff --git a/internal/dataframe/shaping_test.go b/internal/dataframe/shaping_test.go new file mode 100644 index 0000000..9282781 --- /dev/null +++ b/internal/dataframe/shaping_test.go @@ -0,0 +1,98 @@ +package dataframe + +import "testing" + +func TestAggregateConfigValidate(t *testing.T) { + valid := []AggregateConfig{ + {Function: AggregateCount, NullPolicy: NullIgnore}, + {Function: AggregateCountDistinct, Input: "patient.id", NullPolicy: NullIgnore}, + {Function: AggregateExists, Input: "condition.id", NullPolicy: NullReject}, + {Function: AggregateDistinctValues, Input: "code", NullPolicy: NullInclude}, + {Function: AggregateMin, Input: "date", NullPolicy: NullIgnore}, + {Function: AggregateMax, Input: "date", NullPolicy: NullIgnore}, + } + for _, config := range valid { + if err := config.Validate(); err != nil { + t.Errorf("Validate(%#v): %v", config, err) + } + } + + invalid := []AggregateConfig{ + {}, + {Function: AggregateMin, NullPolicy: NullIgnore}, + {Function: AggregateCount, NullPolicy: "sometimes"}, + {Function: "median", Input: "value", NullPolicy: NullIgnore}, + } + for _, config := range invalid { + if err := config.Validate(); err == nil { + t.Errorf("invalid aggregate %#v unexpectedly succeeded", config) + } + } +} + +func TestPivotConfigRequestedColumns(t *testing.T) { + config := PivotConfig{ + Key: "observation.code", + Value: "observation.value", + DuplicatePolicy: DuplicateDistinctArray, + NullPolicy: NullIgnore, + CardinalityPolicy: PivotRequestedColumns, + SparsePolicy: SparsePivotNull, + RequestedColumns: []string{"height", "weight"}, + MaxColumns: 2, + } + if err := config.Validate(); err != nil { + t.Fatalf("valid requested-columns pivot: %v", err) + } + + config.RequestedColumns = nil + if err := config.Validate(); err == nil { + t.Fatal("requested-columns pivot without columns unexpectedly succeeded") + } +} + +func TestPivotConfigBoundedDiscovery(t *testing.T) { + config := PivotConfig{ + Key: "observation.code", + Value: "observation.value", + DuplicatePolicy: DuplicateReject, + NullPolicy: NullReject, + CardinalityPolicy: PivotBoundedDiscovery, + SparsePolicy: SparsePivotOmit, + MaxColumns: 100, + } + if err := config.Validate(); err != nil { + t.Fatalf("valid bounded-discovery pivot: %v", err) + } + + config.MaxColumns = 0 + if err := config.Validate(); err == nil { + t.Fatal("unbounded pivot discovery unexpectedly succeeded") + } +} + +func TestPivotConfigRejectsInvalidShape(t *testing.T) { + base := PivotConfig{ + Key: "code", + Value: "value", + DuplicatePolicy: DuplicateFirst, + NullPolicy: NullIgnore, + CardinalityPolicy: PivotRequestedColumns, + SparsePolicy: SparsePivotNull, + RequestedColumns: []string{"a"}, + } + tests := []PivotConfig{ + func() PivotConfig { c := base; c.Key = ""; return c }(), + func() PivotConfig { c := base; c.Value = " "; return c }(), + func() PivotConfig { c := base; c.DuplicatePolicy = "merge"; return c }(), + func() PivotConfig { c := base; c.SparsePolicy = "zero"; return c }(), + func() PivotConfig { c := base; c.RequestedColumns = []string{"a", "a"}; return c }(), + func() PivotConfig { c := base; c.RequestedColumns = []string{" "}; return c }(), + func() PivotConfig { c := base; c.MaxColumns = 1; c.RequestedColumns = []string{"a", "b"}; return c }(), + } + for _, config := range tests { + if err := config.Validate(); err == nil { + t.Errorf("invalid pivot %#v unexpectedly succeeded", config) + } + } +} diff --git a/internal/dataframe/storage_route.go b/internal/dataframe/storage_route.go new file mode 100644 index 0000000..a6678fd --- /dev/null +++ b/internal/dataframe/storage_route.go @@ -0,0 +1,201 @@ +package dataframe + +import ( + "errors" + "fmt" + "strings" + + "github.com/calypr/loom/internal/fhirschema" +) + +// ErrUnsupportedStorageRoute identifies a FHIR relationship that is known to +// the generated schema but has not been proven safe for Loom's stored +// fhir_edge layout. Callers must not substitute a different AQL direction for +// this error: every physical direction must have a compiler-owned storage +// contract. +var ErrUnsupportedStorageRoute = errors.New("unsupported storage route") + +// storageRoute is the compiler-owned bridge from generated FHIR relationship +// metadata to the currently supported stored-edge operation. The generated +// FHIR Direction describes the logical reference, not the Arango direction; +// Direction below is established only by a storage proof in +// resolveStorageRoute. +type storageRoute struct { + Relationship fhirschema.CompilerTraversal + Direction PhysicalTraversalDirection +} + +func (route storageRoute) namedSetDirection() string { + return string(route.Direction) +} + +// targetEdgeTypeField returns the fhir_edge type discriminator for the node +// reached by this route. It is deliberately direction-aware: forward FHIR +// references store their target in to_type, while the generated builder route +// reads the source-side type through an INBOUND traversal. The node +// resourceType predicate remains mandatory even when this edge predicate is +// used as an index-selectivity hint. +func (route storageRoute) targetEdgeTypeField() string { + switch route.Direction { + case PhysicalInbound: + return "from_type" + case PhysicalOutbound: + return "to_type" + default: + return "" + } +} + +// resolveStorageRoute accepts generated synthetic reverse routes for which +// the source resource is provably the reference target. The ingester stores +// normal FHIR references as child _from -> parent _to, so a parent -> child +// dataframe route is an INBOUND fhir_edge traversal. +// +// It also accepts one explicit forward route: ResearchSubject --study--> +// ResearchStudy. The checked-in graph schema proves the logical FHIR target +// (an exact ResearchStudy/* hint, OUTBOUND direction, and has_one +// multiplicity), and the generated edge-extractor regression proves that it +// is materialized as ResearchSubject _from -> ResearchStudy _to in fhir_edge. +// Other generated forward metadata remains deliberately non-executable until +// it has the same storage proof. +func resolveStorageRoute(fromType, edgeLabel, toType string) (storageRoute, error) { + if !fhirschema.HasResource(fromType) { + return storageRoute{}, unsupportedStorageRouteError(fromType, edgeLabel, toType, "source resource type is not represented by the active generated FHIR schema") + } + if !fhirschema.HasResource(toType) { + return storageRoute{}, unsupportedStorageRouteError(fromType, edgeLabel, toType, "target resource type is not represented by the active generated FHIR schema") + } + + spec, found := fhirschema.LookupTraversal(fromType, edgeLabel, toType) + if !found { + return storageRoute{}, unsupportedStorageRouteError(fromType, edgeLabel, toType, "is not represented by the active generated FHIR schema") + } + // LookupTraversal is keyed by this exact tuple, but retain the check so a + // malformed future generated map cannot silently become executable AQL. + if spec.FromType != fromType || spec.EdgeLabel != edgeLabel || spec.ToType != toType { + return storageRoute{}, unsupportedStorageRouteError(fromType, edgeLabel, toType, "generated traversal metadata does not match the requested route") + } + relationship, found, err := fhirschema.ResolveCompilerTraversal(fromType, edgeLabel, toType) + if err != nil { + return storageRoute{}, fmt.Errorf("%w: %s -> %s (%s) has unsafe generated metadata: %v", ErrUnsupportedStorageRoute, fromType, toType, edgeLabel, err) + } + if !found { + return storageRoute{}, unsupportedStorageRouteError(fromType, edgeLabel, toType, "is not represented by the active generated FHIR schema") + } + + // Only a precise, generated /* target hint proves that + // this tuple is the synthetic parent -> child route. In particular, + // Resource/* is deliberately not evidence for a concrete parent type. + if hasExactStorageParentHint(spec.RegexMatch, fromType) { + return storageRoute{Relationship: relationship, Direction: PhysicalInbound}, nil + } + + if isProvenResearchSubjectStudyOutboundRoute(spec, relationship) { + return storageRoute{Relationship: relationship, Direction: PhysicalOutbound}, nil + } + + return storageRoute{}, unsupportedStorageRouteError(fromType, edgeLabel, toType, fmt.Sprintf("is not a proven stored route: generated reverse/builder routes require RegexMatch %q; generated forward routes require an explicit fhir_edge contract (got %s)", fromType+"/*", formatRegexMatchHints(spec.RegexMatch))) +} + +func isProvenResearchSubjectStudyOutboundRoute(spec fhirschema.TraversalSpec, relationship fhirschema.CompilerTraversal) bool { + if spec.FromType != "ResearchSubject" || spec.EdgeLabel != "study" || spec.ToType != "ResearchStudy" { + return false + } + if relationship.Direction != fhirschema.TraversalOutbound || relationship.Multiplicity != fhirschema.TraversalOne { + return false + } + return hasExactStorageTargetHint(spec.RegexMatch, spec.ToType) +} + +func unsupportedStorageRouteError(fromType, edgeLabel, toType, reason string) error { + return fmt.Errorf("%w: %s -> %s (%s): %s", ErrUnsupportedStorageRoute, fromType, toType, edgeLabel, reason) +} + +func hasExactStorageParentHint(hints []string, fromType string) bool { + return hasExactStorageTargetHint(hints, fromType) +} + +func hasExactStorageTargetHint(hints []string, resourceType string) bool { + want := resourceType + "/*" + for _, hint := range hints { + if strings.TrimSpace(hint) == want { + return true + } + } + return false +} + +func formatRegexMatchHints(hints []string) string { + if len(hints) == 0 { + return "none" + } + quoted := make([]string, 0, len(hints)) + for _, hint := range hints { + quoted = append(quoted, fmt.Sprintf("%q", strings.TrimSpace(hint))) + } + return strings.Join(quoted, ", ") +} + +// validateGenericLoweredStorageRoutes closes the pre-lowered Builder path. +// Generic lowering itself emits these sets, but persisted or conformance +// callers can invoke Compile directly. The generic profile contains only a +// root-to-child chain of TRAVERSE sets, so source resource types can be +// derived without trusting caller-provided physical direction. +func validateGenericLoweredStorageRoutes(builder Builder) error { + if builder.PlanHint == nil || builder.PlanHint.Profile != "generic_fhir_graph" { + return nil + } + _, err := resolveGenericLoweredStorageRoutes(builder) + return err +} + +// resolveGenericLoweredStorageRoutes derives the immutable stored-edge route +// for every generic TRAVERSE set. Compile uses the result to emit the edge +// type discriminator in addition to the target node resourceType guard; this +// avoids trusting a persisted lowered Builder's requested direction. +func resolveGenericLoweredStorageRoutes(builder Builder) (map[string]storageRoute, error) { + if builder.PlanHint == nil || builder.PlanHint.Profile != "generic_fhir_graph" { + return nil, nil + } + + setResourceTypes := make(map[string]string, len(builder.Sets)) + routes := make(map[string]storageRoute, len(builder.Sets)) + for _, set := range builder.Sets { + switch strings.ToUpper(strings.TrimSpace(set.Kind)) { + case SetKindTraverse: + fromType := builder.RootResourceType + source := strings.TrimSpace(set.Source) + if source != "" && source != "root" { + var found bool + fromType, found = setResourceTypes[source] + if !found { + return nil, fmt.Errorf("set %q: %w: source set %q does not establish a generated resource type", set.Name, ErrUnsupportedStorageRoute, set.Source) + } + } + route, err := resolveStorageRoute(fromType, set.Label, set.ToResourceType) + if err != nil { + return nil, fmt.Errorf("set %q: %w", set.Name, err) + } + direction := strings.ToUpper(strings.TrimSpace(set.Direction)) + if direction != "" && direction != string(route.Direction) { + return nil, fmt.Errorf("set %q: %w: generic route direction must be %s, got %q", set.Name, ErrUnsupportedStorageRoute, route.Direction, set.Direction) + } + setResourceTypes[set.Name] = set.ToResourceType + routes[set.Name] = route + case SetKindFilter: + source := strings.TrimSpace(set.Source) + fromType, found := setResourceTypes[source] + if source == "root" { + fromType, found = builder.RootResourceType, true + } + if !found { + return nil, fmt.Errorf("set %q: %w: source set %q does not establish a generated resource type", set.Name, ErrUnsupportedStorageRoute, set.Source) + } + if targetType := strings.TrimSpace(set.MatchResourceType); targetType != "" { + fromType = targetType + } + setResourceTypes[set.Name] = fromType + } + } + return routes, nil +} diff --git a/internal/dataframe/storage_route_test.go b/internal/dataframe/storage_route_test.go new file mode 100644 index 0000000..cf0342d --- /dev/null +++ b/internal/dataframe/storage_route_test.go @@ -0,0 +1,274 @@ +package dataframe + +import ( + "errors" + "strings" + "testing" +) + +func TestResolveStorageRouteAcceptsGeneratedBuilderOrientation(t *testing.T) { + route, err := resolveStorageRoute("Patient", "subject_Patient", "Condition") + if err != nil { + t.Fatalf("resolveStorageRoute(Patient -> Condition): %v", err) + } + if route.Direction != PhysicalInbound { + t.Fatalf("route direction = %q, want %q", route.Direction, PhysicalInbound) + } + if route.targetEdgeTypeField() != "from_type" { + t.Fatalf("inbound target edge type field = %q, want from_type", route.targetEdgeTypeField()) + } + + planned, err := lowerGenericGraphQLBuilder(Builder{}, buildLogicalRequest(Builder{ + Project: "P1", + RootResourceType: "Patient", + Traversals: []TraversalStep{{ + Alias: "diagnosis", Label: "subject_Patient", ToResourceType: "Condition", + }}, + })) + if err != nil { + t.Fatalf("lowerGenericGraphQLBuilder: %v", err) + } + if len(planned.Sets) != 1 || planned.Sets[0].Direction != string(PhysicalInbound) { + t.Fatalf("generic sets = %#v, want one INBOUND stored route", planned.Sets) + } + compiled, err := Compile(planned, 5) + if err != nil { + t.Fatalf("Compile(generic builder): %v", err) + } + for _, required := range []string{ + "1..1 INBOUND root fhir_edge", + "__edge.project == @project", + "__node.project == @project", + "__edge.dataset_generation == @dataset_generation", + "__node.dataset_generation == @dataset_generation", + "auth_resource_path IN @auth_resource_paths", + "__edge.from_type == @", + "__node.resourceType == @", + } { + if !strings.Contains(compiled.Query, required) { + t.Fatalf("generic query does not retain %q:\n%s", required, compiled.Query) + } + } +} + +func TestGenericLoweredOutboundTraversalScopesLegacyRenderer(t *testing.T) { + compiled, err := Compile(Builder{ + Project: "P1", + DatasetGeneration: "generation-1", + AuthResourcePaths: []string{"/programs/p1"}, + RootResourceType: "ResearchSubject", + PlanHint: &PlanHint{Mode: "lowered", Profile: "generic_fhir_graph"}, + Fields: []FieldSelect{{Name: "id", Select: "id"}}, + Sets: []NamedSet{{ + Name: "study", Kind: SetKindTraverse, Label: "study", ToResourceType: "ResearchStudy", Direction: "OUTBOUND", + }}, + }, 5) + if err != nil { + t.Fatalf("Compile(generic outbound lowered builder): %v", err) + } + for _, required := range []string{ + "1..1 OUTBOUND root fhir_edge", + "__edge.project == @project", + "__node.project == @project", + "__edge.dataset_generation == @dataset_generation", + "__node.dataset_generation == @dataset_generation", + "__edge.to_type == @", + "__node.resourceType == @", + } { + if !strings.Contains(compiled.Query, required) { + t.Fatalf("legacy outbound traversal is missing %q:\n%s", required, compiled.Query) + } + } + assertBindVarValue(t, compiled.BindVars, "ResearchStudy") +} + +func TestGenericLoweredRequiredOutboundTraversalScopesTargetNode(t *testing.T) { + compiled, err := Compile(Builder{ + Project: "P1", + DatasetGeneration: "generation-1", + AuthResourcePaths: []string{"/programs/p1"}, + RootResourceType: "ResearchSubject", + PlanHint: &PlanHint{Mode: "lowered", Profile: "generic_fhir_graph"}, + RequiredTraversalMatches: []RequiredTraversalMatch{{ + Steps: []TraversalMatchStep{{Label: "study", ToResourceType: "ResearchStudy"}}, + }}, + }, 5) + if err != nil { + t.Fatalf("Compile(generic required outbound lowered builder): %v", err) + } + for _, required := range []string{ + "FOR __match_0_0, __match_edge_0_0 IN 1..1 OUTBOUND root fhir_edge", + "__match_edge_0_0.project == @project", + "__match_0_0.project == @project", + "__match_edge_0_0.dataset_generation == @dataset_generation", + "__match_0_0.dataset_generation == @dataset_generation", + "__match_edge_0_0.to_type == @", + "__match_0_0.resourceType == @", + } { + if !strings.Contains(compiled.Query, required) { + t.Fatalf("required outbound traversal is missing %q:\n%s", required, compiled.Query) + } + } + assertBindVarValue(t, compiled.BindVars, "ResearchStudy") +} + +func TestStorageRouteAcceptsProvenOutboundResearchSubjectStudy(t *testing.T) { + route, err := resolveStorageRoute("ResearchSubject", "study", "ResearchStudy") + if err != nil { + t.Fatalf("resolveStorageRoute(ResearchSubject -> ResearchStudy): %v", err) + } + if route.Direction != PhysicalOutbound { + t.Fatalf("route direction = %q, want %q", route.Direction, PhysicalOutbound) + } + if route.targetEdgeTypeField() != "to_type" { + t.Fatalf("outbound target edge type field = %q, want to_type", route.targetEdgeTypeField()) + } + + request := Builder{ + Project: "P1", + DatasetGeneration: "generation-1", + AuthResourcePaths: []string{"/programs/p1"}, + RootResourceType: "ResearchSubject", + Traversals: []TraversalStep{{ + Alias: "study", Label: "study", ToResourceType: "ResearchStudy", + }}, + } + compiled, err := CompileRequest(request, 5) + if err != nil { + t.Fatalf("CompileRequest(ResearchSubject -> ResearchStudy): %v", err) + } + for _, required := range []string{ + "1..1 OUTBOUND root @@traversal_1_edge_collection", + "edge_1.project == @project", + "node_1.project == @project", + "edge_1.dataset_generation == @dataset_generation", + "node_1.dataset_generation == @dataset_generation", + "auth_resource_path IN @auth_resource_paths", + "edge_1.label == @traversal_1_label", + "edge_1.to_type == @traversal_1_target_type", + "node_1.resourceType == @traversal_1_target_type", + } { + if !strings.Contains(compiled.Query, required) { + t.Fatalf("outbound query does not retain %q:\n%s", required, compiled.Query) + } + } + + explanation, err := ExplainCompilerRequest(request, 5) + if err != nil { + t.Fatalf("ExplainCompilerRequest(ResearchSubject -> ResearchStudy): %v", err) + } + if !explanation.GenericPhysicalPlan.Available || explanation.GenericPhysicalPlan.Plan == nil { + t.Fatalf("outbound generic physical plan = %#v", explanation.GenericPhysicalPlan) + } + var traversal *PhysicalTraversal + for _, operation := range explanation.GenericPhysicalPlan.Plan.Operations { + if operation.Kind == PhysicalTraversalOp { + traversal = operation.Traversal + break + } + } + if traversal == nil || traversal.Direction != PhysicalOutbound { + t.Fatalf("explained outbound traversal = %#v, want OUTBOUND", traversal) + } +} + +func TestStorageRouteRejectsGeneratedForwardFHIRReference(t *testing.T) { + _, err := resolveStorageRoute("Condition", "subject_Patient", "Patient") + if !errors.Is(err, ErrUnsupportedStorageRoute) { + t.Fatalf("resolveStorageRoute(Condition -> Patient) error = %v, want ErrUnsupportedStorageRoute", err) + } + + _, err = CompileRequest(Builder{ + Project: "P1", + RootResourceType: "Condition", + Traversals: []TraversalStep{{ + Alias: "patient", Label: "subject_Patient", ToResourceType: "Patient", + }}, + }, 5) + if !errors.Is(err, ErrUnsupportedStorageRoute) { + t.Fatalf("CompileRequest(forward route) error = %v, want ErrUnsupportedStorageRoute", err) + } +} + +func TestStorageRouteAppliesToNestedRequiredMatches(t *testing.T) { + _, err := Lower(Builder{ + Project: "P1", + RootResourceType: "Patient", + Traversals: []TraversalStep{{ + Alias: "specimen", Label: "subject_Patient", ToResourceType: "Specimen", + Traversals: []TraversalStep{{ + Alias: "patient", Label: "subject_Patient", ToResourceType: "Patient", MatchMode: TraversalMatchRequired, + }}, + }}, + }) + if !errors.Is(err, ErrUnsupportedStorageRoute) { + t.Fatalf("Lower(nested required forward route) error = %v, want ErrUnsupportedStorageRoute", err) + } +} + +func TestStorageRouteAppliesToGenericPhysicalPlansAndPreLoweredBuilders(t *testing.T) { + semantic, err := BuildSemanticPlan(Builder{ + Project: "P1", + RootResourceType: "Patient", + Traversals: []TraversalStep{{ + Alias: "diagnosis", Label: "subject_Patient", ToResourceType: "Condition", + }}, + }) + if err != nil { + t.Fatalf("BuildSemanticPlan(builder route): %v", err) + } + physical, err := BuildGenericPhysicalPlan(semantic) + if err != nil { + t.Fatalf("BuildGenericPhysicalPlan: %v", err) + } + var traversal *PhysicalTraversal + for _, operation := range physical.Operations { + if operation.Kind == PhysicalTraversalOp { + traversal = operation.Traversal + break + } + } + if traversal == nil || traversal.Direction != PhysicalInbound { + t.Fatalf("physical traversal = %#v, want INBOUND", traversal) + } + + _, err = Compile(Builder{ + Project: "P1", + RootResourceType: "Patient", + PlanHint: &PlanHint{Mode: "lowered", Profile: "generic_fhir_graph"}, + Sets: []NamedSet{{ + Name: "diagnosis", Kind: SetKindTraverse, Label: "subject_Patient", ToResourceType: "Condition", Direction: "OUTBOUND", + }}, + }, 1) + if !errors.Is(err, ErrUnsupportedStorageRoute) { + t.Fatalf("Compile(pre-lowered wrong direction) error = %v, want ErrUnsupportedStorageRoute", err) + } + + _, err = Compile(Builder{ + Project: "P1", + RootResourceType: "ResearchSubject", + PlanHint: &PlanHint{Mode: "lowered", Profile: "generic_fhir_graph"}, + Sets: []NamedSet{{ + Name: "study", Kind: SetKindTraverse, Label: "study", ToResourceType: "ResearchStudy", Direction: "INBOUND", + }}, + }, 1) + if !errors.Is(err, ErrUnsupportedStorageRoute) { + t.Fatalf("Compile(pre-lowered outbound route with INBOUND direction) error = %v, want ErrUnsupportedStorageRoute", err) + } +} + +func TestGenericStorageRoutePropagatesTypeThroughFilterSet(t *testing.T) { + _, err := Compile(Builder{ + Project: "P1", + RootResourceType: "Patient", + PlanHint: &PlanHint{Mode: "lowered", Profile: "generic_fhir_graph"}, + Sets: []NamedSet{ + {Name: "specimen", Kind: SetKindTraverse, Label: "subject_Patient", ToResourceType: "Specimen", Direction: "INBOUND"}, + {Name: "filtered_specimen", Kind: SetKindFilter, Source: "specimen", MatchResourceType: "Specimen"}, + {Name: "file", Kind: SetKindTraverse, Source: "filtered_specimen", Label: "subject_Specimen", ToResourceType: "DocumentReference", Direction: "INBOUND"}, + }, + }, 1) + if err != nil { + t.Fatalf("Compile(generic route through FILTER set): %v", err) + } +} diff --git a/internal/dataframe/traversal_rules.go b/internal/dataframe/traversal_rules.go deleted file mode 100644 index 212b078..0000000 --- a/internal/dataframe/traversal_rules.go +++ /dev/null @@ -1,102 +0,0 @@ -package dataframe - -import "github.com/calypr/loom/internal/fhirschema" - -type traversalRole string - -const ( - traversalRolePatientNeighborChild traversalRole = "PATIENT_NEIGHBOR_CHILD" - traversalRolePatientDirectChild traversalRole = "PATIENT_DIRECT_CHILD" - traversalRolePatientDocumentReference traversalRole = "PATIENT_DOCUMENT_REFERENCE" - traversalRoleSpecimenGroup traversalRole = "SPECIMEN_GROUP" - traversalRoleSpecimenDocumentReference traversalRole = "SPECIMEN_DOCUMENT_REFERENCE" - traversalRoleGroupDocumentReference traversalRole = "GROUP_DOCUMENT_REFERENCE" -) - -type plannerTraversal struct { - Schema fhirschema.TraversalSpec - Role traversalRole - SetName string - SharedRootNeighborEligible bool -} - -func lookupPlannerTraversal(fromType, edgeLabel, toType string) (plannerTraversal, bool) { - spec, ok := fhirschema.LookupTraversal(fromType, edgeLabel, toType) - if !ok { - return plannerTraversal{}, false - } - rule, ok := classifyPlannerTraversal(spec) - if !ok { - return plannerTraversal{}, false - } - return rule, true -} - -func classifyPlannerTraversal(spec fhirschema.TraversalSpec) (plannerTraversal, bool) { - switch traversalKey(spec.FromType, spec.EdgeLabel, spec.ToType) { - case traversalKey("Patient", "subject_Patient", "Condition"): - return patientNeighborTraversal(spec, "patient_condition_set"), true - case traversalKey("Patient", "subject_Patient", "ResearchSubject"): - return patientNeighborTraversal(spec, "patient_research_subject_set"), true - case traversalKey("Patient", "subject_Patient", "Specimen"): - return patientNeighborTraversal(spec, "patient_specimen_set"), true - case traversalKey("Patient", "subject_Patient", "MedicationAdministration"): - return patientNeighborTraversal(spec, "patient_medication_administration_set"), true - case traversalKey("Patient", "subject_Patient", "Observation"): - return patientNeighborTraversal(spec, "patient_subject_observation_set"), true - case traversalKey("Patient", "subject_Patient", "ImagingStudy"): - return patientNeighborTraversal(spec, "patient_imaging_study_set"), true - case traversalKey("Patient", "subject_Patient", "DocumentReference"): - return plannerTraversal{ - Schema: spec, - Role: traversalRolePatientDocumentReference, - SetName: "patient_document_reference_set", - SharedRootNeighborEligible: true, - }, true - case traversalKey("Patient", "focus_Patient", "Observation"): - return patientDirectTraversal(spec, "patient_focus_observation_set"), true - case traversalKey("Patient", "member_entity_Patient", "Group"): - return patientDirectTraversal(spec, "patient_group_set"), true - case traversalKey("Specimen", "member_entity_Specimen", "Group"): - return plannerTraversal{ - Schema: spec, - Role: traversalRoleSpecimenGroup, - SetName: "specimen_group_set", - }, true - case traversalKey("Specimen", "subject_Specimen", "DocumentReference"): - return plannerTraversal{ - Schema: spec, - Role: traversalRoleSpecimenDocumentReference, - SetName: "specimen_document_reference_set", - }, true - case traversalKey("Group", "subject_Group", "DocumentReference"): - return plannerTraversal{ - Schema: spec, - Role: traversalRoleGroupDocumentReference, - SetName: "group_document_reference_set", - }, true - default: - return plannerTraversal{}, false - } -} - -func patientNeighborTraversal(spec fhirschema.TraversalSpec, setName string) plannerTraversal { - return plannerTraversal{ - Schema: spec, - Role: traversalRolePatientNeighborChild, - SetName: setName, - SharedRootNeighborEligible: true, - } -} - -func patientDirectTraversal(spec fhirschema.TraversalSpec, setName string) plannerTraversal { - return plannerTraversal{ - Schema: spec, - Role: traversalRolePatientDirectChild, - SetName: setName, - } -} - -func traversalKey(fromType, edgeLabel, toType string) string { - return fromType + "|" + edgeLabel + "|" + toType -} diff --git a/internal/dataframe/validation.go b/internal/dataframe/validation.go index b1dcd60..61f3062 100644 --- a/internal/dataframe/validation.go +++ b/internal/dataframe/validation.go @@ -11,37 +11,45 @@ import ( func (s *Service) validateBuilder(ctx context.Context, builder Builder) error { seenAliases := map[string]struct{}{} + authResourcePathsUnrestricted := builderAuthScopeUnrestricted(builder) rootFields, err := s.discoverFields(ctx, catalog.PopulatedFieldOptions{ - ConnectionOptions: s.connOpts, - Project: builder.Project, - AuthResourcePaths: builder.AuthResourcePaths, - ResourceType: builder.RootResourceType, + ConnectionOptions: s.connOpts, + Project: builder.Project, + DatasetGeneration: builder.DatasetGeneration, + AuthResourcePathsUnrestricted: catalog.ExplicitAuthResourcePathsUnrestricted(authResourcePathsUnrestricted), + AuthResourcePaths: builder.AuthResourcePaths, + ResourceType: builder.RootResourceType, }) if err != nil { return err } rootPivots, err := s.discoverFields(ctx, catalog.PopulatedFieldOptions{ - ConnectionOptions: s.connOpts, - Project: builder.Project, - AuthResourcePaths: builder.AuthResourcePaths, - ResourceType: builder.RootResourceType, - PivotOnly: true, + ConnectionOptions: s.connOpts, + Project: builder.Project, + DatasetGeneration: builder.DatasetGeneration, + AuthResourcePathsUnrestricted: catalog.ExplicitAuthResourcePathsUnrestricted(authResourcePathsUnrestricted), + AuthResourcePaths: builder.AuthResourcePaths, + ResourceType: builder.RootResourceType, + PivotOnly: true, }) if err != nil { return err } - if err := validateNodeSelections(builder.Fields, builder.Pivots, builder.Aggregates, builder.Slices, rootFields, rootPivots); err != nil { + if err := validateNodeSelections(builder.Fields, builder.Filters, builder.Pivots, builder.Aggregates, builder.Slices, rootFields, rootPivots); err != nil { return err } for _, step := range builder.Traversals { - if err := s.validateTraversal(ctx, builder.Project, builder.AuthResourcePaths, builder.RootResourceType, step, seenAliases); err != nil { + if err := s.validateTraversal(ctx, builder.Project, builder.DatasetGeneration, builder.AuthResourcePaths, authResourcePathsUnrestricted, builder.RootResourceType, step, seenAliases); err != nil { return err } } return nil } -func (s *Service) validateTraversal(ctx context.Context, project string, authResourcePaths []string, sourceType string, step TraversalStep, seenAliases map[string]struct{}) error { +func (s *Service) validateTraversal(ctx context.Context, project, datasetGeneration string, authResourcePaths []string, authResourcePathsUnrestricted bool, sourceType string, step TraversalStep, seenAliases map[string]struct{}) error { + if err := step.MatchMode.Validate(); err != nil { + return fmt.Errorf("traversal %s -> %s (%s): %w", sourceType, step.ToResourceType, step.Label, err) + } if step.Alias == "" { return fmt.Errorf("traversal alias is required") } @@ -51,11 +59,13 @@ func (s *Service) validateTraversal(ctx context.Context, project string, authRes seenAliases[step.Alias] = struct{}{} refs, err := s.discoverReferences(ctx, catalog.PopulatedReferenceOptions{ - ConnectionOptions: s.connOpts, - Project: project, - AuthResourcePaths: authResourcePaths, - NodeType: sourceType, - Mode: catalog.TraversalModeBuilder, + ConnectionOptions: s.connOpts, + Project: project, + DatasetGeneration: datasetGeneration, + AuthResourcePathsUnrestricted: catalog.ExplicitAuthResourcePathsUnrestricted(authResourcePathsUnrestricted), + AuthResourcePaths: authResourcePaths, + NodeType: sourceType, + Mode: catalog.TraversalModeBuilder, }) if err != nil { return err @@ -72,36 +82,40 @@ func (s *Service) validateTraversal(ctx context.Context, project string, authRes } fields, err := s.discoverFields(ctx, catalog.PopulatedFieldOptions{ - ConnectionOptions: s.connOpts, - Project: project, - AuthResourcePaths: authResourcePaths, - ResourceType: step.ToResourceType, + ConnectionOptions: s.connOpts, + Project: project, + DatasetGeneration: datasetGeneration, + AuthResourcePathsUnrestricted: catalog.ExplicitAuthResourcePathsUnrestricted(authResourcePathsUnrestricted), + AuthResourcePaths: authResourcePaths, + ResourceType: step.ToResourceType, }) if err != nil { return err } pivotFields, err := s.discoverFields(ctx, catalog.PopulatedFieldOptions{ - ConnectionOptions: s.connOpts, - Project: project, - AuthResourcePaths: authResourcePaths, - ResourceType: step.ToResourceType, - PivotOnly: true, + ConnectionOptions: s.connOpts, + Project: project, + DatasetGeneration: datasetGeneration, + AuthResourcePathsUnrestricted: catalog.ExplicitAuthResourcePathsUnrestricted(authResourcePathsUnrestricted), + AuthResourcePaths: authResourcePaths, + ResourceType: step.ToResourceType, + PivotOnly: true, }) if err != nil { return err } - if err := validateNodeSelections(step.Fields, step.Pivots, step.Aggregates, step.Slices, fields, pivotFields); err != nil { + if err := validateNodeSelections(step.Fields, step.Filters, step.Pivots, step.Aggregates, step.Slices, fields, pivotFields); err != nil { return fmt.Errorf("alias %s: %w", step.Alias, err) } for _, child := range step.Traversals { - if err := s.validateTraversal(ctx, project, authResourcePaths, step.ToResourceType, child, seenAliases); err != nil { + if err := s.validateTraversal(ctx, project, datasetGeneration, authResourcePaths, authResourcePathsUnrestricted, step.ToResourceType, child, seenAliases); err != nil { return err } } return nil } -func validateNodeSelections(fields []FieldSelect, pivots []PivotSelect, aggregates []AggregateSelect, slices []RepresentativeSlice, discovered []catalog.PopulatedField, pivotable []catalog.PopulatedField) error { +func validateNodeSelections(fields []FieldSelect, filters []TypedFilter, pivots []PivotSelect, aggregates []AggregateSelect, slices []RepresentativeSlice, discovered []catalog.PopulatedField, pivotable []catalog.PopulatedField) error { seenFields := map[string]struct{}{} for _, field := range fields { if field.Name == "" || field.Select == "" { @@ -121,6 +135,19 @@ func validateNodeSelections(fields []FieldSelect, pivots []PivotSelect, aggregat } } + for _, filter := range filters { + if err := ValidateTypedFilterForResource(resourceTypeFromDiscovered(discovered), filter); err != nil { + return fmt.Errorf("invalid filter %q: %w", filter.FieldRef, err) + } + sel, err := ParseSelector(filter.Selector) + if err != nil { + return fmt.Errorf("invalid filter selector for %q: %w", filter.FieldRef, err) + } + if findFieldByPath(discovered, sel.CanonicalPath()) == nil { + return fmt.Errorf("filter selector %q is not present in populated fields", filter.Selector) + } + } + seenPivots := map[string]struct{}{} for _, pivot := range pivots { if pivot.Name == "" || pivot.ColumnSelect == "" || pivot.ValueSelect == "" { @@ -164,7 +191,7 @@ func validateNodeSelections(fields []FieldSelect, pivots []PivotSelect, aggregat } seenAggregates[agg.Name] = struct{}{} switch strings.ToUpper(strings.TrimSpace(agg.Operation)) { - case "COUNT", "COUNT_DISTINCT", "EXISTS", "DISTINCT_VALUES": + case "COUNT", "COUNT_DISTINCT", "EXISTS", "DISTINCT_VALUES", "MIN", "MAX": default: return fmt.Errorf("aggregate %q uses unsupported operation %q", agg.Name, agg.Operation) } @@ -177,6 +204,9 @@ func validateNodeSelections(fields []FieldSelect, pivots []PivotSelect, aggregat return fmt.Errorf("aggregate selector %q is not present in populated fields", agg.Select) } } + if aggregateOperationRequiresSelector(strings.ToUpper(strings.TrimSpace(agg.Operation))) && strings.TrimSpace(agg.Select) == "" { + return fmt.Errorf("aggregate %q operation %s requires a selector", agg.Name, agg.Operation) + } if strings.TrimSpace(agg.PredicatePath) != "" { sel, err := ParseSelector(agg.PredicatePath) if err != nil { diff --git a/internal/dataframe/value_mode_test.go b/internal/dataframe/value_mode_test.go new file mode 100644 index 0000000..a52b790 --- /dev/null +++ b/internal/dataframe/value_mode_test.go @@ -0,0 +1,82 @@ +package dataframe + +import ( + "strings" + "testing" +) + +func TestRootValueModesCompileToDistinctShapes(t *testing.T) { + for mode, want := range map[string]string{ + "FIRST": "FIRST(", + "ALL": "FOR __root", + "DISTINCT": "UNIQUE(", + } { + t.Run(mode, func(t *testing.T) { + compiled, err := CompileRequest(Builder{ + Project: "P1", + RootResourceType: "Patient", + Fields: []FieldSelect{{ + Name: "identifier", Select: "identifier[].value", ValueMode: mode, + }}, + }, 1) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(compiled.Query, want) { + t.Fatalf("%s query missing %q:\n%s", mode, want, compiled.Query) + } + }) + } +} + +func TestGenericTraversalValueModesLowerToPhysicalOperations(t *testing.T) { + for mode, wantOperation := range map[string]string{ + "FIRST": DerivedOpFirstNonNull, + "ALL": DerivedOpAll, + "DISTINCT": DerivedOpUnique, + "AUTO": DerivedOpFirstNonNull, + } { + t.Run(mode, func(t *testing.T) { + planned, err := lowerGenericGraphQLBuilder(Builder{}, buildLogicalRequest(Builder{ + Project: "P1", RootResourceType: "Patient", + Traversals: []TraversalStep{{ + Label: "subject_Patient", ToResourceType: "Condition", Alias: "condition", + Fields: []FieldSelect{{Name: "code", Select: "code.coding[].display", ValueMode: mode}}, + }}, + })) + if err != nil { + t.Fatal(err) + } + if len(planned.DerivedFields) != 1 || planned.DerivedFields[0].Operation != wantOperation { + t.Fatalf("%s derived fields = %#v, want %s", mode, planned.DerivedFields, wantOperation) + } + }) + } +} + +func TestGenericFirstLikeTraversalSelectionSortsSourceSetByStableKey(t *testing.T) { + for _, mode := range []string{"FIRST", "AUTO"} { + t.Run(mode, func(t *testing.T) { + planned, err := Lower(Builder{ + Project: "P1", RootResourceType: "Specimen", + Traversals: []TraversalStep{{ + Label: "subject_Specimen", ToResourceType: "DocumentReference", Alias: "file", + Fields: []FieldSelect{{Name: "title", Select: "content[].attachment.title", ValueMode: mode}}, + }}, + }) + if err != nil { + t.Fatal(err) + } + if len(planned.Sets) != 1 || planned.Sets[0].SortField != "_key" { + t.Fatalf("%s traversal did not request a stable source order: %#v", mode, planned.Sets) + } + compiled, err := Compile(planned, 1) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(compiled.Query, "SORT __item._key") { + t.Fatalf("%s traversal query does not sort its source set:\n%s", mode, compiled.Query) + } + }) + } +} diff --git a/internal/dataframebuilder/active_generation.go b/internal/dataframebuilder/active_generation.go new file mode 100644 index 0000000..a07ff65 --- /dev/null +++ b/internal/dataframebuilder/active_generation.go @@ -0,0 +1,22 @@ +package dataframebuilder + +import ( + "context" + "fmt" + + "github.com/calypr/loom/internal/dataset" +) + +// resolveActiveGeneration pins builder-side catalog discovery to the exact +// READY manifest selected for this request. Without a configured resolver the +// legacy catalog namespace remains the explicit empty generation. +func (s *Service) resolveActiveGeneration(ctx context.Context, project string) (string, error) { + if s == nil || s.activeManifestResolver == nil { + return "", nil + } + manifest, err := dataset.ResolveReadyActiveManifest(ctx, s.activeManifestResolver, project) + if err != nil { + return "", fmt.Errorf("resolve active dataset generation: %w", err) + } + return manifest.Dataset.Generation, nil +} diff --git a/internal/dataframebuilder/active_generation_test.go b/internal/dataframebuilder/active_generation_test.go new file mode 100644 index 0000000..7a6c32f --- /dev/null +++ b/internal/dataframebuilder/active_generation_test.go @@ -0,0 +1,212 @@ +package dataframebuilder + +import ( + "context" + "strings" + "testing" + + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/dataframe" + "github.com/calypr/loom/internal/dataset" + "github.com/calypr/loom/internal/discovery" + "github.com/calypr/loom/internal/graphqlapi/model" + "github.com/calypr/loom/internal/recipe" +) + +type builderActiveManifestResolver struct { + manifest dataset.Manifest + projects []string +} + +type builderActiveResourceAccess struct{} + +func (builderActiveResourceAccess) GetAllowedResources(context.Context, string, string, string) ([]string, error) { + return []string{"/programs/example/projects/allowed"}, nil +} + +func (r *builderActiveManifestResolver) ResolveActiveManifest(_ context.Context, project string) (dataset.Manifest, error) { + r.projects = append(r.projects, project) + return r.manifest.Clone(), nil +} + +func builderReadyManifest(t *testing.T, project, generation string) dataset.Manifest { + t.Helper() + schema, err := dataset.NewSchemaIdentitySnapshot( + "urn:loom:dataframebuilder-active-test", + "", + strings.Repeat("b", 64), + []string{"Patient", "Specimen"}, + ) + if err != nil { + t.Fatalf("NewSchemaIdentitySnapshot() error = %v", err) + } + ref, err := dataset.NewDatasetRef(project, generation) + if err != nil { + t.Fatalf("NewDatasetRef() error = %v", err) + } + manifest, err := dataset.NewManifest(ref, schema) + if err != nil { + t.Fatalf("NewManifest() error = %v", err) + } + for _, state := range []dataset.ManifestState{ + dataset.ManifestStateLoading, + dataset.ManifestStateAnalyzing, + dataset.ManifestStateReady, + } { + manifest, err = manifest.Transition(state) + if err != nil { + t.Fatalf("Transition(%s) error = %v", state, err) + } + } + return manifest +} + +func TestActiveGenerationPropagatesThroughBuilderCatalogEntrypoints(t *testing.T) { + const project = "project-a" + const generation = "generation-a" + active := &builderActiveManifestResolver{manifest: builderReadyManifest(t, project, generation)} + var fieldCalls []catalog.PopulatedFieldOptions + var referenceCalls []catalog.PopulatedReferenceOptions + + discoverFields := func(_ context.Context, options catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + fieldCalls = append(fieldCalls, options) + if options.PivotOnly { + return []catalog.PopulatedField{}, nil + } + switch options.ResourceType { + case "", "Patient": + return []catalog.PopulatedField{{ + Project: project, ResourceType: "Patient", Path: "gender", Kind: "scalar", DocCount: 2, + DistinctValues: []string{"female", "male"}, + }}, nil + case "Specimen": + return []catalog.PopulatedField{{Project: project, ResourceType: "Specimen", Path: "id", Kind: "scalar", DocCount: 1}}, nil + default: + return []catalog.PopulatedField{}, nil + } + } + discoverReferences := func(_ context.Context, options catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + referenceCalls = append(referenceCalls, options) + return []catalog.PopulatedReference{{FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 1}}, nil + } + dataframes := dataframe.NewService(dataframe.ServiceConfig{ + ActiveManifestResolver: active, + DiscoverFields: discoverFields, + DiscoverReferences: discoverReferences, + ExecuteRows: func(_ context.Context, _ dataframe.ExecuteQueryOptions, _ string, bindVars map[string]any, _ func(map[string]any) error) error { + if got := bindVars["dataset_generation"]; got != generation { + t.Fatalf("dataframe execution generation = %#v, want %q", got, generation) + } + return nil + }, + }) + service := NewService(Config{ + ActiveManifestResolver: active, + DiscoverFields: discoverFields, + DiscoverReferences: discoverReferences, + Dataframes: dataframes, + }) + + if _, err := service.Run(context.Background(), model.FhirDataframeInput{ + Project: project, RootResourceType: "Patient", + }, nil); err != nil { + t.Fatalf("Run() error = %v", err) + } + if _, err := service.PrepareRunInput(context.Background(), model.FhirDataframeInput{ + Project: project, RootResourceType: "Patient", + }); err != nil { + t.Fatalf("PrepareRunInput() error = %v", err) + } + if _, err := service.Introspect(context.Background(), IntrospectionRequest{ + Project: project, RootResourceType: "Patient", + }); err != nil { + t.Fatalf("Introspect() error = %v", err) + } + if _, err := service.DiscoverGuided(context.Background(), GuidedDiscoveryRequest{Project: project}); err != nil { + t.Fatalf("DiscoverGuided() error = %v", err) + } + + facts := discovery.CatalogFacts{ + Project: project, + Fields: []catalog.PopulatedField{{ + Project: project, ResourceType: "Patient", Path: "gender", Kind: "scalar", DocCount: 2, + DistinctValues: []string{"female", "male"}, + }}, + } + snapshot, err := discovery.BuildSnapshot(facts) + if err != nil { + t.Fatalf("BuildSnapshot() error = %v", err) + } + if len(snapshot.Columns) != 1 { + t.Fatalf("snapshot columns = %#v, want one gender capability", snapshot.Columns) + } + plan, err := service.PrepareRecipe(context.Background(), RecipeRequest{Recipe: recipe.Recipe{ + Version: recipe.VersionV1, + Template: recipe.TemplatePatientCohort, + TemplateVersion: 1, + Project: project, + GenerationPolicy: recipe.GenerationLatest, + Grain: recipe.GrainPatient, + Columns: []recipe.ColumnSelection{{ID: string(snapshot.Columns[0].ID)}}, + Destination: recipe.Destination{Type: recipe.DestinationPreview}, + }}) + if err != nil { + t.Fatalf("PrepareRecipe() error = %v", err) + } + if plan.Builder.DatasetGeneration != generation { + t.Fatalf("prepared recipe generation = %q, want %q", plan.Builder.DatasetGeneration, generation) + } + + if len(active.projects) < 6 { + t.Fatalf("active resolver calls = %#v, want one selection for each builder/dataframe entrypoint", active.projects) + } + if len(fieldCalls) == 0 || len(referenceCalls) == 0 { + t.Fatalf("catalog calls fields=%d references=%d, want both", len(fieldCalls), len(referenceCalls)) + } + for index, options := range fieldCalls { + if options.Project != project || options.DatasetGeneration != generation { + t.Fatalf("field catalog call %d = %+v, want %s/%s", index, options, project, generation) + } + } + for index, options := range referenceCalls { + if options.Project != project || options.DatasetGeneration != generation { + t.Fatalf("reference catalog call %d = %+v, want %s/%s", index, options, project, generation) + } + } +} + +func TestBuilderActiveGenerationKeepsRestrictedEmptyScopeForGuidedCatalog(t *testing.T) { + const project = "project-a" + const generation = "generation-a" + scopeResolver := authscope.NewScopeResolver(authscope.ScopeResolverConfig{ + ResourceAccess: builderActiveResourceAccess{}, + ListExistingAuthResourcePaths: func(_ context.Context, options catalog.AuthResourcePathOptions) ([]string, error) { + if options.Project != project || options.DatasetGeneration != generation { + t.Fatalf("generation-aware scope options = %+v, want %s/%s", options, project, generation) + } + return []string{"example-unrelated"}, nil + }, + }) + assertRestricted := func(unrestricted *bool, paths []string, gotGeneration string) { + if gotGeneration != generation || unrestricted == nil || *unrestricted || len(paths) != 0 { + t.Fatalf("restricted empty catalog scope generation=%q unrestricted=%#v paths=%#v", gotGeneration, unrestricted, paths) + } + } + service := NewService(Config{ + ActiveManifestResolver: &builderActiveManifestResolver{manifest: builderReadyManifest(t, project, generation)}, + ScopeResolver: scopeResolver, + DiscoverFields: func(_ context.Context, options catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + assertRestricted(options.AuthResourcePathsUnrestricted, options.AuthResourcePaths, options.DatasetGeneration) + return []catalog.PopulatedField{}, nil + }, + DiscoverReferences: func(_ context.Context, options catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + assertRestricted(options.AuthResourcePathsUnrestricted, options.AuthResourcePaths, options.DatasetGeneration) + return []catalog.PopulatedReference{}, nil + }, + }) + ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{AuthorizationHeader: "Bearer header.payload.signature"}) + if _, err := service.DiscoverGuided(ctx, GuidedDiscoveryRequest{Project: project}); err != nil { + t.Fatalf("DiscoverGuided() error = %v", err) + } +} diff --git a/internal/dataframebuilder/auth_scope_test.go b/internal/dataframebuilder/auth_scope_test.go new file mode 100644 index 0000000..5ed67c4 --- /dev/null +++ b/internal/dataframebuilder/auth_scope_test.go @@ -0,0 +1,155 @@ +package dataframebuilder + +import ( + "context" + "testing" + + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/dataframe" + "github.com/calypr/loom/internal/graphqlapi/model" +) + +type dataframeBuilderRestrictedEmptyResourceAccess struct{} + +func (dataframeBuilderRestrictedEmptyResourceAccess) GetAllowedResources(context.Context, string, string, string) ([]string, error) { + return []string{"/programs/example/projects/allowed"}, nil +} + +func dataframeBuilderRestrictedEmptyScopeResolver() *authscope.ScopeResolver { + return authscope.NewScopeResolver(authscope.ScopeResolverConfig{ + ResourceAccess: dataframeBuilderRestrictedEmptyResourceAccess{}, + ListExistingAuthResourcePaths: func(context.Context, catalog.AuthResourcePathOptions) ([]string, error) { + return []string{"example-different"}, nil + }, + }) +} + +func dataframeBuilderRestrictedEmptyContext() context.Context { + return authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{ + AuthorizationHeader: "Bearer header.payload.signature", + }) +} + +func TestRunPreservesRestrictedEmptyScopeIntoDataframeService(t *testing.T) { + resolver := dataframeBuilderRestrictedEmptyScopeResolver() + preparedCatalogCalls := 0 + dataframeCatalogCalls := 0 + + dataframes := dataframe.NewService(dataframe.ServiceConfig{ + // This intentionally has no ScopeResolver. It proves the marker carried + // by dataframebuilder survives into a separately configured dataframe + // service instead of being reinterpreted as unrestricted. + DiscoverFields: func(_ context.Context, options catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + dataframeCatalogCalls++ + assertRestrictedEmptyFieldScope(t, options) + return []catalog.PopulatedField{}, nil + }, + DiscoverReferences: func(_ context.Context, options catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + assertRestrictedEmptyReferenceScope(t, options) + return []catalog.PopulatedReference{}, nil + }, + ExecuteRows: func(_ context.Context, _ dataframe.ExecuteQueryOptions, _ string, bindVars map[string]any, _ func(map[string]any) error) error { + if got, ok := bindVars["auth_resource_paths_unrestricted"].(bool); !ok || got { + t.Fatalf("dataframe AQL unrestricted bind = %#v, want false", bindVars["auth_resource_paths_unrestricted"]) + } + return nil + }, + }) + service := NewService(Config{ + ScopeResolver: resolver, + DiscoverFields: func(_ context.Context, options catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + preparedCatalogCalls++ + assertRestrictedEmptyFieldScope(t, options) + return []catalog.PopulatedField{}, nil + }, + Dataframes: dataframes, + }) + + result, err := service.Run(dataframeBuilderRestrictedEmptyContext(), model.FhirDataframeInput{ + Project: "P1", + RootResourceType: "Patient", + }, nil) + if err != nil { + t.Fatalf("Run() error = %v", err) + } + if result.RowCount != 0 { + t.Fatalf("result row count = %d, want no fake rows", result.RowCount) + } + if preparedCatalogCalls == 0 || dataframeCatalogCalls == 0 { + t.Fatalf("catalog calls = prepared %d dataframe %d, want both paths", preparedCatalogCalls, dataframeCatalogCalls) + } +} + +func TestIntrospectAndGuidedDiscoveryKeepRestrictedEmptyCatalogMode(t *testing.T) { + resolver := dataframeBuilderRestrictedEmptyScopeResolver() + fieldCalls := 0 + referenceCalls := 0 + service := NewService(Config{ + ScopeResolver: resolver, + DiscoverFields: func(_ context.Context, options catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + fieldCalls++ + assertRestrictedEmptyFieldScope(t, options) + return []catalog.PopulatedField{}, nil + }, + DiscoverReferences: func(_ context.Context, options catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + referenceCalls++ + assertRestrictedEmptyReferenceScope(t, options) + return []catalog.PopulatedReference{}, nil + }, + }) + ctx := dataframeBuilderRestrictedEmptyContext() + + if _, err := service.Introspect(ctx, IntrospectionRequest{Project: "P1", RootResourceType: "Patient"}); err != nil { + t.Fatalf("Introspect() error = %v", err) + } + if _, err := service.DiscoverGuided(ctx, GuidedDiscoveryRequest{Project: "P1"}); err != nil { + t.Fatalf("DiscoverGuided() error = %v", err) + } + if fieldCalls == 0 || referenceCalls == 0 { + t.Fatalf("catalog calls = fields %d references %d, want both", fieldCalls, referenceCalls) + } +} + +func TestPrepareRecipeKeepsRestrictedEmptyCatalogMode(t *testing.T) { + facts := recipeServiceFacts() + genderID := recipeServiceCapabilityID(t, facts, "Patient", "gender") + service := NewService(Config{ + ScopeResolver: dataframeBuilderRestrictedEmptyScopeResolver(), + DiscoverFields: func(_ context.Context, options catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + assertRestrictedEmptyFieldScope(t, options) + return append([]catalog.PopulatedField(nil), facts.Fields...), nil + }, + }) + + plan, err := service.PrepareRecipe(dataframeBuilderRestrictedEmptyContext(), RecipeRequest{Recipe: recipePreview(genderID)}) + if err != nil { + t.Fatalf("PrepareRecipe() error = %v", err) + } + if plan.Builder.AuthScopeMode != authscope.ReadScopeRestricted { + t.Fatalf("prepared recipe scope mode = %q, want restricted", plan.Builder.AuthScopeMode) + } + if len(plan.Builder.AuthResourcePaths) != 0 { + t.Fatalf("prepared recipe paths = %#v, want empty", plan.Builder.AuthResourcePaths) + } +} + +func assertRestrictedEmptyFieldScope(t *testing.T, options catalog.PopulatedFieldOptions) { + t.Helper() + if options.AuthResourcePathsUnrestricted == nil || *options.AuthResourcePathsUnrestricted { + t.Fatalf("field catalog scope = %#v, want explicit false", options.AuthResourcePathsUnrestricted) + } + if len(options.AuthResourcePaths) != 0 { + t.Fatalf("field catalog paths = %#v, want empty", options.AuthResourcePaths) + } +} + +func assertRestrictedEmptyReferenceScope(t *testing.T, options catalog.PopulatedReferenceOptions) { + t.Helper() + if options.AuthResourcePathsUnrestricted == nil || *options.AuthResourcePathsUnrestricted { + t.Fatalf("reference catalog scope = %#v, want explicit false", options.AuthResourcePathsUnrestricted) + } + if len(options.AuthResourcePaths) != 0 { + t.Fatalf("reference catalog paths = %#v, want empty", options.AuthResourcePaths) + } +} diff --git a/internal/dataframebuilder/guided_discovery.go b/internal/dataframebuilder/guided_discovery.go new file mode 100644 index 0000000..e8bd77e --- /dev/null +++ b/internal/dataframebuilder/guided_discovery.go @@ -0,0 +1,79 @@ +package dataframebuilder + +import ( + "context" + "fmt" + "strings" + + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/discovery" +) + +// GuidedDiscoveryRequest describes the small project/scope input needed to +// power the product's first questions. It intentionally has no FHIR paths, +// root choice, or AQL fragments: those are derived from the scoped catalog and +// generated FHIR metadata. +type GuidedDiscoveryRequest struct { + Project string + AuthResourcePaths []string +} + +// DiscoverGuided returns a safe, schema-backed capability snapshot for the +// guided dataframe flow. It composes the existing project- and +// auth-scope-aware catalog queries, then removes their implementation details +// behind opaque IDs in internal/discovery. It is not a public transport API +// yet; GraphQL/HTTP exposure remains deliberately unwired while generation +// selection is an internal service dependency. +func (s *Service) DiscoverGuided(ctx context.Context, req GuidedDiscoveryRequest) (discovery.Snapshot, error) { + project := strings.TrimSpace(req.Project) + if project == "" { + return discovery.Snapshot{}, fmt.Errorf("project is required") + } + + principal, _ := authscope.PrincipalFromContext(ctx) + if err := authorizeProject(principal, project, s.scopeResolver != nil); err != nil { + return discovery.Snapshot{}, err + } + generation, err := s.resolveActiveGeneration(ctx, project) + if err != nil { + return discovery.Snapshot{}, err + } + scope, err := s.resolveReadScopeForGeneration(ctx, principal, project, generation, req.AuthResourcePaths) + if err != nil { + return discovery.Snapshot{}, err + } + + fields, err := s.discoverFields(ctx, catalog.PopulatedFieldOptions{ + ConnectionOptions: s.connOpts, + Project: project, + DatasetGeneration: generation, + AuthResourcePathsUnrestricted: catalog.ExplicitAuthResourcePathsUnrestricted(scope.Unrestricted()), + AuthResourcePaths: cloneStrings(scope.AuthResourcePaths), + // An empty resource type is the existing catalog reader's all-types + // query. Discovery filters the result back through generated FHIR + // metadata before anything leaves this service. + ResourceType: "", + PivotOnly: false, + }) + if err != nil { + return discovery.Snapshot{}, err + } + relationships, err := s.discoverReferences(ctx, catalog.PopulatedReferenceOptions{ + ConnectionOptions: s.connOpts, + Project: project, + DatasetGeneration: generation, + AuthResourcePathsUnrestricted: catalog.ExplicitAuthResourcePathsUnrestricted(scope.Unrestricted()), + AuthResourcePaths: cloneStrings(scope.AuthResourcePaths), + Mode: catalog.TraversalModeStorage, + }) + if err != nil { + return discovery.Snapshot{}, err + } + + return discovery.BuildSnapshot(discovery.CatalogFacts{ + Project: project, + Fields: fields, + Relationships: relationships, + }) +} diff --git a/internal/dataframebuilder/guided_discovery_test.go b/internal/dataframebuilder/guided_discovery_test.go new file mode 100644 index 0000000..d852fb4 --- /dev/null +++ b/internal/dataframebuilder/guided_discovery_test.go @@ -0,0 +1,76 @@ +package dataframebuilder + +import ( + "context" + "testing" + + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/catalog" +) + +func TestServiceDiscoverGuidedUsesResolvedScopeAndExistingCatalogQueries(t *testing.T) { + var gotFieldOptions catalog.PopulatedFieldOptions + var gotReferenceOptions catalog.PopulatedReferenceOptions + service := NewService(Config{ + DiscoverFields: func(_ context.Context, options catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + gotFieldOptions = options + return []catalog.PopulatedField{ + {Project: options.Project, ResourceType: "Patient", Path: "gender", Kind: "scalar", DocCount: 3, DistinctValues: []string{"female", "male"}}, + }, nil + }, + DiscoverReferences: func(_ context.Context, options catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + gotReferenceOptions = options + return []catalog.PopulatedReference{ + {FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 3}, + }, nil + }, + }) + ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{ + Subject: "user-1", + Projects: []string{"project-a"}, + AuthResourcePaths: []string{"scope-a", "scope-b"}, + }) + + snapshot, err := service.DiscoverGuided(ctx, GuidedDiscoveryRequest{Project: " project-a "}) + if err != nil { + t.Fatalf("DiscoverGuided() error = %v", err) + } + if gotFieldOptions.Project != "project-a" || gotFieldOptions.ResourceType != "" || gotFieldOptions.PivotOnly { + t.Fatalf("field options = %+v, want all scoped catalog fields", gotFieldOptions) + } + if len(gotFieldOptions.AuthResourcePaths) != 2 || gotFieldOptions.AuthResourcePaths[0] != "scope-a" || gotFieldOptions.AuthResourcePaths[1] != "scope-b" { + t.Fatalf("field auth scope = %#v", gotFieldOptions.AuthResourcePaths) + } + if gotReferenceOptions.Project != "project-a" || gotReferenceOptions.Mode != catalog.TraversalModeStorage || gotReferenceOptions.FromType != "" || gotReferenceOptions.NodeType != "" { + t.Fatalf("reference options = %+v, want all scoped storage relationships", gotReferenceOptions) + } + if err := snapshot.Validate(); err != nil { + t.Fatalf("snapshot validation = %v", err) + } + if snapshot.Dataset.Project != "project-a" || len(snapshot.Columns) != 1 || len(snapshot.Relationships.Entries) != 1 || len(snapshot.Filters) != 1 { + t.Fatalf("guided snapshot = %+v", snapshot) + } +} + +func TestServiceDiscoverGuidedRejectsUnauthorizedProjectAndScope(t *testing.T) { + service := NewService(Config{ + DiscoverFields: func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + return nil, nil + }, + DiscoverReferences: func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + return nil, nil + }, + }) + ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{ + Subject: "user-1", + Projects: []string{"project-a"}, + AuthResourcePaths: []string{"scope-a"}, + }) + + if _, err := service.DiscoverGuided(ctx, GuidedDiscoveryRequest{Project: "project-b"}); err == nil { + t.Fatal("expected unauthorized project error") + } + if _, err := service.DiscoverGuided(ctx, GuidedDiscoveryRequest{Project: "project-a", AuthResourcePaths: []string{"scope-b"}}); err == nil { + t.Fatal("expected unauthorized auth scope error") + } +} diff --git a/internal/dataframebuilder/input_resolution.go b/internal/dataframebuilder/input_resolution.go index e04eba4..53694a6 100644 --- a/internal/dataframebuilder/input_resolution.go +++ b/internal/dataframebuilder/input_resolution.go @@ -11,58 +11,74 @@ import ( ) func (s *Service) PrepareRunInput(ctx context.Context, input model.FhirDataframeInput) (model.FhirDataframeInput, error) { + prepared, _, _, err := s.prepareRunInput(ctx, input) + return prepared, err +} + +// prepareRunInput resolves field references and returns the effective scope +// and selected generation alongside the GraphQL-shaped input. The public +// PrepareRunInput wrapper keeps its compatibility return type, while Run uses +// this private form so it can carry a restricted empty scope and generation +// into dataframe.Builder without exposing generation in GraphQL. +func (s *Service) prepareRunInput(ctx context.Context, input model.FhirDataframeInput) (model.FhirDataframeInput, authscope.ReadScope, string, error) { if input.Project == "" { - return input, fmt.Errorf("project is required") + return input, authscope.ReadScope{}, "", fmt.Errorf("project is required") } if input.RootResourceType == "" { - return input, fmt.Errorf("rootResourceType is required") + return input, authscope.ReadScope{}, "", fmt.Errorf("rootResourceType is required") } principal, _ := authscope.PrincipalFromContext(ctx) - resolvedPaths, err := s.resolveAuthResourcePaths(ctx, principal, input.Project, input.AuthResourcePaths) + if err := authorizeProject(principal, input.Project, s.scopeResolver != nil); err != nil { + return input, authscope.ReadScope{}, "", err + } + generation, err := s.resolveActiveGeneration(ctx, input.Project) if err != nil { - return input, err + return input, authscope.ReadScope{}, "", err } - if err := authorizeProject(principal, input.Project, s.scopeResolver != nil); err != nil { - return input, err + scope, err := s.resolveReadScopeForGeneration(ctx, principal, input.Project, generation, input.AuthResourcePaths) + if err != nil { + return input, authscope.ReadScope{}, "", err } - input.AuthResourcePaths = resolvedPaths + input.AuthResourcePaths = cloneStrings(scope.AuthResourcePaths) if len(input.AuthResourcePaths) == 0 { input.AuthResourcePaths = nil } - if err := s.resolveNodeInputRefs(ctx, input.Project, input.AuthResourcePaths, input.RootResourceType, input.RootFields, input.RootPivots, input.RootAggregates, input.RootSlices); err != nil { - return input, err + if err := s.resolveNodeInputRefs(ctx, input.Project, generation, scope, input.RootResourceType, input.RootFields, input.RootPivots, input.RootAggregates, input.RootSlices); err != nil { + return input, authscope.ReadScope{}, "", err } for _, step := range input.Traverse { - if err := s.resolveTraversalInputRefs(ctx, input.Project, input.AuthResourcePaths, step); err != nil { - return input, err + if err := s.resolveTraversalInputRefs(ctx, input.Project, generation, scope, step); err != nil { + return input, authscope.ReadScope{}, "", err } } - return input, nil + return input, scope.Clone(), generation, nil } -func (s *Service) resolveTraversalInputRefs(ctx context.Context, project string, authResourcePaths []string, step *model.FhirTraversalStepInput) error { +func (s *Service) resolveTraversalInputRefs(ctx context.Context, project, datasetGeneration string, scope authscope.ReadScope, step *model.FhirTraversalStepInput) error { if step == nil { return nil } - if err := s.resolveNodeInputRefs(ctx, project, authResourcePaths, step.ToResourceType, step.Fields, step.Pivots, step.Aggregates, step.Slices); err != nil { + if err := s.resolveNodeInputRefs(ctx, project, datasetGeneration, scope, step.ToResourceType, step.Fields, step.Pivots, step.Aggregates, step.Slices); err != nil { return err } for _, child := range step.Traverse { - if err := s.resolveTraversalInputRefs(ctx, project, authResourcePaths, child); err != nil { + if err := s.resolveTraversalInputRefs(ctx, project, datasetGeneration, scope, child); err != nil { return err } } return nil } -func (s *Service) resolveNodeInputRefs(ctx context.Context, project string, authResourcePaths []string, resourceType string, fields []*model.FhirFieldSelectInput, pivots []*model.FhirPivotInput, aggregates []*model.FhirAggregateInput, slices []*model.FhirRepresentativeSliceInput) error { +func (s *Service) resolveNodeInputRefs(ctx context.Context, project, datasetGeneration string, scope authscope.ReadScope, resourceType string, fields []*model.FhirFieldSelectInput, pivots []*model.FhirPivotInput, aggregates []*model.FhirAggregateInput, slices []*model.FhirRepresentativeSliceInput) error { discovered, err := s.discoverFields(ctx, catalog.PopulatedFieldOptions{ - ConnectionOptions: s.connOpts, - Project: project, - AuthResourcePaths: authResourcePaths, - ResourceType: resourceType, + ConnectionOptions: s.connOpts, + Project: project, + DatasetGeneration: datasetGeneration, + AuthResourcePathsUnrestricted: catalog.ExplicitAuthResourcePathsUnrestricted(scope.Unrestricted()), + AuthResourcePaths: cloneStrings(scope.AuthResourcePaths), + ResourceType: resourceType, }) if err != nil { return err @@ -197,18 +213,24 @@ func authorizeProject(principal *authscope.Principal, project string, ignorePrin return fmt.Errorf("principal is not authorized for project %q", project) } -func (s *Service) resolveAuthResourcePaths(ctx context.Context, principal *authscope.Principal, project string, requested []string) ([]string, error) { +func (s *Service) resolveReadScopeForGeneration(ctx context.Context, principal *authscope.Principal, project, datasetGeneration string, requested []string) (authscope.ReadScope, error) { if s.scopeResolver != nil { - return s.scopeResolver.ResolveReadAuthResourcePaths(ctx, principal, project, requested) + return s.scopeResolver.ResolveReadScopeForGeneration(ctx, principal, project, datasetGeneration, requested) } if len(requested) == 0 { if principal == nil || len(principal.AuthResourcePaths) == 0 { - return nil, nil + return authscope.ReadScope{Mode: authscope.ReadScopeUnrestricted}, nil } - return append([]string(nil), principal.AuthResourcePaths...), nil + return authscope.ReadScope{ + AuthResourcePaths: append([]string(nil), principal.AuthResourcePaths...), + Mode: authscope.ReadScopeRestricted, + }, nil } if principal == nil || len(principal.AuthResourcePaths) == 0 { - return append([]string(nil), requested...), nil + return authscope.ReadScope{ + AuthResourcePaths: append([]string(nil), requested...), + Mode: authscope.ReadScopeRestricted, + }, nil } for _, path := range requested { found := false @@ -219,10 +241,13 @@ func (s *Service) resolveAuthResourcePaths(ctx context.Context, principal *auths } } if !found { - return nil, fmt.Errorf("authResourcePath %q is outside caller scope", path) + return authscope.ReadScope{}, fmt.Errorf("authResourcePath %q is outside caller scope", path) } } - return append([]string(nil), requested...), nil + return authscope.ReadScope{ + AuthResourcePaths: append([]string(nil), requested...), + Mode: authscope.ReadScopeRestricted, + }, nil } func selectorInputFromExpression(expression string) *model.FhirFieldSelectorInput { diff --git a/internal/dataframebuilder/introspection.go b/internal/dataframebuilder/introspection.go index 1a4cf69..4fd976e 100644 --- a/internal/dataframebuilder/introspection.go +++ b/internal/dataframebuilder/introspection.go @@ -17,30 +17,36 @@ func (s *Service) Introspect(ctx context.Context, req IntrospectionRequest) (*In } principal, _ := authscope.PrincipalFromContext(ctx) - resolvedPaths, err := s.resolveAuthResourcePaths(ctx, principal, req.Project, req.AuthResourcePaths) + if err := authorizeProject(principal, req.Project, s.scopeResolver != nil); err != nil { + return nil, err + } + generation, err := s.resolveActiveGeneration(ctx, req.Project) if err != nil { return nil, err } - if err := authorizeProject(principal, req.Project, s.scopeResolver != nil); err != nil { + scope, err := s.resolveReadScopeForGeneration(ctx, principal, req.Project, generation, req.AuthResourcePaths) + if err != nil { return nil, err } traversals, err := s.discoverReferences(ctx, catalog.PopulatedReferenceOptions{ - ConnectionOptions: s.connOpts, - Project: req.Project, - AuthResourcePaths: resolvedPaths, - NodeType: req.RootResourceType, - Mode: catalog.TraversalModeBuilder, + ConnectionOptions: s.connOpts, + Project: req.Project, + DatasetGeneration: generation, + AuthResourcePathsUnrestricted: catalog.ExplicitAuthResourcePathsUnrestricted(scope.Unrestricted()), + AuthResourcePaths: cloneStrings(scope.AuthResourcePaths), + NodeType: req.RootResourceType, + Mode: catalog.TraversalModeBuilder, }) if err != nil { return nil, err } - rootHints, err := s.buildResourceHints(ctx, req.Project, resolvedPaths, req.RootResourceType, traversals, req.IncludePivotOnlyFields) + rootHints, err := s.buildResourceHints(ctx, req.Project, generation, scope, req.RootResourceType, traversals, req.IncludePivotOnlyFields) if err != nil { return nil, err } - relatedHints, err := s.buildRelatedResourceHints(ctx, req.Project, resolvedPaths, traversals, req.IncludePivotOnlyFields) + relatedHints, err := s.buildRelatedResourceHints(ctx, req.Project, generation, scope, traversals, req.IncludePivotOnlyFields) if err != nil { return nil, err } @@ -48,7 +54,7 @@ func (s *Service) Introspect(ctx context.Context, req IntrospectionRequest) (*In return &IntrospectionResponse{ Project: req.Project, RootResourceType: req.RootResourceType, - AuthResourcePaths: resolvedPaths, + AuthResourcePaths: cloneStrings(scope.AuthResourcePaths), Root: rootHints, RelatedResources: relatedHints, Traversals: rootHints.Traversals, @@ -57,13 +63,15 @@ func (s *Service) Introspect(ctx context.Context, req IntrospectionRequest) (*In }, nil } -func (s *Service) buildResourceHints(ctx context.Context, project string, authResourcePaths []string, resourceType string, traversals []catalog.PopulatedReference, includePivotOnlyFields bool) (ResourceHints, error) { +func (s *Service) buildResourceHints(ctx context.Context, project, datasetGeneration string, scope authscope.ReadScope, resourceType string, traversals []catalog.PopulatedReference, includePivotOnlyFields bool) (ResourceHints, error) { fields, err := s.discoverFields(ctx, catalog.PopulatedFieldOptions{ - ConnectionOptions: s.connOpts, - Project: project, - AuthResourcePaths: authResourcePaths, - ResourceType: resourceType, - PivotOnly: false, + ConnectionOptions: s.connOpts, + Project: project, + DatasetGeneration: datasetGeneration, + AuthResourcePathsUnrestricted: catalog.ExplicitAuthResourcePathsUnrestricted(scope.Unrestricted()), + AuthResourcePaths: cloneStrings(scope.AuthResourcePaths), + ResourceType: resourceType, + PivotOnly: false, }) if err != nil { return ResourceHints{}, err @@ -72,11 +80,13 @@ func (s *Service) buildResourceHints(ctx context.Context, project string, authRe pivotFields := []catalog.PopulatedField{} if includePivotOnlyFields { pivotFields, err = s.discoverFields(ctx, catalog.PopulatedFieldOptions{ - ConnectionOptions: s.connOpts, - Project: project, - AuthResourcePaths: authResourcePaths, - ResourceType: resourceType, - PivotOnly: true, + ConnectionOptions: s.connOpts, + Project: project, + DatasetGeneration: datasetGeneration, + AuthResourcePathsUnrestricted: catalog.ExplicitAuthResourcePathsUnrestricted(scope.Unrestricted()), + AuthResourcePaths: cloneStrings(scope.AuthResourcePaths), + ResourceType: resourceType, + PivotOnly: true, }) if err != nil { return ResourceHints{}, err @@ -91,7 +101,7 @@ func (s *Service) buildResourceHints(ctx context.Context, project string, authRe }, nil } -func (s *Service) buildRelatedResourceHints(ctx context.Context, project string, authResourcePaths []string, traversals []catalog.PopulatedReference, includePivotOnlyFields bool) ([]RelatedResourceHints, error) { +func (s *Service) buildRelatedResourceHints(ctx context.Context, project, datasetGeneration string, scope authscope.ReadScope, traversals []catalog.PopulatedReference, includePivotOnlyFields bool) ([]RelatedResourceHints, error) { if len(traversals) == 0 { return []RelatedResourceHints{}, nil } @@ -101,7 +111,7 @@ func (s *Service) buildRelatedResourceHints(ctx context.Context, project string, for _, ref := range traversals { target, ok := typeCache[ref.ToType] if !ok { - hints, err := s.buildResourceHints(ctx, project, authResourcePaths, ref.ToType, nil, includePivotOnlyFields) + hints, err := s.buildResourceHints(ctx, project, datasetGeneration, scope, ref.ToType, nil, includePivotOnlyFields) if err != nil { return nil, err } diff --git a/internal/dataframebuilder/recipe.go b/internal/dataframebuilder/recipe.go new file mode 100644 index 0000000..0266861 --- /dev/null +++ b/internal/dataframebuilder/recipe.go @@ -0,0 +1,146 @@ +package dataframebuilder + +import ( + "context" + "fmt" + "strings" + + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/dataframe" + "github.com/calypr/loom/internal/discovery" + "github.com/calypr/loom/internal/recipe" + "github.com/calypr/loom/internal/recipecompiler" +) + +// RecipeRequest is the scoped, internal invocation envelope for a product +// recipe. Recipe itself deliberately contains no authorization paths: they are +// resolved from the calling principal at execution time instead of becoming +// durable recipe data. +// +// Column and filter values in Recipe are opaque capability IDs. This request +// accepts neither FHIR selectors nor graph labels. +type RecipeRequest struct { + Recipe recipe.Recipe + AuthResourcePaths []string +} + +// RecipeRunRequest adds a bounded dataframe-service limit to RecipeRequest. +// A non-positive limit retains dataframe.Service's existing default behavior. +// Destination delivery is intentionally outside this type: RunRecipe evaluates +// rows for callers such as a preview, but does not create files or write to +// Elasticsearch. +type RecipeRunRequest struct { + Recipe recipe.Recipe + AuthResourcePaths []string + Limit int +} + +// PrepareRecipe resolves a product recipe against fresh catalog facts for the +// caller's current project and authorization scope. It never caches facts or +// treats an opaque capability ID as a FHIR path. The returned Builder carries +// the resolved scope so its subsequent dataframe execution uses the exact same +// scope that supplied the capabilities. +// +// The current recipe compiler supports root-only selections and filters. It +// receives all currently scoped catalog fields because recipe IDs are opaque; +// narrowing the catalog read based on an untrusted recipe ID would both leak +// implementation details and make stale IDs ambiguous. +func (s *Service) PrepareRecipe(ctx context.Context, req RecipeRequest) (recipecompiler.Plan, error) { + normalized, err := req.Recipe.Normalize() + if err != nil { + return recipecompiler.Plan{}, err + } + + project := strings.TrimSpace(normalized.Project) + if project == "" { + // Normalize currently guarantees this condition, but keep the service + // boundary closed if the recipe contract changes in the future. + return recipecompiler.Plan{}, fmt.Errorf("project is required") + } + + principal, _ := authscope.PrincipalFromContext(ctx) + if err := authorizeProject(principal, project, s.scopeResolver != nil); err != nil { + return recipecompiler.Plan{}, err + } + generation, err := s.resolveActiveGeneration(ctx, project) + if err != nil { + return recipecompiler.Plan{}, err + } + scope, err := s.resolveReadScopeForGeneration(ctx, principal, project, generation, req.AuthResourcePaths) + if err != nil { + return recipecompiler.Plan{}, err + } + + fields, err := s.discoverFields(ctx, catalog.PopulatedFieldOptions{ + ConnectionOptions: s.connOpts, + Project: project, + DatasetGeneration: generation, + AuthResourcePathsUnrestricted: catalog.ExplicitAuthResourcePathsUnrestricted(scope.Unrestricted()), + AuthResourcePaths: cloneStrings(scope.AuthResourcePaths), + // Empty ResourceType is the existing catalog reader's all-types query. + // recipecompiler resolves the chosen opaque IDs against this one fresh, + // scope-constrained fact set. + ResourceType: "", + PivotOnly: false, + }) + if err != nil { + return recipecompiler.Plan{}, err + } + + plan, err := recipecompiler.Build(normalized, discovery.CatalogFacts{ + Project: project, + Fields: fields, + }) + if err != nil { + return recipecompiler.Plan{}, err + } + + // recipecompiler intentionally does not own authorization. Copy rather + // than aliasing the resolver's result so callers cannot mutate a prepared + // plan by retaining the request or resolver-owned slice. + if len(scope.AuthResourcePaths) == 0 { + plan.Builder.AuthResourcePaths = nil + } else { + plan.Builder.AuthResourcePaths = append([]string(nil), scope.AuthResourcePaths...) + } + plan.Builder.DatasetGeneration = generation + plan.Builder.AuthScopeMode = scope.Mode + return plan, nil +} + +// RunRecipe prepares fresh authorized facts and evaluates the resulting +// root-only dataframe plan through dataframe.Service. It is an execution +// primitive for preview-like callers; Recipe.Destination is validated as +// product intent but no export or Elasticsearch delivery occurs here. +func (s *Service) RunRecipe(ctx context.Context, req RecipeRunRequest) (*dataframe.Result, error) { + plan, err := s.PrepareRecipe(ctx, RecipeRequest{ + Recipe: req.Recipe, + AuthResourcePaths: req.AuthResourcePaths, + }) + if err != nil { + return nil, err + } + return s.dataframes.Run(ctx, dataframe.RunRequest{ + Builder: plan.Builder, + Limit: req.Limit, + }) +} + +// StreamRecipe prepares fresh authorized facts and forwards rows through the +// dataframe row-stream. As with RunRecipe, this does not implement any recipe +// destination sink; NDJSON, CSV, and Elasticsearch remain consumers to add on +// top of this shared stream. +func (s *Service) StreamRecipe(ctx context.Context, req RecipeRunRequest, visit func(map[string]any) error) (dataframe.StreamResult, error) { + plan, err := s.PrepareRecipe(ctx, RecipeRequest{ + Recipe: req.Recipe, + AuthResourcePaths: req.AuthResourcePaths, + }) + if err != nil { + return dataframe.StreamResult{}, err + } + return s.dataframes.Stream(ctx, dataframe.RunRequest{ + Builder: plan.Builder, + Limit: req.Limit, + }, visit) +} diff --git a/internal/dataframebuilder/recipe_test.go b/internal/dataframebuilder/recipe_test.go new file mode 100644 index 0000000..73f53ff --- /dev/null +++ b/internal/dataframebuilder/recipe_test.go @@ -0,0 +1,308 @@ +package dataframebuilder + +import ( + "context" + "errors" + "reflect" + "testing" + + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/dataframe" + "github.com/calypr/loom/internal/discovery" + "github.com/calypr/loom/internal/recipe" + "github.com/calypr/loom/internal/recipecompiler" +) + +func TestServicePrepareRecipeUsesFreshScopedCatalogFacts(t *testing.T) { + facts := recipeServiceFacts() + genderID := recipeServiceCapabilityID(t, facts, "Patient", "gender") + requestedPaths := []string{"scope-b"} + var fieldOptions []catalog.PopulatedFieldOptions + service := NewService(Config{ + DiscoverFields: func(_ context.Context, options catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + fieldOptions = append(fieldOptions, options) + return append([]catalog.PopulatedField(nil), facts.Fields...), nil + }, + }) + ctx := recipeServiceContext() + + plan, err := service.PrepareRecipe(ctx, RecipeRequest{ + Recipe: recipePreview(genderID), + AuthResourcePaths: requestedPaths, + }) + if err != nil { + t.Fatalf("PrepareRecipe() error = %v", err) + } + if len(fieldOptions) != 1 { + t.Fatalf("discover fields calls = %d, want 1", len(fieldOptions)) + } + if got := fieldOptions[0]; got.Project != "project-a" || got.ResourceType != "" || got.PivotOnly { + t.Fatalf("catalog options = %+v, want normalized all-types non-pivot read", got) + } + if got, want := fieldOptions[0].AuthResourcePaths, []string{"scope-b"}; !reflect.DeepEqual(got, want) { + t.Fatalf("catalog scope = %#v, want %#v", got, want) + } + if plan.Recipe.Project != "project-a" || plan.Builder.Project != "project-a" { + t.Fatalf("normalized project = recipe %q builder %q", plan.Recipe.Project, plan.Builder.Project) + } + if plan.Builder.RootResourceType != "Patient" || plan.Builder.RowGrain != dataframe.RowGrainPatient { + t.Fatalf("root-only recipe builder = %+v", plan.Builder) + } + if got, want := plan.Builder.AuthResourcePaths, []string{"scope-b"}; !reflect.DeepEqual(got, want) { + t.Fatalf("prepared builder scope = %#v, want %#v", got, want) + } + if len(plan.Builder.Fields) != 1 || plan.Builder.Fields[0].FieldRef != genderID || plan.Builder.Fields[0].Select != "gender" { + t.Fatalf("opaque root field did not resolve through fresh facts: %#v", plan.Builder.Fields) + } + + // Neither the request nor a resolver-owned result can mutate the prepared + // builder's authorization scope after preparation. + requestedPaths[0] = "changed-after-prepare" + if got := plan.Builder.AuthResourcePaths[0]; got != "scope-b" { + t.Fatalf("prepared builder aliases request auth scope: %q", got) + } +} + +func TestServiceRunAndStreamRecipeUsePreparedScopeWithoutDatabase(t *testing.T) { + facts := recipeServiceFacts() + genderID := recipeServiceCapabilityID(t, facts, "Patient", "gender") + var prepareOptions []catalog.PopulatedFieldOptions + var dataframeOptions []catalog.PopulatedFieldOptions + var executionScopes [][]string + + dataframes := dataframe.NewService(dataframe.ServiceConfig{ + DiscoverFields: func(_ context.Context, options catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + dataframeOptions = append(dataframeOptions, options) + if options.PivotOnly { + return []catalog.PopulatedField{}, nil + } + return []catalog.PopulatedField{facts.Fields[0]}, nil // Patient.gender + }, + ExecuteRows: func(_ context.Context, _ dataframe.ExecuteQueryOptions, _ string, bindVars map[string]any, visit func(map[string]any) error) error { + paths, ok := bindVars["auth_resource_paths"].([]string) + if !ok { + t.Fatalf("auth_resource_paths bind type = %T, want []string", bindVars["auth_resource_paths"]) + } + executionScopes = append(executionScopes, append([]string(nil), paths...)) + return visit(map[string]any{"_key": "patient-1", "gender": "female"}) + }, + }) + service := NewService(Config{ + DiscoverFields: func(_ context.Context, options catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + prepareOptions = append(prepareOptions, options) + return append([]catalog.PopulatedField(nil), facts.Fields...), nil + }, + Dataframes: dataframes, + }) + ctx := recipeServiceContext() + req := RecipeRunRequest{ + Recipe: recipePreview(genderID), + AuthResourcePaths: []string{"scope-b"}, + Limit: 7, + } + + result, err := service.RunRecipe(ctx, req) + if err != nil { + t.Fatalf("RunRecipe() error = %v", err) + } + if result.RowCount != 1 || len(result.Rows) != 1 || result.Rows[0]["gender"] != "female" { + t.Fatalf("RunRecipe result = %#v", result) + } + + streamedRows := 0 + streamed, err := service.StreamRecipe(ctx, req, func(row map[string]any) error { + streamedRows++ + if row["_key"] != "patient-1" || row["gender"] != "female" { + t.Fatalf("streamed row = %#v", row) + } + return nil + }) + if err != nil { + t.Fatalf("StreamRecipe() error = %v", err) + } + if streamed.RowCount != 1 || streamedRows != 1 { + t.Fatalf("StreamRecipe counts = result %d visitor %d", streamed.RowCount, streamedRows) + } + + if len(prepareOptions) != 2 { + t.Fatalf("fresh recipe catalog reads = %d, want one per run", len(prepareOptions)) + } + for _, options := range prepareOptions { + if options.ResourceType != "" || options.PivotOnly || !reflect.DeepEqual(options.AuthResourcePaths, []string{"scope-b"}) { + t.Fatalf("recipe catalog options = %+v", options) + } + } + if len(dataframeOptions) != 6 { // validation fields/pivots plus pivot expansion for Run and Stream + t.Fatalf("dataframe catalog reads = %d, want 6", len(dataframeOptions)) + } + for _, options := range dataframeOptions { + if options.ResourceType != "Patient" || !reflect.DeepEqual(options.AuthResourcePaths, []string{"scope-b"}) { + t.Fatalf("dataframe catalog options = %+v", options) + } + } + if got, want := executionScopes, [][]string{{"scope-b"}, {"scope-b"}}; !reflect.DeepEqual(got, want) { + t.Fatalf("query execution scopes = %#v, want %#v", got, want) + } +} + +func TestServicePrepareRecipeRejectsStaleRelatedAndRawCapabilities(t *testing.T) { + facts := recipeServiceFacts() + genderID := recipeServiceCapabilityID(t, facts, "Patient", "gender") + birthDateID := recipeServiceCapabilityID(t, facts, "Patient", "birthDate") + observationID := recipeServiceCapabilityID(t, facts, "Observation", "valueInteger") + + tests := []struct { + name string + fields []catalog.PopulatedField + recipe recipe.Recipe + want error + }{ + { + name: "stale opaque capability", + fields: []catalog.PopulatedField{facts.Fields[1]}, // Patient.birthDate, no longer gender + recipe: recipePreview(genderID), + want: recipecompiler.ErrColumnCapabilityUnavailable, + }, + { + name: "related root capability", + fields: facts.Fields, + recipe: recipePreview(genderID, observationID), + want: recipecompiler.ErrRelatedResource, + }, + { + name: "raw FHIR path is not a capability", + fields: facts.Fields, + recipe: recipePreview("gender"), + want: recipecompiler.ErrColumnCapabilityUnavailable, + }, + { + name: "unknown opaque-looking capability", + fields: facts.Fields, + recipe: recipePreview("col_0000000000000000000000000000000000000000000000000000000000000000"), + want: recipecompiler.ErrColumnCapabilityUnavailable, + }, + { + name: "fresh root capability remains accepted", + fields: facts.Fields, + recipe: recipePreview(birthDateID), + want: nil, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + service := NewService(Config{ + DiscoverFields: func(_ context.Context, _ catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + return append([]catalog.PopulatedField(nil), test.fields...), nil + }, + }) + plan, err := service.PrepareRecipe(recipeServiceContext(), RecipeRequest{Recipe: test.recipe}) + if test.want == nil { + if err != nil { + t.Fatalf("PrepareRecipe() error = %v", err) + } + if len(plan.Builder.Fields) != 1 || plan.Builder.Fields[0].Select != "birthDate" { + t.Fatalf("fresh opaque root plan = %+v", plan.Builder) + } + return + } + if !errors.Is(err, test.want) { + t.Fatalf("PrepareRecipe() error = %v, want %v", err, test.want) + } + if len(plan.Builder.Fields) != 0 || len(plan.Builder.Filters) != 0 { + t.Fatalf("failed capability resolution returned builder = %+v", plan.Builder) + } + }) + } +} + +func TestServicePrepareRecipeRejectsUnauthorizedScopeBeforeCatalogRead(t *testing.T) { + facts := recipeServiceFacts() + genderID := recipeServiceCapabilityID(t, facts, "Patient", "gender") + called := false + service := NewService(Config{ + DiscoverFields: func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + called = true + return facts.Fields, nil + }, + }) + ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{ + Projects: []string{"project-a"}, + AuthResourcePaths: []string{"scope-a"}, + }) + + _, err := service.PrepareRecipe(ctx, RecipeRequest{ + Recipe: recipePreview(genderID), + AuthResourcePaths: []string{"scope-b"}, + }) + if err == nil { + t.Fatal("expected unauthorized scope error") + } + if called { + t.Fatal("catalog read occurred before scope authorization") + } +} + +func recipeServiceFacts() discovery.CatalogFacts { + return discovery.CatalogFacts{ + Project: "project-a", + Fields: []catalog.PopulatedField{ + {Project: "project-a", ResourceType: "Patient", Path: "gender", Kind: "scalar", DocCount: 3, DistinctValues: []string{"female", "male"}}, + {Project: "project-a", ResourceType: "Patient", Path: "birthDate", Kind: "scalar", DocCount: 3, DistinctValues: []string{"1970-01-01", "2000-12-31"}}, + {Project: "project-a", ResourceType: "Observation", Path: "valueInteger", Kind: "scalar", DocCount: 2, DistinctValues: []string{"12", "13"}}, + }, + } +} + +func recipeServiceCapabilityID(t *testing.T, facts discovery.CatalogFacts, resourceType string, canonicalPath string) string { + t.Helper() + snapshot, err := discovery.BuildSnapshot(facts) + if err != nil { + t.Fatalf("BuildSnapshot() error = %v", err) + } + resolver, err := discovery.NewCapabilityResolver(facts) + if err != nil { + t.Fatalf("NewCapabilityResolver() error = %v", err) + } + for _, column := range snapshot.Columns { + resolved, err := resolver.ResolveColumn(column.ID) + if err != nil { + t.Fatalf("ResolveColumn(%q) error = %v", column.ID, err) + } + if resolved.ResourceType == resourceType && resolved.CanonicalPath == canonicalPath { + return string(column.ID) + } + } + t.Fatalf("no opaque capability for %s.%s", resourceType, canonicalPath) + return "" +} + +func recipePreview(columnIDs ...string) recipe.Recipe { + columns := make([]recipe.ColumnSelection, 0, len(columnIDs)) + for index, id := range columnIDs { + name := "column" + if index == 0 { + name = "gender" + } + columns = append(columns, recipe.ColumnSelection{ID: id, OutputName: name}) + } + return recipe.Recipe{ + Version: recipe.VersionV1, + Template: recipe.TemplatePatientCohort, + TemplateVersion: 1, + Project: " project-a ", + GenerationPolicy: recipe.GenerationLatest, + Grain: recipe.GrainPatient, + Columns: columns, + Destination: recipe.Destination{Type: recipe.DestinationPreview}, + } +} + +func recipeServiceContext() context.Context { + return authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{ + Subject: "recipe-user", + Projects: []string{"project-a"}, + AuthResourcePaths: []string{"scope-a", "scope-b"}, + }) +} diff --git a/internal/dataframebuilder/service.go b/internal/dataframebuilder/service.go index 404eac7..fb2e13e 100644 --- a/internal/dataframebuilder/service.go +++ b/internal/dataframebuilder/service.go @@ -6,16 +6,18 @@ import ( "github.com/calypr/loom/internal/authscope" "github.com/calypr/loom/internal/catalog" "github.com/calypr/loom/internal/dataframe" + "github.com/calypr/loom/internal/dataset" "github.com/calypr/loom/internal/graphqlapi/model" arangostore "github.com/calypr/loom/internal/store/arango" ) type Service struct { - connOpts arangostore.ConnectionOptions - discoverReferences func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) - discoverFields func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) - dataframes *dataframe.Service - scopeResolver *authscope.ScopeResolver + connOpts arangostore.ConnectionOptions + discoverReferences func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) + discoverFields func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) + dataframes *dataframe.Service + scopeResolver *authscope.ScopeResolver + activeManifestResolver dataset.ActiveManifestResolver } type Config struct { @@ -24,12 +26,17 @@ type Config struct { DiscoverFields func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) Dataframes *dataframe.Service ScopeResolver *authscope.ScopeResolver + // ActiveManifestResolver is optional. When present, builder catalog + // discovery and recipe preparation resolve one READY active generation + // before inspecting any fields or relationship routes. + ActiveManifestResolver dataset.ActiveManifestResolver } func NewService(cfg Config) *Service { service := &Service{ - connOpts: cfg.ConnectionOptions, - scopeResolver: cfg.ScopeResolver, + connOpts: cfg.ConnectionOptions, + scopeResolver: cfg.ScopeResolver, + activeManifestResolver: cfg.ActiveManifestResolver, } if cfg.DiscoverReferences != nil { service.discoverReferences = cfg.DiscoverReferences @@ -45,17 +52,18 @@ func NewService(cfg Config) *Service { service.dataframes = cfg.Dataframes } else { service.dataframes = dataframe.NewService(dataframe.ServiceConfig{ - ConnectionOptions: cfg.ConnectionOptions, - DiscoverReferences: service.discoverReferences, - DiscoverFields: service.discoverFields, - ScopeResolver: cfg.ScopeResolver, + ConnectionOptions: cfg.ConnectionOptions, + DiscoverReferences: service.discoverReferences, + DiscoverFields: service.discoverFields, + ScopeResolver: cfg.ScopeResolver, + ActiveManifestResolver: cfg.ActiveManifestResolver, }) } return service } func (s *Service) Run(ctx context.Context, input model.FhirDataframeInput, limit *int) (*dataframe.Result, error) { - normalizedInput, err := s.PrepareRunInput(ctx, input) + normalizedInput, scope, generation, err := s.prepareRunInput(ctx, input) if err != nil { return nil, err } @@ -65,8 +73,14 @@ func (s *Service) Run(ctx context.Context, input model.FhirDataframeInput, limit } else if normalizedInput.Limit != nil { rowLimit = *normalizedInput.Limit } + builder := BuilderFromInput(normalizedInput) + builder.DatasetGeneration = generation + // Preserve the scope mode that resolved the catalog references above. This + // matters when no catalog paths survive a restricted caller's intersection: + // an empty list alone would otherwise be legacy-unrestricted downstream. + builder.AuthScopeMode = scope.Mode return s.dataframes.Run(ctx, dataframe.RunRequest{ - Builder: BuilderFromInput(normalizedInput), + Builder: builder, Limit: rowLimit, }) } diff --git a/internal/dataframeexport/doc.go b/internal/dataframeexport/doc.go new file mode 100644 index 0000000..089c8b8 --- /dev/null +++ b/internal/dataframeexport/doc.go @@ -0,0 +1,16 @@ +// Package dataframeexport connects validated dataframe execution to the +// row-only export encoders. +// +// It deliberately owns neither dataframe compilation nor artifact storage, +// jobs, delivery transports, or destination-specific behavior. A RowStream +// calls its Runner for every invocation. With a *dataframe.Service, the +// RunRequest is therefore catalog- and authorization-validated as part of +// each execution; this package neither caches that validation nor collects +// result rows. +// +// Inferred CSV columns require two executions: one to discover the column +// union and one to write rows. Those executions must observe the same logical +// dataframe and ordering, which requires an externally stable dataset +// generation or snapshot. Loom does not provide that generation/snapshot +// contract yet. Supplying explicit CSV columns uses exactly one execution. +package dataframeexport diff --git a/internal/dataframeexport/stream.go b/internal/dataframeexport/stream.go new file mode 100644 index 0000000..41ccfdc --- /dev/null +++ b/internal/dataframeexport/stream.go @@ -0,0 +1,65 @@ +package dataframeexport + +import ( + "context" + "errors" + "fmt" + "io" + + "github.com/calypr/loom/internal/dataframe" + "github.com/calypr/loom/internal/export" +) + +var errRunnerRequired = errors.New("dataframe stream runner is required") + +// Runner is the narrow dataframe execution boundary needed for export. It is +// satisfied by *dataframe.Service. Keeping it small lets callers retain the +// dataframe service's existing validation, authorization, and streaming +// behavior without coupling export code to service construction. +type Runner interface { + Stream(context.Context, dataframe.RunRequest, func(map[string]any) error) (dataframe.StreamResult, error) +} + +// NewRowStream creates an export.RowStream backed by runner for request. The +// request is passed unchanged to every invocation, and no rows are buffered or +// copied by this adapter. A dataframe.Service validates the request when each +// stream invocation begins. +// +// The returned stream preserves a runner error and a row-visitor error without +// wrapping either. It also checks cancellation before invoking the runner and +// after a successful invocation. This matters because inferred CSV executes +// the stream twice; callers need an externally stable dataset generation or +// snapshot for that mode, which Loom does not provide yet. +func NewRowStream(runner Runner, request dataframe.RunRequest) (export.RowStream, error) { + if runner == nil { + return nil, errRunnerRequired + } + + return func(ctx context.Context, visit export.RowVisitor) error { + if visit == nil { + return fmt.Errorf("export row visitor is required") + } + if err := ctx.Err(); err != nil { + return err + } + + _, err := runner.Stream(ctx, request, visit) + if err != nil { + return err + } + return ctx.Err() + }, nil +} + +// EncodeCSV writes CSV rows from request using the existing export encoder. +// Explicit options.Columns executes the dataframe request once. Omitting +// columns executes it twice (discovery, then writing), so it is safe only when +// an external caller guarantees a stable dataset generation or snapshot; Loom +// does not provide that contract yet. +func EncodeCSV(ctx context.Context, dst io.Writer, options export.CSVOptions, runner Runner, request dataframe.RunRequest) (export.Result, error) { + stream, err := NewRowStream(runner, request) + if err != nil { + return export.Result{}, err + } + return export.EncodeCSV(ctx, dst, options, stream) +} diff --git a/internal/dataframeexport/stream_test.go b/internal/dataframeexport/stream_test.go new file mode 100644 index 0000000..114ac3c --- /dev/null +++ b/internal/dataframeexport/stream_test.go @@ -0,0 +1,176 @@ +package dataframeexport + +import ( + "bytes" + "context" + "errors" + "reflect" + "testing" + + "github.com/calypr/loom/internal/dataframe" + "github.com/calypr/loom/internal/export" +) + +func TestNewRowStreamForwardsRowsAndRequest(t *testing.T) { + request := dataframe.RunRequest{ + Builder: dataframe.Builder{Project: "project-a", RootResourceType: "Patient"}, + Limit: 9, + } + runner := &fakeRunner{rows: []map[string]any{ + {"patient_id": "p1", "status": "active"}, + {"patient_id": "p2", "status": "inactive"}, + }} + stream, err := NewRowStream(runner, request) + if err != nil { + t.Fatalf("NewRowStream() error = %v", err) + } + + var got []map[string]any + err = stream(context.Background(), func(row map[string]any) error { + got = append(got, row) + return nil + }) + if err != nil { + t.Fatalf("RowStream() error = %v", err) + } + if !reflect.DeepEqual(got, runner.rows) { + t.Fatalf("forwarded rows = %#v, want %#v", got, runner.rows) + } + if runner.calls != 1 { + t.Fatalf("runner calls = %d, want 1", runner.calls) + } + if !reflect.DeepEqual(runner.requests, []dataframe.RunRequest{request}) { + t.Fatalf("runner requests = %#v, want %#v", runner.requests, []dataframe.RunRequest{request}) + } +} + +func TestNewRowStreamPreservesRunnerAndVisitorErrors(t *testing.T) { + t.Run("runner", func(t *testing.T) { + runnerErr := errors.New("runner stopped") + stream, err := NewRowStream(&fakeRunner{err: runnerErr}, dataframe.RunRequest{}) + if err != nil { + t.Fatalf("NewRowStream() error = %v", err) + } + if err := stream(context.Background(), func(map[string]any) error { return nil }); !errors.Is(err, runnerErr) { + t.Fatalf("RowStream() error = %v, want runner error", err) + } + }) + + t.Run("visitor", func(t *testing.T) { + visitorErr := errors.New("stop after first row") + stream, err := NewRowStream(&fakeRunner{rows: []map[string]any{{"id": "one"}}}, dataframe.RunRequest{}) + if err != nil { + t.Fatalf("NewRowStream() error = %v", err) + } + if err := stream(context.Background(), func(map[string]any) error { return visitorErr }); !errors.Is(err, visitorErr) { + t.Fatalf("RowStream() error = %v, want visitor error", err) + } + }) +} + +func TestNewRowStreamPreservesCanceledContextWithoutCallingRunner(t *testing.T) { + runner := &fakeRunner{rows: []map[string]any{{"id": "one"}}} + stream, err := NewRowStream(runner, dataframe.RunRequest{}) + if err != nil { + t.Fatalf("NewRowStream() error = %v", err) + } + ctx, cancel := context.WithCancel(context.Background()) + cancel() + + err = stream(ctx, func(map[string]any) error { return nil }) + if !errors.Is(err, context.Canceled) { + t.Fatalf("RowStream() error = %v, want context.Canceled", err) + } + if runner.calls != 0 { + t.Fatalf("runner calls = %d, want 0 after cancellation", runner.calls) + } +} + +func TestEncodeCSVWithExplicitColumnsRunsOneDataframeStream(t *testing.T) { + request := dataframe.RunRequest{Builder: dataframe.Builder{Project: "project-a"}, Limit: 2} + runner := &fakeRunner{rows: []map[string]any{ + {"patient_id": "p1", "status": "active"}, + {"patient_id": "p2", "status": "inactive"}, + }} + var output bytes.Buffer + + result, err := EncodeCSV(context.Background(), &output, export.CSVOptions{Columns: []string{"patient_id", "status"}}, runner, request) + if err != nil { + t.Fatalf("EncodeCSV() error = %v", err) + } + if runner.calls != 1 { + t.Fatalf("runner calls = %d, want one explicit-schema pass", runner.calls) + } + if result.Rows != 2 { + t.Fatalf("rows = %d, want 2", result.Rows) + } + if got, want := output.String(), "patient_id,status\np1,active\np2,inactive\n"; got != want { + t.Fatalf("CSV = %q, want %q", got, want) + } + if !reflect.DeepEqual(runner.requests, []dataframe.RunRequest{request}) { + t.Fatalf("runner requests = %#v, want one original request", runner.requests) + } +} + +func TestEncodeCSVWithInferredColumnsReplaysDataframeStream(t *testing.T) { + request := dataframe.RunRequest{Builder: dataframe.Builder{Project: "project-a"}, Limit: 2} + runner := &fakeRunner{rows: []map[string]any{ + {"patient_id": "p1", "status": "active"}, + {"patient_id": "p2", "status": "inactive"}, + }} + var output bytes.Buffer + + result, err := EncodeCSV(context.Background(), &output, export.CSVOptions{}, runner, request) + if err != nil { + t.Fatalf("EncodeCSV() error = %v", err) + } + if runner.calls != 2 { + t.Fatalf("runner calls = %d, want discovery and writing passes", runner.calls) + } + if result.Rows != 2 { + t.Fatalf("rows = %d, want 2 from the writing pass", result.Rows) + } + if got, want := output.String(), "patient_id,status\np1,active\np2,inactive\n"; got != want { + t.Fatalf("CSV = %q, want %q", got, want) + } + wantRequests := []dataframe.RunRequest{request, request} + if !reflect.DeepEqual(runner.requests, wantRequests) { + t.Fatalf("runner requests = %#v, want %#v", runner.requests, wantRequests) + } +} + +func TestNewRowStreamRejectsNilRunner(t *testing.T) { + stream, err := NewRowStream(nil, dataframe.RunRequest{}) + if err == nil { + t.Fatal("NewRowStream() error = nil, want runner-required error") + } + if stream != nil { + t.Fatalf("NewRowStream() stream = %v, want nil", stream) + } +} + +type fakeRunner struct { + rows []map[string]any + err error + calls int + requests []dataframe.RunRequest +} + +func (r *fakeRunner) Stream(ctx context.Context, request dataframe.RunRequest, visit func(map[string]any) error) (dataframe.StreamResult, error) { + r.calls++ + r.requests = append(r.requests, request) + var count int + for _, row := range r.rows { + if err := ctx.Err(); err != nil { + return dataframe.StreamResult{RowCount: count}, err + } + if err := visit(row); err != nil { + return dataframe.StreamResult{RowCount: count}, err + } + count++ + } + if r.err != nil { + return dataframe.StreamResult{RowCount: count}, r.err + } + return dataframe.StreamResult{RowCount: count}, nil +} diff --git a/internal/dataset/active.go b/internal/dataset/active.go new file mode 100644 index 0000000..7694b70 --- /dev/null +++ b/internal/dataset/active.go @@ -0,0 +1,182 @@ +package dataset + +import ( + "encoding/json" + "fmt" +) + +// ActiveGeneration is the project-level reference selected for reads. It is +// intentionally only a DatasetRef: resolving it against persisted manifests +// must prove that exactly one matching manifest is still READY. +type ActiveGeneration struct { + Dataset DatasetRef `json:"dataset"` +} + +// ActiveGenerationFor returns a reference only for a validated READY +// manifest. Failed, loading, preflight, and superseded generations cannot be +// activated or reactivated through this API. +func ActiveGenerationFor(manifest Manifest) (ActiveGeneration, error) { + if err := manifest.Validate(); err != nil { + return ActiveGeneration{}, err + } + if manifest.State != ManifestStateReady { + return ActiveGeneration{}, fmt.Errorf("%w: %s is %s", ErrGenerationNotReady, manifest.Dataset.Generation, manifest.State) + } + return ActiveGeneration{Dataset: manifest.Dataset}, nil +} + +// Validate checks only the reference's key representation. Read adapters must +// call ResolveActive against their persisted manifest set to verify readiness. +func (a ActiveGeneration) Validate() error { + if err := a.Dataset.Validate(); err != nil { + return fmt.Errorf("%w: %w", ErrInvalidActiveGeneration, err) + } + return nil +} + +// ResolveActive returns the single READY manifest named by active. It rejects +// missing, duplicate, failed, loading, and superseded matches, which prevents +// a caller from silently reading a different generation. +func ResolveActive(active ActiveGeneration, manifests []Manifest) (Manifest, error) { + if err := active.Validate(); err != nil { + return Manifest{}, err + } + + var matched *Manifest + for index, manifest := range manifests { + if !manifest.Dataset.Equal(active.Dataset) { + continue + } + if err := manifest.Validate(); err != nil { + return Manifest{}, fmt.Errorf("%w: matching manifest at index %d: %w", ErrInvalidActiveGeneration, index, err) + } + if matched != nil { + return Manifest{}, fmt.Errorf("%w: multiple manifests match %s/%s", ErrInvalidActiveGeneration, active.Dataset.Project, active.Dataset.Generation) + } + copy := manifest.Clone() + matched = © + } + if matched == nil { + return Manifest{}, fmt.Errorf("%w: %s/%s was not found", ErrInvalidActiveGeneration, active.Dataset.Project, active.Dataset.Generation) + } + if matched.State != ManifestStateReady { + return Manifest{}, fmt.Errorf("%w: %s/%s is %s", ErrGenerationNotReady, active.Dataset.Project, active.Dataset.Generation, matched.State) + } + return matched.Clone(), nil +} + +// ActivationPlan is a persistence-neutral description of an active-generation +// switch. A storage adapter must atomically persist Active and, when Previous +// is non-nil, supersede that previous manifest in its own transaction. +// +// This value does not claim to perform an atomic switch itself. +type ActivationPlan struct { + Active ActiveGeneration `json:"active"` + Previous *DatasetRef `json:"previous,omitempty"` +} + +// PlanActivation validates a READY candidate and an optional currently active +// READY manifest. The existing manifest is not mutated. If a replacement is +// needed, Previous names the generation a persistence adapter must supersede +// atomically with writing the new active reference. +func PlanActivation(current *Manifest, candidate Manifest) (ActivationPlan, error) { + active, err := ActiveGenerationFor(candidate) + if err != nil { + return ActivationPlan{}, err + } + plan := ActivationPlan{Active: active} + if current == nil { + return plan, nil + } + if err := current.Validate(); err != nil { + return ActivationPlan{}, err + } + if current.State != ManifestStateReady { + return ActivationPlan{}, fmt.Errorf("%w: current generation %s is %s", ErrGenerationNotReady, current.Dataset.Generation, current.State) + } + if current.Dataset.Project != candidate.Dataset.Project { + return ActivationPlan{}, fmt.Errorf("%w: current and candidate projects differ", ErrInvalidActiveGeneration) + } + if current.Dataset.Equal(candidate.Dataset) { + return plan, nil + } + previous := current.Dataset + plan.Previous = &previous + return plan, nil +} + +// Validate checks that an activation plan is internally coherent. It does not +// verify that a storage transaction was executed. +func (p ActivationPlan) Validate() error { + if err := p.Active.Validate(); err != nil { + return err + } + if p.Previous == nil { + return nil + } + if err := p.Previous.Validate(); err != nil { + return fmt.Errorf("%w: previous: %w", ErrInvalidActiveGeneration, err) + } + if p.Previous.Project != p.Active.Dataset.Project { + return fmt.Errorf("%w: previous and active projects differ", ErrInvalidActiveGeneration) + } + if p.Previous.Equal(p.Active.Dataset) { + return fmt.Errorf("%w: previous and active generations must differ", ErrInvalidActiveGeneration) + } + return nil +} + +func (a ActiveGeneration) MarshalJSON() ([]byte, error) { + if err := a.Validate(); err != nil { + return nil, err + } + return json.Marshal(activeGenerationWire{Dataset: a.Dataset}) +} + +func (a *ActiveGeneration) UnmarshalJSON(data []byte) error { + if a == nil { + return fmt.Errorf("%w: cannot unmarshal into nil ActiveGeneration", ErrInvalidActiveGeneration) + } + var decoded activeGenerationWire + if err := decodeStrictJSON(data, &decoded); err != nil { + return fmt.Errorf("%w: decode JSON: %v", ErrInvalidActiveGeneration, err) + } + value := ActiveGeneration{Dataset: decoded.Dataset} + if err := value.Validate(); err != nil { + return err + } + *a = value + return nil +} + +func (p ActivationPlan) MarshalJSON() ([]byte, error) { + if err := p.Validate(); err != nil { + return nil, err + } + return json.Marshal(activationPlanWire{Active: p.Active, Previous: p.Previous}) +} + +func (p *ActivationPlan) UnmarshalJSON(data []byte) error { + if p == nil { + return fmt.Errorf("%w: cannot unmarshal into nil ActivationPlan", ErrInvalidActiveGeneration) + } + var decoded activationPlanWire + if err := decodeStrictJSON(data, &decoded); err != nil { + return fmt.Errorf("%w: decode JSON: %v", ErrInvalidActiveGeneration, err) + } + plan := ActivationPlan{Active: decoded.Active, Previous: decoded.Previous} + if err := plan.Validate(); err != nil { + return err + } + *p = plan + return nil +} + +type activeGenerationWire struct { + Dataset DatasetRef `json:"dataset"` +} + +type activationPlanWire struct { + Active ActiveGeneration `json:"active"` + Previous *DatasetRef `json:"previous,omitempty"` +} diff --git a/internal/dataset/active_resolver.go b/internal/dataset/active_resolver.go new file mode 100644 index 0000000..0486ef8 --- /dev/null +++ b/internal/dataset/active_resolver.go @@ -0,0 +1,41 @@ +package dataset + +import ( + "context" + "fmt" +) + +// ActiveManifestResolver is the read-side persistence boundary for selecting +// a project's active dataset generation. Implementations must resolve the +// currently active pointer and return the exact READY manifest it names in one +// consistent storage read. They must not infer a generation from catalog rows +// or silently fall back to another manifest. +// +// The interface intentionally carries no authorization scope: generation +// selection is project-wide immutable metadata, while authorization remains a +// per-read concern owned by the request service. +type ActiveManifestResolver interface { + ResolveActiveManifest(context.Context, string) (Manifest, error) +} + +// ResolveReadyActiveManifest validates an ActiveManifestResolver result at the +// persistence-neutral boundary. It protects request services from a malformed +// or stale adapter result before they propagate its generation into catalog or +// dataframe work. The returned value is a defensive clone. +func ResolveReadyActiveManifest(ctx context.Context, resolver ActiveManifestResolver, project string) (Manifest, error) { + if resolver == nil { + return Manifest{}, fmt.Errorf("%w: active manifest resolver is required", ErrInvalidActiveGeneration) + } + manifest, err := resolver.ResolveActiveManifest(ctx, project) + if err != nil { + return Manifest{}, err + } + active, err := ActiveGenerationFor(manifest) + if err != nil { + return Manifest{}, fmt.Errorf("resolve active manifest for project %q: %w", project, err) + } + if active.Dataset.Project != project { + return Manifest{}, fmt.Errorf("%w: resolver returned project %q for requested project %q", ErrInvalidActiveGeneration, active.Dataset.Project, project) + } + return manifest.Clone(), nil +} diff --git a/internal/dataset/active_resolver_test.go b/internal/dataset/active_resolver_test.go new file mode 100644 index 0000000..88c0e34 --- /dev/null +++ b/internal/dataset/active_resolver_test.go @@ -0,0 +1,51 @@ +package dataset + +import ( + "context" + "errors" + "testing" +) + +type staticActiveManifestResolver struct { + manifest Manifest + err error + projects []string +} + +func (r *staticActiveManifestResolver) ResolveActiveManifest(_ context.Context, project string) (Manifest, error) { + r.projects = append(r.projects, project) + if r.err != nil { + return Manifest{}, r.err + } + return r.manifest.Clone(), nil +} + +func TestResolveReadyActiveManifestValidatesResolverBoundary(t *testing.T) { + ready := readyManifest(t, "project-a", "generation-a") + resolver := &staticActiveManifestResolver{manifest: ready} + + got, err := ResolveReadyActiveManifest(context.Background(), resolver, "project-a") + if err != nil { + t.Fatalf("ResolveReadyActiveManifest() error = %v", err) + } + if !got.Dataset.Equal(ready.Dataset) || got.State != ManifestStateReady { + t.Fatalf("resolved manifest = %#v, want READY %#v", got, ready) + } + if len(resolver.projects) != 1 || resolver.projects[0] != "project-a" { + t.Fatalf("resolver projects = %#v, want project-a", resolver.projects) + } + + wrongProject := &staticActiveManifestResolver{manifest: ready} + if _, err := ResolveReadyActiveManifest(context.Background(), wrongProject, "project-b"); !errors.Is(err, ErrInvalidActiveGeneration) { + t.Fatalf("wrong-project resolver error = %v, want ErrInvalidActiveGeneration", err) + } + + notReady := &staticActiveManifestResolver{manifest: fixtureManifest(t, "project-a", "generation-a")} + if _, err := ResolveReadyActiveManifest(context.Background(), notReady, "project-a"); !errors.Is(err, ErrGenerationNotReady) { + t.Fatalf("not-ready resolver error = %v, want ErrGenerationNotReady", err) + } + + if _, err := ResolveReadyActiveManifest(context.Background(), nil, "project-a"); !errors.Is(err, ErrInvalidActiveGeneration) { + t.Fatalf("nil resolver error = %v, want ErrInvalidActiveGeneration", err) + } +} diff --git a/internal/dataset/active_test.go b/internal/dataset/active_test.go new file mode 100644 index 0000000..a2126a7 --- /dev/null +++ b/internal/dataset/active_test.go @@ -0,0 +1,139 @@ +package dataset + +import ( + "bytes" + "encoding/json" + "errors" + "testing" +) + +func TestActiveGenerationResolutionAndActivationPlan(t *testing.T) { + previous := readyManifest(t, "project-a", "generation-old") + candidate := readyManifest(t, "project-a", "generation-new") + active, err := ActiveGenerationFor(candidate) + if err != nil { + t.Fatalf("ActiveGenerationFor(candidate): %v", err) + } + resolved, err := ResolveActive(active, []Manifest{previous, candidate}) + if err != nil { + t.Fatalf("ResolveActive: %v", err) + } + if !resolved.Dataset.Equal(candidate.Dataset) { + t.Fatalf("ResolveActive dataset = %#v, want %#v", resolved.Dataset, candidate.Dataset) + } + + plan, err := PlanActivation(&previous, candidate) + if err != nil { + t.Fatalf("PlanActivation: %v", err) + } + if !plan.Active.Dataset.Equal(candidate.Dataset) { + t.Fatalf("activation active = %#v, want %#v", plan.Active.Dataset, candidate.Dataset) + } + if plan.Previous == nil || !plan.Previous.Equal(previous.Dataset) { + t.Fatalf("activation previous = %#v, want %#v", plan.Previous, previous.Dataset) + } + if previous.State != ManifestStateReady { + t.Fatalf("PlanActivation mutated previous manifest to %s", previous.State) + } + + idempotent, err := PlanActivation(&candidate, candidate) + if err != nil { + t.Fatalf("PlanActivation(idempotent): %v", err) + } + if idempotent.Previous != nil { + t.Fatalf("idempotent plan Previous = %#v, want nil", idempotent.Previous) + } + + encoded, err := json.Marshal(plan) + if err != nil { + t.Fatalf("json.Marshal(ActivationPlan): %v", err) + } + var decoded ActivationPlan + if err := json.Unmarshal(encoded, &decoded); err != nil { + t.Fatalf("json.Unmarshal(ActivationPlan): %v", err) + } + if !decoded.Active.Dataset.Equal(plan.Active.Dataset) || decoded.Previous == nil || !decoded.Previous.Equal(*plan.Previous) { + t.Fatalf("activation plan did not round trip\ngot: %#v\nwant: %#v", decoded, plan) + } + + otherProject := readyManifest(t, "project-b", "generation-old") + if _, err := PlanActivation(&otherProject, candidate); !errors.Is(err, ErrInvalidActiveGeneration) { + t.Fatalf("PlanActivation(cross-project) error = %v, want ErrInvalidActiveGeneration", err) + } + loading := transitionManifest(t, fixtureManifest(t, "project-a", "generation-loading"), ManifestStateLoading) + if _, err := PlanActivation(&previous, loading); !errors.Is(err, ErrGenerationNotReady) { + t.Fatalf("PlanActivation(LOADING candidate) error = %v, want ErrGenerationNotReady", err) + } + if _, err := PlanActivation(&previous, failedManifest(t, "project-a", "generation-failed")); !errors.Is(err, ErrGenerationNotReady) { + t.Fatalf("PlanActivation(FAILED candidate) error = %v, want ErrGenerationNotReady", err) + } +} + +func TestResolveActiveRejectsMissingDuplicateAndNonReadyManifests(t *testing.T) { + ready := readyManifest(t, "project-a", "generation-ready") + active, err := ActiveGenerationFor(ready) + if err != nil { + t.Fatal(err) + } + if _, err := ResolveActive(active, nil); !errors.Is(err, ErrInvalidActiveGeneration) { + t.Fatalf("ResolveActive(missing) error = %v, want ErrInvalidActiveGeneration", err) + } + if _, err := ResolveActive(active, []Manifest{ready, ready.Clone()}); !errors.Is(err, ErrInvalidActiveGeneration) { + t.Fatalf("ResolveActive(duplicate) error = %v, want ErrInvalidActiveGeneration", err) + } + + failed := failedManifest(t, "project-a", "generation-ready") + if _, err := ResolveActive(active, []Manifest{failed}); !errors.Is(err, ErrGenerationNotReady) { + t.Fatalf("ResolveActive(FAILED matching generation) error = %v, want ErrGenerationNotReady", err) + } + if _, err := ActiveGenerationFor(failed); !errors.Is(err, ErrGenerationNotReady) { + t.Fatalf("ActiveGenerationFor(FAILED) error = %v, want ErrGenerationNotReady", err) + } +} + +func TestReadBindingPinsReadyGenerationAndScope(t *testing.T) { + ready := readyManifest(t, "project-a", "generation-ready") + active, err := ActiveGenerationFor(ready) + if err != nil { + t.Fatal(err) + } + scope, err := RestrictedAuthScopeFingerprint([]string{"project-a-scope"}) + if err != nil { + t.Fatal(err) + } + binding, err := BindActive(active, ready, scope) + if err != nil { + t.Fatalf("BindActive: %v", err) + } + if !binding.Dataset().Equal(ready.Dataset) || !binding.AuthScopeFingerprint().Equal(scope) { + t.Fatalf("binding = %#v, want generation/scope from ready manifest", binding) + } + + encoded, err := json.Marshal(binding) + if err != nil { + t.Fatalf("json.Marshal(ReadBinding): %v", err) + } + if bytes.Contains(encoded, []byte("project-a-scope")) { + t.Fatalf("ReadBinding exposed raw scope path: %s", encoded) + } + var decoded ReadBinding + if err := json.Unmarshal(encoded, &decoded); err != nil { + t.Fatalf("json.Unmarshal(ReadBinding): %v", err) + } + if !decoded.Dataset().Equal(binding.Dataset()) || decoded.AnalysisVersion() != binding.AnalysisVersion() || !decoded.AuthScopeFingerprint().Equal(binding.AuthScopeFingerprint()) { + t.Fatalf("ReadBinding did not round trip\ngot: %#v\nwant: %#v", decoded, binding) + } + + loading := transitionManifest(t, fixtureManifest(t, "project-a", "generation-loading"), ManifestStateLoading) + loadingActive := ActiveGeneration{Dataset: loading.Dataset} + if _, err := BindActive(loadingActive, loading, scope); !errors.Is(err, ErrGenerationNotReady) { + t.Fatalf("BindActive(LOADING) error = %v, want ErrGenerationNotReady", err) + } + other := readyManifest(t, "project-a", "generation-other") + if _, err := BindActive(active, other, scope); !errors.Is(err, ErrInvalidActiveGeneration) { + t.Fatalf("BindActive(mismatch) error = %v, want ErrInvalidActiveGeneration", err) + } + if _, err := BindActive(active, ready, AuthScopeFingerprint{}); !errors.Is(err, ErrInvalidAuthScopeFingerprint) { + t.Fatalf("BindActive(invalid scope) error = %v, want ErrInvalidAuthScopeFingerprint", err) + } +} diff --git a/internal/dataset/binding.go b/internal/dataset/binding.go new file mode 100644 index 0000000..6f96c0d --- /dev/null +++ b/internal/dataset/binding.go @@ -0,0 +1,112 @@ +package dataset + +import ( + "encoding/json" + "fmt" +) + +// ReadBinding is the immutable identity envelope that a future analysis, +// discovery, dataframe, cache, or export adapter can carry after it has +// resolved a READY active generation. It does not itself query data or prove a +// persistence transaction occurred. +type ReadBinding struct { + dataset DatasetRef + analysisVersion AnalysisVersion + authScopeFingerprint AuthScopeFingerprint +} + +// BindActive constructs a generation-pinned, authorization-scoped read value. +// The supplied manifest must be the READY manifest named by active. The empty +// AnalysisVersion placeholder remains valid, but consumers that require an +// analysis snapshot must require binding.AnalysisVersion().IsSet(). +func BindActive(active ActiveGeneration, manifest Manifest, scope AuthScopeFingerprint) (ReadBinding, error) { + if err := active.Validate(); err != nil { + return ReadBinding{}, err + } + if err := manifest.Validate(); err != nil { + return ReadBinding{}, err + } + if !active.Dataset.Equal(manifest.Dataset) { + return ReadBinding{}, fmt.Errorf("%w: active generation does not match manifest", ErrInvalidActiveGeneration) + } + if manifest.State != ManifestStateReady { + return ReadBinding{}, fmt.Errorf("%w: %s/%s is %s", ErrGenerationNotReady, manifest.Dataset.Project, manifest.Dataset.Generation, manifest.State) + } + if err := scope.Validate(); err != nil { + return ReadBinding{}, err + } + binding := ReadBinding{ + dataset: manifest.Dataset, + analysisVersion: manifest.AnalysisVersion, + authScopeFingerprint: scope, + } + if err := binding.Validate(); err != nil { + return ReadBinding{}, err + } + return binding, nil +} + +// Dataset returns the immutable generation selected for this binding. +func (b ReadBinding) Dataset() DatasetRef { return b.dataset } + +// AnalysisVersion returns the opaque attached analysis version, or the empty +// C1 placeholder when the generation has no finalized analysis snapshot yet. +func (b ReadBinding) AnalysisVersion() AnalysisVersion { return b.analysisVersion } + +// AuthScopeFingerprint returns the authorization-scope cache key without +// exposing raw authorization paths. +func (b ReadBinding) AuthScopeFingerprint() AuthScopeFingerprint { + return b.authScopeFingerprint +} + +// Validate checks a serialized binding's fields. It cannot prove that its +// DatasetRef is active without resolving it through the manifest store. +func (b ReadBinding) Validate() error { + if err := b.dataset.Validate(); err != nil { + return fmt.Errorf("%w: dataset: %w", ErrInvalidActiveGeneration, err) + } + if err := b.analysisVersion.Validate(); err != nil { + return fmt.Errorf("%w: analysisVersion: %w", ErrInvalidActiveGeneration, err) + } + if err := b.authScopeFingerprint.Validate(); err != nil { + return fmt.Errorf("%w: authScopeFingerprint: %w", ErrInvalidActiveGeneration, err) + } + return nil +} + +func (b ReadBinding) MarshalJSON() ([]byte, error) { + if err := b.Validate(); err != nil { + return nil, err + } + return json.Marshal(readBindingWire{ + Dataset: b.dataset, + AnalysisVersion: b.analysisVersion, + AuthScopeFingerprint: b.authScopeFingerprint, + }) +} + +func (b *ReadBinding) UnmarshalJSON(data []byte) error { + if b == nil { + return fmt.Errorf("%w: cannot unmarshal into nil ReadBinding", ErrInvalidActiveGeneration) + } + var decoded readBindingWire + if err := decodeStrictJSON(data, &decoded); err != nil { + return fmt.Errorf("%w: decode JSON: %v", ErrInvalidActiveGeneration, err) + } + binding := ReadBinding{ + dataset: decoded.Dataset, + analysisVersion: decoded.AnalysisVersion, + authScopeFingerprint: decoded.AuthScopeFingerprint, + } + if err := binding.Validate(); err != nil { + return err + } + *b = binding + return nil +} + +type readBindingWire struct { + Dataset DatasetRef `json:"dataset"` + AnalysisVersion AnalysisVersion `json:"analysisVersion"` + AuthScopeFingerprint AuthScopeFingerprint `json:"authScopeFingerprint"` +} diff --git a/internal/dataset/doc.go b/internal/dataset/doc.go new file mode 100644 index 0000000..63921d9 --- /dev/null +++ b/internal/dataset/doc.go @@ -0,0 +1,10 @@ +// Package dataset defines the persistence-neutral identity and lifecycle +// contract for an immutable project dataset generation. +// +// It intentionally does not open a database transaction, persist manifests, +// mutate Arango collections, or resolve authorization. Storage and ingest +// adapters must apply its validated values atomically in their own storage +// transaction. In particular, a successful activation means a READY manifest +// is selected by an ActiveGeneration reference; this package never claims that +// persisting that reference and superseding a prior manifest is atomic. +package dataset diff --git a/internal/dataset/manifest.go b/internal/dataset/manifest.go new file mode 100644 index 0000000..a28cb7f --- /dev/null +++ b/internal/dataset/manifest.go @@ -0,0 +1,248 @@ +package dataset + +import ( + "encoding/json" + "fmt" +) + +// ManifestState is the lifecycle state of one immutable dataset generation. +type ManifestState string + +const ( + ManifestStatePreflight ManifestState = "PREFLIGHT" + ManifestStateLoading ManifestState = "LOADING" + ManifestStateAnalyzing ManifestState = "ANALYZING" + ManifestStateReady ManifestState = "READY" + ManifestStateFailed ManifestState = "FAILED" + ManifestStateSuperseded ManifestState = "SUPERSEDED" +) + +// AnalysisVersion is an opaque version emitted by the future analysis owner. +// The empty value is the intentional C1 placeholder: it means no finalized +// analysis version has been attached and must never be auto-filled by dataset +// lifecycle code. +type AnalysisVersion string + +// NewAnalysisVersion validates a non-empty opaque analysis-version value. +func NewAnalysisVersion(value string) (AnalysisVersion, error) { + version := AnalysisVersion(value) + if !version.IsSet() { + return "", fmt.Errorf("%w: value is required", ErrInvalidAnalysisVersion) + } + if err := version.Validate(); err != nil { + return "", err + } + return version, nil +} + +// IsSet reports whether a finalized analysis version is present. +func (v AnalysisVersion) IsSet() bool { return v != "" } + +// Validate accepts the explicit empty placeholder or one canonical opaque +// version. It never creates a synthetic analysis version. +func (v AnalysisVersion) Validate() error { + if err := validateOpaqueIdentifier("analysisVersion", string(v), true); err != nil { + return fmt.Errorf("%w: %v", ErrInvalidAnalysisVersion, err) + } + return nil +} + +func (v AnalysisVersion) MarshalJSON() ([]byte, error) { + if err := v.Validate(); err != nil { + return nil, err + } + return json.Marshal(string(v)) +} + +func (v *AnalysisVersion) UnmarshalJSON(data []byte) error { + if v == nil { + return fmt.Errorf("%w: cannot unmarshal into nil AnalysisVersion", ErrInvalidAnalysisVersion) + } + if isJSONNull(data) { + return fmt.Errorf("%w: JSON null is not an analysis version", ErrInvalidAnalysisVersion) + } + var value string + if err := decodeStrictJSON(data, &value); err != nil { + return fmt.Errorf("%w: decode JSON: %v", ErrInvalidAnalysisVersion, err) + } + version := AnalysisVersion(value) + if err := version.Validate(); err != nil { + return err + } + *v = version + return nil +} + +// Manifest records the lifecycle state and immutable schema metadata of one +// dataset generation. It is a value contract only; callers persist it and +// attach load/error metrics in their storage layer. +type Manifest struct { + Dataset DatasetRef `json:"dataset"` + State ManifestState `json:"state"` + SchemaIdentity SchemaIdentitySnapshot `json:"schemaIdentity"` + AnalysisVersion AnalysisVersion `json:"analysisVersion"` +} + +// NewManifest starts a new generation in PREFLIGHT. Once a caller's external +// preflight succeeds, it must use Transition(ManifestStateLoading) before +// writing data or catalog records. +func NewManifest(ref DatasetRef, schema SchemaIdentitySnapshot) (Manifest, error) { + manifest := Manifest{ + Dataset: ref, + State: ManifestStatePreflight, + SchemaIdentity: schema.Clone(), + } + if err := manifest.Validate(); err != nil { + return Manifest{}, err + } + return manifest, nil +} + +// Clone returns an independent copy. SchemaIdentity's slice is copied even +// though it is not exposed directly, so future internal changes cannot alias +// a manifest's stored metadata. +func (m Manifest) Clone() Manifest { + return Manifest{ + Dataset: m.Dataset, + State: m.State, + SchemaIdentity: m.SchemaIdentity.Clone(), + AnalysisVersion: m.AnalysisVersion, + } +} + +// Validate checks a manifest without making persistence or transaction claims. +func (m Manifest) Validate() error { + if err := m.Dataset.Validate(); err != nil { + return fmt.Errorf("%w: dataset: %w", ErrInvalidManifest, err) + } + if !m.State.valid() { + return fmt.Errorf("%w: state %q is not recognized", ErrInvalidManifest, m.State) + } + if err := m.SchemaIdentity.Validate(); err != nil { + return fmt.Errorf("%w: schemaIdentity: %w", ErrInvalidManifest, err) + } + if err := m.AnalysisVersion.Validate(); err != nil { + return fmt.Errorf("%w: analysisVersion: %w", ErrInvalidManifest, err) + } + return nil +} + +// Transition returns a new manifest in the requested state. It never mutates +// the source value and disallows terminal-state reactivation. +// +// Allowed transitions are: +// +// - PREFLIGHT -> LOADING or FAILED +// - LOADING -> ANALYZING or FAILED +// - ANALYZING -> READY or FAILED +// - READY -> SUPERSEDED +// +// FAILED and SUPERSEDED are terminal. A failed or superseded generation can +// never be transitioned back to LOADING, ANALYZING, or READY. +func (m Manifest) Transition(next ManifestState) (Manifest, error) { + if err := m.Validate(); err != nil { + return Manifest{}, err + } + if !canTransition(m.State, next) { + return Manifest{}, fmt.Errorf("%w: %s -> %s", ErrInvalidTransition, m.State, next) + } + result := m.Clone() + result.State = next + if err := result.Validate(); err != nil { + return Manifest{}, err + } + return result, nil +} + +// WithAnalysisVersion attaches a finalized analysis version while a generation +// is in ANALYZING. The lifecycle package neither generates that value nor +// allows changing it after READY. +func (m Manifest) WithAnalysisVersion(version AnalysisVersion) (Manifest, error) { + if err := m.Validate(); err != nil { + return Manifest{}, err + } + if m.State != ManifestStateAnalyzing { + return Manifest{}, fmt.Errorf("%w: analysisVersion can only be attached while state is %s", ErrInvalidTransition, ManifestStateAnalyzing) + } + if !version.IsSet() { + return Manifest{}, fmt.Errorf("%w: value is required while attaching an analysis version", ErrInvalidAnalysisVersion) + } + if err := version.Validate(); err != nil { + return Manifest{}, err + } + result := m.Clone() + result.AnalysisVersion = version + return result, nil +} + +// IsReady reports whether this manifest is eligible to become the active +// generation. A caller that needs analysis facts must separately require a set +// AnalysisVersion; READY intentionally permits the C1 empty placeholder. +func (m Manifest) IsReady() bool { + return m.Validate() == nil && m.State == ManifestStateReady +} + +func (s ManifestState) valid() bool { + switch s { + case ManifestStatePreflight, ManifestStateLoading, ManifestStateAnalyzing, + ManifestStateReady, ManifestStateFailed, ManifestStateSuperseded: + return true + default: + return false + } +} + +func canTransition(from, to ManifestState) bool { + switch from { + case ManifestStatePreflight: + return to == ManifestStateLoading || to == ManifestStateFailed + case ManifestStateLoading: + return to == ManifestStateAnalyzing || to == ManifestStateFailed + case ManifestStateAnalyzing: + return to == ManifestStateReady || to == ManifestStateFailed + case ManifestStateReady: + return to == ManifestStateSuperseded + default: + return false + } +} + +func (m Manifest) MarshalJSON() ([]byte, error) { + if err := m.Validate(); err != nil { + return nil, err + } + return json.Marshal(manifestWire{ + Dataset: m.Dataset, + State: m.State, + SchemaIdentity: m.SchemaIdentity, + AnalysisVersion: m.AnalysisVersion, + }) +} + +func (m *Manifest) UnmarshalJSON(data []byte) error { + if m == nil { + return fmt.Errorf("%w: cannot unmarshal into nil Manifest", ErrInvalidManifest) + } + var decoded manifestWire + if err := decodeStrictJSON(data, &decoded); err != nil { + return fmt.Errorf("%w: decode JSON: %v", ErrInvalidManifest, err) + } + manifest := Manifest{ + Dataset: decoded.Dataset, + State: decoded.State, + SchemaIdentity: decoded.SchemaIdentity, + AnalysisVersion: decoded.AnalysisVersion, + } + if err := manifest.Validate(); err != nil { + return err + } + *m = manifest.Clone() + return nil +} + +type manifestWire struct { + Dataset DatasetRef `json:"dataset"` + State ManifestState `json:"state"` + SchemaIdentity SchemaIdentitySnapshot `json:"schemaIdentity"` + AnalysisVersion AnalysisVersion `json:"analysisVersion"` +} diff --git a/internal/dataset/manifest_test.go b/internal/dataset/manifest_test.go new file mode 100644 index 0000000..0700f5e --- /dev/null +++ b/internal/dataset/manifest_test.go @@ -0,0 +1,123 @@ +package dataset + +import ( + "encoding/json" + "errors" + "testing" +) + +func TestManifestLifecycleTransitionsAndTerminalStates(t *testing.T) { + preflight := fixtureManifest(t, "project-a", "generation-a") + if got, want := preflight.State, ManifestStatePreflight; got != want { + t.Fatalf("initial state = %s, want %s", got, want) + } + if _, err := preflight.Transition(ManifestStateReady); !errors.Is(err, ErrInvalidTransition) { + t.Fatalf("PREFLIGHT -> READY error = %v, want ErrInvalidTransition", err) + } + + loading := transitionManifest(t, preflight, ManifestStateLoading) + if preflight.State != ManifestStatePreflight { + t.Fatalf("Transition mutated source state to %s", preflight.State) + } + if _, err := loading.Transition(ManifestStateReady); !errors.Is(err, ErrInvalidTransition) { + t.Fatalf("LOADING -> READY error = %v, want ErrInvalidTransition", err) + } + + analyzing := transitionManifest(t, loading, ManifestStateAnalyzing) + version, err := NewAnalysisVersion("analysis-2026-07-11") + if err != nil { + t.Fatalf("NewAnalysisVersion: %v", err) + } + withAnalysis, err := analyzing.WithAnalysisVersion(version) + if err != nil { + t.Fatalf("WithAnalysisVersion: %v", err) + } + if analyzing.AnalysisVersion.IsSet() { + t.Fatal("WithAnalysisVersion mutated source manifest") + } + if got, want := withAnalysis.AnalysisVersion, version; got != want { + t.Fatalf("AnalysisVersion = %q, want %q", got, want) + } + + ready := transitionManifest(t, withAnalysis, ManifestStateReady) + if !ready.IsReady() { + t.Fatal("READY manifest was not eligible for activation") + } + if _, err := ready.WithAnalysisVersion(version); !errors.Is(err, ErrInvalidTransition) { + t.Fatalf("READY WithAnalysisVersion error = %v, want ErrInvalidTransition", err) + } + if _, err := ready.Transition(ManifestStateFailed); !errors.Is(err, ErrInvalidTransition) { + t.Fatalf("READY -> FAILED error = %v, want ErrInvalidTransition", err) + } + + superseded := transitionManifest(t, ready, ManifestStateSuperseded) + if _, err := superseded.Transition(ManifestStateReady); !errors.Is(err, ErrInvalidTransition) { + t.Fatalf("SUPERSEDED -> READY error = %v, want ErrInvalidTransition", err) + } + if _, err := ActiveGenerationFor(superseded); !errors.Is(err, ErrGenerationNotReady) { + t.Fatalf("ActiveGenerationFor(SUPERSEDED) error = %v, want ErrGenerationNotReady", err) + } + + failed := failedManifest(t, "project-a", "generation-failed") + if _, err := failed.Transition(ManifestStateLoading); !errors.Is(err, ErrInvalidTransition) { + t.Fatalf("FAILED -> LOADING error = %v, want ErrInvalidTransition", err) + } + if _, err := ActiveGenerationFor(failed); !errors.Is(err, ErrGenerationNotReady) { + t.Fatalf("ActiveGenerationFor(FAILED) error = %v, want ErrGenerationNotReady", err) + } +} + +func TestManifestReadyAllowsAnalysisPlaceholderButNeverSynthesizesIt(t *testing.T) { + ready := readyManifest(t, "project-a", "generation-no-analysis") + if ready.AnalysisVersion.IsSet() { + t.Fatalf("ready AnalysisVersion = %q, want empty C1 placeholder", ready.AnalysisVersion) + } + if err := ready.AnalysisVersion.Validate(); err != nil { + t.Fatalf("empty analysis placeholder Validate: %v", err) + } + if _, err := NewAnalysisVersion(""); !errors.Is(err, ErrInvalidAnalysisVersion) { + t.Fatalf("NewAnalysisVersion(empty) error = %v, want ErrInvalidAnalysisVersion", err) + } + var decoded AnalysisVersion + if err := json.Unmarshal([]byte("null"), &decoded); !errors.Is(err, ErrInvalidAnalysisVersion) { + t.Fatalf("json.Unmarshal(null AnalysisVersion) error = %v, want ErrInvalidAnalysisVersion", err) + } +} + +func TestManifestJSONValidationAndCopy(t *testing.T) { + manifest := readyManifest(t, "project-a", "generation-a") + encoded, err := json.Marshal(manifest) + if err != nil { + t.Fatalf("json.Marshal(Manifest): %v", err) + } + var decoded Manifest + if err := json.Unmarshal(encoded, &decoded); err != nil { + t.Fatalf("json.Unmarshal(Manifest): %v", err) + } + if !decoded.Dataset.Equal(manifest.Dataset) || decoded.State != manifest.State || !decoded.SchemaIdentity.Equal(manifest.SchemaIdentity) || decoded.AnalysisVersion != manifest.AnalysisVersion { + t.Fatalf("manifest did not round trip\ngot: %#v\nwant: %#v", decoded, manifest) + } + + clone := decoded.Clone() + cloneTypes := clone.SchemaIdentity.GeneratedResourceTypes() + cloneTypes[0] = "mutated" + if decoded.SchemaIdentity.GeneratedResourceTypes()[0] == "mutated" { + t.Fatal("manifest clone exposed shared schema slice") + } + + if _, err := json.Marshal(Manifest{}); !errors.Is(err, ErrInvalidManifest) { + t.Fatalf("json.Marshal(invalid Manifest) error = %v, want ErrInvalidManifest", err) + } + var fields map[string]json.RawMessage + if err := json.Unmarshal(encoded, &fields); err != nil { + t.Fatalf("decode manifest JSON: %v", err) + } + fields["unknown"] = json.RawMessage(`true`) + unknown, err := json.Marshal(fields) + if err != nil { + t.Fatalf("encode unknown manifest JSON: %v", err) + } + if err := json.Unmarshal(unknown, &decoded); !errors.Is(err, ErrInvalidManifest) { + t.Fatalf("json.Unmarshal(unknown Manifest field) error = %v, want ErrInvalidManifest", err) + } +} diff --git a/internal/dataset/ref.go b/internal/dataset/ref.go new file mode 100644 index 0000000..5d3f208 --- /dev/null +++ b/internal/dataset/ref.go @@ -0,0 +1,67 @@ +package dataset + +import ( + "encoding/json" + "fmt" +) + +// DatasetRef names one immutable dataset generation in one project. +// Generation is intentionally opaque: callers must not assume it is a UUID, +// timestamp, counter, or sortable value. +type DatasetRef struct { + Project string `json:"project"` + Generation string `json:"generation"` +} + +// NewDatasetRef returns a validated, canonical project/generation reference. +// It preserves valid identifiers exactly; it never invents or rewrites a +// generation value. +func NewDatasetRef(project, generation string) (DatasetRef, error) { + ref := DatasetRef{Project: project, Generation: generation} + if err := ref.Validate(); err != nil { + return DatasetRef{}, err + } + return ref, nil +} + +// Validate checks the stable key representation used by manifests, active +// references, and generation-bound reads. +func (r DatasetRef) Validate() error { + if err := validateOpaqueIdentifier("project", r.Project, false); err != nil { + return fmt.Errorf("%w: %v", ErrInvalidDatasetRef, err) + } + if err := validateOpaqueIdentifier("generation", r.Generation, false); err != nil { + return fmt.Errorf("%w: %v", ErrInvalidDatasetRef, err) + } + return nil +} + +// Equal reports whether two references name exactly the same generation. +func (r DatasetRef) Equal(other DatasetRef) bool { + return r.Project == other.Project && r.Generation == other.Generation +} + +func (r DatasetRef) MarshalJSON() ([]byte, error) { + if err := r.Validate(); err != nil { + return nil, err + } + type wire DatasetRef + return json.Marshal(wire(r)) +} + +func (r *DatasetRef) UnmarshalJSON(data []byte) error { + if r == nil { + return fmt.Errorf("%w: cannot unmarshal into nil DatasetRef", ErrInvalidDatasetRef) + } + type wire DatasetRef + var decoded wire + if err := decodeStrictJSON(data, &decoded); err != nil { + return fmt.Errorf("%w: decode JSON: %v", ErrInvalidDatasetRef, err) + } + value := DatasetRef(decoded) + if err := value.Validate(); err != nil { + return err + } + *r = value + return nil +} diff --git a/internal/dataset/ref_test.go b/internal/dataset/ref_test.go new file mode 100644 index 0000000..598f6fc --- /dev/null +++ b/internal/dataset/ref_test.go @@ -0,0 +1,58 @@ +package dataset + +import ( + "encoding/json" + "errors" + "testing" +) + +func TestDatasetRefValidationAndJSON(t *testing.T) { + ref, err := NewDatasetRef("demo-project", "load:2026-07-11/v1") + if err != nil { + t.Fatalf("NewDatasetRef: %v", err) + } + if got, want := ref.Project, "demo-project"; got != want { + t.Fatalf("Project = %q, want %q", got, want) + } + if got, want := ref.Generation, "load:2026-07-11/v1"; got != want { + t.Fatalf("Generation = %q, want %q", got, want) + } + + encoded, err := json.Marshal(ref) + if err != nil { + t.Fatalf("json.Marshal(DatasetRef): %v", err) + } + var decoded DatasetRef + if err := json.Unmarshal(encoded, &decoded); err != nil { + t.Fatalf("json.Unmarshal(DatasetRef): %v", err) + } + if !decoded.Equal(ref) { + t.Fatalf("round trip = %#v, want %#v", decoded, ref) + } + + for _, candidate := range []DatasetRef{ + {}, + {Project: " project", Generation: "generation"}, + {Project: "project", Generation: "generation\nnext"}, + {Project: repeated("p", maxOpaqueIdentifierBytes+1), Generation: "generation"}, + } { + if err := candidate.Validate(); !errors.Is(err, ErrInvalidDatasetRef) { + t.Errorf("Validate(%#v) error = %v, want ErrInvalidDatasetRef", candidate, err) + } + if _, err := json.Marshal(candidate); !errors.Is(err, ErrInvalidDatasetRef) { + t.Errorf("json.Marshal(%#v) error = %v, want ErrInvalidDatasetRef", candidate, err) + } + } + + for _, raw := range []string{ + `{"project":"demo"}`, + `{"project":"demo","generation":"g","unknown":true}`, + `{"project":"demo","generation":" g"}`, + `[]`, + } { + var value DatasetRef + if err := json.Unmarshal([]byte(raw), &value); !errors.Is(err, ErrInvalidDatasetRef) { + t.Errorf("json.Unmarshal(%s) error = %v, want ErrInvalidDatasetRef", raw, err) + } + } +} diff --git a/internal/dataset/schema.go b/internal/dataset/schema.go new file mode 100644 index 0000000..c3ee763 --- /dev/null +++ b/internal/dataset/schema.go @@ -0,0 +1,201 @@ +package dataset + +import ( + "encoding/hex" + "encoding/json" + "fmt" + "slices" + "sort" + "strings" + "unicode/utf8" + + "github.com/calypr/loom/internal/schemaidentity" +) + +// SchemaIdentitySnapshot is the serializable, immutable schema metadata +// attached to a dataset generation. It is copied from the active Loom binary's +// schemaidentity.Identity when a generation is created. +// +// FHIRVersion is deliberately empty when the configured graph schema does not +// explicitly declare one. This package never infers a FHIR version from a URL, +// resource type, or generated code. +type SchemaIdentitySnapshot struct { + schemaID string + fhirVersion string + schemaSHA256 string + generatedResourceTypes []string +} + +// SnapshotSchemaIdentity copies an immutable schemaidentity.Identity into the +// public dataset lifecycle value. The resulting snapshot has no reference to +// the source identity's backing data. +func SnapshotSchemaIdentity(identity schemaidentity.Identity) (SchemaIdentitySnapshot, error) { + return NewSchemaIdentitySnapshot( + identity.SchemaID(), + identity.FHIRVersion(), + identity.SchemaSHA256(), + identity.GeneratedResourceTypes(), + ) +} + +// NewSchemaIdentitySnapshot creates a validated schema snapshot. Resource +// types are canonicalized into lexicographic order; duplicate or malformed +// entries are rejected rather than silently coalesced. +func NewSchemaIdentitySnapshot(schemaID, fhirVersion, schemaSHA256 string, generatedResourceTypes []string) (SchemaIdentitySnapshot, error) { + resourceTypes := append([]string(nil), generatedResourceTypes...) + sort.Strings(resourceTypes) + snapshot := SchemaIdentitySnapshot{ + schemaID: schemaID, + fhirVersion: fhirVersion, + schemaSHA256: schemaSHA256, + generatedResourceTypes: resourceTypes, + } + if err := snapshot.Validate(); err != nil { + return SchemaIdentitySnapshot{}, err + } + return snapshot, nil +} + +// SchemaID returns the exact graph-schema $id copied from schemaidentity, or +// an empty string when the source schema does not declare one. +func (s SchemaIdentitySnapshot) SchemaID() string { return s.schemaID } + +// FHIRVersion returns only an explicitly declared source FHIR version. An +// empty result means that the source schema did not declare fhirVersion. +func (s SchemaIdentitySnapshot) FHIRVersion() string { return s.fhirVersion } + +// SchemaSHA256 returns the SHA-256 digest of the exact graph-schema bytes. +func (s SchemaIdentitySnapshot) SchemaSHA256() string { return s.schemaSHA256 } + +// GeneratedResourceTypes returns a sorted defensive copy of the compiled +// generated FHIR roots captured in this snapshot. +func (s SchemaIdentitySnapshot) GeneratedResourceTypes() []string { + return append([]string(nil), s.generatedResourceTypes...) +} + +// Clone returns an independent value with its own resource-type slice. +func (s SchemaIdentitySnapshot) Clone() SchemaIdentitySnapshot { + return SchemaIdentitySnapshot{ + schemaID: s.schemaID, + fhirVersion: s.fhirVersion, + schemaSHA256: s.schemaSHA256, + generatedResourceTypes: s.GeneratedResourceTypes(), + } +} + +// Equal reports exact identity equality. Generated resource types are already +// canonicalized, so ordering cannot make equivalent snapshots compare unequal. +func (s SchemaIdentitySnapshot) Equal(other SchemaIdentitySnapshot) bool { + return s.schemaID == other.schemaID && + s.fhirVersion == other.fhirVersion && + s.schemaSHA256 == other.schemaSHA256 && + slices.Equal(s.generatedResourceTypes, other.generatedResourceTypes) +} + +// Validate checks a persisted or manually constructed snapshot. It does not +// re-read a schema file; compatibility decisions belong to an ingest adapter. +func (s SchemaIdentitySnapshot) Validate() error { + if err := validateOptionalSchemaMetadata("schemaId", s.schemaID); err != nil { + return fmt.Errorf("%w: %v", ErrInvalidSchemaIdentity, err) + } + if err := validateOptionalSchemaMetadata("fhirVersion", s.fhirVersion); err != nil { + return fmt.Errorf("%w: %v", ErrInvalidSchemaIdentity, err) + } + if len(s.schemaSHA256) != 64 || strings.ToLower(s.schemaSHA256) != s.schemaSHA256 { + return fmt.Errorf("%w: schemaSha256 must be a lower-case 64-character SHA-256 digest", ErrInvalidSchemaIdentity) + } + if _, err := hex.DecodeString(s.schemaSHA256); err != nil { + return fmt.Errorf("%w: schemaSha256 is not hexadecimal: %v", ErrInvalidSchemaIdentity, err) + } + if len(s.generatedResourceTypes) == 0 { + return fmt.Errorf("%w: generatedResourceTypes is required", ErrInvalidSchemaIdentity) + } + if len(s.generatedResourceTypes) > maxResourceTypes { + return fmt.Errorf("%w: generatedResourceTypes exceeds %d entries", ErrInvalidSchemaIdentity, maxResourceTypes) + } + if !sort.StringsAreSorted(s.generatedResourceTypes) { + return fmt.Errorf("%w: generatedResourceTypes must be sorted", ErrInvalidSchemaIdentity) + } + for index, resourceType := range s.generatedResourceTypes { + if err := validateOpaqueIdentifier(fmt.Sprintf("generatedResourceTypes[%d]", index), resourceType, false); err != nil { + return fmt.Errorf("%w: %v", ErrInvalidSchemaIdentity, err) + } + if index > 0 && resourceType == s.generatedResourceTypes[index-1] { + return fmt.Errorf("%w: generatedResourceTypes[%d] duplicates %q", ErrInvalidSchemaIdentity, index, resourceType) + } + } + return nil +} + +func validateOptionalSchemaMetadata(field, value string) error { + if value == "" { + return nil + } + if len(value) > maxOpaqueIdentifierBytes { + return fmt.Errorf("%s exceeds %d bytes", field, maxOpaqueIdentifierBytes) + } + if !utf8ValidNonControl(value) { + return fmt.Errorf("%s must be valid UTF-8 without control characters", field) + } + return nil +} + +func utf8ValidNonControl(value string) bool { + // Schema metadata must retain the exact text that schemaidentity observed; + // unlike a project key it is not whitespace-normalized here. + for _, r := range value { + if r < 0x20 || r == 0x7f { + return false + } + } + return utf8.ValidString(value) +} + +func (s SchemaIdentitySnapshot) MarshalJSON() ([]byte, error) { + if err := s.Validate(); err != nil { + return nil, err + } + return json.Marshal(schemaIdentitySnapshotWire{ + SchemaID: s.schemaID, + FHIRVersion: s.fhirVersion, + SchemaSHA256: s.schemaSHA256, + GeneratedResourceTypes: s.GeneratedResourceTypes(), + }) +} + +func (s *SchemaIdentitySnapshot) UnmarshalJSON(data []byte) error { + if s == nil { + return fmt.Errorf("%w: cannot unmarshal into nil SchemaIdentitySnapshot", ErrInvalidSchemaIdentity) + } + var decoded schemaIdentitySnapshotWire + if err := decodeStrictJSON(data, &decoded); err != nil { + return fmt.Errorf("%w: decode JSON: %v", ErrInvalidSchemaIdentity, err) + } + var rawFields map[string]json.RawMessage + if err := json.Unmarshal(data, &rawFields); err != nil { + return fmt.Errorf("%w: decode JSON fields: %v", ErrInvalidSchemaIdentity, err) + } + for _, field := range []string{"schemaId", "fhirVersion"} { + if raw, present := rawFields[field]; present && isJSONNull(raw) { + return fmt.Errorf("%w: %s must be a string when present", ErrInvalidSchemaIdentity, field) + } + } + snapshot, err := NewSchemaIdentitySnapshot( + decoded.SchemaID, + decoded.FHIRVersion, + decoded.SchemaSHA256, + decoded.GeneratedResourceTypes, + ) + if err != nil { + return err + } + *s = snapshot + return nil +} + +type schemaIdentitySnapshotWire struct { + SchemaID string `json:"schemaId,omitempty"` + FHIRVersion string `json:"fhirVersion,omitempty"` + SchemaSHA256 string `json:"schemaSha256"` + GeneratedResourceTypes []string `json:"generatedResourceTypes"` +} diff --git a/internal/dataset/schema_test.go b/internal/dataset/schema_test.go new file mode 100644 index 0000000..8dfb791 --- /dev/null +++ b/internal/dataset/schema_test.go @@ -0,0 +1,123 @@ +package dataset + +import ( + "encoding/json" + "errors" + "path/filepath" + "reflect" + "testing" + + "github.com/calypr/loom/internal/schemaidentity" +) + +func TestSnapshotSchemaIdentityPreservesSourceAndCopies(t *testing.T) { + identity, err := schemaidentity.Load(filepath.Join("..", "..", "schemas", "graph-fhir.json")) + if err != nil { + t.Fatalf("schemaidentity.Load: %v", err) + } + snapshot, err := SnapshotSchemaIdentity(identity) + if err != nil { + t.Fatalf("SnapshotSchemaIdentity: %v", err) + } + if got, want := snapshot.SchemaID(), identity.SchemaID(); got != want { + t.Fatalf("SchemaID() = %q, want %q", got, want) + } + if got, want := snapshot.SchemaSHA256(), identity.SchemaSHA256(); got != want { + t.Fatalf("SchemaSHA256() = %q, want %q", got, want) + } + if got := snapshot.FHIRVersion(); got != "" { + t.Fatalf("FHIRVersion() = %q, want empty: graph-fhir.json has no explicit fhirVersion", got) + } + + resourceTypes := snapshot.GeneratedResourceTypes() + if len(resourceTypes) == 0 { + t.Fatal("GeneratedResourceTypes() returned no roots") + } + resourceTypes[0] = "mutated" + if snapshot.GeneratedResourceTypes()[0] == "mutated" { + t.Fatal("GeneratedResourceTypes() exposed mutable backing storage") + } + + encoded, err := json.Marshal(snapshot) + if err != nil { + t.Fatalf("json.Marshal(SchemaIdentitySnapshot): %v", err) + } + var wire map[string]json.RawMessage + if err := json.Unmarshal(encoded, &wire); err != nil { + t.Fatalf("decode schema snapshot JSON: %v", err) + } + if _, ok := wire["fhirVersion"]; ok { + t.Fatalf("serialized snapshot invented fhirVersion: %s", encoded) + } + + var decoded SchemaIdentitySnapshot + if err := json.Unmarshal(encoded, &decoded); err != nil { + t.Fatalf("json.Unmarshal(SchemaIdentitySnapshot): %v", err) + } + if !decoded.Equal(snapshot) { + t.Fatalf("schema snapshot did not round trip\ngot: %#v\nwant: %#v", decoded, snapshot) + } +} + +func TestSchemaIdentitySnapshotCanonicalizesAndValidates(t *testing.T) { + source := []string{"Patient", "Observation"} + snapshot, err := NewSchemaIdentitySnapshot("urn:example", "R5", fixtureSchemaSHA256, source) + if err != nil { + t.Fatalf("NewSchemaIdentitySnapshot: %v", err) + } + if got, want := snapshot.GeneratedResourceTypes(), []string{"Observation", "Patient"}; !reflect.DeepEqual(got, want) { + t.Fatalf("GeneratedResourceTypes() = %#v, want %#v", got, want) + } + source[0] = "mutated" + if got, want := snapshot.GeneratedResourceTypes(), []string{"Observation", "Patient"}; !reflect.DeepEqual(got, want) { + t.Fatalf("snapshot changed after source mutation: %#v, want %#v", got, want) + } + + clone := snapshot.Clone() + cloneTypes := clone.GeneratedResourceTypes() + cloneTypes[0] = "mutated" + if got, want := snapshot.GeneratedResourceTypes(), []string{"Observation", "Patient"}; !reflect.DeepEqual(got, want) { + t.Fatalf("snapshot changed after clone accessor mutation: %#v, want %#v", got, want) + } + + for _, test := range []struct { + name string + digest string + resourceTypes []string + }{ + {name: "nonhex digest", digest: repeated("z", 64), resourceTypes: []string{"Patient"}}, + {name: "uppercase digest", digest: repeated("A", 64), resourceTypes: []string{"Patient"}}, + {name: "empty roots", digest: fixtureSchemaSHA256, resourceTypes: nil}, + {name: "duplicate roots", digest: fixtureSchemaSHA256, resourceTypes: []string{"Patient", "Patient"}}, + {name: "blank root", digest: fixtureSchemaSHA256, resourceTypes: []string{" "}}, + } { + t.Run(test.name, func(t *testing.T) { + _, err := NewSchemaIdentitySnapshot("urn:example", "", test.digest, test.resourceTypes) + if !errors.Is(err, ErrInvalidSchemaIdentity) { + t.Fatalf("NewSchemaIdentitySnapshot error = %v, want ErrInvalidSchemaIdentity", err) + } + }) + } + + var decoded SchemaIdentitySnapshot + if err := json.Unmarshal([]byte(`{"schemaId":"urn:example","schemaSha256":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","generatedResourceTypes":["Patient","Observation"]}`), &decoded); err != nil { + t.Fatalf("json.Unmarshal canonicalizable snapshot: %v", err) + } + if got, want := decoded.GeneratedResourceTypes(), []string{"Observation", "Patient"}; !reflect.DeepEqual(got, want) { + t.Fatalf("decoded resources = %#v, want %#v", got, want) + } + if _, err := json.Marshal(decoded); err != nil { + t.Fatalf("json.Marshal canonicalized snapshot: %v", err) + } + + for _, raw := range []string{ + `{"schemaSha256":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","generatedResourceTypes":["Patient"],"unknown":true}`, + `{"schemaSha256":"bad","generatedResourceTypes":["Patient"]}`, + `{"fhirVersion":null,"schemaSha256":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","generatedResourceTypes":["Patient"]}`, + } { + var value SchemaIdentitySnapshot + if err := json.Unmarshal([]byte(raw), &value); !errors.Is(err, ErrInvalidSchemaIdentity) { + t.Errorf("json.Unmarshal(%s) error = %v, want ErrInvalidSchemaIdentity", raw, err) + } + } +} diff --git a/internal/dataset/scope.go b/internal/dataset/scope.go new file mode 100644 index 0000000..b9cdc04 --- /dev/null +++ b/internal/dataset/scope.go @@ -0,0 +1,164 @@ +package dataset + +import ( + "crypto/sha256" + "encoding/hex" + "encoding/json" + "fmt" + "sort" + "strings" +) + +const ( + authScopeFingerprintVersion = "loom-auth-scope-v1" + fingerprintAlgorithmSHA256 = "sha256" +) + +// AuthScopeMode distinguishes an unscoped caller from a caller with a scoped +// authorization result. In particular, a restricted caller with zero allowed +// paths must not share a cache key with an unrestricted caller. +type AuthScopeMode string + +const ( + AuthScopeUnrestricted AuthScopeMode = "unrestricted" + AuthScopeRestricted AuthScopeMode = "restricted" +) + +// AuthScopeFingerprint is a stable, serializable representation of an +// effective authorization scope. It intentionally retains no raw paths, token, +// subject, or claims. Callers must construct it from the already-authorized, +// canonical effective scope returned by the authorization layer. +type AuthScopeFingerprint struct { + mode AuthScopeMode + algorithm string + digest string +} + +// UnrestrictedAuthScopeFingerprint returns the canonical fingerprint for an +// authorization layer that is explicitly unrestricted. +func UnrestrictedAuthScopeFingerprint() AuthScopeFingerprint { + return AuthScopeFingerprint{ + mode: AuthScopeUnrestricted, + algorithm: fingerprintAlgorithmSHA256, + digest: fingerprintDigest(AuthScopeUnrestricted, nil), + } +} + +// RestrictedAuthScopeFingerprint returns a fingerprint for one effective, +// restricted scope. Input paths must already be canonical authorization-path +// identifiers. Ordering does not matter; duplicate or noncanonical values are +// rejected so two integrations cannot silently hash different representations +// of the same scope. +func RestrictedAuthScopeFingerprint(paths []string) (AuthScopeFingerprint, error) { + canonicalPaths, err := canonicalScopePaths(paths) + if err != nil { + return AuthScopeFingerprint{}, err + } + return AuthScopeFingerprint{ + mode: AuthScopeRestricted, + algorithm: fingerprintAlgorithmSHA256, + digest: fingerprintDigest(AuthScopeRestricted, canonicalPaths), + }, nil +} + +// Mode returns whether the fingerprint represents an unrestricted or +// restricted authorization result. +func (f AuthScopeFingerprint) Mode() AuthScopeMode { return f.mode } + +// Algorithm returns the digest algorithm used for this fingerprint. +func (f AuthScopeFingerprint) Algorithm() string { return f.algorithm } + +// Digest returns the lower-case hexadecimal digest. It never exposes raw +// authorization paths. +func (f AuthScopeFingerprint) Digest() string { return f.digest } + +// Equal reports exact cache-key equality. +func (f AuthScopeFingerprint) Equal(other AuthScopeFingerprint) bool { + return f.mode == other.mode && f.algorithm == other.algorithm && f.digest == other.digest +} + +// Validate checks a persisted fingerprint. It cannot recompute a digest +// without the intentionally omitted raw scope paths. +func (f AuthScopeFingerprint) Validate() error { + if f.mode != AuthScopeUnrestricted && f.mode != AuthScopeRestricted { + return fmt.Errorf("%w: mode must be unrestricted or restricted", ErrInvalidAuthScopeFingerprint) + } + if f.algorithm != fingerprintAlgorithmSHA256 { + return fmt.Errorf("%w: algorithm must be %q", ErrInvalidAuthScopeFingerprint, fingerprintAlgorithmSHA256) + } + if len(f.digest) != sha256.Size*2 || strings.ToLower(f.digest) != f.digest { + return fmt.Errorf("%w: digest must be a lower-case SHA-256 hexadecimal value", ErrInvalidAuthScopeFingerprint) + } + if _, err := hex.DecodeString(f.digest); err != nil { + return fmt.Errorf("%w: digest is not hexadecimal: %v", ErrInvalidAuthScopeFingerprint, err) + } + return nil +} + +func canonicalScopePaths(paths []string) ([]string, error) { + canonical := append([]string(nil), paths...) + if len(canonical) > maxScopePaths { + return nil, fmt.Errorf("%w: scope has more than %d paths", ErrInvalidAuthScopeFingerprint, maxScopePaths) + } + for index, path := range canonical { + if err := validateOpaqueIdentifier(fmt.Sprintf("scope path at index %d", index), path, false); err != nil { + return nil, fmt.Errorf("%w: %v", ErrInvalidAuthScopeFingerprint, err) + } + } + sort.Strings(canonical) + for index := 1; index < len(canonical); index++ { + if canonical[index] == canonical[index-1] { + return nil, fmt.Errorf("%w: duplicate scope path", ErrInvalidAuthScopeFingerprint) + } + } + return canonical, nil +} + +func fingerprintDigest(mode AuthScopeMode, canonicalPaths []string) string { + hash := sha256.New() + _, _ = hash.Write([]byte(authScopeFingerprintVersion)) + _, _ = hash.Write([]byte{0}) + _, _ = hash.Write([]byte(mode)) + for _, path := range canonicalPaths { + _, _ = hash.Write([]byte{0}) + _, _ = hash.Write([]byte(path)) + } + return hex.EncodeToString(hash.Sum(nil)) +} + +func (f AuthScopeFingerprint) MarshalJSON() ([]byte, error) { + if err := f.Validate(); err != nil { + return nil, err + } + return json.Marshal(authScopeFingerprintWire{ + Mode: f.mode, + Algorithm: f.algorithm, + Digest: f.digest, + }) +} + +func (f *AuthScopeFingerprint) UnmarshalJSON(data []byte) error { + if f == nil { + return fmt.Errorf("%w: cannot unmarshal into nil AuthScopeFingerprint", ErrInvalidAuthScopeFingerprint) + } + var decoded authScopeFingerprintWire + if err := decodeStrictJSON(data, &decoded); err != nil { + return fmt.Errorf("%w: decode JSON: %v", ErrInvalidAuthScopeFingerprint, err) + } + value := AuthScopeFingerprint{ + mode: decoded.Mode, + algorithm: decoded.Algorithm, + digest: decoded.Digest, + } + if err := value.Validate(); err != nil { + return err + } + *f = value + return nil +} + +type authScopeFingerprintWire struct { + Mode AuthScopeMode `json:"mode"` + Algorithm string `json:"algorithm"` + Digest string `json:"digest"` +} diff --git a/internal/dataset/scope_test.go b/internal/dataset/scope_test.go new file mode 100644 index 0000000..1afd3de --- /dev/null +++ b/internal/dataset/scope_test.go @@ -0,0 +1,78 @@ +package dataset + +import ( + "bytes" + "encoding/json" + "errors" + "testing" +) + +func TestAuthScopeFingerprintCanonicalizesWithoutRetainingPaths(t *testing.T) { + paths := []string{"project-beta", "project-alpha"} + first, err := RestrictedAuthScopeFingerprint(paths) + if err != nil { + t.Fatalf("RestrictedAuthScopeFingerprint: %v", err) + } + second, err := RestrictedAuthScopeFingerprint([]string{"project-alpha", "project-beta"}) + if err != nil { + t.Fatalf("RestrictedAuthScopeFingerprint reordered: %v", err) + } + if !first.Equal(second) { + t.Fatalf("reordered scopes differ\nfirst: %#v\nsecond: %#v", first, second) + } + paths[0] = "mutated-after-construction" + if !first.Equal(second) { + t.Fatal("fingerprint changed after source slice mutation") + } + + emptyRestricted, err := RestrictedAuthScopeFingerprint(nil) + if err != nil { + t.Fatalf("RestrictedAuthScopeFingerprint(empty): %v", err) + } + unrestricted := UnrestrictedAuthScopeFingerprint() + if emptyRestricted.Equal(unrestricted) { + t.Fatal("restricted empty scope collided with unrestricted scope") + } + if got, want := emptyRestricted.Mode(), AuthScopeRestricted; got != want { + t.Fatalf("empty restricted mode = %q, want %q", got, want) + } + + encoded, err := json.Marshal(first) + if err != nil { + t.Fatalf("json.Marshal(AuthScopeFingerprint): %v", err) + } + if bytes.Contains(encoded, []byte("project-alpha")) || bytes.Contains(encoded, []byte("project-beta")) { + t.Fatalf("scope fingerprint JSON exposed raw paths: %s", encoded) + } + var decoded AuthScopeFingerprint + if err := json.Unmarshal(encoded, &decoded); err != nil { + t.Fatalf("json.Unmarshal(AuthScopeFingerprint): %v", err) + } + if !decoded.Equal(first) { + t.Fatalf("scope fingerprint did not round trip\ngot: %#v\nwant: %#v", decoded, first) + } +} + +func TestAuthScopeFingerprintRejectsAmbiguousOrInvalidValues(t *testing.T) { + for _, paths := range [][]string{ + {"project-a", "project-a"}, + {" project-a"}, + {""}, + {"project-a\nproject-b"}, + } { + if _, err := RestrictedAuthScopeFingerprint(paths); !errors.Is(err, ErrInvalidAuthScopeFingerprint) { + t.Errorf("RestrictedAuthScopeFingerprint(%#v) error = %v, want ErrInvalidAuthScopeFingerprint", paths, err) + } + } + + for _, raw := range []string{ + `{"mode":"restricted","algorithm":"md5","digest":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}`, + `{"mode":"restricted","algorithm":"sha256","digest":"not-a-digest"}`, + `{"mode":"restricted","algorithm":"sha256","digest":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","unknown":true}`, + } { + var fingerprint AuthScopeFingerprint + if err := json.Unmarshal([]byte(raw), &fingerprint); !errors.Is(err, ErrInvalidAuthScopeFingerprint) { + t.Errorf("json.Unmarshal(%s) error = %v, want ErrInvalidAuthScopeFingerprint", raw, err) + } + } +} diff --git a/internal/dataset/test_helpers_test.go b/internal/dataset/test_helpers_test.go new file mode 100644 index 0000000..418e510 --- /dev/null +++ b/internal/dataset/test_helpers_test.go @@ -0,0 +1,67 @@ +package dataset + +import ( + "strings" + "testing" +) + +const fixtureSchemaSHA256 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + +func fixtureSchema(t *testing.T) SchemaIdentitySnapshot { + t.Helper() + schema, err := NewSchemaIdentitySnapshot( + "urn:loom:test-schema", + "", + fixtureSchemaSHA256, + []string{"Patient", "Observation"}, + ) + if err != nil { + t.Fatalf("NewSchemaIdentitySnapshot: %v", err) + } + return schema +} + +func fixtureRef(t *testing.T, project, generation string) DatasetRef { + t.Helper() + ref, err := NewDatasetRef(project, generation) + if err != nil { + t.Fatalf("NewDatasetRef(%q, %q): %v", project, generation, err) + } + return ref +} + +func fixtureManifest(t *testing.T, project, generation string) Manifest { + t.Helper() + manifest, err := NewManifest(fixtureRef(t, project, generation), fixtureSchema(t)) + if err != nil { + t.Fatalf("NewManifest: %v", err) + } + return manifest +} + +func transitionManifest(t *testing.T, manifest Manifest, state ManifestState) Manifest { + t.Helper() + next, err := manifest.Transition(state) + if err != nil { + t.Fatalf("Transition(%s -> %s): %v", manifest.State, state, err) + } + return next +} + +func readyManifest(t *testing.T, project, generation string) Manifest { + t.Helper() + manifest := fixtureManifest(t, project, generation) + manifest = transitionManifest(t, manifest, ManifestStateLoading) + manifest = transitionManifest(t, manifest, ManifestStateAnalyzing) + return transitionManifest(t, manifest, ManifestStateReady) +} + +func failedManifest(t *testing.T, project, generation string) Manifest { + t.Helper() + manifest := fixtureManifest(t, project, generation) + return transitionManifest(t, manifest, ManifestStateFailed) +} + +func repeated(char string, count int) string { + return strings.Repeat(char, count) +} diff --git a/internal/dataset/validation.go b/internal/dataset/validation.go new file mode 100644 index 0000000..7bb4559 --- /dev/null +++ b/internal/dataset/validation.go @@ -0,0 +1,86 @@ +package dataset + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io" + "strings" + "unicode" + "unicode/utf8" +) + +const ( + maxOpaqueIdentifierBytes = 512 + maxResourceTypes = 4096 + maxScopePaths = 4096 +) + +var ( + // ErrInvalidDatasetRef reports a malformed project/generation pair. + ErrInvalidDatasetRef = errors.New("invalid dataset reference") + // ErrInvalidSchemaIdentity reports a malformed schema snapshot. + ErrInvalidSchemaIdentity = errors.New("invalid schema identity") + // ErrInvalidAnalysisVersion reports a malformed analysis-version value. + ErrInvalidAnalysisVersion = errors.New("invalid analysis version") + // ErrInvalidAuthScopeFingerprint reports a malformed scope fingerprint. + ErrInvalidAuthScopeFingerprint = errors.New("invalid authorization scope fingerprint") + // ErrInvalidManifest reports a manifest whose immutable values or state are + // not valid for this lifecycle contract. + ErrInvalidManifest = errors.New("invalid dataset manifest") + // ErrInvalidTransition reports a lifecycle transition that is not allowed. + ErrInvalidTransition = errors.New("invalid dataset manifest transition") + // ErrGenerationNotReady reports an attempt to select a generation that is + // not a finalized READY manifest. + ErrGenerationNotReady = errors.New("dataset generation is not ready") + // ErrInvalidActiveGeneration reports an invalid active-generation reference + // or an active-generation lookup that cannot resolve exactly one READY + // manifest. + ErrInvalidActiveGeneration = errors.New("invalid active dataset generation") +) + +func validateOpaqueIdentifier(field, value string, allowEmpty bool) error { + if value == "" { + if allowEmpty { + return nil + } + return fmt.Errorf("%s is required", field) + } + if !utf8.ValidString(value) { + return fmt.Errorf("%s must be valid UTF-8", field) + } + if len(value) > maxOpaqueIdentifierBytes { + return fmt.Errorf("%s exceeds %d bytes", field, maxOpaqueIdentifierBytes) + } + if strings.TrimSpace(value) != value { + return fmt.Errorf("%s must not have leading or trailing whitespace", field) + } + for _, r := range value { + if unicode.IsControl(r) { + return fmt.Errorf("%s must not contain control characters", field) + } + } + return nil +} + +// decodeStrictJSON rejects unknown fields and trailing values. The concrete +// value type still performs all semantic validation after decoding. +func decodeStrictJSON(data []byte, destination any) error { + decoder := json.NewDecoder(bytes.NewReader(data)) + decoder.DisallowUnknownFields() + if err := decoder.Decode(destination); err != nil { + return err + } + if err := decoder.Decode(&struct{}{}); !errors.Is(err, io.EOF) { + if err == nil { + return errors.New("multiple JSON values") + } + return err + } + return nil +} + +func isJSONNull(data []byte) bool { + return bytes.Equal(bytes.TrimSpace(data), []byte("null")) +} diff --git a/internal/datasetstore/collections.go b/internal/datasetstore/collections.go new file mode 100644 index 0000000..349fa4c --- /dev/null +++ b/internal/datasetstore/collections.go @@ -0,0 +1,35 @@ +package datasetstore + +import arangostore "github.com/calypr/loom/internal/store/arango" + +const ( + // LifecycleCollection stores two internal document shapes: immutable + // generation manifests and one active-generation pointer per project. They + // intentionally share a collection so activation can use one AQL UPDATE + // operation to change both records atomically. + LifecycleCollection = "loom_dataset_lifecycle" + + manifestRecordType = "manifest" + activeRecordType = "active_generation" +) + +// CollectionSpecs returns a fresh bootstrap specification for persistent +// dataset lifecycle metadata. It never requests truncation: a FHIR reload +// must not erase manifest history or an active-generation selection. +func CollectionSpecs() []arangostore.CollectionSpec { + return []arangostore.CollectionSpec{{ + Name: LifecycleCollection, + Indexes: [][]string{ + {"recordType", "dataset.project", "dataset.generation"}, + {"recordType", "state", "dataset.project"}, + {"recordType", "project"}, + }, + }} +} + +// BootstrapSpec returns the Arango bootstrap work needed by this adapter. +// Callers own when to bootstrap it; this package never wires the collection +// into ingest's truncate-oriented bootstrap path. +func BootstrapSpec() arangostore.BootstrapSpec { + return arangostore.BootstrapSpec{Collections: CollectionSpecs()} +} diff --git a/internal/datasetstore/doc.go b/internal/datasetstore/doc.go new file mode 100644 index 0000000..ad151f0 --- /dev/null +++ b/internal/datasetstore/doc.go @@ -0,0 +1,17 @@ +// Package datasetstore persists the immutable dataset generation lifecycle in +// ArangoDB. +// +// The adapter deliberately owns only manifests and the selected active +// generation. It does not load FHIR resources, build a catalog, resolve +// authorization, execute dataframes, or expose a public API. In particular it +// never stores raw authorization paths, tokens, subjects, claims, or a +// dataset.AuthScopeFingerprint: authorization scope is a per-read concern, +// not persistent generation metadata. +// +// A manifest record and its project's active-generation record live in one +// physical collection, distinguished by an internal record type. ArangoDB AQL +// permits one data-modification operation per statement. Keeping these two +// lifecycle records together lets Activate use one UPDATE statement to +// supersede the old READY manifest and select the new one atomically on a +// single-server deployment. +package datasetstore diff --git a/internal/datasetstore/store.go b/internal/datasetstore/store.go new file mode 100644 index 0000000..2f2f9ea --- /dev/null +++ b/internal/datasetstore/store.go @@ -0,0 +1,704 @@ +package datasetstore + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + + "github.com/calypr/loom/internal/dataset" + arangostore "github.com/calypr/loom/internal/store/arango" +) + +const ( + defaultCursorBatchSize = 32 + documentKeyDomain = "loom.datasetstore.v1" +) + +var ( + // ErrNilQueryClient reports an unusable Store dependency. + ErrNilQueryClient = errors.New("dataset store query client is required") + // ErrInvalidCursorBatchSize reports a non-positive cursor batch size. + ErrInvalidCursorBatchSize = errors.New("dataset store cursor batch size must be positive") + // ErrManifestAlreadyExists reports an attempt to create a second immutable + // manifest for the same project and generation. + ErrManifestAlreadyExists = errors.New("dataset manifest already exists") + // ErrManifestNotFound reports a missing manifest reference. + ErrManifestNotFound = errors.New("dataset manifest was not found") + // ErrManifestTransitionConflict reports that the persisted manifest no + // longer exactly matches the caller's expected immutable version and state. + ErrManifestTransitionConflict = errors.New("dataset manifest transition conflict") + // ErrActiveGenerationNotFound reports a project with no active READY + // generation. It also protects callers from treating a corrupt active + // pointer as a usable generation. + ErrActiveGenerationNotFound = errors.New("active dataset generation was not found") + // ErrActivationConflict reports a candidate that was not persisted READY, + // a missing active pointer record, or an invalid prior active pointer. + ErrActivationConflict = errors.New("dataset activation conflict") + // ErrUnexpectedStoreResult reports malformed, duplicate, or inconsistent + // rows returned by the persistence backend. + ErrUnexpectedStoreResult = errors.New("unexpected dataset store result") +) + +// QueryRowsClient is the minimal Arango capability required by Store. The +// concrete *arango.Client satisfies it, while tests and future transaction +// adapters can supply a small fake without opening a network connection. +type QueryRowsClient interface { + QueryRows(context.Context, string, int, map[string]interface{}, arangostore.RowVisitor) error +} + +var _ QueryRowsClient = (*arangostore.Client)(nil) +var _ dataset.ActiveManifestResolver = (*Store)(nil) + +// Store persists dataset manifests and active-generation pointers. Its zero +// value is intentionally unusable; construct it with New or NewWithBatchSize. +type Store struct { + client QueryRowsClient + batchSize int +} + +// New constructs a Store with a small metadata-oriented cursor batch size. +func New(client QueryRowsClient) (*Store, error) { + return NewWithBatchSize(client, defaultCursorBatchSize) +} + +// NewWithBatchSize constructs a Store with an explicit positive cursor batch +// size. It performs no I/O and does not bootstrap collections. +func NewWithBatchSize(client QueryRowsClient, batchSize int) (*Store, error) { + if client == nil { + return nil, ErrNilQueryClient + } + if batchSize <= 0 { + return nil, ErrInvalidCursorBatchSize + } + return &Store{client: client, batchSize: batchSize}, nil +} + +// CreateManifest persists a new immutable PREFLIGHT manifest. It uses a +// deterministic, opaque document key for the project/generation reference and +// creates an empty active-generation pointer for a project the first time it +// is seen. Neither document contains authorization scope data. +func (s *Store) CreateManifest(ctx context.Context, manifest dataset.Manifest) (dataset.Manifest, error) { + if err := manifest.Validate(); err != nil { + return dataset.Manifest{}, fmt.Errorf("create dataset manifest: %w", err) + } + if manifest.State != dataset.ManifestStatePreflight { + return dataset.Manifest{}, fmt.Errorf("create dataset manifest: %w: state must be %s, got %s", dataset.ErrInvalidTransition, dataset.ManifestStatePreflight, manifest.State) + } + if err := s.validate(); err != nil { + return dataset.Manifest{}, err + } + + document, err := manifestDocument(manifest) + if err != nil { + return dataset.Manifest{}, err + } + bindVars := lifecycleBindVars(manifest.Dataset.Project) + bindVars["manifest"] = document + bindVars["active_placeholder"] = activePlaceholderDocument(manifest.Dataset.Project) + bindVars["manifest_key"] = manifestDocumentKey(manifest.Dataset) + bindVars["active_key"] = activeDocumentKey(manifest.Dataset.Project) + + var created *dataset.Manifest + var unexpected error + err = s.client.QueryRows(ctx, createManifestAQL, s.batchSize, bindVars, func(row map[string]any) error { + recordType, _ := row["recordType"].(string) + switch recordType { + case manifestRecordType: + if created != nil { + unexpected = fmt.Errorf("%w: create returned more than one manifest", ErrUnexpectedStoreResult) + return unexpected + } + decoded, err := manifestFromValue(row["manifest"]) + if err != nil { + unexpected = err + return err + } + if !decoded.Dataset.Equal(manifest.Dataset) || decoded.State != dataset.ManifestStatePreflight || !decoded.SchemaIdentity.Equal(manifest.SchemaIdentity) || decoded.AnalysisVersion != manifest.AnalysisVersion { + unexpected = fmt.Errorf("%w: created manifest does not match request", ErrUnexpectedStoreResult) + return unexpected + } + copy := decoded.Clone() + created = © + case activeRecordType: + // The first manifest for a project also inserts its empty active + // pointer. There is deliberately no active dataset to decode yet. + default: + unexpected = fmt.Errorf("%w: create returned record type %q", ErrUnexpectedStoreResult, recordType) + return unexpected + } + return nil + }) + if err != nil { + if unexpected != nil { + return dataset.Manifest{}, unexpected + } + return dataset.Manifest{}, fmt.Errorf("create dataset manifest: %w", err) + } + if created == nil { + return dataset.Manifest{}, fmt.Errorf("%w: %s/%s", ErrManifestAlreadyExists, manifest.Dataset.Project, manifest.Dataset.Generation) + } + return created.Clone(), nil +} + +// ReadManifest returns exactly one persisted manifest named by ref. It does +// not infer a generation or silently select a different one. +func (s *Store) ReadManifest(ctx context.Context, ref dataset.DatasetRef) (dataset.Manifest, error) { + if err := ref.Validate(); err != nil { + return dataset.Manifest{}, fmt.Errorf("read dataset manifest: %w", err) + } + if err := s.validate(); err != nil { + return dataset.Manifest{}, err + } + bindVars := lifecycleBindVars(ref.Project) + bindVars["manifest_key"] = manifestDocumentKey(ref) + bindVars["generation"] = ref.Generation + + rows, err := s.manifestRows(ctx, readManifestAQL, bindVars) + if err != nil { + return dataset.Manifest{}, fmt.Errorf("read dataset manifest: %w", err) + } + if len(rows) == 0 { + return dataset.Manifest{}, fmt.Errorf("%w: %s/%s", ErrManifestNotFound, ref.Project, ref.Generation) + } + if len(rows) != 1 { + return dataset.Manifest{}, fmt.Errorf("%w: read returned %d manifests for %s/%s", ErrUnexpectedStoreResult, len(rows), ref.Project, ref.Generation) + } + manifest := rows[0] + if !manifest.Dataset.Equal(ref) { + return dataset.Manifest{}, fmt.Errorf("%w: read manifest reference does not match request", ErrUnexpectedStoreResult) + } + return manifest.Clone(), nil +} + +// TransitionManifest applies one allowed lifecycle transition to the exact +// immutable manifest value supplied by the caller. The AQL filter includes +// schema and analysis metadata as well as the current state, so a stale or +// substituted manifest cannot mutate a different persisted generation. +func (s *Store) TransitionManifest(ctx context.Context, manifest dataset.Manifest, next dataset.ManifestState) (dataset.Manifest, error) { + nextManifest, err := manifest.Transition(next) + if err != nil { + return dataset.Manifest{}, fmt.Errorf("transition dataset manifest: %w", err) + } + if err := s.validate(); err != nil { + return dataset.Manifest{}, err + } + + schemaIdentity, err := schemaIdentityBindValue(manifest.SchemaIdentity) + if err != nil { + return dataset.Manifest{}, err + } + bindVars := lifecycleBindVars(manifest.Dataset.Project) + bindVars["manifest_key"] = manifestDocumentKey(manifest.Dataset) + bindVars["generation"] = manifest.Dataset.Generation + bindVars["expected_state"] = string(manifest.State) + bindVars["next_state"] = string(next) + bindVars["schema_identity"] = schemaIdentity + bindVars["analysis_version"] = string(manifest.AnalysisVersion) + + rows, err := s.manifestRows(ctx, transitionManifestAQL, bindVars) + if err != nil { + return dataset.Manifest{}, fmt.Errorf("transition dataset manifest: %w", err) + } + if len(rows) == 0 { + return dataset.Manifest{}, fmt.Errorf("%w: %s/%s was not %s with the expected immutable metadata", ErrManifestTransitionConflict, manifest.Dataset.Project, manifest.Dataset.Generation, manifest.State) + } + if len(rows) != 1 { + return dataset.Manifest{}, fmt.Errorf("%w: transition returned %d manifests", ErrUnexpectedStoreResult, len(rows)) + } + persisted := rows[0] + if !manifestIdentityEqual(persisted, nextManifest) { + return dataset.Manifest{}, fmt.Errorf("%w: transition result does not match requested state", ErrUnexpectedStoreResult) + } + return persisted.Clone(), nil +} + +// ReadActive returns the active generation only when its pointer resolves to +// the exact persisted READY manifest. It is a convenience wrapper around +// ResolveActiveManifest; callers that also need immutable generation metadata +// should use that method to avoid a second read and an active-switch race. +func (s *Store) ReadActive(ctx context.Context, project string) (dataset.ActiveGeneration, error) { + resolution, err := s.resolveActive(ctx, project) + if err != nil { + return dataset.ActiveGeneration{}, err + } + return resolution.active, nil +} + +// ResolveActiveManifest returns the immutable READY manifest named by a +// project's active pointer using one AQL join. It is the race-free read entry +// point for future discovery, dataframe, cache, and export adapters that need +// both the active selection and its schema or analysis metadata. +func (s *Store) ResolveActiveManifest(ctx context.Context, project string) (dataset.Manifest, error) { + resolution, err := s.resolveActive(ctx, project) + if err != nil { + return dataset.Manifest{}, err + } + return resolution.manifest.Clone(), nil +} + +type activeResolution struct { + active dataset.ActiveGeneration + manifest dataset.Manifest +} + +func (s *Store) resolveActive(ctx context.Context, project string) (activeResolution, error) { + if err := validateProject(project); err != nil { + return activeResolution{}, fmt.Errorf("resolve active dataset generation: %w", err) + } + if err := s.validate(); err != nil { + return activeResolution{}, err + } + bindVars := lifecycleBindVars(project) + bindVars["active_key"] = activeDocumentKey(project) + bindVars["ready_state"] = string(dataset.ManifestStateReady) + + var resolutions []activeResolution + var unexpected error + err := s.client.QueryRows(ctx, readActiveAQL, s.batchSize, bindVars, func(row map[string]any) error { + decoded, err := activeResolutionFromRow(row) + if err != nil { + unexpected = err + return err + } + if decoded.active.Dataset.Project != project || !decoded.active.Dataset.Equal(decoded.manifest.Dataset) || decoded.manifest.State != dataset.ManifestStateReady { + unexpected = fmt.Errorf("%w: active pointer and READY manifest are inconsistent", ErrUnexpectedStoreResult) + return unexpected + } + resolutions = append(resolutions, decoded) + if len(resolutions) > 1 { + unexpected = fmt.Errorf("%w: read active returned multiple rows", ErrUnexpectedStoreResult) + return unexpected + } + return nil + }) + if err != nil { + if unexpected != nil { + return activeResolution{}, unexpected + } + return activeResolution{}, fmt.Errorf("resolve active dataset generation: %w", err) + } + if len(resolutions) == 0 { + return activeResolution{}, fmt.Errorf("%w: %s", ErrActiveGenerationNotFound, project) + } + return resolutions[0], nil +} + +// Activate atomically selects a persisted READY candidate as a project's +// active generation. If a different READY generation was already active, the +// same single AQL UPDATE statement changes it to SUPERSEDED. The returned +// plan records the switch that was actually performed. The statement includes +// a state-preserving candidate update with revision checking so a concurrently +// superseded candidate cannot be selected from a stale read snapshot. +func (s *Store) Activate(ctx context.Context, candidate dataset.Manifest) (dataset.ActivationPlan, error) { + active, err := dataset.ActiveGenerationFor(candidate) + if err != nil { + return dataset.ActivationPlan{}, fmt.Errorf("activate dataset generation: %w", err) + } + if err := s.validate(); err != nil { + return dataset.ActivationPlan{}, err + } + schemaIdentity, err := schemaIdentityBindValue(candidate.SchemaIdentity) + if err != nil { + return dataset.ActivationPlan{}, err + } + + bindVars := lifecycleBindVars(candidate.Dataset.Project) + bindVars["candidate_key"] = manifestDocumentKey(candidate.Dataset) + bindVars["active_key"] = activeDocumentKey(candidate.Dataset.Project) + bindVars["generation"] = candidate.Dataset.Generation + bindVars["schema_identity"] = schemaIdentity + bindVars["analysis_version"] = string(candidate.AnalysisVersion) + bindVars["ready_state"] = string(dataset.ManifestStateReady) + bindVars["superseded_state"] = string(dataset.ManifestStateSuperseded) + bindVars["superseded_role"] = "superseded_manifest" + bindVars["candidate_guard_role"] = "candidate_guard" + + var result dataset.ActivationPlan + var candidateGuardSeen bool + var activeSeen bool + var previousSeen bool + var unexpected error + err = s.client.QueryRows(ctx, activateAQL, s.batchSize, bindVars, func(row map[string]any) error { + role, _ := row["role"].(string) + switch role { + case "candidate_guard": + if candidateGuardSeen { + unexpected = fmt.Errorf("%w: activation returned more than one candidate guard", ErrUnexpectedStoreResult) + return unexpected + } + guarded, err := datasetRefFromValue(row["dataset"]) + if err != nil { + unexpected = err + return err + } + if !guarded.Equal(candidate.Dataset) { + unexpected = fmt.Errorf("%w: candidate guard updated a different dataset", ErrUnexpectedStoreResult) + return unexpected + } + candidateGuardSeen = true + case activeRecordType: + if activeSeen { + unexpected = fmt.Errorf("%w: activation returned more than one active pointer", ErrUnexpectedStoreResult) + return unexpected + } + decoded, err := activeFromValue(map[string]any{"dataset": row["dataset"]}) + if err != nil { + unexpected = err + return err + } + if !decoded.Dataset.Equal(active.Dataset) { + unexpected = fmt.Errorf("%w: activation selected a different dataset", ErrUnexpectedStoreResult) + return unexpected + } + result.Active = decoded + activeSeen = true + case "superseded_manifest": + if previousSeen { + unexpected = fmt.Errorf("%w: activation returned more than one superseded manifest", ErrUnexpectedStoreResult) + return unexpected + } + previous, err := datasetRefFromValue(row["previous"]) + if err != nil { + unexpected = err + return err + } + if previous.Project != candidate.Dataset.Project || previous.Equal(candidate.Dataset) { + unexpected = fmt.Errorf("%w: invalid superseded dataset reference", ErrUnexpectedStoreResult) + return unexpected + } + result.Previous = &previous + previousSeen = true + default: + unexpected = fmt.Errorf("%w: activation returned role %q", ErrUnexpectedStoreResult, role) + return unexpected + } + return nil + }) + if err != nil { + if unexpected != nil { + return dataset.ActivationPlan{}, unexpected + } + return dataset.ActivationPlan{}, fmt.Errorf("activate dataset generation: %w", err) + } + if !candidateGuardSeen || !activeSeen { + return dataset.ActivationPlan{}, fmt.Errorf("%w: candidate %s/%s was not a persisted READY manifest with a valid active pointer", ErrActivationConflict, candidate.Dataset.Project, candidate.Dataset.Generation) + } + if err := result.Validate(); err != nil { + return dataset.ActivationPlan{}, fmt.Errorf("%w: activation result: %v", ErrUnexpectedStoreResult, err) + } + return result, nil +} + +func (s *Store) validate() error { + if s == nil || s.client == nil { + return ErrNilQueryClient + } + if s.batchSize <= 0 { + return ErrInvalidCursorBatchSize + } + return nil +} + +func (s *Store) manifestRows(ctx context.Context, query string, bindVars map[string]any) ([]dataset.Manifest, error) { + rows := make([]dataset.Manifest, 0, 1) + var unexpected error + err := s.client.QueryRows(ctx, query, s.batchSize, bindVars, func(row map[string]any) error { + manifest, err := manifestFromValue(row) + if err != nil { + unexpected = err + return err + } + rows = append(rows, manifest) + if len(rows) > 1 { + unexpected = fmt.Errorf("%w: query returned multiple manifests", ErrUnexpectedStoreResult) + return unexpected + } + return nil + }) + if err != nil { + if unexpected != nil { + return nil, unexpected + } + return nil, err + } + return rows, nil +} + +func lifecycleBindVars(project string) map[string]any { + return map[string]any{ + "@lifecycle_collection": LifecycleCollection, + "project": project, + "manifest_record_type": manifestRecordType, + "active_record_type": activeRecordType, + } +} + +func validateProject(project string) error { + _, err := dataset.NewDatasetRef(project, "datasetstore-project-validation") + return err +} + +func manifestDocument(manifest dataset.Manifest) (map[string]any, error) { + data, err := json.Marshal(manifest) + if err != nil { + return nil, fmt.Errorf("encode dataset manifest document: %w", err) + } + var document map[string]any + if err := json.Unmarshal(data, &document); err != nil { + return nil, fmt.Errorf("decode dataset manifest document: %w", err) + } + document["_key"] = manifestDocumentKey(manifest.Dataset) + document["recordType"] = manifestRecordType + return document, nil +} + +func activePlaceholderDocument(project string) map[string]any { + return map[string]any{ + "_key": activeDocumentKey(project), + "recordType": activeRecordType, + "project": project, + } +} + +func schemaIdentityBindValue(identity dataset.SchemaIdentitySnapshot) (map[string]any, error) { + data, err := json.Marshal(identity) + if err != nil { + return nil, fmt.Errorf("encode schema identity bind value: %w", err) + } + var value map[string]any + if err := json.Unmarshal(data, &value); err != nil { + return nil, fmt.Errorf("decode schema identity bind value: %w", err) + } + return value, nil +} + +func manifestFromValue(value any) (dataset.Manifest, error) { + data, err := json.Marshal(value) + if err != nil { + return dataset.Manifest{}, fmt.Errorf("%w: encode manifest row: %v", ErrUnexpectedStoreResult, err) + } + var manifest dataset.Manifest + if err := json.Unmarshal(data, &manifest); err != nil { + return dataset.Manifest{}, fmt.Errorf("%w: decode manifest row: %v", ErrUnexpectedStoreResult, err) + } + return manifest, nil +} + +func activeResolutionFromRow(row map[string]any) (activeResolution, error) { + active, err := activeFromValue(row["active"]) + if err != nil { + return activeResolution{}, err + } + manifest, err := manifestFromValue(row["manifest"]) + if err != nil { + return activeResolution{}, err + } + return activeResolution{active: active, manifest: manifest}, nil +} + +func activeFromValue(value any) (dataset.ActiveGeneration, error) { + data, err := json.Marshal(value) + if err != nil { + return dataset.ActiveGeneration{}, fmt.Errorf("%w: encode active generation row: %v", ErrUnexpectedStoreResult, err) + } + var active dataset.ActiveGeneration + if err := json.Unmarshal(data, &active); err != nil { + return dataset.ActiveGeneration{}, fmt.Errorf("%w: decode active generation row: %v", ErrUnexpectedStoreResult, err) + } + return active, nil +} + +func datasetRefFromValue(value any) (dataset.DatasetRef, error) { + data, err := json.Marshal(value) + if err != nil { + return dataset.DatasetRef{}, fmt.Errorf("%w: encode dataset reference row: %v", ErrUnexpectedStoreResult, err) + } + var ref dataset.DatasetRef + if err := json.Unmarshal(data, &ref); err != nil { + return dataset.DatasetRef{}, fmt.Errorf("%w: decode dataset reference row: %v", ErrUnexpectedStoreResult, err) + } + return ref, nil +} + +func manifestIdentityEqual(left, right dataset.Manifest) bool { + return left.Dataset.Equal(right.Dataset) && + left.State == right.State && + left.SchemaIdentity.Equal(right.SchemaIdentity) && + left.AnalysisVersion == right.AnalysisVersion +} + +func manifestDocumentKey(ref dataset.DatasetRef) string { + return documentKey("manifest", ref.Project, ref.Generation) +} + +func activeDocumentKey(project string) string { + return documentKey("active", project) +} + +func documentKey(kind string, values ...string) string { + hash := sha256.New() + _, _ = hash.Write([]byte(documentKeyDomain)) + for _, value := range append([]string{kind}, values...) { + _, _ = hash.Write([]byte{0}) + _, _ = hash.Write([]byte(value)) + } + return kind + "_" + hex.EncodeToString(hash.Sum(nil)) +} + +// The collection is always bound through @@lifecycle_collection. Project, +// generation, states, schema metadata, and document payloads are scalar bind +// values; no user-controlled identifier is interpolated into AQL text. +const createManifestAQL = ` +LET existing = FIRST( + FOR manifest IN @@lifecycle_collection + FILTER manifest._key == @manifest_key + FILTER manifest.recordType == @manifest_record_type + RETURN manifest +) +FILTER existing == null +LET active = FIRST( + FOR pointer IN @@lifecycle_collection + FILTER pointer._key == @active_key + FILTER pointer.recordType == @active_record_type + FILTER pointer.project == @project + RETURN pointer +) +LET documents = active == null ? [@manifest, @active_placeholder] : [@manifest] +FOR document IN documents + INSERT document INTO @@lifecycle_collection + RETURN { + recordType: NEW.recordType, + manifest: NEW.recordType == @manifest_record_type ? { + dataset: NEW.dataset, + state: NEW.state, + schemaIdentity: NEW.schemaIdentity, + analysisVersion: NEW.analysisVersion + } : null + } +` + +const readManifestAQL = ` +FOR manifest IN @@lifecycle_collection + FILTER manifest._key == @manifest_key + FILTER manifest.recordType == @manifest_record_type + FILTER manifest.dataset.project == @project + FILTER manifest.dataset.generation == @generation + LIMIT 2 + RETURN { + dataset: manifest.dataset, + state: manifest.state, + schemaIdentity: manifest.schemaIdentity, + analysisVersion: manifest.analysisVersion + } +` + +const transitionManifestAQL = ` +FOR manifest IN @@lifecycle_collection + FILTER manifest._key == @manifest_key + FILTER manifest.recordType == @manifest_record_type + FILTER manifest.dataset.project == @project + FILTER manifest.dataset.generation == @generation + FILTER manifest.state == @expected_state + FILTER manifest.schemaIdentity == @schema_identity + FILTER manifest.analysisVersion == @analysis_version + UPDATE manifest WITH { state: @next_state } IN @@lifecycle_collection + RETURN { + dataset: NEW.dataset, + state: NEW.state, + schemaIdentity: NEW.schemaIdentity, + analysisVersion: NEW.analysisVersion + } +` + +const readActiveAQL = ` +FOR active IN @@lifecycle_collection + FILTER active._key == @active_key + FILTER active.recordType == @active_record_type + FILTER active.project == @project + FILTER active.manifestKey != null + FOR manifest IN @@lifecycle_collection + FILTER manifest._key == active.manifestKey + FILTER manifest.recordType == @manifest_record_type + FILTER manifest.dataset == active.dataset + FILTER manifest.state == @ready_state + LIMIT 2 + RETURN { + active: { dataset: active.dataset }, + manifest: { + dataset: manifest.dataset, + state: manifest.state, + schemaIdentity: manifest.schemaIdentity, + analysisVersion: manifest.analysisVersion + } + } +` + +// activateAQL has exactly one UPDATE statement. The candidate guard updates +// READY to READY only to put its revision into the AQL write set; it is a CAS +// guard, not a lifecycle transition. With ignoreRevs:false, a concurrent +// change to the candidate, prior active manifest, or active pointer aborts the +// whole single-server transaction instead of selecting stale state. +const activateAQL = ` +LET candidate = FIRST( + FOR manifest IN @@lifecycle_collection + FILTER manifest._key == @candidate_key + FILTER manifest.recordType == @manifest_record_type + FILTER manifest.dataset.project == @project + FILTER manifest.dataset.generation == @generation + FILTER manifest.state == @ready_state + FILTER manifest.schemaIdentity == @schema_identity + FILTER manifest.analysisVersion == @analysis_version + RETURN manifest +) +LET active = FIRST( + FOR pointer IN @@lifecycle_collection + FILTER pointer._key == @active_key + FILTER pointer.recordType == @active_record_type + FILTER pointer.project == @project + RETURN pointer +) +FILTER candidate != null +FILTER active != null +LET previous = FIRST( + FOR manifest IN @@lifecycle_collection + FILTER active.manifestKey != null + FILTER manifest._key == active.manifestKey + FILTER manifest.recordType == @manifest_record_type + FILTER manifest.dataset == active.dataset + FILTER manifest.state == @ready_state + RETURN manifest +) +FILTER ( + (active.dataset == null AND active.manifestKey == null) OR + ( + active.dataset != null AND + active.dataset.project == @project AND + active.manifestKey != null AND + previous != null + ) +) +LET updates = APPEND( + [{ document: candidate, patch: { state: @ready_state }, role: @candidate_guard_role }], + APPEND( + previous != null AND previous._key != candidate._key + ? [{ document: previous, patch: { state: @superseded_state }, role: @superseded_role }] + : [], + [{ + document: active, + patch: { dataset: candidate.dataset, manifestKey: candidate._key }, + role: @active_record_type + }] + ) +) +FOR update IN updates + UPDATE update.document WITH update.patch IN @@lifecycle_collection + OPTIONS { ignoreRevs: false, mergeObjects: false } + RETURN { + role: update.role, + dataset: NEW.dataset, + previous: update.role == @superseded_role ? OLD.dataset : null + } +` diff --git a/internal/datasetstore/store_test.go b/internal/datasetstore/store_test.go new file mode 100644 index 0000000..393ef9d --- /dev/null +++ b/internal/datasetstore/store_test.go @@ -0,0 +1,477 @@ +package datasetstore + +import ( + "context" + "encoding/json" + "errors" + "reflect" + "regexp" + "strings" + "testing" + + "github.com/calypr/loom/internal/dataset" + arangostore "github.com/calypr/loom/internal/store/arango" +) + +func TestCollectionSpecsKeepLifecycleMetadataOutOfTruncateBootstrap(t *testing.T) { + specs := CollectionSpecs() + if len(specs) != 1 { + t.Fatalf("CollectionSpecs() length = %d, want 1", len(specs)) + } + spec := specs[0] + if spec.Name != LifecycleCollection { + t.Fatalf("collection name = %q, want %q", spec.Name, LifecycleCollection) + } + if spec.Edge || spec.Truncate { + t.Fatalf("lifecycle collection edge/truncate = %t/%t, want false/false", spec.Edge, spec.Truncate) + } + for _, required := range [][]string{ + {"recordType", "dataset.project", "dataset.generation"}, + {"recordType", "state", "dataset.project"}, + {"recordType", "project"}, + } { + if !hasIndex(spec.Indexes, required) { + t.Fatalf("indexes %#v do not contain %#v", spec.Indexes, required) + } + } + + bootstrap := BootstrapSpec() + if len(bootstrap.Collections) != 1 || bootstrap.Collections[0].Name != LifecycleCollection { + t.Fatalf("BootstrapSpec() = %#v, want only %q", bootstrap, LifecycleCollection) + } +} + +func TestNewValidatesDependencyAndCursorBatch(t *testing.T) { + if _, err := New(nil); !errors.Is(err, ErrNilQueryClient) { + t.Fatalf("New(nil) error = %v, want ErrNilQueryClient", err) + } + if _, err := NewWithBatchSize(&fakeQueryClient{}, 0); !errors.Is(err, ErrInvalidCursorBatchSize) { + t.Fatalf("NewWithBatchSize(..., 0) error = %v, want ErrInvalidCursorBatchSize", err) + } + store, err := NewWithBatchSize(&fakeQueryClient{}, 7) + if err != nil { + t.Fatalf("NewWithBatchSize: %v", err) + } + if store.batchSize != 7 { + t.Fatalf("batch size = %d, want 7", store.batchSize) + } +} + +func TestCreateManifestBuildsOpaqueBoundDocumentsAndNeverPersistsAuthScope(t *testing.T) { + manifest := fixtureManifest(t, "project-a", "generation-a", dataset.ManifestStatePreflight) + fake := &fakeQueryClient{responses: [][]map[string]any{{ + { + "recordType": manifestRecordType, + "manifest": jsonObject(t, manifest), + }, + {"recordType": activeRecordType, "manifest": nil}, + }}} + store := mustStore(t, fake) + + created, err := store.CreateManifest(context.Background(), manifest) + if err != nil { + t.Fatalf("CreateManifest: %v", err) + } + if !manifestIdentityEqual(created, manifest) { + t.Fatalf("created manifest = %#v, want %#v", created, manifest) + } + call := fake.onlyCall(t) + assertAllAQLBindsSupplied(t, call) + if strings.Count(call.query, "INSERT ") != 1 || !strings.Contains(call.query, "@@lifecycle_collection") { + t.Fatalf("create query is not the expected single INSERT statement:\n%s", call.query) + } + if strings.Contains(call.query, manifest.Dataset.Project) || strings.Contains(call.query, manifest.Dataset.Generation) { + t.Fatalf("create query interpolated request identity:\n%s", call.query) + } + if got := call.bindVars["@lifecycle_collection"]; got != LifecycleCollection { + t.Fatalf("collection bind = %#v, want %q", got, LifecycleCollection) + } + stored, ok := call.bindVars["manifest"].(map[string]any) + if !ok { + t.Fatalf("manifest bind type = %T, want map[string]any", call.bindVars["manifest"]) + } + if stored["_key"] != manifestDocumentKey(manifest.Dataset) || stored["recordType"] != manifestRecordType { + t.Fatalf("manifest bind identity = %#v", stored) + } + if call.bindVars["manifest_key"] != manifestDocumentKey(manifest.Dataset) || call.bindVars["active_key"] != activeDocumentKey(manifest.Dataset.Project) { + t.Fatalf("create document key binds = %#v", call.bindVars) + } + activePlaceholder, ok := call.bindVars["active_placeholder"].(map[string]any) + if !ok { + t.Fatalf("active placeholder bind type = %T", call.bindVars["active_placeholder"]) + } + if activePlaceholder["_key"] != activeDocumentKey(manifest.Dataset.Project) || activePlaceholder["project"] != manifest.Dataset.Project { + t.Fatalf("active placeholder = %#v", activePlaceholder) + } + assertNoAuthScope(t, call.bindVars) + + if strings.Contains(manifestDocumentKey(manifest.Dataset), manifest.Dataset.Project) || strings.Contains(activeDocumentKey(manifest.Dataset.Project), manifest.Dataset.Project) { + t.Fatal("deterministic document key leaked the raw project") + } +} + +func TestCreateManifestRejectsNonPreflightAndDoesNotQuery(t *testing.T) { + fake := &fakeQueryClient{} + store := mustStore(t, fake) + ready := fixtureManifest(t, "project-a", "generation-a", dataset.ManifestStateReady) + if _, err := store.CreateManifest(context.Background(), ready); !errors.Is(err, dataset.ErrInvalidTransition) { + t.Fatalf("CreateManifest(READY) error = %v, want ErrInvalidTransition", err) + } + if len(fake.calls) != 0 { + t.Fatalf("CreateManifest(READY) made %d queries", len(fake.calls)) + } +} + +func TestReadAndTransitionManifestUseExactIdentityAndBoundValues(t *testing.T) { + loading := fixtureManifest(t, "project-a", "generation-a", dataset.ManifestStateLoading) + analyzing, err := loading.Transition(dataset.ManifestStateAnalyzing) + if err != nil { + t.Fatalf("loading.Transition(ANALYZING): %v", err) + } + fake := &fakeQueryClient{responses: [][]map[string]any{ + {jsonObject(t, loading)}, + {jsonObject(t, analyzing)}, + }} + store := mustStore(t, fake) + + read, err := store.ReadManifest(context.Background(), loading.Dataset) + if err != nil { + t.Fatalf("ReadManifest: %v", err) + } + if !manifestIdentityEqual(read, loading) { + t.Fatalf("ReadManifest = %#v, want %#v", read, loading) + } + readCall := fake.calls[0] + assertAllAQLBindsSupplied(t, readCall) + if !strings.Contains(readCall.query, "manifest._key == @manifest_key") || strings.Contains(readCall.query, loading.Dataset.Project) { + t.Fatalf("read query/binding is unsafe:\n%s", readCall.query) + } + if got := readCall.bindVars["manifest_key"]; got != manifestDocumentKey(loading.Dataset) { + t.Fatalf("read manifest key = %#v", got) + } + + transitioned, err := store.TransitionManifest(context.Background(), loading, dataset.ManifestStateAnalyzing) + if err != nil { + t.Fatalf("TransitionManifest: %v", err) + } + if !manifestIdentityEqual(transitioned, analyzing) { + t.Fatalf("TransitionManifest = %#v, want %#v", transitioned, analyzing) + } + transitionCall := fake.calls[1] + assertAllAQLBindsSupplied(t, transitionCall) + if strings.Count(transitionCall.query, "UPDATE ") != 1 || !strings.Contains(transitionCall.query, "manifest.schemaIdentity == @schema_identity") || !strings.Contains(transitionCall.query, "manifest.analysisVersion == @analysis_version") { + t.Fatalf("transition query is missing immutable guards:\n%s", transitionCall.query) + } + if transitionCall.bindVars["expected_state"] != string(dataset.ManifestStateLoading) || transitionCall.bindVars["next_state"] != string(dataset.ManifestStateAnalyzing) { + t.Fatalf("transition state binds = %#v", transitionCall.bindVars) + } + if _, ok := transitionCall.bindVars["schema_identity"].(map[string]any); !ok { + t.Fatalf("schema identity bind type = %T", transitionCall.bindVars["schema_identity"]) + } + assertNoAuthScope(t, transitionCall.bindVars) +} + +func TestTransitionManifestRejectsInvalidTransitionBeforeQuery(t *testing.T) { + fake := &fakeQueryClient{} + store := mustStore(t, fake) + ready := fixtureManifest(t, "project-a", "generation-a", dataset.ManifestStateReady) + if _, err := store.TransitionManifest(context.Background(), ready, dataset.ManifestStateLoading); !errors.Is(err, dataset.ErrInvalidTransition) { + t.Fatalf("TransitionManifest(READY -> LOADING) error = %v, want ErrInvalidTransition", err) + } + if len(fake.calls) != 0 { + t.Fatalf("invalid transition made %d queries", len(fake.calls)) + } +} + +func TestReadActiveRequiresPersistedReadyManifest(t *testing.T) { + ready := fixtureManifest(t, "project-a", "generation-a", dataset.ManifestStateReady) + fake := &fakeQueryClient{responses: [][]map[string]any{{ + { + "active": map[string]any{"dataset": jsonObject(t, ready.Dataset)}, + "manifest": jsonObject(t, ready), + }, + }}} + store := mustStore(t, fake) + + active, err := store.ReadActive(context.Background(), ready.Dataset.Project) + if err != nil { + t.Fatalf("ReadActive: %v", err) + } + if !active.Dataset.Equal(ready.Dataset) { + t.Fatalf("ReadActive dataset = %#v, want %#v", active.Dataset, ready.Dataset) + } + call := fake.onlyCall(t) + assertAllAQLBindsSupplied(t, call) + if !strings.Contains(call.query, "manifest.state == @ready_state") || !strings.Contains(call.query, "manifest.dataset == active.dataset") { + t.Fatalf("read-active query does not validate persisted READY manifest:\n%s", call.query) + } + if call.bindVars["ready_state"] != string(dataset.ManifestStateReady) { + t.Fatalf("read-active ready state bind = %#v", call.bindVars["ready_state"]) + } + if got := call.bindVars["active_key"]; got != activeDocumentKey(ready.Dataset.Project) { + t.Fatalf("active key = %#v", got) + } + assertNoAuthScope(t, call.bindVars) +} + +func TestResolveActiveManifestReturnsReadySnapshotFromSameQuery(t *testing.T) { + ready := fixtureManifest(t, "project-a", "generation-a", dataset.ManifestStateReady) + fake := &fakeQueryClient{responses: [][]map[string]any{{ + { + "active": map[string]any{"dataset": jsonObject(t, ready.Dataset)}, + "manifest": jsonObject(t, ready), + }, + }}} + store := mustStore(t, fake) + + resolved, err := store.ResolveActiveManifest(context.Background(), ready.Dataset.Project) + if err != nil { + t.Fatalf("ResolveActiveManifest: %v", err) + } + if !manifestIdentityEqual(resolved, ready) { + t.Fatalf("ResolveActiveManifest = %#v, want %#v", resolved, ready) + } + call := fake.onlyCall(t) + assertAllAQLBindsSupplied(t, call) + if !strings.Contains(call.query, "active: { dataset: active.dataset }") || !strings.Contains(call.query, "manifest: {") { + t.Fatalf("resolve query does not return the active/manifest snapshot:\n%s", call.query) + } +} + +func TestReadActiveRejectsInvalidProjectAndMissingReadyPointer(t *testing.T) { + fake := &fakeQueryClient{} + store := mustStore(t, fake) + if _, err := store.ReadActive(context.Background(), " project-a"); !errors.Is(err, dataset.ErrInvalidDatasetRef) { + t.Fatalf("ReadActive(invalid project) error = %v, want ErrInvalidDatasetRef", err) + } + if len(fake.calls) != 0 { + t.Fatalf("invalid project made %d queries", len(fake.calls)) + } + if _, err := store.ReadActive(context.Background(), "project-a"); !errors.Is(err, ErrActiveGenerationNotFound) { + t.Fatalf("ReadActive(missing) error = %v, want ErrActiveGenerationNotFound", err) + } +} + +func TestActivateUsesOneUpdateToSupersedeAndSelectReadyCandidate(t *testing.T) { + previous := fixtureManifest(t, "project-a", "generation-old", dataset.ManifestStateReady) + candidate := fixtureManifest(t, "project-a", "generation-new", dataset.ManifestStateReady) + fake := &fakeQueryClient{responses: [][]map[string]any{{ + { + "role": "candidate_guard", + "dataset": jsonObject(t, candidate.Dataset), + "previous": nil, + }, + { + "role": "superseded_manifest", + "dataset": nil, + "previous": jsonObject(t, previous.Dataset), + }, + { + "role": activeRecordType, + "dataset": jsonObject(t, candidate.Dataset), + "previous": nil, + }, + }}} + store := mustStore(t, fake) + + plan, err := store.Activate(context.Background(), candidate) + if err != nil { + t.Fatalf("Activate: %v", err) + } + if !plan.Active.Dataset.Equal(candidate.Dataset) { + t.Fatalf("activation active = %#v, want %#v", plan.Active.Dataset, candidate.Dataset) + } + if plan.Previous == nil || !plan.Previous.Equal(previous.Dataset) { + t.Fatalf("activation previous = %#v, want %#v", plan.Previous, previous.Dataset) + } + call := fake.onlyCall(t) + assertAllAQLBindsSupplied(t, call) + if strings.Count(call.query, "UPDATE ") != 1 || strings.Contains(call.query, "UPSERT") || strings.Contains(call.query, "INSERT ") { + t.Fatalf("activation must be exactly one UPDATE operation:\n%s", call.query) + } + for _, fragment := range []string{ + "FILTER manifest.state == @ready_state", + "active.dataset.project == @project", + "active.manifestKey != null AND", + "previous != null", + "state: @superseded_state", + "document: candidate, patch: { state: @ready_state }, role: @candidate_guard_role", + "manifestKey: candidate._key", + "OPTIONS { ignoreRevs: false, mergeObjects: false }", + } { + if !strings.Contains(call.query, fragment) { + t.Fatalf("activation query missing %q:\n%s", fragment, call.query) + } + } + if call.bindVars["candidate_key"] != manifestDocumentKey(candidate.Dataset) || call.bindVars["active_key"] != activeDocumentKey(candidate.Dataset.Project) { + t.Fatalf("activation document keys = %#v", call.bindVars) + } + if call.bindVars["ready_state"] != string(dataset.ManifestStateReady) || call.bindVars["superseded_state"] != string(dataset.ManifestStateSuperseded) { + t.Fatalf("activation state binds = %#v", call.bindVars) + } + assertNoAuthScope(t, call.bindVars) +} + +func TestActivateRejectsNonReadyAndMissingPersistedCandidate(t *testing.T) { + loading := fixtureManifest(t, "project-a", "generation-a", dataset.ManifestStateLoading) + fake := &fakeQueryClient{} + store := mustStore(t, fake) + if _, err := store.Activate(context.Background(), loading); !errors.Is(err, dataset.ErrGenerationNotReady) { + t.Fatalf("Activate(LOADING) error = %v, want ErrGenerationNotReady", err) + } + if len(fake.calls) != 0 { + t.Fatalf("non-ready activation made %d queries", len(fake.calls)) + } + + ready := fixtureManifest(t, "project-a", "generation-a", dataset.ManifestStateReady) + if _, err := store.Activate(context.Background(), ready); !errors.Is(err, ErrActivationConflict) { + t.Fatalf("Activate(missing persisted candidate) error = %v, want ErrActivationConflict", err) + } +} + +func TestManifestReadRejectsInconsistentStoreResult(t *testing.T) { + want := fixtureManifest(t, "project-a", "generation-a", dataset.ManifestStatePreflight) + wrong := fixtureManifest(t, "project-a", "generation-b", dataset.ManifestStatePreflight) + fake := &fakeQueryClient{responses: [][]map[string]any{{jsonObject(t, wrong)}}} + store := mustStore(t, fake) + if _, err := store.ReadManifest(context.Background(), want.Dataset); !errors.Is(err, ErrUnexpectedStoreResult) { + t.Fatalf("ReadManifest(inconsistent row) error = %v, want ErrUnexpectedStoreResult", err) + } +} + +func fixtureManifest(t *testing.T, project, generation string, state dataset.ManifestState) dataset.Manifest { + t.Helper() + ref, err := dataset.NewDatasetRef(project, generation) + if err != nil { + t.Fatalf("NewDatasetRef: %v", err) + } + schema, err := dataset.NewSchemaIdentitySnapshot( + "https://example.test/loom-fhir-schema", + "4.0.1", + strings.Repeat("a", 64), + []string{"Observation", "Patient"}, + ) + if err != nil { + t.Fatalf("NewSchemaIdentitySnapshot: %v", err) + } + manifest, err := dataset.NewManifest(ref, schema) + if err != nil { + t.Fatalf("NewManifest: %v", err) + } + for manifest.State != state { + var next dataset.ManifestState + switch manifest.State { + case dataset.ManifestStatePreflight: + next = dataset.ManifestStateLoading + case dataset.ManifestStateLoading: + next = dataset.ManifestStateAnalyzing + case dataset.ManifestStateAnalyzing: + next = dataset.ManifestStateReady + default: + t.Fatalf("cannot construct fixture state %s from %s", state, manifest.State) + } + manifest, err = manifest.Transition(next) + if err != nil { + t.Fatalf("fixture transition: %v", err) + } + } + return manifest +} + +func mustStore(t *testing.T, client QueryRowsClient) *Store { + t.Helper() + store, err := New(client) + if err != nil { + t.Fatalf("New: %v", err) + } + return store +} + +func jsonObject(t *testing.T, value any) map[string]any { + t.Helper() + data, err := json.Marshal(value) + if err != nil { + t.Fatalf("json.Marshal(%T): %v", value, err) + } + var decoded map[string]any + if err := json.Unmarshal(data, &decoded); err != nil { + t.Fatalf("json.Unmarshal(%T): %v", value, err) + } + return decoded +} + +func hasIndex(indexes [][]string, want []string) bool { + for _, index := range indexes { + if reflect.DeepEqual(index, want) { + return true + } + } + return false +} + +func assertNoAuthScope(t *testing.T, value any) { + t.Helper() + encoded, err := json.Marshal(value) + if err != nil { + t.Fatalf("json.Marshal(%T): %v", value, err) + } + lower := strings.ToLower(string(encoded)) + for _, forbidden := range []string{"auth_resource_path", "authscope", "authorization", "token", "claims", "subject"} { + if strings.Contains(lower, forbidden) { + t.Fatalf("persistent bind contains forbidden authorization data %q: %s", forbidden, encoded) + } + } +} + +var aqlBindPattern = regexp.MustCompile(`@@?[A-Za-z_][A-Za-z0-9_]*`) + +func assertAllAQLBindsSupplied(t *testing.T, call queryCall) { + t.Helper() + for _, token := range aqlBindPattern.FindAllString(call.query, -1) { + key := token[1:] + if _, found := call.bindVars[key]; !found { + t.Fatalf("query bind %q from %q is missing from %#v", key, token, call.bindVars) + } + } +} + +type queryCall struct { + query string + batch int + bindVars map[string]any +} + +type fakeQueryClient struct { + responses [][]map[string]any + err error + calls []queryCall +} + +func (f *fakeQueryClient) QueryRows(_ context.Context, query string, batchSize int, bindVars map[string]interface{}, visit arangostore.RowVisitor) error { + call := queryCall{query: query, batch: batchSize, bindVars: cloneMap(bindVars)} + f.calls = append(f.calls, call) + responseIndex := len(f.calls) - 1 + if responseIndex < len(f.responses) { + for _, row := range f.responses[responseIndex] { + if err := visit(cloneMap(row)); err != nil { + return err + } + } + } + return f.err +} + +func (f *fakeQueryClient) onlyCall(t *testing.T) queryCall { + t.Helper() + if len(f.calls) != 1 { + t.Fatalf("query call count = %d, want 1", len(f.calls)) + } + return f.calls[0] +} + +func cloneMap(source map[string]any) map[string]any { + data, _ := json.Marshal(source) + var clone map[string]any + _ = json.Unmarshal(data, &clone) + return clone +} diff --git a/internal/discovery/build.go b/internal/discovery/build.go new file mode 100644 index 0000000..ed89a41 --- /dev/null +++ b/internal/discovery/build.go @@ -0,0 +1,640 @@ +package discovery + +import ( + "crypto/sha256" + "encoding/hex" + "fmt" + "sort" + "strings" + "unicode" + "unicode/utf8" + + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/fhirschema" +) + +// GeneratedRootSummaries returns every concrete root supported by the active +// generated FHIR schema. No root is marked available because this function +// deliberately has no dataset or catalog dependency. +func GeneratedRootSummaries() []RootResourceSummary { + resourceTypes := fhirschema.ResourceTypes() + roots := make([]RootResourceSummary, 0, len(resourceTypes)) + for _, resourceType := range resourceTypes { + roots = append(roots, RootResourceSummary{ + ResourceType: resourceType, + Supported: true, + SupportReason: RootSupportNotObservedInCatalog, + }) + } + return roots +} + +// BuildSnapshot converts already-authorized catalog facts into a deterministic +// guided-discovery response. It intentionally ignores catalog fields and +// relationships that are not representable by the active generated schema; +// exposing them would let the frontend offer a choice that the compiler cannot +// prove safe. +func BuildSnapshot(facts CatalogFacts) (Snapshot, error) { + evidence, err := collectEvidence(facts) + if err != nil { + return Snapshot{}, err + } + return snapshotFromEvidence(evidence) +} + +// discoveryEvidence is the common schema/catalog-normalized source for both +// the JSON-safe Snapshot and the non-JSON capability resolver. Keeping this +// private prevents raw catalog paths and graph labels from becoming a product +// transport contract. +type discoveryEvidence struct { + project string + roots []RootResourceSummary + rootIndexes map[string]int + columns map[ColumnID]*columnAggregate + relationships map[RelationshipID]*relationshipAggregate +} + +func collectEvidence(facts CatalogFacts) (discoveryEvidence, error) { + project := strings.TrimSpace(facts.Project) + if project == "" { + return discoveryEvidence{}, fmt.Errorf("catalog facts require a project") + } + roots := GeneratedRootSummaries() + rootIndexes := rootIndexes(roots) + columns, err := aggregateColumns(project, facts.Fields, rootIndexes) + if err != nil { + return discoveryEvidence{}, err + } + relationships, err := aggregateRelationships(facts.Relationships, rootIndexes) + if err != nil { + return discoveryEvidence{}, err + } + return discoveryEvidence{ + project: project, + roots: roots, + rootIndexes: rootIndexes, + columns: columns, + relationships: relationships, + }, nil +} + +func snapshotFromEvidence(evidence discoveryEvidence) (Snapshot, error) { + snapshot := Snapshot{ + Dataset: DatasetSummary{ + Project: evidence.project, + Roots: append([]RootResourceSummary(nil), evidence.roots...), + }, + Relationships: RelationshipInventory{Entries: []Relationship{}}, + Columns: []CandidateColumn{}, + Filters: []GuidedFilterSuggestion{}, + } + columns := materializeColumns(evidence.columns) + snapshot.Columns = columns + for _, column := range columns { + root := &snapshot.Dataset.Roots[evidence.rootIndexes[column.ResourceType]] + markRootAvailable(root) + root.CandidateColumnCount++ + } + + relationships := materializeRelationships(evidence.relationships) + snapshot.Relationships.Entries = relationships + for _, relationship := range relationships { + from := &snapshot.Dataset.Roots[evidence.rootIndexes[relationship.FromResourceType]] + to := &snapshot.Dataset.Roots[evidence.rootIndexes[relationship.ToResourceType]] + markRootAvailable(from) + markRootAvailable(to) + from.RelationshipCount++ + } + + snapshot.Filters = materializeFilterSuggestions(columns) + if err := snapshot.Validate(); err != nil { + return Snapshot{}, fmt.Errorf("build discovery snapshot: %w", err) + } + return snapshot, nil +} + +func markRootAvailable(root *RootResourceSummary) { + root.Available = true + root.SupportReason = RootSupportObservedInCatalog +} + +type columnSpec struct { + resourceType string + canonical string + selector fhirschema.FieldSelectorSpec + hasSelector bool + valueKind ValueKind + repeated bool + canSelect bool + canFilter bool + canPivot bool +} + +type columnAggregate struct { + columnSpec + populatedDocumentCount int64 + values map[string]struct{} + valuesTruncated bool + pivots map[string]*pivotAggregate +} + +// pivotSpec is schema-validated metadata derived from a populated catalog +// field. It remains private until a caller resolves an opaque ColumnID. +type pivotSpec struct { + family string + columnSelector fhirschema.FieldSelectorSpec + valueSelector fhirschema.FieldSelectorSpec +} + +type pivotAggregate struct { + spec pivotSpec + columns map[string]struct{} + truncated bool +} + +func aggregateColumns(project string, fields []catalog.PopulatedField, roots map[string]int) (map[ColumnID]*columnAggregate, error) { + aggregates := make(map[ColumnID]*columnAggregate) + for _, field := range fields { + resourceType := strings.TrimSpace(field.ResourceType) + if resourceType == "" || strings.TrimSpace(field.Path) == "" { + return nil, fmt.Errorf("catalog field requires resource type and path") + } + if field.DocCount < 0 || field.SampleCount < 0 { + return nil, fmt.Errorf("catalog field has a negative population count") + } + if strings.TrimSpace(field.Project) != project { + return nil, fmt.Errorf("catalog field project does not match requested project") + } + if _, ok := roots[resourceType]; !ok { + // The checked-in generated schema is the authoritative compiler + // boundary. A stale or wider catalog must not widen this response. + continue + } + + canonical := fhirschema.CanonicalizePath(field.Path) + if canonical == "" { + return nil, fmt.Errorf("catalog field path has no canonical form") + } + pivot, pivotAvailable := observedPivotSpec(resourceType, canonical, field) + spec, ok := classifyColumn(resourceType, canonical, pivotAvailable) + if !ok { + // Object, extension, and unrepresented paths remain intentionally + // hidden until the generated schema can describe their lowering. + continue + } + id := opaqueColumnID(resourceType, canonical) + aggregate, ok := aggregates[id] + if !ok { + aggregate = &columnAggregate{ + columnSpec: spec, + values: make(map[string]struct{}), + pivots: make(map[string]*pivotAggregate), + } + aggregates[id] = aggregate + } + if pivotAvailable { + aggregate.canPivot = true + aggregate.addPivot(pivot, field.PivotColumns, field.DistinctTruncated) + } + aggregate.populatedDocumentCount += field.DocCount + aggregate.valuesTruncated = aggregate.valuesTruncated || field.DistinctTruncated + for _, value := range field.DistinctValues { + value = strings.TrimSpace(value) + if value != "" { + aggregate.values[value] = struct{}{} + } + } + } + return aggregates, nil +} + +func (aggregate *columnAggregate) addPivot(spec pivotSpec, columns []string, truncated bool) { + key := pivotSpecKey(spec) + pivot, ok := aggregate.pivots[key] + if !ok { + pivot = &pivotAggregate{ + spec: spec, + columns: make(map[string]struct{}), + } + aggregate.pivots[key] = pivot + } + pivot.truncated = pivot.truncated || truncated + for _, column := range columns { + column = strings.TrimSpace(column) + if column != "" { + pivot.columns[column] = struct{}{} + } + } +} + +func classifyColumn(resourceType, canonical string, pivotAvailable bool) (columnSpec, bool) { + if metadata, ok := fhirschema.ResolveTerminalScalarMetadata(resourceType, canonical); ok { + if valueKind, ok := valueKindFromPrimitive(metadata.Primitive); ok { + field, found := fhirschema.LookupField(resourceType, canonical) + if !found { + return columnSpec{}, false + } + return columnSpec{ + resourceType: resourceType, + canonical: canonical, + selector: fhirschema.SelectorFromField(field), + hasSelector: true, + valueKind: valueKind, + repeated: metadata.Repeated, + canSelect: true, + canFilter: true, + canPivot: pivotAvailable, + }, true + } + } + + // The catalog knows whether a populated object was observed as a pivot + // candidate, but generated schema metadata still decides whether that pivot + // has a supported compiler family. The opaque ID resolves back to the + // catalog-owned selectors only after the user makes a choice. + if pivotAvailable { + return columnSpec{ + resourceType: resourceType, + canonical: canonical, + valueKind: ValueKindComposite, + canPivot: true, + }, true + } + return columnSpec{}, false +} + +func observedPivotSpec(resourceType, canonical string, field catalog.PopulatedField) (pivotSpec, bool) { + if !field.PivotCandidate { + return pivotSpec{}, false + } + columnExpression := strings.TrimSpace(field.PivotColumnSelect) + valueExpression := strings.TrimSpace(field.PivotValueSelect) + var columnSelector, valueSelector fhirschema.FieldSelectorSpec + if columnExpression == "" && valueExpression == "" { + defaultSpec, ok := fhirschema.DefaultPivotSpec(resourceType, canonical, "") + if !ok { + return pivotSpec{}, false + } + columnSelector = defaultSpec.ColumnSelector + valueSelector = defaultSpec.ValueSelector + } else { + if columnExpression == "" || valueExpression == "" { + return pivotSpec{}, false + } + var ok bool + columnSelector, ok = selectorSpecFromExpression(columnExpression) + if !ok { + return pivotSpec{}, false + } + valueSelector, ok = selectorSpecFromExpression(valueExpression) + if !ok { + return pivotSpec{}, false + } + } + pivot, err := fhirschema.ValidatePivotSelectors(resourceType, columnSelector, valueSelector) + if err != nil || pivot.CatalogRootPath != canonical { + return pivotSpec{}, false + } + if family := strings.TrimSpace(field.PivotFamily); family != "" && family != pivot.Family { + return pivotSpec{}, false + } + return pivotSpec{ + family: pivot.Family, + columnSelector: pivot.ColumnSelector, + valueSelector: pivot.ValueSelector, + }, true +} + +func selectorSpecFromExpression(expression string) (fhirschema.FieldSelectorSpec, bool) { + selector, err := fhirschema.ParseSelector(expression) + if err != nil || len(selector.Steps) == 0 { + return fhirschema.FieldSelectorSpec{}, false + } + parts := make([]string, 0, len(selector.Steps)) + for _, step := range selector.Steps { + parts = append(parts, selectorStepExpression(step)) + } + spec := fhirschema.FieldSelectorSpec{ValuePath: parts[len(parts)-1]} + if len(parts) > 1 { + spec.SourcePath = strings.Join(parts[:len(parts)-1], ".") + } + if selector.Filter != nil { + spec.Where = &fhirschema.FieldPredicateSpec{ + Path: selector.Filter.Field, + Op: fhirschema.PredicateContains, + Value: selector.Filter.Needle, + } + } + return spec, true +} + +func selectorStepExpression(step fhirschema.SelectorStep) string { + if step.Iterate { + return step.Field + "[]" + } + if step.Index != nil { + return fmt.Sprintf("%s[%d]", step.Field, *step.Index) + } + return step.Field +} + +func pivotSpecKey(spec pivotSpec) string { + return strings.Join([]string{ + spec.family, + fhirschema.SelectorExpression(spec.columnSelector), + fhirschema.SelectorExpression(spec.valueSelector), + }, "\x00") +} + +func valueKindFromPrimitive(primitive fhirschema.PrimitiveKind) (ValueKind, bool) { + switch primitive { + case fhirschema.PrimitiveString: + return ValueKindString, true + case fhirschema.PrimitiveBoolean: + return ValueKindBoolean, true + case fhirschema.PrimitiveInteger: + return ValueKindInteger, true + case fhirschema.PrimitiveDecimal: + return ValueKindDecimal, true + case fhirschema.PrimitiveDate: + return ValueKindDate, true + case fhirschema.PrimitiveDateTime: + return ValueKindDateTime, true + default: + return "", false + } +} + +func materializeColumns(aggregates map[ColumnID]*columnAggregate) []CandidateColumn { + columns := make([]CandidateColumn, 0, len(aggregates)) + for id, aggregate := range aggregates { + values, truncated := normalizedValues(aggregate.values, aggregate.valuesTruncated) + columns = append(columns, CandidateColumn{ + ID: id, + ResourceType: aggregate.resourceType, + Label: humanizePath(aggregate.canonical), + ValueKind: aggregate.valueKind, + Repeated: aggregate.repeated, + CanSelect: aggregate.canSelect, + CanFilter: aggregate.canFilter, + CanPivot: aggregate.canPivot, + PopulatedDocumentCount: aggregate.populatedDocumentCount, + SuggestedValues: values, + ValuesTruncated: truncated, + }) + } + sort.Slice(columns, func(i, j int) bool { + if columns[i].ResourceType != columns[j].ResourceType { + return columns[i].ResourceType < columns[j].ResourceType + } + if columns[i].Label != columns[j].Label { + return columns[i].Label < columns[j].Label + } + return columns[i].ID < columns[j].ID + }) + return columns +} + +type relationshipAggregate struct { + fromType string + label string + toType string + multiple RelationshipMultiplicity + traversal fhirschema.CompilerTraversal + edgeCount int64 +} + +func aggregateRelationships(references []catalog.PopulatedReference, roots map[string]int) (map[RelationshipID]*relationshipAggregate, error) { + aggregates := make(map[RelationshipID]*relationshipAggregate) + for _, reference := range references { + fromType := strings.TrimSpace(reference.FromType) + label := strings.TrimSpace(reference.Label) + toType := strings.TrimSpace(reference.ToType) + if fromType == "" || label == "" || toType == "" { + return nil, fmt.Errorf("catalog relationship requires source, label, and target") + } + if reference.EdgeCount < 0 { + return nil, fmt.Errorf("catalog relationship has a negative edge count") + } + if _, ok := roots[fromType]; !ok { + continue + } + if _, ok := roots[toType]; !ok { + continue + } + traversal, found, err := fhirschema.ResolveCompilerTraversal(fromType, label, toType) + if err != nil { + return nil, fmt.Errorf("active generated schema has unsafe traversal metadata") + } + if !found { + continue + } + + id := opaqueRelationshipID(fromType, label, toType) + multiplicity := RelationshipOne + if traversal.Multiplicity == fhirschema.TraversalMany { + multiplicity = RelationshipMany + } + aggregate, ok := aggregates[id] + if !ok { + aggregate = &relationshipAggregate{ + fromType: fromType, + label: label, + toType: toType, + multiple: multiplicity, + traversal: traversal, + } + aggregates[id] = aggregate + } + // DiscoverPopulatedReferences already aggregates each route. If a + // caller accidentally supplies it more than once, max preserves an + // idempotent normalized snapshot instead of double-counting a route. + if reference.EdgeCount > aggregate.edgeCount { + aggregate.edgeCount = reference.EdgeCount + } + } + + return aggregates, nil +} + +func materializeRelationships(aggregates map[RelationshipID]*relationshipAggregate) []Relationship { + relationships := make([]Relationship, 0, len(aggregates)) + for id, aggregate := range aggregates { + relationships = append(relationships, Relationship{ + ID: id, + FromResourceType: aggregate.fromType, + ToResourceType: aggregate.toType, + Label: humanizeRelationshipLabel(aggregate.label, aggregate.toType), + Multiplicity: aggregate.multiple, + ObservedEdgeCount: aggregate.edgeCount, + }) + } + sort.Slice(relationships, func(i, j int) bool { + if relationships[i].FromResourceType != relationships[j].FromResourceType { + return relationships[i].FromResourceType < relationships[j].FromResourceType + } + if relationships[i].ToResourceType != relationships[j].ToResourceType { + return relationships[i].ToResourceType < relationships[j].ToResourceType + } + if relationships[i].Label != relationships[j].Label { + return relationships[i].Label < relationships[j].Label + } + return relationships[i].ID < relationships[j].ID + }) + return relationships +} + +func materializeFilterSuggestions(columns []CandidateColumn) []GuidedFilterSuggestion { + filters := make([]GuidedFilterSuggestion, 0, len(columns)) + for _, column := range columns { + if !column.CanFilter { + continue + } + filters = append(filters, GuidedFilterSuggestion{ + ID: opaqueFilterSuggestionID(column.ID), + ColumnID: column.ID, + ResourceType: column.ResourceType, + Label: column.Label, + ValueKind: column.ValueKind, + Repeated: column.Repeated, + Operators: filterOperators(column.ValueKind), + Quantifiers: filterQuantifiers(column.Repeated), + SuggestedValues: append([]string(nil), column.SuggestedValues...), + ValuesTruncated: column.ValuesTruncated, + }) + } + sort.Slice(filters, func(i, j int) bool { + if filters[i].ResourceType != filters[j].ResourceType { + return filters[i].ResourceType < filters[j].ResourceType + } + if filters[i].Label != filters[j].Label { + return filters[i].Label < filters[j].Label + } + return filters[i].ID < filters[j].ID + }) + return filters +} + +func filterOperators(kind ValueKind) []FilterOperator { + operators := []FilterOperator{ + FilterEquals, + FilterNotEquals, + FilterIn, + FilterExists, + FilterMissing, + } + switch kind { + case ValueKindString: + operators = append(operators, FilterContains) + case ValueKindInteger, ValueKindDecimal, ValueKindDate, ValueKindDateTime: + operators = append(operators, FilterGreaterThan, FilterGreaterEq, FilterLessThan, FilterLessEq) + } + return operators +} + +func filterQuantifiers(repeated bool) []FilterQuantifier { + if !repeated { + return []FilterQuantifier{} + } + return []FilterQuantifier{FilterAny, FilterAll, FilterNone} +} + +func normalizedValues(values map[string]struct{}, alreadyTruncated bool) ([]string, bool) { + if len(values) == 0 { + return []string{}, alreadyTruncated + } + out := make([]string, 0, len(values)) + for value := range values { + out = append(out, value) + } + sort.Strings(out) + if len(out) > maxSuggestedValues { + return append([]string(nil), out[:maxSuggestedValues]...), true + } + return out, alreadyTruncated +} + +func rootIndexes(roots []RootResourceSummary) map[string]int { + indexes := make(map[string]int, len(roots)) + for i, root := range roots { + indexes[root.ResourceType] = i + } + return indexes +} + +func opaqueColumnID(resourceType, canonical string) ColumnID { + return ColumnID("col_" + stableHash("column", resourceType, canonical)) +} + +func opaqueRelationshipID(fromType, label, toType string) RelationshipID { + return RelationshipID("rel_" + stableHash("relationship", fromType, label, toType)) +} + +func opaqueFilterSuggestionID(columnID ColumnID) FilterSuggestionID { + return FilterSuggestionID("flt_" + stableHash("filter", string(columnID))) +} + +func stableHash(parts ...string) string { + hash := sha256.New() + for _, part := range parts { + _, _ = hash.Write([]byte(part)) + _, _ = hash.Write([]byte{0}) + } + return hex.EncodeToString(hash.Sum(nil)) +} + +func humanizePath(canonical string) string { + segments := strings.Split(canonical, ".") + words := make([]string, 0, len(segments)) + for _, segment := range segments { + segment = strings.TrimSuffix(segment, "[]") + if label := humanizeIdentifier(segment); label != "" { + words = append(words, label) + } + } + return strings.Join(words, " ") +} + +func humanizeRelationshipLabel(label, toType string) string { + label = strings.TrimSuffix(label, "_"+toType) + parts := strings.Split(label, "_") + if len(parts) > 1 && fhirschema.HasResource(parts[len(parts)-1]) { + label = strings.Join(parts[:len(parts)-1], "_") + } + return humanizeIdentifier(label) +} + +func humanizeIdentifier(value string) string { + value = strings.TrimSpace(value) + if value == "" { + return "" + } + var words []string + var word []rune + flush := func() { + if len(word) == 0 { + return + } + words = append(words, strings.ToLower(string(word))) + word = word[:0] + } + for _, r := range value { + if r == '_' || r == '-' || r == '.' || unicode.IsSpace(r) { + flush() + continue + } + if len(word) > 0 && unicode.IsUpper(r) && unicode.IsLower(word[len(word)-1]) { + flush() + } + word = append(word, r) + } + flush() + for i, word := range words { + if word == "" { + continue + } + first, size := utf8.DecodeRuneInString(word) + words[i] = string(unicode.ToUpper(first)) + word[size:] + } + return strings.Join(words, " ") +} diff --git a/internal/discovery/discovery_test.go b/internal/discovery/discovery_test.go new file mode 100644 index 0000000..033ef5c --- /dev/null +++ b/internal/discovery/discovery_test.go @@ -0,0 +1,253 @@ +package discovery + +import ( + "encoding/json" + "reflect" + "slices" + "strings" + "testing" + + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/fhirschema" +) + +func TestGeneratedRootSummariesFollowActiveGeneratedSchema(t *testing.T) { + got := GeneratedRootSummaries() + want := fhirschema.ResourceTypes() + if len(got) != len(want) { + t.Fatalf("GeneratedRootSummaries() length = %d, want %d", len(got), len(want)) + } + for index, resourceType := range want { + root := got[index] + if root.ResourceType != resourceType { + t.Errorf("root %d resourceType = %q, want %q", index, root.ResourceType, resourceType) + } + if !root.Supported || root.Available || root.SupportReason != RootSupportNotObservedInCatalog { + t.Errorf("root %q = %+v, want generated-only supported root", resourceType, root) + } + if root.CandidateColumnCount != 0 || root.RelationshipCount != 0 { + t.Errorf("root %q carries catalog counts without catalog facts: %+v", resourceType, root) + } + } +} + +func TestBuildSnapshotBuildsOpaqueCatalogAndSchemaBackedContract(t *testing.T) { + facts := CatalogFacts{ + Project: "project-a", + Fields: []catalog.PopulatedField{ + { + Project: "project-a", ResourceType: "Patient", Path: "gender", Kind: "scalar", + DocCount: 4, SampleCount: 2, DistinctValues: []string{"male", "female", "female"}, + }, + { + Project: "project-a", AuthResourcePath: "restricted", ResourceType: "Patient", Path: "gender", Kind: "scalar", + DocCount: 2, SampleCount: 2, DistinctValues: []string{"unknown", "female"}, DistinctTruncated: true, + }, + { + Project: "project-a", ResourceType: "Patient", Path: "birthDate", Kind: "scalar", + DocCount: 5, SampleCount: 2, DistinctValues: []string{"1990-01-01", "2000-02-02"}, + }, + { + Project: "project-a", ResourceType: "Patient", Path: "name[].family", Kind: "scalar", + DocCount: 4, SampleCount: 2, DistinctValues: []string{"Ng", "Smith"}, + }, + { + Project: "project-a", ResourceType: "Observation", Path: "code", Kind: "codeable_concept", + DocCount: 4, SampleCount: 1, DistinctValues: []string{"Hemoglobin"}, PivotCandidate: true, + }, + { + Project: "project-a", ResourceType: "Observation", Path: "valueInteger", Kind: "scalar", + DocCount: 4, SampleCount: 2, DistinctValues: []string{"12", "13"}, + }, + // Unsupported schema paths and resource types must never reach the + // guided response merely because they appear in an old catalog. + {Project: "project-a", ResourceType: "Patient", Path: "notRepresented", Kind: "scalar", DocCount: 1}, + {Project: "project-a", ResourceType: "Encounter", Path: "status", Kind: "scalar", DocCount: 1}, + }, + Relationships: []catalog.PopulatedReference{ + {FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 7}, + // Duplicate source facts normalize idempotently rather than making + // the discovery result depend on caller pagination/retries. + {FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 2}, + {FromType: "Patient", Label: "not_a_generated_route", ToType: "Specimen", EdgeCount: 99}, + {FromType: "Encounter", Label: "subject_Patient", ToType: "Patient", EdgeCount: 3}, + }, + } + + snapshot, err := BuildSnapshot(facts) + if err != nil { + t.Fatalf("BuildSnapshot() error = %v", err) + } + if err := snapshot.Validate(); err != nil { + t.Fatalf("snapshot.Validate() error = %v", err) + } + + patient := findRoot(t, snapshot.Dataset.Roots, "Patient") + if !patient.Supported || !patient.Available || patient.SupportReason != RootSupportObservedInCatalog || patient.CandidateColumnCount != 3 || patient.RelationshipCount != 1 { + t.Errorf("Patient summary = %+v, want observed supported root with 3 columns and 1 route", patient) + } + observation := findRoot(t, snapshot.Dataset.Roots, "Observation") + if !observation.Available || observation.CandidateColumnCount != 2 || observation.RelationshipCount != 0 { + t.Errorf("Observation summary = %+v, want 2 candidate columns", observation) + } + specimen := findRoot(t, snapshot.Dataset.Roots, "Specimen") + if !specimen.Available || specimen.SupportReason != RootSupportObservedInCatalog || specimen.CandidateColumnCount != 0 { + t.Errorf("Specimen summary = %+v, want availability through incoming route", specimen) + } + diagnosticReport := findRoot(t, snapshot.Dataset.Roots, "DiagnosticReport") + if !diagnosticReport.Supported || diagnosticReport.Available || diagnosticReport.SupportReason != RootSupportNotObservedInCatalog { + t.Errorf("DiagnosticReport summary = %+v, want supported but not observed", diagnosticReport) + } + + if len(snapshot.Relationships.Entries) != 1 { + t.Fatalf("relationship count = %d, want 1: %+v", len(snapshot.Relationships.Entries), snapshot.Relationships.Entries) + } + relationship := snapshot.Relationships.Entries[0] + if relationship.FromResourceType != "Patient" || relationship.ToResourceType != "Specimen" || relationship.Label != "Subject" || relationship.ObservedEdgeCount != 7 { + t.Errorf("relationship = %+v, want normalized Patient Subject Specimen route", relationship) + } + if strings.Contains(string(relationship.ID), "subject_Patient") { + t.Errorf("relationship ID leaked underlying graph label: %q", relationship.ID) + } + + gender := findColumn(t, snapshot.Columns, "Patient", "Gender") + if gender.ValueKind != ValueKindString || !gender.CanSelect || !gender.CanFilter || gender.CanPivot || gender.Repeated || gender.PopulatedDocumentCount != 6 { + t.Errorf("gender column = %+v", gender) + } + if !reflect.DeepEqual(gender.SuggestedValues, []string{"female", "male", "unknown"}) || !gender.ValuesTruncated { + t.Errorf("gender values = %#v truncated=%t", gender.SuggestedValues, gender.ValuesTruncated) + } + if strings.Contains(string(gender.ID), "gender") { + t.Errorf("column ID leaked canonical field path: %q", gender.ID) + } + + pivot := findColumn(t, snapshot.Columns, "Observation", "Code") + if pivot.ValueKind != ValueKindComposite || pivot.CanSelect || pivot.CanFilter || !pivot.CanPivot || pivot.Repeated { + t.Errorf("Observation code pivot candidate = %+v", pivot) + } + + repeated := findFilter(t, snapshot.Filters, "Patient", "Name Family") + if !repeated.Repeated || !reflect.DeepEqual(repeated.Quantifiers, []FilterQuantifier{FilterAny, FilterAll, FilterNone}) { + t.Errorf("repeated filter = %+v", repeated) + } + date := findFilter(t, snapshot.Filters, "Patient", "Birth Date") + if !slices.Contains(date.Operators, FilterGreaterEq) || !slices.Contains(date.Operators, FilterLessEq) { + t.Errorf("date filter lacks ordered operations: %+v", date.Operators) + } + if got, want := len(snapshot.Filters), 4; got != want { + t.Errorf("filter count = %d, want %d", got, want) + } + + encoded, err := json.Marshal(snapshot) + if err != nil { + t.Fatalf("marshal snapshot: %v", err) + } + for _, forbidden := range []string{"name[].family", "subject_Patient", "auth_resource_path", "selector", "fieldRef"} { + if strings.Contains(string(encoded), forbidden) { + t.Errorf("snapshot JSON leaked internal catalog/query detail %q: %s", forbidden, encoded) + } + } +} + +func TestBuildSnapshotIsDeterministicAcrossCatalogFactOrder(t *testing.T) { + facts := CatalogFacts{ + Project: "project-a", + Fields: []catalog.PopulatedField{ + {Project: "project-a", ResourceType: "Patient", Path: "gender", Kind: "scalar", DocCount: 3, DistinctValues: []string{"male", "female"}}, + {Project: "project-a", ResourceType: "Patient", Path: "birthDate", Kind: "scalar", DocCount: 3, DistinctValues: []string{"2000-01-01"}}, + }, + Relationships: []catalog.PopulatedReference{ + {FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 4}, + }, + } + first, err := BuildSnapshot(facts) + if err != nil { + t.Fatalf("first BuildSnapshot() error = %v", err) + } + facts.Fields = append([]catalog.PopulatedField(nil), facts.Fields...) + facts.Relationships = append([]catalog.PopulatedReference(nil), facts.Relationships...) + slices.Reverse(facts.Fields) + slices.Reverse(facts.Relationships) + second, err := BuildSnapshot(facts) + if err != nil { + t.Fatalf("second BuildSnapshot() error = %v", err) + } + if !reflect.DeepEqual(first, second) { + t.Errorf("BuildSnapshot() changed with input order\nfirst: %#v\nsecond: %#v", first, second) + } +} + +func TestBuildSnapshotBoundsSuggestedValuesAndRejectsWrongScope(t *testing.T) { + values := make([]string, 0, maxSuggestedValues+5) + for index := 0; index < maxSuggestedValues+5; index++ { + values = append(values, string(rune('a'+index/10))+string(rune('0'+index%10))) + } + snapshot, err := BuildSnapshot(CatalogFacts{ + Project: "project-a", + Fields: []catalog.PopulatedField{{ + Project: "project-a", ResourceType: "Patient", Path: "gender", Kind: "scalar", DocCount: 55, DistinctValues: values, + }}, + }) + if err != nil { + t.Fatalf("BuildSnapshot() error = %v", err) + } + column := findColumn(t, snapshot.Columns, "Patient", "Gender") + if len(column.SuggestedValues) != maxSuggestedValues || !column.ValuesTruncated { + t.Errorf("bounded values = %d truncated=%t, want %d/true", len(column.SuggestedValues), column.ValuesTruncated, maxSuggestedValues) + } + + _, err = BuildSnapshot(CatalogFacts{ + Project: "project-a", + Fields: []catalog.PopulatedField{{Project: "other-project", ResourceType: "Patient", Path: "gender", Kind: "scalar"}}, + }) + if err == nil || !strings.Contains(err.Error(), "project") { + t.Errorf("scope-mismatched catalog field error = %v, want project error", err) + } +} + +func TestSnapshotValidateRejectsNonOpaqueColumnIdentifier(t *testing.T) { + snapshot, err := BuildSnapshot(CatalogFacts{ + Project: "project-a", + Fields: []catalog.PopulatedField{{Project: "project-a", ResourceType: "Patient", Path: "gender", Kind: "scalar", DocCount: 1}}, + }) + if err != nil { + t.Fatalf("BuildSnapshot() error = %v", err) + } + snapshot.Columns[0].ID = "Patient.gender" + if err := snapshot.Validate(); err == nil || !strings.Contains(err.Error(), "opaque") { + t.Errorf("Validate() error = %v, want opaque ID failure", err) + } +} + +func findRoot(t *testing.T, roots []RootResourceSummary, resourceType string) RootResourceSummary { + t.Helper() + for _, root := range roots { + if root.ResourceType == resourceType { + return root + } + } + t.Fatalf("root %q not found", resourceType) + return RootResourceSummary{} +} + +func findColumn(t *testing.T, columns []CandidateColumn, resourceType, label string) CandidateColumn { + t.Helper() + for _, column := range columns { + if column.ResourceType == resourceType && column.Label == label { + return column + } + } + t.Fatalf("column %s/%s not found in %+v", resourceType, label, columns) + return CandidateColumn{} +} + +func findFilter(t *testing.T, filters []GuidedFilterSuggestion, resourceType, label string) GuidedFilterSuggestion { + t.Helper() + for _, filter := range filters { + if filter.ResourceType == resourceType && filter.Label == label { + return filter + } + } + t.Fatalf("filter %s/%s not found in %+v", resourceType, label, filters) + return GuidedFilterSuggestion{} +} diff --git a/internal/discovery/resolution.go b/internal/discovery/resolution.go new file mode 100644 index 0000000..2e0c193 --- /dev/null +++ b/internal/discovery/resolution.go @@ -0,0 +1,169 @@ +package discovery + +import ( + "errors" + "sort" + + "github.com/calypr/loom/internal/fhirschema" +) + +// ErrColumnUnavailable is returned for both unknown and stale column IDs. The +// error intentionally does not disclose whether an identifier was once valid +// in another project, authorization scope, or catalog state. +var ErrColumnUnavailable = errors.New("discovery column capability is unavailable in current catalog facts") + +// ErrRelationshipUnavailable is returned for both unknown and stale route +// IDs, without disclosing graph labels outside the current scoped facts. +var ErrRelationshipUnavailable = errors.New("discovery relationship capability is unavailable in current catalog facts") + +// CapabilityResolver resolves opaque Snapshot identifiers against one fresh, +// already-authorized CatalogFacts value. It is intentionally in-memory only: +// the caller owns catalog reads, authorization, and any future dataset identity +// integration. +type CapabilityResolver struct { + evidence discoveryEvidence +} + +// NewCapabilityResolver builds a resolver from one current project/scope's +// catalog facts. It applies exactly the same generated-schema and catalog +// normalization as BuildSnapshot. +func NewCapabilityResolver(facts CatalogFacts) (*CapabilityResolver, error) { + evidence, err := collectEvidence(facts) + if err != nil { + return nil, err + } + return &CapabilityResolver{evidence: evidence}, nil +} + +// ResolvedColumn contains compiler-adjacent facts that must never be used as +// transport data. All fields are excluded from JSON to prevent canonical FHIR +// paths or selectors from escaping the opaque Snapshot boundary. +type ResolvedColumn struct { + ID ColumnID `json:"-"` + ResourceType string `json:"-"` + CanonicalPath string `json:"-"` + Selector *fhirschema.FieldSelectorSpec `json:"-"` + ValueKind ValueKind `json:"-"` + Repeated bool `json:"-"` + CanSelect bool `json:"-"` + CanFilter bool `json:"-"` + CanPivot bool `json:"-"` + FilterOperators []FilterOperator `json:"-"` + FilterQuantifiers []FilterQuantifier `json:"-"` + PopulatedDocumentCount int64 `json:"-"` + SuggestedValues []string `json:"-"` + ValuesTruncated bool `json:"-"` + Pivot *ResolvedPivot `json:"-"` +} + +// ResolvedPivot is a schema-validated, catalog-observed pivot family. Its +// selector fields remain internal and are omitted from JSON even when a caller +// accidentally marshals a resolved capability. +type ResolvedPivot struct { + Family string `json:"-"` + ColumnSelector fhirschema.FieldSelectorSpec `json:"-"` + ValueSelector fhirschema.FieldSelectorSpec `json:"-"` + Columns []string `json:"-"` + ColumnsTruncated bool `json:"-"` +} + +// ResolvedRelationship contains the raw generated graph route required by a +// later mapper. Snapshot intentionally exposes only an opaque ID and a human +// label, while this record is kept entirely out of JSON. +type ResolvedRelationship struct { + ID RelationshipID `json:"-"` + FromResourceType string `json:"-"` + EdgeLabel string `json:"-"` + ToResourceType string `json:"-"` + Multiplicity RelationshipMultiplicity `json:"-"` + ObservedEdgeCount int64 `json:"-"` + Traversal fhirschema.CompilerTraversal `json:"-"` +} + +// ResolveColumn resolves a ColumnID only when it is still present in the fresh +// schema-supported catalog evidence used to construct this resolver. +func (resolver *CapabilityResolver) ResolveColumn(id ColumnID) (ResolvedColumn, error) { + if resolver == nil { + return ResolvedColumn{}, ErrColumnUnavailable + } + aggregate, ok := resolver.evidence.columns[id] + if !ok { + return ResolvedColumn{}, ErrColumnUnavailable + } + values, truncated := normalizedValues(aggregate.values, aggregate.valuesTruncated) + resolved := ResolvedColumn{ + ID: id, + ResourceType: aggregate.resourceType, + CanonicalPath: aggregate.canonical, + ValueKind: aggregate.valueKind, + Repeated: aggregate.repeated, + CanSelect: aggregate.canSelect, + CanFilter: aggregate.canFilter, + CanPivot: aggregate.canPivot, + PopulatedDocumentCount: aggregate.populatedDocumentCount, + SuggestedValues: values, + ValuesTruncated: truncated, + } + if aggregate.hasSelector { + selector := cloneSelectorSpec(aggregate.selector) + resolved.Selector = &selector + } + if aggregate.canFilter { + resolved.FilterOperators = append([]FilterOperator(nil), filterOperators(aggregate.valueKind)...) + resolved.FilterQuantifiers = append([]FilterQuantifier(nil), filterQuantifiers(aggregate.repeated)...) + } + if pivot := resolvedPivot(aggregate); pivot != nil { + resolved.Pivot = pivot + } + return resolved, nil +} + +// ResolveRelationship resolves a RelationshipID only when its route remains +// populated and represented by the active generated FHIR graph schema. +func (resolver *CapabilityResolver) ResolveRelationship(id RelationshipID) (ResolvedRelationship, error) { + if resolver == nil { + return ResolvedRelationship{}, ErrRelationshipUnavailable + } + aggregate, ok := resolver.evidence.relationships[id] + if !ok { + return ResolvedRelationship{}, ErrRelationshipUnavailable + } + return ResolvedRelationship{ + ID: id, + FromResourceType: aggregate.fromType, + EdgeLabel: aggregate.label, + ToResourceType: aggregate.toType, + Multiplicity: aggregate.multiple, + ObservedEdgeCount: aggregate.edgeCount, + Traversal: aggregate.traversal, + }, nil +} + +func resolvedPivot(aggregate *columnAggregate) *ResolvedPivot { + if len(aggregate.pivots) == 0 { + return nil + } + keys := make([]string, 0, len(aggregate.pivots)) + for key := range aggregate.pivots { + keys = append(keys, key) + } + sort.Strings(keys) + pivot := aggregate.pivots[keys[0]] + columns, truncated := normalizedValues(pivot.columns, pivot.truncated) + return &ResolvedPivot{ + Family: pivot.spec.family, + ColumnSelector: cloneSelectorSpec(pivot.spec.columnSelector), + ValueSelector: cloneSelectorSpec(pivot.spec.valueSelector), + Columns: columns, + ColumnsTruncated: truncated, + } +} + +func cloneSelectorSpec(spec fhirschema.FieldSelectorSpec) fhirschema.FieldSelectorSpec { + cloned := spec + if spec.Where != nil { + where := *spec.Where + cloned.Where = &where + } + return cloned +} diff --git a/internal/discovery/resolution_test.go b/internal/discovery/resolution_test.go new file mode 100644 index 0000000..d39117c --- /dev/null +++ b/internal/discovery/resolution_test.go @@ -0,0 +1,201 @@ +package discovery + +import ( + "encoding/json" + "errors" + "strings" + "testing" + + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/fhirschema" +) + +func TestCapabilityResolverResolvesEverySnapshotIDFromSameFacts(t *testing.T) { + facts := resolutionFacts() + snapshot, err := BuildSnapshot(facts) + if err != nil { + t.Fatalf("BuildSnapshot() error = %v", err) + } + resolver, err := NewCapabilityResolver(facts) + if err != nil { + t.Fatalf("NewCapabilityResolver() error = %v", err) + } + + for _, candidate := range snapshot.Columns { + resolved, err := resolver.ResolveColumn(candidate.ID) + if err != nil { + t.Fatalf("ResolveColumn(%q) error = %v", candidate.ID, err) + } + if resolved.ID != candidate.ID || resolved.ResourceType != candidate.ResourceType || resolved.ValueKind != candidate.ValueKind || resolved.Repeated != candidate.Repeated || resolved.CanSelect != candidate.CanSelect || resolved.CanFilter != candidate.CanFilter || resolved.CanPivot != candidate.CanPivot { + t.Errorf("column resolution for %q does not match snapshot candidate\nresolved: %+v\ncandidate: %+v", candidate.ID, resolved, candidate) + } + } + for _, relationship := range snapshot.Relationships.Entries { + resolved, err := resolver.ResolveRelationship(relationship.ID) + if err != nil { + t.Fatalf("ResolveRelationship(%q) error = %v", relationship.ID, err) + } + if resolved.ID != relationship.ID || resolved.FromResourceType != relationship.FromResourceType || resolved.ToResourceType != relationship.ToResourceType || resolved.Multiplicity != relationship.Multiplicity || resolved.ObservedEdgeCount != relationship.ObservedEdgeCount { + t.Errorf("relationship resolution for %q does not match snapshot relationship\nresolved: %+v\nrelationship: %+v", relationship.ID, resolved, relationship) + } + if resolved.EdgeLabel != "subject_Patient" || resolved.Traversal.FromType != "Patient" || resolved.Traversal.ToType != "Specimen" { + t.Errorf("relationship resolution lost generated route metadata: %+v", resolved) + } + } + + gender := findColumn(t, snapshot.Columns, "Patient", "Gender") + resolvedGender, err := resolver.ResolveColumn(gender.ID) + if err != nil { + t.Fatalf("ResolveColumn(gender) error = %v", err) + } + if resolvedGender.CanonicalPath != "gender" || resolvedGender.Selector == nil || fhirschema.SelectorExpression(*resolvedGender.Selector) != "gender" { + t.Errorf("gender resolution selector = %+v path=%q", resolvedGender.Selector, resolvedGender.CanonicalPath) + } + if !containsFilterOperator(resolvedGender.FilterOperators, FilterContains) || len(resolvedGender.FilterQuantifiers) != 0 { + t.Errorf("gender resolution filter metadata = operators=%v quantifiers=%v", resolvedGender.FilterOperators, resolvedGender.FilterQuantifiers) + } + + code := findColumn(t, snapshot.Columns, "Observation", "Code") + resolvedCode, err := resolver.ResolveColumn(code.ID) + if err != nil { + t.Fatalf("ResolveColumn(code) error = %v", err) + } + if resolvedCode.Selector != nil || resolvedCode.Pivot == nil { + t.Fatalf("code resolution = %+v, want pivot-only capability", resolvedCode) + } + if resolvedCode.Pivot.Family != fhirschema.PivotFamilyObservationCodeValue || + fhirschema.SelectorExpression(resolvedCode.Pivot.ColumnSelector) != "code.coding[].display" || + fhirschema.SelectorExpression(resolvedCode.Pivot.ValueSelector) != "valueInteger" || + !equalStrings(resolvedCode.Pivot.Columns, []string{"Hemoglobin"}) { + t.Errorf("code pivot metadata = %+v", resolvedCode.Pivot) + } + + resolvedRelationship, err := resolver.ResolveRelationship(snapshot.Relationships.Entries[0].ID) + if err != nil { + t.Fatalf("ResolveRelationship() before JSON check: %v", err) + } + for _, value := range []any{resolvedGender, resolvedCode, resolvedRelationship} { + encoded, err := json.Marshal(value) + if err != nil { + t.Fatalf("marshal resolved capability: %v", err) + } + if string(encoded) != "{}" { + t.Errorf("resolved capability unexpectedly has JSON surface: %s", encoded) + } + } +} + +func TestCapabilityResolverRejectsUnknownStaleAndCrossProjectFacts(t *testing.T) { + facts := resolutionFacts() + snapshot, err := BuildSnapshot(facts) + if err != nil { + t.Fatalf("BuildSnapshot() error = %v", err) + } + gender := findColumn(t, snapshot.Columns, "Patient", "Gender") + relationshipID := snapshot.Relationships.Entries[0].ID + + freshFacts := CatalogFacts{ + Project: "project-a", + Fields: []catalog.PopulatedField{{ + Project: "project-a", ResourceType: "Patient", Path: "birthDate", Kind: "scalar", DocCount: 1, + }}, + } + resolver, err := NewCapabilityResolver(freshFacts) + if err != nil { + t.Fatalf("NewCapabilityResolver(fresh) error = %v", err) + } + if _, err := resolver.ResolveColumn(gender.ID); !errors.Is(err, ErrColumnUnavailable) { + t.Errorf("stale column error = %v, want ErrColumnUnavailable", err) + } + if _, err := resolver.ResolveRelationship(relationshipID); !errors.Is(err, ErrRelationshipUnavailable) { + t.Errorf("stale relationship error = %v, want ErrRelationshipUnavailable", err) + } + unknownColumn := ColumnID("col_" + strings.Repeat("0", 64)) + unknownRelationship := RelationshipID("rel_" + strings.Repeat("0", 64)) + if _, err := resolver.ResolveColumn(unknownColumn); !errors.Is(err, ErrColumnUnavailable) { + t.Errorf("unknown column error = %v, want ErrColumnUnavailable", err) + } + if _, err := resolver.ResolveRelationship(unknownRelationship); !errors.Is(err, ErrRelationshipUnavailable) { + t.Errorf("unknown relationship error = %v, want ErrRelationshipUnavailable", err) + } + + _, err = NewCapabilityResolver(CatalogFacts{ + Project: "project-a", + Fields: []catalog.PopulatedField{{ + Project: "other-project", ResourceType: "Patient", Path: "gender", Kind: "scalar", DocCount: 1, + }}, + }) + if err == nil || !strings.Contains(err.Error(), "project") { + t.Errorf("cross-project facts error = %v, want project mismatch", err) + } +} + +func TestInvalidCatalogPivotDoesNotBecomeResolvableCapability(t *testing.T) { + facts := CatalogFacts{ + Project: "project-a", + Fields: []catalog.PopulatedField{{ + Project: "project-a", + ResourceType: "Observation", + Path: "code", + Kind: "codeable_concept", + DocCount: 1, + PivotCandidate: true, + PivotColumnSelect: "code.coding[].display", + PivotValueSelect: "notARepresentedValue", + PivotColumns: []string{"Hemoglobin"}, + }}, + } + snapshot, err := BuildSnapshot(facts) + if err != nil { + t.Fatalf("BuildSnapshot() error = %v", err) + } + for _, column := range snapshot.Columns { + if column.ResourceType == "Observation" && column.Label == "Code" { + t.Errorf("unsupported observed pivot leaked into Snapshot: %+v", column) + } + } + resolver, err := NewCapabilityResolver(facts) + if err != nil { + t.Fatalf("NewCapabilityResolver() error = %v", err) + } + if _, err := resolver.ResolveColumn(opaqueColumnID("Observation", "code")); !errors.Is(err, ErrColumnUnavailable) { + t.Errorf("unsupported pivot resolution error = %v, want ErrColumnUnavailable", err) + } +} + +func resolutionFacts() CatalogFacts { + return CatalogFacts{ + Project: "project-a", + Fields: []catalog.PopulatedField{ + { + Project: "project-a", ResourceType: "Patient", Path: "gender", Kind: "scalar", DocCount: 3, + DistinctValues: []string{"female", "male"}, + }, + { + Project: "project-a", + ResourceType: "Observation", + Path: "code", + Kind: "codeable_concept", + DocCount: 3, + DistinctValues: []string{"Hemoglobin"}, + PivotCandidate: true, + PivotFamily: fhirschema.PivotFamilyObservationCodeValue, + PivotColumnSelect: "code.coding[].display", + PivotValueSelect: "valueInteger", + PivotColumns: []string{"Hemoglobin"}, + }, + }, + Relationships: []catalog.PopulatedReference{ + {FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 3}, + }, + } +} + +func containsFilterOperator(operators []FilterOperator, want FilterOperator) bool { + for _, operator := range operators { + if operator == want { + return true + } + } + return false +} diff --git a/internal/discovery/types.go b/internal/discovery/types.go new file mode 100644 index 0000000..e2f379c --- /dev/null +++ b/internal/discovery/types.go @@ -0,0 +1,186 @@ +// Package discovery defines the internal, catalog-backed vocabulary used to +// build a guided dataframe experience. It deliberately exposes opaque column +// and relationship identifiers instead of FHIR selectors or graph labels. +// +// The package has no transport or database dependency. A caller first obtains +// scoped facts from internal/catalog, then passes those facts to BuildSnapshot. +// A later command handler must resolve every opaque identifier against a fresh, +// authorized snapshot before it asks the dataframe compiler to lower a query. +package discovery + +import "github.com/calypr/loom/internal/catalog" + +const maxSuggestedValues = 50 + +// CatalogFacts is a server-internal adapter input. Fields and Relationships +// must already have been read for one authorized project/scope using the +// existing catalog readers. It is intentionally not a transport request: it +// carries catalog facts, including implementation-level field paths, only long +// enough for BuildSnapshot to turn them into opaque user-facing identifiers. +// This package deliberately does not create a dataset, generation, or scope +// identity model; an owning identity layer can correlate this scoped snapshot +// later without changing the discovery vocabulary. +type CatalogFacts struct { + Project string + Fields []catalog.PopulatedField + Relationships []catalog.PopulatedReference +} + +// Snapshot is the bounded discovery response that a guided frontend may use. +// It contains no FHIR field paths, selectors, AQL fragments, collection names, +// authorization paths, or graph edge labels. +type Snapshot struct { + Dataset DatasetSummary `json:"dataset"` + Relationships RelationshipInventory `json:"relationships"` + Columns []CandidateColumn `json:"columns"` + Filters []GuidedFilterSuggestion `json:"filters"` +} + +// DatasetSummary describes the generated-schema root resources and their +// availability in the supplied catalog facts. Roots remain present even when +// unavailable so a caller can distinguish "not loaded in this scope" from +// "not represented by this Loom build". A user-facing chooser should normally +// offer only roots whose Available flag is true. +type DatasetSummary struct { + Project string `json:"project"` + Roots []RootResourceSummary `json:"roots"` +} + +// RootResourceSummary is derived from the active generated FHIR schema and +// then annotated from catalog facts. The counts describe discoverable compiler +// inputs, not a total number of FHIR documents. +type RootResourceSummary struct { + ResourceType string `json:"resourceType"` + Supported bool `json:"supported"` + Available bool `json:"available"` + SupportReason RootSupportReason `json:"supportReason"` + CandidateColumnCount int `json:"candidateColumnCount"` + RelationshipCount int `json:"relationshipCount"` +} + +// RootSupportReason is intentionally small and stable. It describes only the +// generated-schema/catalog evidence available to this package; it is not a +// dataset generation, load job, or persistence state. +type RootSupportReason string + +const ( + RootSupportObservedInCatalog RootSupportReason = "OBSERVED_IN_CATALOG" + RootSupportNotObservedInCatalog RootSupportReason = "NOT_OBSERVED_IN_CATALOG" +) + +// RelationshipID is an opaque, deterministic identifier. It is stable for a +// generated-schema route while the active graph schema remains the same. +type RelationshipID string + +// RelationshipInventory contains only populated routes that are represented +// by the active generated FHIR graph schema. Its entries are suitable for a +// guided "include related …" chooser, but do not imply a physical AQL +// direction. +type RelationshipInventory struct { + Entries []Relationship `json:"entries"` +} + +// RelationshipMultiplicity is the schema-declared target cardinality. It is a +// semantic fact, not an estimate of rows or an AQL traversal direction. +type RelationshipMultiplicity string + +const ( + RelationshipOne RelationshipMultiplicity = "ONE" + RelationshipMany RelationshipMultiplicity = "MANY" +) + +// Relationship is a populated, compiler-safe route between concrete generated +// FHIR resource roots. Label is presentation text; the underlying graph label +// remains internal and is recoverable only by resolving ID against facts. +type Relationship struct { + ID RelationshipID `json:"id"` + FromResourceType string `json:"fromResourceType"` + ToResourceType string `json:"toResourceType"` + Label string `json:"label"` + Multiplicity RelationshipMultiplicity `json:"multiplicity"` + ObservedEdgeCount int64 `json:"observedEdgeCount"` +} + +// ColumnID is an opaque, deterministic identifier for a catalog field. It is +// deliberately not a field path or a dataframe FieldRef. +type ColumnID string + +// ValueKind is the safe scalar shape known from generated FHIR metadata. A +// COMPOSITE candidate represents a catalog pivot root and is not directly +// filterable or selectable until a later compiler adapter resolves it. +type ValueKind string + +const ( + ValueKindString ValueKind = "STRING" + ValueKindBoolean ValueKind = "BOOLEAN" + ValueKindInteger ValueKind = "INTEGER" + ValueKindDecimal ValueKind = "DECIMAL" + ValueKindDate ValueKind = "DATE" + ValueKindDateTime ValueKind = "DATE_TIME" + ValueKindComposite ValueKind = "COMPOSITE" +) + +// CandidateColumn is a safe frontend-facing field choice. Capability flags +// make composite pivot roots explicit instead of pretending every observed +// catalog object can be lowered as a scalar dataframe column. +type CandidateColumn struct { + ID ColumnID `json:"id"` + ResourceType string `json:"resourceType"` + Label string `json:"label"` + ValueKind ValueKind `json:"valueKind"` + Repeated bool `json:"repeated"` + CanSelect bool `json:"canSelect"` + CanFilter bool `json:"canFilter"` + CanPivot bool `json:"canPivot"` + PopulatedDocumentCount int64 `json:"populatedDocumentCount"` + SuggestedValues []string `json:"suggestedValues"` + ValuesTruncated bool `json:"valuesTruncated"` +} + +// FilterSuggestionID is an opaque, deterministic identifier for the guided +// filter affordance associated with a scalar CandidateColumn. +type FilterSuggestionID string + +// FilterOperator is intentionally a closed product vocabulary. A later +// compiler adapter maps these tokens to dataframe.TypedFilter only after it +// resolves ColumnID against the current authorized catalog facts. +type FilterOperator string + +const ( + FilterEquals FilterOperator = "EQUALS" + FilterNotEquals FilterOperator = "NOT_EQUALS" + FilterIn FilterOperator = "IN" + FilterExists FilterOperator = "EXISTS" + FilterMissing FilterOperator = "MISSING" + FilterContains FilterOperator = "CONTAINS_TEXT" + FilterGreaterThan FilterOperator = "GT" + FilterGreaterEq FilterOperator = "GTE" + FilterLessThan FilterOperator = "LT" + FilterLessEq FilterOperator = "LTE" +) + +// FilterQuantifier controls how a repeated scalar field is evaluated. Scalar +// candidates have no quantifier options. +type FilterQuantifier string + +const ( + FilterAny FilterQuantifier = "ANY" + FilterAll FilterQuantifier = "ALL" + FilterNone FilterQuantifier = "NONE" +) + +// GuidedFilterSuggestion is the complete field/operator/value vocabulary for +// a guided filter sentence such as "Gender is female." Values are examples +// observed by the catalog, not an exhaustive terminology list. +type GuidedFilterSuggestion struct { + ID FilterSuggestionID `json:"id"` + ColumnID ColumnID `json:"columnId"` + ResourceType string `json:"resourceType"` + Label string `json:"label"` + ValueKind ValueKind `json:"valueKind"` + Repeated bool `json:"repeated"` + Operators []FilterOperator `json:"operators"` + Quantifiers []FilterQuantifier `json:"quantifiers"` + SuggestedValues []string `json:"suggestedValues"` + ValuesTruncated bool `json:"valuesTruncated"` +} diff --git a/internal/discovery/validation.go b/internal/discovery/validation.go new file mode 100644 index 0000000..bb9e732 --- /dev/null +++ b/internal/discovery/validation.go @@ -0,0 +1,326 @@ +package discovery + +import ( + "encoding/hex" + "fmt" + "strings" + + "github.com/calypr/loom/internal/fhirschema" +) + +// Validate proves that a Snapshot remains a normalized, compiler-safe product +// contract. It is useful at the boundary where a later command handler accepts +// IDs chosen from a prior discovery response. +func (snapshot Snapshot) Validate() error { + if strings.TrimSpace(snapshot.Dataset.Project) == "" { + return fmt.Errorf("dataset project is required") + } + roots, err := validateRoots(snapshot.Dataset.Roots) + if err != nil { + return err + } + + columnCounts := make(map[string]int, len(roots)) + columns, err := validateColumns(snapshot.Columns, roots, columnCounts) + if err != nil { + return err + } + relationshipCounts := make(map[string]int, len(roots)) + if err := validateRelationships(snapshot.Relationships.Entries, roots, relationshipCounts); err != nil { + return err + } + if err := validateFilters(snapshot.Filters, columns); err != nil { + return err + } + + for _, root := range snapshot.Dataset.Roots { + if root.CandidateColumnCount != columnCounts[root.ResourceType] { + return fmt.Errorf("root candidate column count does not match columns") + } + if root.RelationshipCount != relationshipCounts[root.ResourceType] { + return fmt.Errorf("root relationship count does not match relationships") + } + if root.Available != (root.CandidateColumnCount > 0 || root.RelationshipCount > 0 || hasIncomingRelationship(snapshot.Relationships.Entries, root.ResourceType)) { + return fmt.Errorf("root availability does not match supplied catalog facts") + } + } + return nil +} + +func validateRoots(roots []RootResourceSummary) (map[string]RootResourceSummary, error) { + expected := fhirschema.ResourceTypes() + if len(roots) != len(expected) { + return nil, fmt.Errorf("dataset roots do not match active generated schema") + } + byType := make(map[string]RootResourceSummary, len(roots)) + for i, root := range roots { + if root.ResourceType != expected[i] { + return nil, fmt.Errorf("dataset roots are not the sorted active generated schema roots") + } + if !root.Supported { + return nil, fmt.Errorf("generated schema root must be marked supported") + } + if !root.SupportReason.Valid() { + return nil, fmt.Errorf("root support reason is invalid") + } + if root.Available && root.SupportReason != RootSupportObservedInCatalog { + return nil, fmt.Errorf("available root must have observed catalog support reason") + } + if !root.Available && root.SupportReason != RootSupportNotObservedInCatalog { + return nil, fmt.Errorf("unavailable root must have not observed support reason") + } + if root.CandidateColumnCount < 0 || root.RelationshipCount < 0 { + return nil, fmt.Errorf("root counts must not be negative") + } + byType[root.ResourceType] = root + } + return byType, nil +} + +func validateColumns(columns []CandidateColumn, roots map[string]RootResourceSummary, counts map[string]int) (map[ColumnID]CandidateColumn, error) { + byID := make(map[ColumnID]CandidateColumn, len(columns)) + var previous CandidateColumn + for index, column := range columns { + if !validOpaqueID(string(column.ID), "col_") { + return nil, fmt.Errorf("candidate column ID is not a valid opaque identifier") + } + if _, ok := roots[column.ResourceType]; !ok { + return nil, fmt.Errorf("candidate column resource type is not an active generated root") + } + if strings.TrimSpace(column.Label) == "" { + return nil, fmt.Errorf("candidate column label is required") + } + if !column.ValueKind.Valid() { + return nil, fmt.Errorf("candidate column has an unsupported value kind") + } + if column.PopulatedDocumentCount < 0 { + return nil, fmt.Errorf("candidate column population count must not be negative") + } + if err := validateColumnCapabilities(column); err != nil { + return nil, err + } + if err := validateSuggestedValues(column.SuggestedValues); err != nil { + return nil, err + } + if _, exists := byID[column.ID]; exists { + return nil, fmt.Errorf("candidate column IDs must be unique") + } + if index > 0 && compareColumns(previous, column) >= 0 { + return nil, fmt.Errorf("candidate columns are not sorted deterministically") + } + previous = column + byID[column.ID] = column + counts[column.ResourceType]++ + } + return byID, nil +} + +func validateColumnCapabilities(column CandidateColumn) error { + switch column.ValueKind { + case ValueKindComposite: + if column.Repeated || column.CanSelect || column.CanFilter || !column.CanPivot { + return fmt.Errorf("composite candidate must be pivot-only") + } + default: + if !column.CanSelect || !column.CanFilter { + return fmt.Errorf("scalar candidate must support selection and filtering") + } + } + return nil +} + +func validateRelationships(relationships []Relationship, roots map[string]RootResourceSummary, counts map[string]int) error { + seen := make(map[RelationshipID]struct{}, len(relationships)) + var previous Relationship + for index, relationship := range relationships { + if !validOpaqueID(string(relationship.ID), "rel_") { + return fmt.Errorf("relationship ID is not a valid opaque identifier") + } + if _, ok := roots[relationship.FromResourceType]; !ok { + return fmt.Errorf("relationship source is not an active generated root") + } + if _, ok := roots[relationship.ToResourceType]; !ok { + return fmt.Errorf("relationship target is not an active generated root") + } + if strings.TrimSpace(relationship.Label) == "" { + return fmt.Errorf("relationship label is required") + } + if !relationship.Multiplicity.Valid() { + return fmt.Errorf("relationship has unsupported multiplicity") + } + if relationship.ObservedEdgeCount < 0 { + return fmt.Errorf("relationship edge count must not be negative") + } + if _, exists := seen[relationship.ID]; exists { + return fmt.Errorf("relationship IDs must be unique") + } + if index > 0 && compareRelationships(previous, relationship) >= 0 { + return fmt.Errorf("relationships are not sorted deterministically") + } + previous = relationship + seen[relationship.ID] = struct{}{} + counts[relationship.FromResourceType]++ + } + return nil +} + +func validateFilters(filters []GuidedFilterSuggestion, columns map[ColumnID]CandidateColumn) error { + seen := make(map[FilterSuggestionID]struct{}, len(filters)) + var previous GuidedFilterSuggestion + filterableColumns := 0 + for _, column := range columns { + if column.CanFilter { + filterableColumns++ + } + } + if len(filters) != filterableColumns { + return fmt.Errorf("guided filters must cover every filterable candidate exactly once") + } + for index, filter := range filters { + if !validOpaqueID(string(filter.ID), "flt_") { + return fmt.Errorf("guided filter ID is not a valid opaque identifier") + } + column, ok := columns[filter.ColumnID] + if !ok || !column.CanFilter { + return fmt.Errorf("guided filter does not resolve to a filterable candidate") + } + if filter.ID != opaqueFilterSuggestionID(filter.ColumnID) || + filter.ResourceType != column.ResourceType || + filter.Label != column.Label || + filter.ValueKind != column.ValueKind || + filter.Repeated != column.Repeated || + !equalFilterOperators(filter.Operators, filterOperators(column.ValueKind)) || + !equalFilterQuantifiers(filter.Quantifiers, filterQuantifiers(column.Repeated)) || + !equalStrings(filter.SuggestedValues, column.SuggestedValues) || + filter.ValuesTruncated != column.ValuesTruncated { + return fmt.Errorf("guided filter does not match its candidate") + } + if _, exists := seen[filter.ID]; exists { + return fmt.Errorf("guided filter IDs must be unique") + } + if index > 0 && compareFilters(previous, filter) >= 0 { + return fmt.Errorf("guided filters are not sorted deterministically") + } + previous = filter + seen[filter.ID] = struct{}{} + } + return nil +} + +func hasIncomingRelationship(relationships []Relationship, resourceType string) bool { + for _, relationship := range relationships { + if relationship.ToResourceType == resourceType { + return true + } + } + return false +} + +func validOpaqueID(value, prefix string) bool { + if !strings.HasPrefix(value, prefix) || len(value) != len(prefix)+64 { + return false + } + _, err := hex.DecodeString(strings.TrimPrefix(value, prefix)) + return err == nil +} + +func validateSuggestedValues(values []string) error { + if len(values) > maxSuggestedValues { + return fmt.Errorf("suggested values exceed the bounded limit") + } + for index, value := range values { + if strings.TrimSpace(value) == "" { + return fmt.Errorf("suggested values must not be empty") + } + if index > 0 && values[index-1] >= value { + return fmt.Errorf("suggested values are not sorted and unique") + } + } + return nil +} + +func compareColumns(left, right CandidateColumn) int { + if left.ResourceType != right.ResourceType { + return strings.Compare(left.ResourceType, right.ResourceType) + } + if left.Label != right.Label { + return strings.Compare(left.Label, right.Label) + } + return strings.Compare(string(left.ID), string(right.ID)) +} + +func compareRelationships(left, right Relationship) int { + if left.FromResourceType != right.FromResourceType { + return strings.Compare(left.FromResourceType, right.FromResourceType) + } + if left.ToResourceType != right.ToResourceType { + return strings.Compare(left.ToResourceType, right.ToResourceType) + } + if left.Label != right.Label { + return strings.Compare(left.Label, right.Label) + } + return strings.Compare(string(left.ID), string(right.ID)) +} + +func compareFilters(left, right GuidedFilterSuggestion) int { + if left.ResourceType != right.ResourceType { + return strings.Compare(left.ResourceType, right.ResourceType) + } + if left.Label != right.Label { + return strings.Compare(left.Label, right.Label) + } + return strings.Compare(string(left.ID), string(right.ID)) +} + +func equalStrings(left, right []string) bool { + if len(left) != len(right) { + return false + } + for index := range left { + if left[index] != right[index] { + return false + } + } + return true +} + +func equalFilterOperators(left, right []FilterOperator) bool { + if len(left) != len(right) { + return false + } + for index := range left { + if left[index] != right[index] { + return false + } + } + return true +} + +func equalFilterQuantifiers(left, right []FilterQuantifier) bool { + if len(left) != len(right) { + return false + } + for index := range left { + if left[index] != right[index] { + return false + } + } + return true +} + +func (kind ValueKind) Valid() bool { + switch kind { + case ValueKindString, ValueKindBoolean, ValueKindInteger, ValueKindDecimal, ValueKindDate, ValueKindDateTime, ValueKindComposite: + return true + default: + return false + } +} + +func (multiplicity RelationshipMultiplicity) Valid() bool { + return multiplicity == RelationshipOne || multiplicity == RelationshipMany +} + +func (reason RootSupportReason) Valid() bool { + return reason == RootSupportObservedInCatalog || reason == RootSupportNotObservedInCatalog +} diff --git a/internal/export/encode.go b/internal/export/encode.go new file mode 100644 index 0000000..eb0622c --- /dev/null +++ b/internal/export/encode.go @@ -0,0 +1,369 @@ +// Package export serializes flat dataframe rows to portable export formats. +// +// It deliberately owns only row encoding. Query execution, artifact storage, +// delivery transports, and job management stay outside this package so every +// destination can consume the same flat-row contract. +package export + +import ( + "context" + "encoding/csv" + "encoding/json" + "fmt" + "io" + "math" + "reflect" + "sort" + "strconv" +) + +// RowVisitor receives one flat dataframe row. Returning an error asks the +// producer to stop iteration. +type RowVisitor func(map[string]any) error + +// RowStream emits rows without materializing the dataframe in this package. +// +// A stream must respect an error returned by RowVisitor. EncodeCSV calls a +// stream once when CSVOptions.Columns is supplied and twice otherwise: once +// to discover the deterministic column union and once to write records. For +// that mode, callers must provide a replayable stream that returns the same +// logical rows in the same order for each invocation (for example, re-running +// a stable compiled query). +type RowStream func(context.Context, RowVisitor) error + +// Result describes encoder progress. On success it describes the complete +// export. If an encoder returns an error, Rows and Bytes describe only the +// progress observed before that error. Columns is always in output order. +type Result struct { + Rows int64 + Bytes int64 + Columns []string +} + +// CSVOptions controls CSV schema selection. A non-empty Columns slice is the +// exact header and field order to write. Rows containing a column outside the +// configured schema are rejected rather than silently discarded. With no +// columns, EncodeCSV discovers the union of all row keys and sorts it +// lexicographically. +type CSVOptions struct { + Columns []string +} + +// ValueError reports a value that cannot be represented as a flat dataframe +// scalar. Maps, slices, structs, pointers, and non-finite numbers are +// intentionally rejected instead of being stringified or nested in output. +type ValueError struct { + Row int64 + Column string + ValueType string + Reason string +} + +func (e *ValueError) Error() string { + if e.Reason != "" { + return fmt.Sprintf("row %d column %q has unsupported value of type %s: %s", e.Row, e.Column, e.ValueType, e.Reason) + } + return fmt.Sprintf("row %d column %q has unsupported nested value of type %s; export rows must contain scalar values", e.Row, e.Column, e.ValueType) +} + +// ColumnError reports an invalid CSV schema or a row field that cannot be +// represented by that schema. Row is zero for a configured-header error. +type ColumnError struct { + Row int64 + Column string + Reason string +} + +func (e *ColumnError) Error() string { + if e.Row == 0 { + return fmt.Sprintf("CSV column %q %s", e.Column, e.Reason) + } + return fmt.Sprintf("row %d column %q %s", e.Row, e.Column, e.Reason) +} + +// EncodeNDJSON writes one JSON object and exactly one trailing newline for +// every row in stream. It retains at most one encoded row plus the observed +// column set, never the complete dataframe. +func EncodeNDJSON(ctx context.Context, dst io.Writer, stream RowStream) (Result, error) { + if dst == nil { + return Result{}, fmt.Errorf("NDJSON destination writer is required") + } + + writer := &countingWriter{dst: dst} + columns := make(map[string]struct{}) + var result Result + err := visitRows(ctx, stream, func(row map[string]any) error { + rowNumber := result.Rows + 1 + keys, err := validateRow(row, rowNumber) + if err != nil { + return err + } + for _, key := range keys { + columns[key] = struct{}{} + } + + encoded, err := marshalRow(row) + if err != nil { + return fmt.Errorf("row %d: encode NDJSON: %w", rowNumber, err) + } + encoded = append(encoded, '\n') + if _, err := writeAll(writer, encoded); err != nil { + return fmt.Errorf("row %d: write NDJSON: %w", rowNumber, err) + } + result.Rows++ + return nil + }) + result.Bytes = writer.n + result.Columns = sortedColumns(columns) + if err != nil { + return result, err + } + return result, nil +} + +// EncodeCSV writes a CSV header followed by one record for each row. It uses +// encoding/csv for RFC 4180-compatible escaping. When Columns is omitted the +// source is scanned once to discover a sorted column union, then replayed to +// encode rows; this keeps memory proportional to the number of columns rather +// than the number of rows. +func EncodeCSV(ctx context.Context, dst io.Writer, options CSVOptions, stream RowStream) (Result, error) { + if dst == nil { + return Result{}, fmt.Errorf("CSV destination writer is required") + } + + columns, allowed, err := configuredColumns(options.Columns) + if err != nil { + return Result{}, err + } + if len(columns) == 0 { + columns, err = discoverColumns(ctx, stream) + if err != nil { + return Result{}, err + } + allowed = make(map[string]struct{}, len(columns)) + for _, column := range columns { + allowed[column] = struct{}{} + } + } + + writer := &countingWriter{dst: dst} + csvWriter := csv.NewWriter(writer) + if len(columns) > 0 { + if err := csvWriter.Write(columns); err != nil { + return Result{Columns: cloneStrings(columns)}, fmt.Errorf("write CSV header: %w", err) + } + } + + result := Result{Columns: cloneStrings(columns)} + streamErr := visitRows(ctx, stream, func(row map[string]any) error { + rowNumber := result.Rows + 1 + keys, err := validateRow(row, rowNumber) + if err != nil { + return err + } + for _, key := range keys { + if _, ok := allowed[key]; !ok { + return &ColumnError{Row: rowNumber, Column: key, Reason: "is not present in the CSV schema"} + } + } + + record := make([]string, len(columns)) + for i, column := range columns { + record[i] = scalarString(row[column]) + } + if err := csvWriter.Write(record); err != nil { + return fmt.Errorf("row %d: write CSV: %w", rowNumber, err) + } + result.Rows++ + return nil + }) + csvWriter.Flush() + result.Bytes = writer.n + if streamErr != nil { + return result, streamErr + } + if err := csvWriter.Error(); err != nil { + return result, fmt.Errorf("write CSV: %w", err) + } + return result, nil +} + +func visitRows(ctx context.Context, stream RowStream, visit RowVisitor) error { + if stream == nil { + return fmt.Errorf("export row stream is required") + } + if err := ctx.Err(); err != nil { + return err + } + if err := stream(ctx, func(row map[string]any) error { + if err := ctx.Err(); err != nil { + return err + } + return visit(row) + }); err != nil { + return fmt.Errorf("stream export rows: %w", err) + } + return ctx.Err() +} + +func configuredColumns(columns []string) ([]string, map[string]struct{}, error) { + if len(columns) == 0 { + return nil, nil, nil + } + out := cloneStrings(columns) + seen := make(map[string]struct{}, len(out)) + for _, column := range out { + if column == "" { + return nil, nil, &ColumnError{Column: column, Reason: "must not be empty"} + } + if _, ok := seen[column]; ok { + return nil, nil, &ColumnError{Column: column, Reason: "is duplicated"} + } + seen[column] = struct{}{} + } + return out, seen, nil +} + +func discoverColumns(ctx context.Context, stream RowStream) ([]string, error) { + columns := make(map[string]struct{}) + var rows int64 + err := visitRows(ctx, stream, func(row map[string]any) error { + rows++ + keys, err := validateRow(row, rows) + if err != nil { + return err + } + for _, key := range keys { + columns[key] = struct{}{} + } + return nil + }) + if err != nil { + return nil, err + } + return sortedColumns(columns), nil +} + +func validateRow(row map[string]any, rowNumber int64) ([]string, error) { + keys := make([]string, 0, len(row)) + for key := range row { + keys = append(keys, key) + } + sort.Strings(keys) + for _, key := range keys { + if key == "" { + return nil, &ColumnError{Row: rowNumber, Column: key, Reason: "must not be empty"} + } + if err := validateScalar(row[key], rowNumber, key); err != nil { + return nil, err + } + } + return keys, nil +} + +func validateScalar(value any, rowNumber int64, column string) error { + if value == nil { + return nil + } + valueType := reflect.TypeOf(value).String() + if _, ok := value.(json.Marshaler); ok { + return &ValueError{Row: rowNumber, Column: column, ValueType: valueType, Reason: "custom JSON marshalers are not supported for flat export values"} + } + valueOf := reflect.ValueOf(value) + switch valueOf.Kind() { + case reflect.Bool, reflect.String, + reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + if number, ok := value.(json.Number); ok { + if _, err := json.Marshal(number); err != nil { + return &ValueError{Row: rowNumber, Column: column, ValueType: valueType, Reason: "invalid JSON number"} + } + } + return nil + case reflect.Float32, reflect.Float64: + floatValue := valueOf.Float() + if math.IsNaN(floatValue) || math.IsInf(floatValue, 0) { + return &ValueError{Row: rowNumber, Column: column, ValueType: valueType, Reason: "non-finite numbers are not valid JSON"} + } + return nil + default: + return &ValueError{Row: rowNumber, Column: column, ValueType: valueType} + } +} + +func marshalRow(row map[string]any) ([]byte, error) { + if row == nil { + return []byte("{}"), nil + } + return json.Marshal(row) +} + +func scalarString(value any) string { + if value == nil { + return "" + } + valueOf := reflect.ValueOf(value) + switch valueOf.Kind() { + case reflect.String: + return valueOf.String() + case reflect.Bool: + return strconv.FormatBool(valueOf.Bool()) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return strconv.FormatInt(valueOf.Int(), 10) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return strconv.FormatUint(valueOf.Uint(), 10) + case reflect.Float32, reflect.Float64: + return strconv.FormatFloat(valueOf.Float(), 'g', -1, valueOf.Type().Bits()) + default: + return "" + } +} + +func sortedColumns(columns map[string]struct{}) []string { + if len(columns) == 0 { + return []string{} + } + out := make([]string, 0, len(columns)) + for column := range columns { + out = append(out, column) + } + sort.Strings(out) + return out +} + +func cloneStrings(values []string) []string { + if len(values) == 0 { + return []string{} + } + return append([]string(nil), values...) +} + +type countingWriter struct { + dst io.Writer + n int64 +} + +func (w *countingWriter) Write(p []byte) (int, error) { + n, err := w.dst.Write(p) + w.n += int64(n) + if err == nil && n != len(p) { + return n, io.ErrShortWrite + } + return n, err +} + +func writeAll(dst io.Writer, data []byte) (int64, error) { + var written int64 + for len(data) > 0 { + n, err := dst.Write(data) + written += int64(n) + data = data[n:] + if err != nil { + return written, err + } + if n == 0 { + return written, io.ErrShortWrite + } + } + return written, nil +} diff --git a/internal/export/encode_test.go b/internal/export/encode_test.go new file mode 100644 index 0000000..009fd37 --- /dev/null +++ b/internal/export/encode_test.go @@ -0,0 +1,215 @@ +package export + +import ( + "bytes" + "context" + "encoding/csv" + "encoding/json" + "errors" + "reflect" + "strings" + "testing" +) + +func TestEncodeNDJSONWritesOneDeterministicObjectPerLine(t *testing.T) { + rows := staticRows( + map[string]any{"zeta": 2, "alpha": "first"}, + map[string]any{"alpha": "second", "nullable": nil}, + ) + + var output bytes.Buffer + result, err := EncodeNDJSON(context.Background(), &output, rows) + if err != nil { + t.Fatalf("EncodeNDJSON() error = %v", err) + } + const want = "{\"alpha\":\"first\",\"zeta\":2}\n{\"alpha\":\"second\",\"nullable\":null}\n" + if got := output.String(); got != want { + t.Fatalf("NDJSON = %q, want %q", got, want) + } + if result.Rows != 2 { + t.Fatalf("Rows = %d, want 2", result.Rows) + } + if result.Bytes != int64(len(want)) { + t.Fatalf("Bytes = %d, want %d", result.Bytes, len(want)) + } + if wantColumns := []string{"alpha", "nullable", "zeta"}; !reflect.DeepEqual(result.Columns, wantColumns) { + t.Fatalf("Columns = %#v, want %#v", result.Columns, wantColumns) + } + + for _, line := range strings.Split(strings.TrimSuffix(output.String(), "\n"), "\n") { + var row map[string]any + if err := json.Unmarshal([]byte(line), &row); err != nil { + t.Fatalf("NDJSON line %q is not an object: %v", line, err) + } + } +} + +func TestEncodeCSVDiscoversSortedColumnUnionWithoutMaterializingRows(t *testing.T) { + var passes int + rows := func(ctx context.Context, visit RowVisitor) error { + passes++ + for _, row := range []map[string]any{ + {"zeta": "z", "alpha": "a"}, + {"middle": 2, "alpha": "again"}, + } { + if err := visit(row); err != nil { + return err + } + } + return nil + } + + var output bytes.Buffer + result, err := EncodeCSV(context.Background(), &output, CSVOptions{}, rows) + if err != nil { + t.Fatalf("EncodeCSV() error = %v", err) + } + const want = "alpha,middle,zeta\na,,z\nagain,2,\n" + if got := output.String(); got != want { + t.Fatalf("CSV = %q, want %q", got, want) + } + if passes != 2 { + t.Fatalf("stream passes = %d, want 2 for inferred columns", passes) + } + if result.Rows != 2 { + t.Fatalf("Rows = %d, want 2", result.Rows) + } + if wantColumns := []string{"alpha", "middle", "zeta"}; !reflect.DeepEqual(result.Columns, wantColumns) { + t.Fatalf("Columns = %#v, want %#v", result.Columns, wantColumns) + } +} + +func TestEncodeCSVUsesConfiguredOrderAndStandardEscaping(t *testing.T) { + rows := staticRows(map[string]any{ + "plain": "value", + "quoted": "say \"hello\"", + "comma": "left,right", + "newline": "first\nsecond", + }) + + var output bytes.Buffer + result, err := EncodeCSV(context.Background(), &output, CSVOptions{Columns: []string{"newline", "comma", "quoted", "plain"}}, rows) + if err != nil { + t.Fatalf("EncodeCSV() error = %v", err) + } + if wantColumns := []string{"newline", "comma", "quoted", "plain"}; !reflect.DeepEqual(result.Columns, wantColumns) { + t.Fatalf("Columns = %#v, want %#v", result.Columns, wantColumns) + } + + parsed, err := csv.NewReader(strings.NewReader(output.String())).ReadAll() + if err != nil { + t.Fatalf("parse CSV: %v", err) + } + want := [][]string{ + {"newline", "comma", "quoted", "plain"}, + {"first\nsecond", "left,right", "say \"hello\"", "value"}, + } + if !reflect.DeepEqual(parsed, want) { + t.Fatalf("parsed CSV = %#v, want %#v; raw=%q", parsed, want, output.String()) + } +} + +func TestEncodeEmptyInput(t *testing.T) { + empty := staticRows() + + var ndjson bytes.Buffer + ndjsonResult, err := EncodeNDJSON(context.Background(), &ndjson, empty) + if err != nil { + t.Fatalf("EncodeNDJSON() error = %v", err) + } + if ndjson.String() != "" || ndjsonResult.Rows != 0 || len(ndjsonResult.Columns) != 0 { + t.Fatalf("empty NDJSON = %q, result=%#v", ndjson.String(), ndjsonResult) + } + + var inferredCSV bytes.Buffer + inferredResult, err := EncodeCSV(context.Background(), &inferredCSV, CSVOptions{}, empty) + if err != nil { + t.Fatalf("EncodeCSV inferred() error = %v", err) + } + if inferredCSV.String() != "" || inferredResult.Rows != 0 || len(inferredResult.Columns) != 0 { + t.Fatalf("empty inferred CSV = %q, result=%#v", inferredCSV.String(), inferredResult) + } + + var configuredCSV bytes.Buffer + configuredResult, err := EncodeCSV(context.Background(), &configuredCSV, CSVOptions{Columns: []string{"patient_id", "status"}}, empty) + if err != nil { + t.Fatalf("EncodeCSV configured() error = %v", err) + } + if got, want := configuredCSV.String(), "patient_id,status\n"; got != want { + t.Fatalf("configured empty CSV = %q, want %q", got, want) + } + if configuredResult.Rows != 0 { + t.Fatalf("configured empty Rows = %d, want 0", configuredResult.Rows) + } +} + +func TestEncodeRejectsNestedValuesWithRowAndColumn(t *testing.T) { + tests := []struct { + name string + run func(*bytes.Buffer) error + }{ + { + name: "ndjson", + run: func(output *bytes.Buffer) error { + _, err := EncodeNDJSON(context.Background(), output, staticRows(map[string]any{"nested": map[string]any{"no": "thanks"}})) + return err + }, + }, + { + name: "csv", + run: func(output *bytes.Buffer) error { + _, err := EncodeCSV(context.Background(), output, CSVOptions{}, staticRows(map[string]any{"nested": []string{"no", "thanks"}})) + return err + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + var output bytes.Buffer + err := test.run(&output) + if err == nil { + t.Fatal("expected an error") + } + var valueErr *ValueError + if !errors.As(err, &valueErr) { + t.Fatalf("error = %T %v, want ValueError", err, err) + } + if valueErr.Row != 1 || valueErr.Column != "nested" { + t.Fatalf("ValueError = %#v, want row 1/nested", valueErr) + } + if !strings.Contains(err.Error(), "unsupported nested value") { + t.Fatalf("error = %q, want clear nested-value explanation", err) + } + }) + } +} + +func TestEncodeCSVRejectsColumnsThatWouldBeDropped(t *testing.T) { + var output bytes.Buffer + _, err := EncodeCSV(context.Background(), &output, CSVOptions{Columns: []string{"included"}}, staticRows(map[string]any{"included": "yes", "extra": "no"})) + if err == nil { + t.Fatal("expected an error") + } + var columnErr *ColumnError + if !errors.As(err, &columnErr) { + t.Fatalf("error = %T %v, want ColumnError", err, err) + } + if columnErr.Row != 1 || columnErr.Column != "extra" { + t.Fatalf("ColumnError = %#v, want row 1 extra", columnErr) + } +} + +func staticRows(rows ...map[string]any) RowStream { + return func(ctx context.Context, visit RowVisitor) error { + for _, row := range rows { + if err := ctx.Err(); err != nil { + return err + } + if err := visit(row); err != nil { + return err + } + } + return nil + } +} diff --git a/internal/fhir/extract.go b/internal/fhir/extract.go index 9ff713e..78926bb 100644 --- a/internal/fhir/extract.go +++ b/internal/fhir/extract.go @@ -7,12 +7,12 @@ import ( "encoding/hex" "encoding/json" "fmt" + "github.com/bytedance/sonic" + "github.com/google/uuid" "hash" "strconv" "strings" "sync" - "github.com/google/uuid" - "github.com/bytedance/sonic" ) // EdgeDocument represents an edge in ArangoDB. @@ -572,7 +572,7 @@ func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandma _ = seen if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -620,7 +620,7 @@ func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandma } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -668,7 +668,7 @@ func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandma } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -716,7 +716,7 @@ func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandma } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -764,7 +764,7 @@ func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandma } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -812,7 +812,7 @@ func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandma } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -860,7 +860,7 @@ func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandma } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -908,7 +908,7 @@ func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandma } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -956,7 +956,7 @@ func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandma } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -1004,7 +1004,7 @@ func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandma } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -1052,7 +1052,7 @@ func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandma } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -1100,7 +1100,7 @@ func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandma } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -1148,7 +1148,7 @@ func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandma } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -1196,7 +1196,7 @@ func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandma } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -1244,7 +1244,7 @@ func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandma } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -1292,7 +1292,7 @@ func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandma } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -1340,7 +1340,7 @@ func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandma } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -1388,7 +1388,7 @@ func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandma } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -1436,7 +1436,7 @@ func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandma } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -1484,7 +1484,7 @@ func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandma } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -1532,7 +1532,7 @@ func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandma } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -1580,7 +1580,7 @@ func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandma } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -1628,7 +1628,7 @@ func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandma } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -2794,7 +2794,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Evidence != nil { for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { + if item_3_x_Evidence != nil { if item_3_x_Evidence.Reference != nil { if item_3_x_Evidence.Reference.Reference != nil { refVal := *item_3_x_Evidence.Reference.Reference @@ -2842,7 +2842,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Evidence != nil { for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { + if item_3_x_Evidence != nil { if item_3_x_Evidence.Reference != nil { if item_3_x_Evidence.Reference.Reference != nil { refVal := *item_3_x_Evidence.Reference.Reference @@ -2890,7 +2890,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Evidence != nil { for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { + if item_3_x_Evidence != nil { if item_3_x_Evidence.Reference != nil { if item_3_x_Evidence.Reference.Reference != nil { refVal := *item_3_x_Evidence.Reference.Reference @@ -2938,7 +2938,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Evidence != nil { for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { + if item_3_x_Evidence != nil { if item_3_x_Evidence.Reference != nil { if item_3_x_Evidence.Reference.Reference != nil { refVal := *item_3_x_Evidence.Reference.Reference @@ -2986,7 +2986,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Evidence != nil { for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { + if item_3_x_Evidence != nil { if item_3_x_Evidence.Reference != nil { if item_3_x_Evidence.Reference.Reference != nil { refVal := *item_3_x_Evidence.Reference.Reference @@ -3034,7 +3034,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Evidence != nil { for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { + if item_3_x_Evidence != nil { if item_3_x_Evidence.Reference != nil { if item_3_x_Evidence.Reference.Reference != nil { refVal := *item_3_x_Evidence.Reference.Reference @@ -3082,7 +3082,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Evidence != nil { for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { + if item_3_x_Evidence != nil { if item_3_x_Evidence.Reference != nil { if item_3_x_Evidence.Reference.Reference != nil { refVal := *item_3_x_Evidence.Reference.Reference @@ -3130,7 +3130,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Evidence != nil { for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { + if item_3_x_Evidence != nil { if item_3_x_Evidence.Reference != nil { if item_3_x_Evidence.Reference.Reference != nil { refVal := *item_3_x_Evidence.Reference.Reference @@ -3178,7 +3178,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Evidence != nil { for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { + if item_3_x_Evidence != nil { if item_3_x_Evidence.Reference != nil { if item_3_x_Evidence.Reference.Reference != nil { refVal := *item_3_x_Evidence.Reference.Reference @@ -3226,7 +3226,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Evidence != nil { for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { + if item_3_x_Evidence != nil { if item_3_x_Evidence.Reference != nil { if item_3_x_Evidence.Reference.Reference != nil { refVal := *item_3_x_Evidence.Reference.Reference @@ -3274,7 +3274,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Evidence != nil { for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { + if item_3_x_Evidence != nil { if item_3_x_Evidence.Reference != nil { if item_3_x_Evidence.Reference.Reference != nil { refVal := *item_3_x_Evidence.Reference.Reference @@ -3322,7 +3322,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Evidence != nil { for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { + if item_3_x_Evidence != nil { if item_3_x_Evidence.Reference != nil { if item_3_x_Evidence.Reference.Reference != nil { refVal := *item_3_x_Evidence.Reference.Reference @@ -3370,7 +3370,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Evidence != nil { for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { + if item_3_x_Evidence != nil { if item_3_x_Evidence.Reference != nil { if item_3_x_Evidence.Reference.Reference != nil { refVal := *item_3_x_Evidence.Reference.Reference @@ -3418,7 +3418,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Evidence != nil { for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { + if item_3_x_Evidence != nil { if item_3_x_Evidence.Reference != nil { if item_3_x_Evidence.Reference.Reference != nil { refVal := *item_3_x_Evidence.Reference.Reference @@ -3466,7 +3466,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Evidence != nil { for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { + if item_3_x_Evidence != nil { if item_3_x_Evidence.Reference != nil { if item_3_x_Evidence.Reference.Reference != nil { refVal := *item_3_x_Evidence.Reference.Reference @@ -3514,7 +3514,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Evidence != nil { for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { + if item_3_x_Evidence != nil { if item_3_x_Evidence.Reference != nil { if item_3_x_Evidence.Reference.Reference != nil { refVal := *item_3_x_Evidence.Reference.Reference @@ -3562,7 +3562,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Evidence != nil { for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { + if item_3_x_Evidence != nil { if item_3_x_Evidence.Reference != nil { if item_3_x_Evidence.Reference.Reference != nil { refVal := *item_3_x_Evidence.Reference.Reference @@ -3610,7 +3610,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Evidence != nil { for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { + if item_3_x_Evidence != nil { if item_3_x_Evidence.Reference != nil { if item_3_x_Evidence.Reference.Reference != nil { refVal := *item_3_x_Evidence.Reference.Reference @@ -3658,7 +3658,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Evidence != nil { for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { + if item_3_x_Evidence != nil { if item_3_x_Evidence.Reference != nil { if item_3_x_Evidence.Reference.Reference != nil { refVal := *item_3_x_Evidence.Reference.Reference @@ -3706,7 +3706,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Evidence != nil { for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { + if item_3_x_Evidence != nil { if item_3_x_Evidence.Reference != nil { if item_3_x_Evidence.Reference.Reference != nil { refVal := *item_3_x_Evidence.Reference.Reference @@ -3754,7 +3754,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Evidence != nil { for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { + if item_3_x_Evidence != nil { if item_3_x_Evidence.Reference != nil { if item_3_x_Evidence.Reference.Reference != nil { refVal := *item_3_x_Evidence.Reference.Reference @@ -3802,7 +3802,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Evidence != nil { for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { + if item_3_x_Evidence != nil { if item_3_x_Evidence.Reference != nil { if item_3_x_Evidence.Reference.Reference != nil { refVal := *item_3_x_Evidence.Reference.Reference @@ -3850,7 +3850,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Evidence != nil { for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { + if item_3_x_Evidence != nil { if item_3_x_Evidence.Reference != nil { if item_3_x_Evidence.Reference.Reference != nil { refVal := *item_3_x_Evidence.Reference.Reference @@ -3898,7 +3898,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -3946,7 +3946,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -3994,7 +3994,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -4042,7 +4042,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -4090,7 +4090,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Participant != nil { for _, item_3_x_Participant := range x.Participant { - if item_3_x_Participant != nil { + if item_3_x_Participant != nil { if item_3_x_Participant.Actor != nil { if item_3_x_Participant.Actor.Reference != nil { refVal := *item_3_x_Participant.Actor.Reference @@ -4138,7 +4138,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Participant != nil { for _, item_3_x_Participant := range x.Participant { - if item_3_x_Participant != nil { + if item_3_x_Participant != nil { if item_3_x_Participant.Actor != nil { if item_3_x_Participant.Actor.Reference != nil { refVal := *item_3_x_Participant.Actor.Reference @@ -4186,7 +4186,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Participant != nil { for _, item_3_x_Participant := range x.Participant { - if item_3_x_Participant != nil { + if item_3_x_Participant != nil { if item_3_x_Participant.Actor != nil { if item_3_x_Participant.Actor.Reference != nil { refVal := *item_3_x_Participant.Actor.Reference @@ -4234,7 +4234,7 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Participant != nil { for _, item_3_x_Participant := range x.Participant { - if item_3_x_Participant != nil { + if item_3_x_Participant != nil { if item_3_x_Participant.Actor != nil { if item_3_x_Participant.Actor.Reference != nil { refVal := *item_3_x_Participant.Actor.Reference @@ -4282,10 +4282,10 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Stage != nil { for _, item_4_x_Stage := range x.Stage { - if item_4_x_Stage != nil { + if item_4_x_Stage != nil { if item_4_x_Stage.Assessment != nil { for _, item_2_item_4_x_Stage_Assessment := range item_4_x_Stage.Assessment { - if item_2_item_4_x_Stage_Assessment != nil { + if item_2_item_4_x_Stage_Assessment != nil { if item_2_item_4_x_Stage_Assessment.Reference != nil { refVal := *item_2_item_4_x_Stage_Assessment.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -4334,10 +4334,10 @@ func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Stage != nil { for _, item_4_x_Stage := range x.Stage { - if item_4_x_Stage != nil { + if item_4_x_Stage != nil { if item_4_x_Stage.Assessment != nil { for _, item_2_item_4_x_Stage_Assessment := range item_4_x_Stage.Assessment { - if item_2_item_4_x_Stage_Assessment != nil { + if item_2_item_4_x_Stage_Assessment != nil { if item_2_item_4_x_Stage_Assessment.Reference != nil { refVal := *item_2_item_4_x_Stage_Assessment.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -4588,7 +4588,7 @@ func (x *ConditionStage) ExtractEdges(project string) ([]json.RawMessage, error) _ = seen if x.Assessment != nil { for _, item_2_x_Assessment := range x.Assessment { - if item_2_x_Assessment != nil { + if item_2_x_Assessment != nil { if item_2_x_Assessment.Reference != nil { refVal := *item_2_x_Assessment.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -4634,7 +4634,7 @@ func (x *ConditionStage) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Assessment != nil { for _, item_2_x_Assessment := range x.Assessment { - if item_2_x_Assessment != nil { + if item_2_x_Assessment != nil { if item_2_x_Assessment.Reference != nil { refVal := *item_2_x_Assessment.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -4875,7 +4875,7 @@ func (x *DiagnosticReport) ExtractEdges(project string) ([]json.RawMessage, erro _ = seen if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -4921,7 +4921,7 @@ func (x *DiagnosticReport) ExtractEdges(project string) ([]json.RawMessage, erro } if x.Performer != nil { for _, item_2_x_Performer := range x.Performer { - if item_2_x_Performer != nil { + if item_2_x_Performer != nil { if item_2_x_Performer.Reference != nil { refVal := *item_2_x_Performer.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -4967,7 +4967,7 @@ func (x *DiagnosticReport) ExtractEdges(project string) ([]json.RawMessage, erro } if x.Performer != nil { for _, item_2_x_Performer := range x.Performer { - if item_2_x_Performer != nil { + if item_2_x_Performer != nil { if item_2_x_Performer.Reference != nil { refVal := *item_2_x_Performer.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -5013,7 +5013,7 @@ func (x *DiagnosticReport) ExtractEdges(project string) ([]json.RawMessage, erro } if x.Performer != nil { for _, item_2_x_Performer := range x.Performer { - if item_2_x_Performer != nil { + if item_2_x_Performer != nil { if item_2_x_Performer.Reference != nil { refVal := *item_2_x_Performer.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -5059,7 +5059,7 @@ func (x *DiagnosticReport) ExtractEdges(project string) ([]json.RawMessage, erro } if x.Result != nil { for _, item_2_x_Result := range x.Result { - if item_2_x_Result != nil { + if item_2_x_Result != nil { if item_2_x_Result.Reference != nil { refVal := *item_2_x_Result.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -5105,7 +5105,7 @@ func (x *DiagnosticReport) ExtractEdges(project string) ([]json.RawMessage, erro } if x.ResultsInterpreter != nil { for _, item_2_x_ResultsInterpreter := range x.ResultsInterpreter { - if item_2_x_ResultsInterpreter != nil { + if item_2_x_ResultsInterpreter != nil { if item_2_x_ResultsInterpreter.Reference != nil { refVal := *item_2_x_ResultsInterpreter.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -5151,7 +5151,7 @@ func (x *DiagnosticReport) ExtractEdges(project string) ([]json.RawMessage, erro } if x.ResultsInterpreter != nil { for _, item_2_x_ResultsInterpreter := range x.ResultsInterpreter { - if item_2_x_ResultsInterpreter != nil { + if item_2_x_ResultsInterpreter != nil { if item_2_x_ResultsInterpreter.Reference != nil { refVal := *item_2_x_ResultsInterpreter.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -5197,7 +5197,7 @@ func (x *DiagnosticReport) ExtractEdges(project string) ([]json.RawMessage, erro } if x.ResultsInterpreter != nil { for _, item_2_x_ResultsInterpreter := range x.ResultsInterpreter { - if item_2_x_ResultsInterpreter != nil { + if item_2_x_ResultsInterpreter != nil { if item_2_x_ResultsInterpreter.Reference != nil { refVal := *item_2_x_ResultsInterpreter.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -5243,7 +5243,7 @@ func (x *DiagnosticReport) ExtractEdges(project string) ([]json.RawMessage, erro } if x.Specimen != nil { for _, item_2_x_Specimen := range x.Specimen { - if item_2_x_Specimen != nil { + if item_2_x_Specimen != nil { if item_2_x_Specimen.Reference != nil { refVal := *item_2_x_Specimen.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -5289,7 +5289,7 @@ func (x *DiagnosticReport) ExtractEdges(project string) ([]json.RawMessage, erro } if x.Study != nil { for _, item_2_x_Study := range x.Study { - if item_2_x_Study != nil { + if item_2_x_Study != nil { if item_2_x_Study.Reference != nil { refVal := *item_2_x_Study.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -5587,7 +5587,7 @@ func (x *DiagnosticReport) ExtractEdges(project string) ([]json.RawMessage, erro } if x.Media != nil { for _, item_3_x_Media := range x.Media { - if item_3_x_Media != nil { + if item_3_x_Media != nil { if item_3_x_Media.Link != nil { if item_3_x_Media.Link.Reference != nil { refVal := *item_3_x_Media.Link.Reference @@ -5635,7 +5635,7 @@ func (x *DiagnosticReport) ExtractEdges(project string) ([]json.RawMessage, erro } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -5683,7 +5683,7 @@ func (x *DiagnosticReport) ExtractEdges(project string) ([]json.RawMessage, erro } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -5731,7 +5731,7 @@ func (x *DiagnosticReport) ExtractEdges(project string) ([]json.RawMessage, erro } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -5779,7 +5779,7 @@ func (x *DiagnosticReport) ExtractEdges(project string) ([]json.RawMessage, erro } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -5827,7 +5827,7 @@ func (x *DiagnosticReport) ExtractEdges(project string) ([]json.RawMessage, erro } if x.SupportingInfo != nil { for _, item_3_x_SupportingInfo := range x.SupportingInfo { - if item_3_x_SupportingInfo != nil { + if item_3_x_SupportingInfo != nil { if item_3_x_SupportingInfo.Reference != nil { if item_3_x_SupportingInfo.Reference.Reference != nil { refVal := *item_3_x_SupportingInfo.Reference.Reference @@ -5875,7 +5875,7 @@ func (x *DiagnosticReport) ExtractEdges(project string) ([]json.RawMessage, erro } if x.SupportingInfo != nil { for _, item_3_x_SupportingInfo := range x.SupportingInfo { - if item_3_x_SupportingInfo != nil { + if item_3_x_SupportingInfo != nil { if item_3_x_SupportingInfo.Reference != nil { if item_3_x_SupportingInfo.Reference.Reference != nil { refVal := *item_3_x_SupportingInfo.Reference.Reference @@ -5923,7 +5923,7 @@ func (x *DiagnosticReport) ExtractEdges(project string) ([]json.RawMessage, erro } if x.SupportingInfo != nil { for _, item_3_x_SupportingInfo := range x.SupportingInfo { - if item_3_x_SupportingInfo != nil { + if item_3_x_SupportingInfo != nil { if item_3_x_SupportingInfo.Reference != nil { if item_3_x_SupportingInfo.Reference.Reference != nil { refVal := *item_3_x_SupportingInfo.Reference.Reference @@ -6190,7 +6190,7 @@ func (x *Directory) ExtractEdges(project string) ([]json.RawMessage, error) { _ = seen if x.Child != nil { for _, item_2_x_Child := range x.Child { - if item_2_x_Child != nil { + if item_2_x_Child != nil { if item_2_x_Child.Reference != nil { refVal := *item_2_x_Child.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -6220,7 +6220,7 @@ func (x *Directory) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Child != nil { for _, item_2_x_Child := range x.Child { - if item_2_x_Child != nil { + if item_2_x_Child != nil { if item_2_x_Child.Reference != nil { refVal := *item_2_x_Child.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -6284,7 +6284,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err _ = seen if x.Author != nil { for _, item_2_x_Author := range x.Author { - if item_2_x_Author != nil { + if item_2_x_Author != nil { if item_2_x_Author.Reference != nil { refVal := *item_2_x_Author.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -6330,7 +6330,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Author != nil { for _, item_2_x_Author := range x.Author { - if item_2_x_Author != nil { + if item_2_x_Author != nil { if item_2_x_Author.Reference != nil { refVal := *item_2_x_Author.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -6376,7 +6376,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Author != nil { for _, item_2_x_Author := range x.Author { - if item_2_x_Author != nil { + if item_2_x_Author != nil { if item_2_x_Author.Reference != nil { refVal := *item_2_x_Author.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -6422,7 +6422,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Author != nil { for _, item_2_x_Author := range x.Author { - if item_2_x_Author != nil { + if item_2_x_Author != nil { if item_2_x_Author.Reference != nil { refVal := *item_2_x_Author.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -6468,7 +6468,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -7522,7 +7522,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Attester != nil { for _, item_3_x_Attester := range x.Attester { - if item_3_x_Attester != nil { + if item_3_x_Attester != nil { if item_3_x_Attester.Party != nil { if item_3_x_Attester.Party.Reference != nil { refVal := *item_3_x_Attester.Party.Reference @@ -7570,7 +7570,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Attester != nil { for _, item_3_x_Attester := range x.Attester { - if item_3_x_Attester != nil { + if item_3_x_Attester != nil { if item_3_x_Attester.Party != nil { if item_3_x_Attester.Party.Reference != nil { refVal := *item_3_x_Attester.Party.Reference @@ -7618,7 +7618,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Attester != nil { for _, item_3_x_Attester := range x.Attester { - if item_3_x_Attester != nil { + if item_3_x_Attester != nil { if item_3_x_Attester.Party != nil { if item_3_x_Attester.Party.Reference != nil { refVal := *item_3_x_Attester.Party.Reference @@ -7666,7 +7666,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Attester != nil { for _, item_3_x_Attester := range x.Attester { - if item_3_x_Attester != nil { + if item_3_x_Attester != nil { if item_3_x_Attester.Party != nil { if item_3_x_Attester.Party.Reference != nil { refVal := *item_3_x_Attester.Party.Reference @@ -7714,7 +7714,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BodySite != nil { for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { + if item_3_x_BodySite != nil { if item_3_x_BodySite.Reference != nil { if item_3_x_BodySite.Reference.Reference != nil { refVal := *item_3_x_BodySite.Reference.Reference @@ -7762,7 +7762,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BodySite != nil { for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { + if item_3_x_BodySite != nil { if item_3_x_BodySite.Reference != nil { if item_3_x_BodySite.Reference.Reference != nil { refVal := *item_3_x_BodySite.Reference.Reference @@ -7810,7 +7810,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BodySite != nil { for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { + if item_3_x_BodySite != nil { if item_3_x_BodySite.Reference != nil { if item_3_x_BodySite.Reference.Reference != nil { refVal := *item_3_x_BodySite.Reference.Reference @@ -7858,7 +7858,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BodySite != nil { for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { + if item_3_x_BodySite != nil { if item_3_x_BodySite.Reference != nil { if item_3_x_BodySite.Reference.Reference != nil { refVal := *item_3_x_BodySite.Reference.Reference @@ -7906,7 +7906,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BodySite != nil { for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { + if item_3_x_BodySite != nil { if item_3_x_BodySite.Reference != nil { if item_3_x_BodySite.Reference.Reference != nil { refVal := *item_3_x_BodySite.Reference.Reference @@ -7954,7 +7954,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BodySite != nil { for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { + if item_3_x_BodySite != nil { if item_3_x_BodySite.Reference != nil { if item_3_x_BodySite.Reference.Reference != nil { refVal := *item_3_x_BodySite.Reference.Reference @@ -8002,7 +8002,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BodySite != nil { for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { + if item_3_x_BodySite != nil { if item_3_x_BodySite.Reference != nil { if item_3_x_BodySite.Reference.Reference != nil { refVal := *item_3_x_BodySite.Reference.Reference @@ -8050,7 +8050,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BodySite != nil { for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { + if item_3_x_BodySite != nil { if item_3_x_BodySite.Reference != nil { if item_3_x_BodySite.Reference.Reference != nil { refVal := *item_3_x_BodySite.Reference.Reference @@ -8098,7 +8098,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BodySite != nil { for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { + if item_3_x_BodySite != nil { if item_3_x_BodySite.Reference != nil { if item_3_x_BodySite.Reference.Reference != nil { refVal := *item_3_x_BodySite.Reference.Reference @@ -8146,7 +8146,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BodySite != nil { for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { + if item_3_x_BodySite != nil { if item_3_x_BodySite.Reference != nil { if item_3_x_BodySite.Reference.Reference != nil { refVal := *item_3_x_BodySite.Reference.Reference @@ -8194,7 +8194,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BodySite != nil { for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { + if item_3_x_BodySite != nil { if item_3_x_BodySite.Reference != nil { if item_3_x_BodySite.Reference.Reference != nil { refVal := *item_3_x_BodySite.Reference.Reference @@ -8242,7 +8242,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BodySite != nil { for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { + if item_3_x_BodySite != nil { if item_3_x_BodySite.Reference != nil { if item_3_x_BodySite.Reference.Reference != nil { refVal := *item_3_x_BodySite.Reference.Reference @@ -8290,7 +8290,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BodySite != nil { for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { + if item_3_x_BodySite != nil { if item_3_x_BodySite.Reference != nil { if item_3_x_BodySite.Reference.Reference != nil { refVal := *item_3_x_BodySite.Reference.Reference @@ -8338,7 +8338,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BodySite != nil { for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { + if item_3_x_BodySite != nil { if item_3_x_BodySite.Reference != nil { if item_3_x_BodySite.Reference.Reference != nil { refVal := *item_3_x_BodySite.Reference.Reference @@ -8386,7 +8386,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BodySite != nil { for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { + if item_3_x_BodySite != nil { if item_3_x_BodySite.Reference != nil { if item_3_x_BodySite.Reference.Reference != nil { refVal := *item_3_x_BodySite.Reference.Reference @@ -8434,7 +8434,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BodySite != nil { for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { + if item_3_x_BodySite != nil { if item_3_x_BodySite.Reference != nil { if item_3_x_BodySite.Reference.Reference != nil { refVal := *item_3_x_BodySite.Reference.Reference @@ -8482,7 +8482,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BodySite != nil { for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { + if item_3_x_BodySite != nil { if item_3_x_BodySite.Reference != nil { if item_3_x_BodySite.Reference.Reference != nil { refVal := *item_3_x_BodySite.Reference.Reference @@ -8530,7 +8530,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BodySite != nil { for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { + if item_3_x_BodySite != nil { if item_3_x_BodySite.Reference != nil { if item_3_x_BodySite.Reference.Reference != nil { refVal := *item_3_x_BodySite.Reference.Reference @@ -8578,7 +8578,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BodySite != nil { for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { + if item_3_x_BodySite != nil { if item_3_x_BodySite.Reference != nil { if item_3_x_BodySite.Reference.Reference != nil { refVal := *item_3_x_BodySite.Reference.Reference @@ -8626,7 +8626,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BodySite != nil { for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { + if item_3_x_BodySite != nil { if item_3_x_BodySite.Reference != nil { if item_3_x_BodySite.Reference.Reference != nil { refVal := *item_3_x_BodySite.Reference.Reference @@ -8674,7 +8674,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BodySite != nil { for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { + if item_3_x_BodySite != nil { if item_3_x_BodySite.Reference != nil { if item_3_x_BodySite.Reference.Reference != nil { refVal := *item_3_x_BodySite.Reference.Reference @@ -8722,7 +8722,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BodySite != nil { for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { + if item_3_x_BodySite != nil { if item_3_x_BodySite.Reference != nil { if item_3_x_BodySite.Reference.Reference != nil { refVal := *item_3_x_BodySite.Reference.Reference @@ -8770,7 +8770,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.BodySite != nil { for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { + if item_3_x_BodySite != nil { if item_3_x_BodySite.Reference != nil { if item_3_x_BodySite.Reference.Reference != nil { refVal := *item_3_x_BodySite.Reference.Reference @@ -8818,7 +8818,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Event != nil { for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { + if item_3_x_Event != nil { if item_3_x_Event.Reference != nil { if item_3_x_Event.Reference.Reference != nil { refVal := *item_3_x_Event.Reference.Reference @@ -8866,7 +8866,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Event != nil { for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { + if item_3_x_Event != nil { if item_3_x_Event.Reference != nil { if item_3_x_Event.Reference.Reference != nil { refVal := *item_3_x_Event.Reference.Reference @@ -8914,7 +8914,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Event != nil { for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { + if item_3_x_Event != nil { if item_3_x_Event.Reference != nil { if item_3_x_Event.Reference.Reference != nil { refVal := *item_3_x_Event.Reference.Reference @@ -8962,7 +8962,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Event != nil { for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { + if item_3_x_Event != nil { if item_3_x_Event.Reference != nil { if item_3_x_Event.Reference.Reference != nil { refVal := *item_3_x_Event.Reference.Reference @@ -9010,7 +9010,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Event != nil { for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { + if item_3_x_Event != nil { if item_3_x_Event.Reference != nil { if item_3_x_Event.Reference.Reference != nil { refVal := *item_3_x_Event.Reference.Reference @@ -9058,7 +9058,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Event != nil { for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { + if item_3_x_Event != nil { if item_3_x_Event.Reference != nil { if item_3_x_Event.Reference.Reference != nil { refVal := *item_3_x_Event.Reference.Reference @@ -9106,7 +9106,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Event != nil { for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { + if item_3_x_Event != nil { if item_3_x_Event.Reference != nil { if item_3_x_Event.Reference.Reference != nil { refVal := *item_3_x_Event.Reference.Reference @@ -9154,7 +9154,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Event != nil { for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { + if item_3_x_Event != nil { if item_3_x_Event.Reference != nil { if item_3_x_Event.Reference.Reference != nil { refVal := *item_3_x_Event.Reference.Reference @@ -9202,7 +9202,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Event != nil { for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { + if item_3_x_Event != nil { if item_3_x_Event.Reference != nil { if item_3_x_Event.Reference.Reference != nil { refVal := *item_3_x_Event.Reference.Reference @@ -9250,7 +9250,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Event != nil { for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { + if item_3_x_Event != nil { if item_3_x_Event.Reference != nil { if item_3_x_Event.Reference.Reference != nil { refVal := *item_3_x_Event.Reference.Reference @@ -9298,7 +9298,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Event != nil { for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { + if item_3_x_Event != nil { if item_3_x_Event.Reference != nil { if item_3_x_Event.Reference.Reference != nil { refVal := *item_3_x_Event.Reference.Reference @@ -9346,7 +9346,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Event != nil { for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { + if item_3_x_Event != nil { if item_3_x_Event.Reference != nil { if item_3_x_Event.Reference.Reference != nil { refVal := *item_3_x_Event.Reference.Reference @@ -9394,7 +9394,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Event != nil { for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { + if item_3_x_Event != nil { if item_3_x_Event.Reference != nil { if item_3_x_Event.Reference.Reference != nil { refVal := *item_3_x_Event.Reference.Reference @@ -9442,7 +9442,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Event != nil { for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { + if item_3_x_Event != nil { if item_3_x_Event.Reference != nil { if item_3_x_Event.Reference.Reference != nil { refVal := *item_3_x_Event.Reference.Reference @@ -9490,7 +9490,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Event != nil { for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { + if item_3_x_Event != nil { if item_3_x_Event.Reference != nil { if item_3_x_Event.Reference.Reference != nil { refVal := *item_3_x_Event.Reference.Reference @@ -9538,7 +9538,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Event != nil { for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { + if item_3_x_Event != nil { if item_3_x_Event.Reference != nil { if item_3_x_Event.Reference.Reference != nil { refVal := *item_3_x_Event.Reference.Reference @@ -9586,7 +9586,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Event != nil { for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { + if item_3_x_Event != nil { if item_3_x_Event.Reference != nil { if item_3_x_Event.Reference.Reference != nil { refVal := *item_3_x_Event.Reference.Reference @@ -9634,7 +9634,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Event != nil { for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { + if item_3_x_Event != nil { if item_3_x_Event.Reference != nil { if item_3_x_Event.Reference.Reference != nil { refVal := *item_3_x_Event.Reference.Reference @@ -9682,7 +9682,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Event != nil { for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { + if item_3_x_Event != nil { if item_3_x_Event.Reference != nil { if item_3_x_Event.Reference.Reference != nil { refVal := *item_3_x_Event.Reference.Reference @@ -9730,7 +9730,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Event != nil { for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { + if item_3_x_Event != nil { if item_3_x_Event.Reference != nil { if item_3_x_Event.Reference.Reference != nil { refVal := *item_3_x_Event.Reference.Reference @@ -9778,7 +9778,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Event != nil { for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { + if item_3_x_Event != nil { if item_3_x_Event.Reference != nil { if item_3_x_Event.Reference.Reference != nil { refVal := *item_3_x_Event.Reference.Reference @@ -9826,7 +9826,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Event != nil { for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { + if item_3_x_Event != nil { if item_3_x_Event.Reference != nil { if item_3_x_Event.Reference.Reference != nil { refVal := *item_3_x_Event.Reference.Reference @@ -9874,7 +9874,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.Event != nil { for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { + if item_3_x_Event != nil { if item_3_x_Event.Reference != nil { if item_3_x_Event.Reference.Reference != nil { refVal := *item_3_x_Event.Reference.Reference @@ -9922,7 +9922,7 @@ func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, err } if x.RelatesTo != nil { for _, item_3_x_RelatesTo := range x.RelatesTo { - if item_3_x_RelatesTo != nil { + if item_3_x_RelatesTo != nil { if item_3_x_RelatesTo.Target != nil { if item_3_x_RelatesTo.Target.Reference != nil { refVal := *item_3_x_RelatesTo.Target.Reference @@ -14206,7 +14206,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -14254,7 +14254,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -14302,7 +14302,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -14350,7 +14350,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -14398,7 +14398,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Participant != nil { for _, item_3_x_Participant := range x.Participant { - if item_3_x_Participant != nil { + if item_3_x_Participant != nil { if item_3_x_Participant.Actor != nil { if item_3_x_Participant.Actor.Reference != nil { refVal := *item_3_x_Participant.Actor.Reference @@ -14446,7 +14446,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Participant != nil { for _, item_3_x_Participant := range x.Participant { - if item_3_x_Participant != nil { + if item_3_x_Participant != nil { if item_3_x_Participant.Actor != nil { if item_3_x_Participant.Actor.Reference != nil { refVal := *item_3_x_Participant.Actor.Reference @@ -14494,7 +14494,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Participant != nil { for _, item_3_x_Participant := range x.Participant { - if item_3_x_Participant != nil { + if item_3_x_Participant != nil { if item_3_x_Participant.Actor != nil { if item_3_x_Participant.Actor.Reference != nil { refVal := *item_3_x_Participant.Actor.Reference @@ -14542,7 +14542,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Participant != nil { for _, item_3_x_Participant := range x.Participant { - if item_3_x_Participant != nil { + if item_3_x_Participant != nil { if item_3_x_Participant.Actor != nil { if item_3_x_Participant.Actor.Reference != nil { refVal := *item_3_x_Participant.Actor.Reference @@ -14590,7 +14590,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -14638,7 +14638,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -14686,7 +14686,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -14734,7 +14734,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -14782,7 +14782,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -14830,7 +14830,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -14878,7 +14878,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -14926,7 +14926,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -14974,7 +14974,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -15022,7 +15022,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -15070,7 +15070,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -15118,7 +15118,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -15166,7 +15166,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -15214,7 +15214,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -15262,7 +15262,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -15310,7 +15310,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -15358,7 +15358,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -15406,7 +15406,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -15454,7 +15454,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -15502,7 +15502,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -15550,7 +15550,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -15598,7 +15598,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -15646,7 +15646,7 @@ func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -15711,7 +15711,7 @@ func (x *FamilyMemberHistoryCondition) ExtractEdges(project string) ([]json.RawM _ = seen if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -15759,7 +15759,7 @@ func (x *FamilyMemberHistoryCondition) ExtractEdges(project string) ([]json.RawM } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -15807,7 +15807,7 @@ func (x *FamilyMemberHistoryCondition) ExtractEdges(project string) ([]json.RawM } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -15855,7 +15855,7 @@ func (x *FamilyMemberHistoryCondition) ExtractEdges(project string) ([]json.RawM } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -16105,7 +16105,7 @@ func (x *FamilyMemberHistoryProcedure) ExtractEdges(project string) ([]json.RawM _ = seen if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -16153,7 +16153,7 @@ func (x *FamilyMemberHistoryProcedure) ExtractEdges(project string) ([]json.RawM } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -16201,7 +16201,7 @@ func (x *FamilyMemberHistoryProcedure) ExtractEdges(project string) ([]json.RawM } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -16249,7 +16249,7 @@ func (x *FamilyMemberHistoryProcedure) ExtractEdges(project string) ([]json.RawM } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -16440,7 +16440,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Characteristic != nil { for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { + if item_3_x_Characteristic != nil { if item_3_x_Characteristic.ValueReference != nil { if item_3_x_Characteristic.ValueReference.Reference != nil { refVal := *item_3_x_Characteristic.ValueReference.Reference @@ -16488,7 +16488,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Characteristic != nil { for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { + if item_3_x_Characteristic != nil { if item_3_x_Characteristic.ValueReference != nil { if item_3_x_Characteristic.ValueReference.Reference != nil { refVal := *item_3_x_Characteristic.ValueReference.Reference @@ -16536,7 +16536,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Characteristic != nil { for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { + if item_3_x_Characteristic != nil { if item_3_x_Characteristic.ValueReference != nil { if item_3_x_Characteristic.ValueReference.Reference != nil { refVal := *item_3_x_Characteristic.ValueReference.Reference @@ -16584,7 +16584,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Characteristic != nil { for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { + if item_3_x_Characteristic != nil { if item_3_x_Characteristic.ValueReference != nil { if item_3_x_Characteristic.ValueReference.Reference != nil { refVal := *item_3_x_Characteristic.ValueReference.Reference @@ -16632,7 +16632,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Characteristic != nil { for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { + if item_3_x_Characteristic != nil { if item_3_x_Characteristic.ValueReference != nil { if item_3_x_Characteristic.ValueReference.Reference != nil { refVal := *item_3_x_Characteristic.ValueReference.Reference @@ -16680,7 +16680,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Characteristic != nil { for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { + if item_3_x_Characteristic != nil { if item_3_x_Characteristic.ValueReference != nil { if item_3_x_Characteristic.ValueReference.Reference != nil { refVal := *item_3_x_Characteristic.ValueReference.Reference @@ -16728,7 +16728,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Characteristic != nil { for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { + if item_3_x_Characteristic != nil { if item_3_x_Characteristic.ValueReference != nil { if item_3_x_Characteristic.ValueReference.Reference != nil { refVal := *item_3_x_Characteristic.ValueReference.Reference @@ -16776,7 +16776,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Characteristic != nil { for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { + if item_3_x_Characteristic != nil { if item_3_x_Characteristic.ValueReference != nil { if item_3_x_Characteristic.ValueReference.Reference != nil { refVal := *item_3_x_Characteristic.ValueReference.Reference @@ -16824,7 +16824,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Characteristic != nil { for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { + if item_3_x_Characteristic != nil { if item_3_x_Characteristic.ValueReference != nil { if item_3_x_Characteristic.ValueReference.Reference != nil { refVal := *item_3_x_Characteristic.ValueReference.Reference @@ -16872,7 +16872,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Characteristic != nil { for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { + if item_3_x_Characteristic != nil { if item_3_x_Characteristic.ValueReference != nil { if item_3_x_Characteristic.ValueReference.Reference != nil { refVal := *item_3_x_Characteristic.ValueReference.Reference @@ -16920,7 +16920,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Characteristic != nil { for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { + if item_3_x_Characteristic != nil { if item_3_x_Characteristic.ValueReference != nil { if item_3_x_Characteristic.ValueReference.Reference != nil { refVal := *item_3_x_Characteristic.ValueReference.Reference @@ -16968,7 +16968,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Characteristic != nil { for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { + if item_3_x_Characteristic != nil { if item_3_x_Characteristic.ValueReference != nil { if item_3_x_Characteristic.ValueReference.Reference != nil { refVal := *item_3_x_Characteristic.ValueReference.Reference @@ -17016,7 +17016,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Characteristic != nil { for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { + if item_3_x_Characteristic != nil { if item_3_x_Characteristic.ValueReference != nil { if item_3_x_Characteristic.ValueReference.Reference != nil { refVal := *item_3_x_Characteristic.ValueReference.Reference @@ -17064,7 +17064,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Characteristic != nil { for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { + if item_3_x_Characteristic != nil { if item_3_x_Characteristic.ValueReference != nil { if item_3_x_Characteristic.ValueReference.Reference != nil { refVal := *item_3_x_Characteristic.ValueReference.Reference @@ -17112,7 +17112,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Characteristic != nil { for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { + if item_3_x_Characteristic != nil { if item_3_x_Characteristic.ValueReference != nil { if item_3_x_Characteristic.ValueReference.Reference != nil { refVal := *item_3_x_Characteristic.ValueReference.Reference @@ -17160,7 +17160,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Characteristic != nil { for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { + if item_3_x_Characteristic != nil { if item_3_x_Characteristic.ValueReference != nil { if item_3_x_Characteristic.ValueReference.Reference != nil { refVal := *item_3_x_Characteristic.ValueReference.Reference @@ -17208,7 +17208,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Characteristic != nil { for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { + if item_3_x_Characteristic != nil { if item_3_x_Characteristic.ValueReference != nil { if item_3_x_Characteristic.ValueReference.Reference != nil { refVal := *item_3_x_Characteristic.ValueReference.Reference @@ -17256,7 +17256,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Characteristic != nil { for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { + if item_3_x_Characteristic != nil { if item_3_x_Characteristic.ValueReference != nil { if item_3_x_Characteristic.ValueReference.Reference != nil { refVal := *item_3_x_Characteristic.ValueReference.Reference @@ -17304,7 +17304,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Characteristic != nil { for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { + if item_3_x_Characteristic != nil { if item_3_x_Characteristic.ValueReference != nil { if item_3_x_Characteristic.ValueReference.Reference != nil { refVal := *item_3_x_Characteristic.ValueReference.Reference @@ -17352,7 +17352,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Characteristic != nil { for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { + if item_3_x_Characteristic != nil { if item_3_x_Characteristic.ValueReference != nil { if item_3_x_Characteristic.ValueReference.Reference != nil { refVal := *item_3_x_Characteristic.ValueReference.Reference @@ -17400,7 +17400,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Characteristic != nil { for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { + if item_3_x_Characteristic != nil { if item_3_x_Characteristic.ValueReference != nil { if item_3_x_Characteristic.ValueReference.Reference != nil { refVal := *item_3_x_Characteristic.ValueReference.Reference @@ -17448,7 +17448,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Characteristic != nil { for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { + if item_3_x_Characteristic != nil { if item_3_x_Characteristic.ValueReference != nil { if item_3_x_Characteristic.ValueReference.Reference != nil { refVal := *item_3_x_Characteristic.ValueReference.Reference @@ -17496,7 +17496,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Characteristic != nil { for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { + if item_3_x_Characteristic != nil { if item_3_x_Characteristic.ValueReference != nil { if item_3_x_Characteristic.ValueReference.Reference != nil { refVal := *item_3_x_Characteristic.ValueReference.Reference @@ -17544,7 +17544,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Member != nil { for _, item_3_x_Member := range x.Member { - if item_3_x_Member != nil { + if item_3_x_Member != nil { if item_3_x_Member.Entity != nil { if item_3_x_Member.Entity.Reference != nil { refVal := *item_3_x_Member.Entity.Reference @@ -17592,7 +17592,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Member != nil { for _, item_3_x_Member := range x.Member { - if item_3_x_Member != nil { + if item_3_x_Member != nil { if item_3_x_Member.Entity != nil { if item_3_x_Member.Entity.Reference != nil { refVal := *item_3_x_Member.Entity.Reference @@ -17640,7 +17640,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Member != nil { for _, item_3_x_Member := range x.Member { - if item_3_x_Member != nil { + if item_3_x_Member != nil { if item_3_x_Member.Entity != nil { if item_3_x_Member.Entity.Reference != nil { refVal := *item_3_x_Member.Entity.Reference @@ -17688,7 +17688,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Member != nil { for _, item_3_x_Member := range x.Member { - if item_3_x_Member != nil { + if item_3_x_Member != nil { if item_3_x_Member.Entity != nil { if item_3_x_Member.Entity.Reference != nil { refVal := *item_3_x_Member.Entity.Reference @@ -17736,7 +17736,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Member != nil { for _, item_3_x_Member := range x.Member { - if item_3_x_Member != nil { + if item_3_x_Member != nil { if item_3_x_Member.Entity != nil { if item_3_x_Member.Entity.Reference != nil { refVal := *item_3_x_Member.Entity.Reference @@ -17784,7 +17784,7 @@ func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Member != nil { for _, item_3_x_Member := range x.Member { - if item_3_x_Member != nil { + if item_3_x_Member != nil { if item_3_x_Member.Entity != nil { if item_3_x_Member.Entity.Reference != nil { refVal := *item_3_x_Member.Entity.Reference @@ -19177,7 +19177,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { _ = seen if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -19223,7 +19223,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.PartOf != nil { for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { + if item_2_x_PartOf != nil { if item_2_x_PartOf.Reference != nil { refVal := *item_2_x_PartOf.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -19437,7 +19437,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -19485,7 +19485,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -19533,7 +19533,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -19581,7 +19581,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -19629,7 +19629,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Procedure != nil { for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { + if item_3_x_Procedure != nil { if item_3_x_Procedure.Reference != nil { if item_3_x_Procedure.Reference.Reference != nil { refVal := *item_3_x_Procedure.Reference.Reference @@ -19677,7 +19677,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Procedure != nil { for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { + if item_3_x_Procedure != nil { if item_3_x_Procedure.Reference != nil { if item_3_x_Procedure.Reference.Reference != nil { refVal := *item_3_x_Procedure.Reference.Reference @@ -19725,7 +19725,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Procedure != nil { for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { + if item_3_x_Procedure != nil { if item_3_x_Procedure.Reference != nil { if item_3_x_Procedure.Reference.Reference != nil { refVal := *item_3_x_Procedure.Reference.Reference @@ -19773,7 +19773,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Procedure != nil { for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { + if item_3_x_Procedure != nil { if item_3_x_Procedure.Reference != nil { if item_3_x_Procedure.Reference.Reference != nil { refVal := *item_3_x_Procedure.Reference.Reference @@ -19821,7 +19821,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Procedure != nil { for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { + if item_3_x_Procedure != nil { if item_3_x_Procedure.Reference != nil { if item_3_x_Procedure.Reference.Reference != nil { refVal := *item_3_x_Procedure.Reference.Reference @@ -19869,7 +19869,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Procedure != nil { for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { + if item_3_x_Procedure != nil { if item_3_x_Procedure.Reference != nil { if item_3_x_Procedure.Reference.Reference != nil { refVal := *item_3_x_Procedure.Reference.Reference @@ -19917,7 +19917,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Procedure != nil { for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { + if item_3_x_Procedure != nil { if item_3_x_Procedure.Reference != nil { if item_3_x_Procedure.Reference.Reference != nil { refVal := *item_3_x_Procedure.Reference.Reference @@ -19965,7 +19965,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Procedure != nil { for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { + if item_3_x_Procedure != nil { if item_3_x_Procedure.Reference != nil { if item_3_x_Procedure.Reference.Reference != nil { refVal := *item_3_x_Procedure.Reference.Reference @@ -20013,7 +20013,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Procedure != nil { for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { + if item_3_x_Procedure != nil { if item_3_x_Procedure.Reference != nil { if item_3_x_Procedure.Reference.Reference != nil { refVal := *item_3_x_Procedure.Reference.Reference @@ -20061,7 +20061,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Procedure != nil { for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { + if item_3_x_Procedure != nil { if item_3_x_Procedure.Reference != nil { if item_3_x_Procedure.Reference.Reference != nil { refVal := *item_3_x_Procedure.Reference.Reference @@ -20109,7 +20109,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Procedure != nil { for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { + if item_3_x_Procedure != nil { if item_3_x_Procedure.Reference != nil { if item_3_x_Procedure.Reference.Reference != nil { refVal := *item_3_x_Procedure.Reference.Reference @@ -20157,7 +20157,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Procedure != nil { for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { + if item_3_x_Procedure != nil { if item_3_x_Procedure.Reference != nil { if item_3_x_Procedure.Reference.Reference != nil { refVal := *item_3_x_Procedure.Reference.Reference @@ -20205,7 +20205,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Procedure != nil { for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { + if item_3_x_Procedure != nil { if item_3_x_Procedure.Reference != nil { if item_3_x_Procedure.Reference.Reference != nil { refVal := *item_3_x_Procedure.Reference.Reference @@ -20253,7 +20253,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Procedure != nil { for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { + if item_3_x_Procedure != nil { if item_3_x_Procedure.Reference != nil { if item_3_x_Procedure.Reference.Reference != nil { refVal := *item_3_x_Procedure.Reference.Reference @@ -20301,7 +20301,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Procedure != nil { for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { + if item_3_x_Procedure != nil { if item_3_x_Procedure.Reference != nil { if item_3_x_Procedure.Reference.Reference != nil { refVal := *item_3_x_Procedure.Reference.Reference @@ -20349,7 +20349,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Procedure != nil { for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { + if item_3_x_Procedure != nil { if item_3_x_Procedure.Reference != nil { if item_3_x_Procedure.Reference.Reference != nil { refVal := *item_3_x_Procedure.Reference.Reference @@ -20397,7 +20397,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Procedure != nil { for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { + if item_3_x_Procedure != nil { if item_3_x_Procedure.Reference != nil { if item_3_x_Procedure.Reference.Reference != nil { refVal := *item_3_x_Procedure.Reference.Reference @@ -20445,7 +20445,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Procedure != nil { for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { + if item_3_x_Procedure != nil { if item_3_x_Procedure.Reference != nil { if item_3_x_Procedure.Reference.Reference != nil { refVal := *item_3_x_Procedure.Reference.Reference @@ -20493,7 +20493,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Procedure != nil { for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { + if item_3_x_Procedure != nil { if item_3_x_Procedure.Reference != nil { if item_3_x_Procedure.Reference.Reference != nil { refVal := *item_3_x_Procedure.Reference.Reference @@ -20541,7 +20541,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Procedure != nil { for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { + if item_3_x_Procedure != nil { if item_3_x_Procedure.Reference != nil { if item_3_x_Procedure.Reference.Reference != nil { refVal := *item_3_x_Procedure.Reference.Reference @@ -20589,7 +20589,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Procedure != nil { for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { + if item_3_x_Procedure != nil { if item_3_x_Procedure.Reference != nil { if item_3_x_Procedure.Reference.Reference != nil { refVal := *item_3_x_Procedure.Reference.Reference @@ -20637,7 +20637,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Procedure != nil { for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { + if item_3_x_Procedure != nil { if item_3_x_Procedure.Reference != nil { if item_3_x_Procedure.Reference.Reference != nil { refVal := *item_3_x_Procedure.Reference.Reference @@ -20685,7 +20685,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Procedure != nil { for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { + if item_3_x_Procedure != nil { if item_3_x_Procedure.Reference != nil { if item_3_x_Procedure.Reference.Reference != nil { refVal := *item_3_x_Procedure.Reference.Reference @@ -20733,7 +20733,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -20781,7 +20781,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -20829,7 +20829,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -20877,7 +20877,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -20925,7 +20925,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -20973,7 +20973,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -21021,7 +21021,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -21069,7 +21069,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -21117,7 +21117,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -21165,7 +21165,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -21213,7 +21213,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -21261,7 +21261,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -21309,7 +21309,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -21357,7 +21357,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -21405,7 +21405,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -21453,7 +21453,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -21501,7 +21501,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -21549,7 +21549,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -21597,7 +21597,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -21645,7 +21645,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -21693,7 +21693,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -21741,7 +21741,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -21789,7 +21789,7 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -21837,10 +21837,10 @@ func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Series != nil { for _, item_4_x_Series := range x.Series { - if item_4_x_Series != nil { + if item_4_x_Series != nil { if item_4_x_Series.Specimen != nil { for _, item_2_item_4_x_Series_Specimen := range item_4_x_Series.Specimen { - if item_2_item_4_x_Series_Specimen != nil { + if item_2_item_4_x_Series_Specimen != nil { if item_2_item_4_x_Series_Specimen.Reference != nil { refVal := *item_2_item_4_x_Series_Specimen.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -21906,7 +21906,7 @@ func (x *ImagingStudySeries) ExtractEdges(project string) ([]json.RawMessage, er _ = seen if x.Specimen != nil { for _, item_2_x_Specimen := range x.Specimen { - if item_2_x_Specimen != nil { + if item_2_x_Specimen != nil { if item_2_x_Specimen.Reference != nil { refVal := *item_2_x_Specimen.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -22964,7 +22964,7 @@ func (x *ImagingStudySeries) ExtractEdges(project string) ([]json.RawMessage, er } if x.Performer != nil { for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { + if item_3_x_Performer != nil { if item_3_x_Performer.Actor != nil { if item_3_x_Performer.Actor.Reference != nil { refVal := *item_3_x_Performer.Actor.Reference @@ -23012,7 +23012,7 @@ func (x *ImagingStudySeries) ExtractEdges(project string) ([]json.RawMessage, er } if x.Performer != nil { for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { + if item_3_x_Performer != nil { if item_3_x_Performer.Actor != nil { if item_3_x_Performer.Actor.Reference != nil { refVal := *item_3_x_Performer.Actor.Reference @@ -23060,7 +23060,7 @@ func (x *ImagingStudySeries) ExtractEdges(project string) ([]json.RawMessage, er } if x.Performer != nil { for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { + if item_3_x_Performer != nil { if item_3_x_Performer.Actor != nil { if item_3_x_Performer.Actor.Reference != nil { refVal := *item_3_x_Performer.Actor.Reference @@ -23108,7 +23108,7 @@ func (x *ImagingStudySeries) ExtractEdges(project string) ([]json.RawMessage, er } if x.Performer != nil { for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { + if item_3_x_Performer != nil { if item_3_x_Performer.Actor != nil { if item_3_x_Performer.Actor.Reference != nil { refVal := *item_3_x_Performer.Actor.Reference @@ -23434,7 +23434,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa _ = seen if x.PartOf != nil { for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { + if item_2_x_PartOf != nil { if item_2_x_PartOf.Reference != nil { refVal := *item_2_x_PartOf.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -23480,7 +23480,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.PartOf != nil { for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { + if item_2_x_PartOf != nil { if item_2_x_PartOf.Reference != nil { refVal := *item_2_x_PartOf.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -23652,7 +23652,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -23698,7 +23698,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -23744,7 +23744,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -23790,7 +23790,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -23836,7 +23836,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -23882,7 +23882,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -23928,7 +23928,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -23974,7 +23974,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -24020,7 +24020,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -24066,7 +24066,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -24112,7 +24112,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -24158,7 +24158,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -24204,7 +24204,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -24250,7 +24250,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -24296,7 +24296,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -24342,7 +24342,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -24388,7 +24388,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -24434,7 +24434,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -24480,7 +24480,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -24526,7 +24526,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -24572,7 +24572,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -24618,7 +24618,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -24664,7 +24664,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -24710,7 +24710,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -24758,7 +24758,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -24806,7 +24806,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -24854,7 +24854,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -24902,7 +24902,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -24950,7 +24950,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -24998,7 +24998,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -25046,7 +25046,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -25094,7 +25094,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -25142,7 +25142,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -25190,7 +25190,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -25238,7 +25238,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -25286,7 +25286,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -25334,7 +25334,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -25382,7 +25382,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -25430,7 +25430,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -25478,7 +25478,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -25526,7 +25526,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -25574,7 +25574,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -25622,7 +25622,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -25670,7 +25670,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -25718,7 +25718,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -25766,7 +25766,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -26826,7 +26826,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -26874,7 +26874,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -26922,7 +26922,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -26970,7 +26970,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -27018,7 +27018,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -27066,7 +27066,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -27114,7 +27114,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -27162,7 +27162,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -27210,7 +27210,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -27258,7 +27258,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -27306,7 +27306,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -27354,7 +27354,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -27402,7 +27402,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -27450,7 +27450,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -27498,7 +27498,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -27546,7 +27546,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -27594,7 +27594,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -27642,7 +27642,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -27690,7 +27690,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -27738,7 +27738,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -27786,7 +27786,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -27834,7 +27834,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -27882,7 +27882,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -27930,7 +27930,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -27978,7 +27978,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -28026,7 +28026,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -28074,7 +28074,7 @@ func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessa } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -30231,7 +30231,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err _ = seen if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -30277,7 +30277,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.InformationSource != nil { for _, item_2_x_InformationSource := range x.InformationSource { - if item_2_x_InformationSource != nil { + if item_2_x_InformationSource != nil { if item_2_x_InformationSource.Reference != nil { refVal := *item_2_x_InformationSource.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -30323,7 +30323,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.InformationSource != nil { for _, item_2_x_InformationSource := range x.InformationSource { - if item_2_x_InformationSource != nil { + if item_2_x_InformationSource != nil { if item_2_x_InformationSource.Reference != nil { refVal := *item_2_x_InformationSource.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -30369,7 +30369,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.InformationSource != nil { for _, item_2_x_InformationSource := range x.InformationSource { - if item_2_x_InformationSource != nil { + if item_2_x_InformationSource != nil { if item_2_x_InformationSource.Reference != nil { refVal := *item_2_x_InformationSource.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -30415,7 +30415,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.InformationSource != nil { for _, item_2_x_InformationSource := range x.InformationSource { - if item_2_x_InformationSource != nil { + if item_2_x_InformationSource != nil { if item_2_x_InformationSource.Reference != nil { refVal := *item_2_x_InformationSource.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -30461,7 +30461,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Performer != nil { for _, item_2_x_Performer := range x.Performer { - if item_2_x_Performer != nil { + if item_2_x_Performer != nil { if item_2_x_Performer.Reference != nil { refVal := *item_2_x_Performer.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -30507,7 +30507,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Performer != nil { for _, item_2_x_Performer := range x.Performer { - if item_2_x_Performer != nil { + if item_2_x_Performer != nil { if item_2_x_Performer.Reference != nil { refVal := *item_2_x_Performer.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -30553,7 +30553,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Performer != nil { for _, item_2_x_Performer := range x.Performer { - if item_2_x_Performer != nil { + if item_2_x_Performer != nil { if item_2_x_Performer.Reference != nil { refVal := *item_2_x_Performer.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -30599,7 +30599,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Performer != nil { for _, item_2_x_Performer := range x.Performer { - if item_2_x_Performer != nil { + if item_2_x_Performer != nil { if item_2_x_Performer.Reference != nil { refVal := *item_2_x_Performer.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -31023,7 +31023,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -31069,7 +31069,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -31115,7 +31115,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -31161,7 +31161,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -31207,7 +31207,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -31253,7 +31253,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -31299,7 +31299,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -31345,7 +31345,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -31391,7 +31391,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -31437,7 +31437,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -31483,7 +31483,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -31529,7 +31529,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -31575,7 +31575,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -31621,7 +31621,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -31667,7 +31667,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -31713,7 +31713,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -31759,7 +31759,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -31805,7 +31805,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -31851,7 +31851,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -31897,7 +31897,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -31943,7 +31943,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -31989,7 +31989,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -32035,7 +32035,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.SupportingInformation != nil { for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation != nil { if item_2_x_SupportingInformation.Reference != nil { refVal := *item_2_x_SupportingInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -32081,7 +32081,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -32129,7 +32129,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -32177,7 +32177,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -32225,7 +32225,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -32273,7 +32273,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -32321,7 +32321,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -32369,7 +32369,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -32417,7 +32417,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -32465,7 +32465,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -32513,7 +32513,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -32561,7 +32561,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -32609,7 +32609,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -32657,7 +32657,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -32705,7 +32705,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -32753,7 +32753,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -32801,7 +32801,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -32849,7 +32849,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -32897,7 +32897,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -32945,7 +32945,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -32993,7 +32993,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -33041,7 +33041,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -33089,7 +33089,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -33137,7 +33137,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Device != nil { for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { + if item_3_x_Device != nil { if item_3_x_Device.Reference != nil { if item_3_x_Device.Reference.Reference != nil { refVal := *item_3_x_Device.Reference.Reference @@ -34241,7 +34241,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -34289,7 +34289,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -34337,7 +34337,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -34385,7 +34385,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -34433,7 +34433,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -34481,7 +34481,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -34529,7 +34529,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -34577,7 +34577,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -34625,7 +34625,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -34673,7 +34673,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -34721,7 +34721,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -34769,7 +34769,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -34817,7 +34817,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -34865,7 +34865,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -34913,7 +34913,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -34961,7 +34961,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -35009,7 +35009,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -35057,7 +35057,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -35105,7 +35105,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -35153,7 +35153,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -35201,7 +35201,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -35249,7 +35249,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -35297,7 +35297,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -35345,7 +35345,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -35393,7 +35393,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -35441,7 +35441,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -35489,7 +35489,7 @@ func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, err } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -35596,7 +35596,7 @@ func (x *MedicationRequestDispenseRequest) ExtractEdges(project string) ([]json. } if x.DispenserInstruction != nil { for _, item_3_x_DispenserInstruction := range x.DispenserInstruction { - if item_3_x_DispenserInstruction != nil { + if item_3_x_DispenserInstruction != nil { if item_3_x_DispenserInstruction.AuthorReference != nil { if item_3_x_DispenserInstruction.AuthorReference.Reference != nil { refVal := *item_3_x_DispenserInstruction.AuthorReference.Reference @@ -35644,7 +35644,7 @@ func (x *MedicationRequestDispenseRequest) ExtractEdges(project string) ([]json. } if x.DispenserInstruction != nil { for _, item_3_x_DispenserInstruction := range x.DispenserInstruction { - if item_3_x_DispenserInstruction != nil { + if item_3_x_DispenserInstruction != nil { if item_3_x_DispenserInstruction.AuthorReference != nil { if item_3_x_DispenserInstruction.AuthorReference.Reference != nil { refVal := *item_3_x_DispenserInstruction.AuthorReference.Reference @@ -35692,7 +35692,7 @@ func (x *MedicationRequestDispenseRequest) ExtractEdges(project string) ([]json. } if x.DispenserInstruction != nil { for _, item_3_x_DispenserInstruction := range x.DispenserInstruction { - if item_3_x_DispenserInstruction != nil { + if item_3_x_DispenserInstruction != nil { if item_3_x_DispenserInstruction.AuthorReference != nil { if item_3_x_DispenserInstruction.AuthorReference.Reference != nil { refVal := *item_3_x_DispenserInstruction.AuthorReference.Reference @@ -35740,7 +35740,7 @@ func (x *MedicationRequestDispenseRequest) ExtractEdges(project string) ([]json. } if x.DispenserInstruction != nil { for _, item_3_x_DispenserInstruction := range x.DispenserInstruction { - if item_3_x_DispenserInstruction != nil { + if item_3_x_DispenserInstruction != nil { if item_3_x_DispenserInstruction.AuthorReference != nil { if item_3_x_DispenserInstruction.AuthorReference.Reference != nil { refVal := *item_3_x_DispenserInstruction.AuthorReference.Reference @@ -35839,7 +35839,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e _ = seen if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -35885,7 +35885,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -35931,7 +35931,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -35977,7 +35977,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -36023,7 +36023,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -36069,7 +36069,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -36115,7 +36115,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -36161,7 +36161,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -36207,7 +36207,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -36253,7 +36253,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -36299,7 +36299,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -36345,7 +36345,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -36391,7 +36391,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -36437,7 +36437,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -36483,7 +36483,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -36529,7 +36529,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -36575,7 +36575,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -36621,7 +36621,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -36667,7 +36667,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -36713,7 +36713,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -36759,7 +36759,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -36805,7 +36805,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -36851,7 +36851,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -36897,7 +36897,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.InformationSource != nil { for _, item_2_x_InformationSource := range x.InformationSource { - if item_2_x_InformationSource != nil { + if item_2_x_InformationSource != nil { if item_2_x_InformationSource.Reference != nil { refVal := *item_2_x_InformationSource.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -36943,7 +36943,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.InformationSource != nil { for _, item_2_x_InformationSource := range x.InformationSource { - if item_2_x_InformationSource != nil { + if item_2_x_InformationSource != nil { if item_2_x_InformationSource.Reference != nil { refVal := *item_2_x_InformationSource.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -36989,7 +36989,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.InformationSource != nil { for _, item_2_x_InformationSource := range x.InformationSource { - if item_2_x_InformationSource != nil { + if item_2_x_InformationSource != nil { if item_2_x_InformationSource.Reference != nil { refVal := *item_2_x_InformationSource.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -37035,7 +37035,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.InformationSource != nil { for _, item_2_x_InformationSource := range x.InformationSource { - if item_2_x_InformationSource != nil { + if item_2_x_InformationSource != nil { if item_2_x_InformationSource.Reference != nil { refVal := *item_2_x_InformationSource.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -37081,7 +37081,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.PartOf != nil { for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { + if item_2_x_PartOf != nil { if item_2_x_PartOf.Reference != nil { refVal := *item_2_x_PartOf.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -37127,7 +37127,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.PartOf != nil { for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { + if item_2_x_PartOf != nil { if item_2_x_PartOf.Reference != nil { refVal := *item_2_x_PartOf.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -37173,7 +37173,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.RelatedClinicalInformation != nil { for _, item_2_x_RelatedClinicalInformation := range x.RelatedClinicalInformation { - if item_2_x_RelatedClinicalInformation != nil { + if item_2_x_RelatedClinicalInformation != nil { if item_2_x_RelatedClinicalInformation.Reference != nil { refVal := *item_2_x_RelatedClinicalInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -37219,7 +37219,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.RelatedClinicalInformation != nil { for _, item_2_x_RelatedClinicalInformation := range x.RelatedClinicalInformation { - if item_2_x_RelatedClinicalInformation != nil { + if item_2_x_RelatedClinicalInformation != nil { if item_2_x_RelatedClinicalInformation.Reference != nil { refVal := *item_2_x_RelatedClinicalInformation.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -38361,7 +38361,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -38409,7 +38409,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -38457,7 +38457,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -38505,7 +38505,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -38553,7 +38553,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -38601,7 +38601,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -38649,7 +38649,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -38697,7 +38697,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -38745,7 +38745,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -38793,7 +38793,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -38841,7 +38841,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -38889,7 +38889,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -38937,7 +38937,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -38985,7 +38985,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -39033,7 +39033,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -39081,7 +39081,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -39129,7 +39129,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -39177,7 +39177,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -39225,7 +39225,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -39273,7 +39273,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -39321,7 +39321,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -39369,7 +39369,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -39417,7 +39417,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -39465,7 +39465,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -39513,7 +39513,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -39561,7 +39561,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -39609,7 +39609,7 @@ func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, e } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -39742,7 +39742,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { _ = seen if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -39830,7 +39830,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -39876,7 +39876,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -39922,7 +39922,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.DerivedFrom != nil { for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom != nil { if item_2_x_DerivedFrom.Reference != nil { refVal := *item_2_x_DerivedFrom.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -39968,7 +39968,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Focus != nil { for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { + if item_2_x_Focus != nil { if item_2_x_Focus.Reference != nil { refVal := *item_2_x_Focus.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -40014,7 +40014,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Focus != nil { for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { + if item_2_x_Focus != nil { if item_2_x_Focus.Reference != nil { refVal := *item_2_x_Focus.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -40060,7 +40060,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Focus != nil { for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { + if item_2_x_Focus != nil { if item_2_x_Focus.Reference != nil { refVal := *item_2_x_Focus.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -40106,7 +40106,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Focus != nil { for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { + if item_2_x_Focus != nil { if item_2_x_Focus.Reference != nil { refVal := *item_2_x_Focus.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -40152,7 +40152,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Focus != nil { for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { + if item_2_x_Focus != nil { if item_2_x_Focus.Reference != nil { refVal := *item_2_x_Focus.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -40198,7 +40198,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Focus != nil { for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { + if item_2_x_Focus != nil { if item_2_x_Focus.Reference != nil { refVal := *item_2_x_Focus.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -40244,7 +40244,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Focus != nil { for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { + if item_2_x_Focus != nil { if item_2_x_Focus.Reference != nil { refVal := *item_2_x_Focus.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -40290,7 +40290,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Focus != nil { for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { + if item_2_x_Focus != nil { if item_2_x_Focus.Reference != nil { refVal := *item_2_x_Focus.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -40336,7 +40336,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Focus != nil { for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { + if item_2_x_Focus != nil { if item_2_x_Focus.Reference != nil { refVal := *item_2_x_Focus.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -40382,7 +40382,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Focus != nil { for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { + if item_2_x_Focus != nil { if item_2_x_Focus.Reference != nil { refVal := *item_2_x_Focus.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -40428,7 +40428,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Focus != nil { for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { + if item_2_x_Focus != nil { if item_2_x_Focus.Reference != nil { refVal := *item_2_x_Focus.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -40474,7 +40474,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Focus != nil { for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { + if item_2_x_Focus != nil { if item_2_x_Focus.Reference != nil { refVal := *item_2_x_Focus.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -40520,7 +40520,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Focus != nil { for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { + if item_2_x_Focus != nil { if item_2_x_Focus.Reference != nil { refVal := *item_2_x_Focus.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -40566,7 +40566,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Focus != nil { for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { + if item_2_x_Focus != nil { if item_2_x_Focus.Reference != nil { refVal := *item_2_x_Focus.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -40612,7 +40612,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Focus != nil { for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { + if item_2_x_Focus != nil { if item_2_x_Focus.Reference != nil { refVal := *item_2_x_Focus.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -40658,7 +40658,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Focus != nil { for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { + if item_2_x_Focus != nil { if item_2_x_Focus.Reference != nil { refVal := *item_2_x_Focus.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -40704,7 +40704,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Focus != nil { for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { + if item_2_x_Focus != nil { if item_2_x_Focus.Reference != nil { refVal := *item_2_x_Focus.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -40750,7 +40750,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Focus != nil { for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { + if item_2_x_Focus != nil { if item_2_x_Focus.Reference != nil { refVal := *item_2_x_Focus.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -40796,7 +40796,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Focus != nil { for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { + if item_2_x_Focus != nil { if item_2_x_Focus.Reference != nil { refVal := *item_2_x_Focus.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -40842,7 +40842,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Focus != nil { for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { + if item_2_x_Focus != nil { if item_2_x_Focus.Reference != nil { refVal := *item_2_x_Focus.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -40888,7 +40888,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Focus != nil { for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { + if item_2_x_Focus != nil { if item_2_x_Focus.Reference != nil { refVal := *item_2_x_Focus.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -40934,7 +40934,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Focus != nil { for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { + if item_2_x_Focus != nil { if item_2_x_Focus.Reference != nil { refVal := *item_2_x_Focus.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -40980,7 +40980,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Focus != nil { for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { + if item_2_x_Focus != nil { if item_2_x_Focus.Reference != nil { refVal := *item_2_x_Focus.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -41026,7 +41026,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.HasMember != nil { for _, item_2_x_HasMember := range x.HasMember { - if item_2_x_HasMember != nil { + if item_2_x_HasMember != nil { if item_2_x_HasMember.Reference != nil { refVal := *item_2_x_HasMember.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -41072,7 +41072,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.PartOf != nil { for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { + if item_2_x_PartOf != nil { if item_2_x_PartOf.Reference != nil { refVal := *item_2_x_PartOf.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -41118,7 +41118,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.PartOf != nil { for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { + if item_2_x_PartOf != nil { if item_2_x_PartOf.Reference != nil { refVal := *item_2_x_PartOf.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -41164,7 +41164,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.PartOf != nil { for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { + if item_2_x_PartOf != nil { if item_2_x_PartOf.Reference != nil { refVal := *item_2_x_PartOf.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -41210,7 +41210,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.PartOf != nil { for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { + if item_2_x_PartOf != nil { if item_2_x_PartOf.Reference != nil { refVal := *item_2_x_PartOf.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -41256,7 +41256,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Performer != nil { for _, item_2_x_Performer := range x.Performer { - if item_2_x_Performer != nil { + if item_2_x_Performer != nil { if item_2_x_Performer.Reference != nil { refVal := *item_2_x_Performer.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -41302,7 +41302,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Performer != nil { for _, item_2_x_Performer := range x.Performer { - if item_2_x_Performer != nil { + if item_2_x_Performer != nil { if item_2_x_Performer.Reference != nil { refVal := *item_2_x_Performer.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -41348,7 +41348,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Performer != nil { for _, item_2_x_Performer := range x.Performer { - if item_2_x_Performer != nil { + if item_2_x_Performer != nil { if item_2_x_Performer.Reference != nil { refVal := *item_2_x_Performer.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -41394,7 +41394,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Performer != nil { for _, item_2_x_Performer := range x.Performer { - if item_2_x_Performer != nil { + if item_2_x_Performer != nil { if item_2_x_Performer.Reference != nil { refVal := *item_2_x_Performer.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -41818,7 +41818,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -41866,7 +41866,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -41914,7 +41914,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -41962,7 +41962,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -42010,7 +42010,7 @@ func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.TriggeredBy != nil { for _, item_3_x_TriggeredBy := range x.TriggeredBy { - if item_3_x_TriggeredBy != nil { + if item_3_x_TriggeredBy != nil { if item_3_x_TriggeredBy.Observation != nil { if item_3_x_TriggeredBy.Observation.Reference != nil { refVal := *item_3_x_TriggeredBy.Observation.Reference @@ -42210,7 +42210,7 @@ func (x *Organization) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Contact != nil { for _, item_3_x_Contact := range x.Contact { - if item_3_x_Contact != nil { + if item_3_x_Contact != nil { if item_3_x_Contact.Organization != nil { if item_3_x_Contact.Organization.Reference != nil { refVal := *item_3_x_Contact.Organization.Reference @@ -42258,7 +42258,7 @@ func (x *Organization) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Qualification != nil { for _, item_3_x_Qualification := range x.Qualification { - if item_3_x_Qualification != nil { + if item_3_x_Qualification != nil { if item_3_x_Qualification.Issuer != nil { if item_3_x_Qualification.Issuer.Reference != nil { refVal := *item_3_x_Qualification.Issuer.Reference @@ -42399,7 +42399,7 @@ func (x *Patient) ExtractEdges(project string) ([]json.RawMessage, error) { _ = seen if x.GeneralPractitioner != nil { for _, item_2_x_GeneralPractitioner := range x.GeneralPractitioner { - if item_2_x_GeneralPractitioner != nil { + if item_2_x_GeneralPractitioner != nil { if item_2_x_GeneralPractitioner.Reference != nil { refVal := *item_2_x_GeneralPractitioner.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -42445,7 +42445,7 @@ func (x *Patient) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.GeneralPractitioner != nil { for _, item_2_x_GeneralPractitioner := range x.GeneralPractitioner { - if item_2_x_GeneralPractitioner != nil { + if item_2_x_GeneralPractitioner != nil { if item_2_x_GeneralPractitioner.Reference != nil { refVal := *item_2_x_GeneralPractitioner.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -42491,7 +42491,7 @@ func (x *Patient) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.GeneralPractitioner != nil { for _, item_2_x_GeneralPractitioner := range x.GeneralPractitioner { - if item_2_x_GeneralPractitioner != nil { + if item_2_x_GeneralPractitioner != nil { if item_2_x_GeneralPractitioner.Reference != nil { refVal := *item_2_x_GeneralPractitioner.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -42579,7 +42579,7 @@ func (x *Patient) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Contact != nil { for _, item_3_x_Contact := range x.Contact { - if item_3_x_Contact != nil { + if item_3_x_Contact != nil { if item_3_x_Contact.Organization != nil { if item_3_x_Contact.Organization.Reference != nil { refVal := *item_3_x_Contact.Organization.Reference @@ -42627,7 +42627,7 @@ func (x *Patient) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Link != nil { for _, item_3_x_Link := range x.Link { - if item_3_x_Link != nil { + if item_3_x_Link != nil { if item_3_x_Link.Other != nil { if item_3_x_Link.Other.Reference != nil { refVal := *item_3_x_Link.Other.Reference @@ -42844,7 +42844,7 @@ func (x *Practitioner) ExtractEdges(project string) ([]json.RawMessage, error) { _ = seen if x.Qualification != nil { for _, item_3_x_Qualification := range x.Qualification { - if item_3_x_Qualification != nil { + if item_3_x_Qualification != nil { if item_3_x_Qualification.Issuer != nil { if item_3_x_Qualification.Issuer.Reference != nil { refVal := *item_3_x_Qualification.Issuer.Reference @@ -43069,7 +43069,7 @@ func (x *PractitionerRole) ExtractEdges(project string) ([]json.RawMessage, erro } if x.Contact != nil { for _, item_3_x_Contact := range x.Contact { - if item_3_x_Contact != nil { + if item_3_x_Contact != nil { if item_3_x_Contact.Organization != nil { if item_3_x_Contact.Organization.Reference != nil { refVal := *item_3_x_Contact.Organization.Reference @@ -43386,7 +43386,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.PartOf != nil { for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { + if item_2_x_PartOf != nil { if item_2_x_PartOf.Reference != nil { refVal := *item_2_x_PartOf.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -43432,7 +43432,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.PartOf != nil { for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { + if item_2_x_PartOf != nil { if item_2_x_PartOf.Reference != nil { refVal := *item_2_x_PartOf.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -43478,7 +43478,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.PartOf != nil { for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { + if item_2_x_PartOf != nil { if item_2_x_PartOf.Reference != nil { refVal := *item_2_x_PartOf.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -43650,7 +43650,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Report != nil { for _, item_2_x_Report := range x.Report { - if item_2_x_Report != nil { + if item_2_x_Report != nil { if item_2_x_Report.Reference != nil { refVal := *item_2_x_Report.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -43696,7 +43696,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Report != nil { for _, item_2_x_Report := range x.Report { - if item_2_x_Report != nil { + if item_2_x_Report != nil { if item_2_x_Report.Reference != nil { refVal := *item_2_x_Report.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -44078,7 +44078,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.SupportingInfo != nil { for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo != nil { if item_2_x_SupportingInfo.Reference != nil { refVal := *item_2_x_SupportingInfo.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -44124,7 +44124,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.SupportingInfo != nil { for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo != nil { if item_2_x_SupportingInfo.Reference != nil { refVal := *item_2_x_SupportingInfo.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -44170,7 +44170,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.SupportingInfo != nil { for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo != nil { if item_2_x_SupportingInfo.Reference != nil { refVal := *item_2_x_SupportingInfo.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -44216,7 +44216,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.SupportingInfo != nil { for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo != nil { if item_2_x_SupportingInfo.Reference != nil { refVal := *item_2_x_SupportingInfo.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -44262,7 +44262,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.SupportingInfo != nil { for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo != nil { if item_2_x_SupportingInfo.Reference != nil { refVal := *item_2_x_SupportingInfo.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -44308,7 +44308,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.SupportingInfo != nil { for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo != nil { if item_2_x_SupportingInfo.Reference != nil { refVal := *item_2_x_SupportingInfo.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -44354,7 +44354,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.SupportingInfo != nil { for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo != nil { if item_2_x_SupportingInfo.Reference != nil { refVal := *item_2_x_SupportingInfo.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -44400,7 +44400,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.SupportingInfo != nil { for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo != nil { if item_2_x_SupportingInfo.Reference != nil { refVal := *item_2_x_SupportingInfo.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -44446,7 +44446,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.SupportingInfo != nil { for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo != nil { if item_2_x_SupportingInfo.Reference != nil { refVal := *item_2_x_SupportingInfo.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -44492,7 +44492,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.SupportingInfo != nil { for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo != nil { if item_2_x_SupportingInfo.Reference != nil { refVal := *item_2_x_SupportingInfo.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -44538,7 +44538,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.SupportingInfo != nil { for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo != nil { if item_2_x_SupportingInfo.Reference != nil { refVal := *item_2_x_SupportingInfo.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -44584,7 +44584,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.SupportingInfo != nil { for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo != nil { if item_2_x_SupportingInfo.Reference != nil { refVal := *item_2_x_SupportingInfo.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -44630,7 +44630,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.SupportingInfo != nil { for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo != nil { if item_2_x_SupportingInfo.Reference != nil { refVal := *item_2_x_SupportingInfo.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -44676,7 +44676,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.SupportingInfo != nil { for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo != nil { if item_2_x_SupportingInfo.Reference != nil { refVal := *item_2_x_SupportingInfo.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -44722,7 +44722,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.SupportingInfo != nil { for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo != nil { if item_2_x_SupportingInfo.Reference != nil { refVal := *item_2_x_SupportingInfo.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -44768,7 +44768,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.SupportingInfo != nil { for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo != nil { if item_2_x_SupportingInfo.Reference != nil { refVal := *item_2_x_SupportingInfo.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -44814,7 +44814,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.SupportingInfo != nil { for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo != nil { if item_2_x_SupportingInfo.Reference != nil { refVal := *item_2_x_SupportingInfo.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -44860,7 +44860,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.SupportingInfo != nil { for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo != nil { if item_2_x_SupportingInfo.Reference != nil { refVal := *item_2_x_SupportingInfo.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -44906,7 +44906,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.SupportingInfo != nil { for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo != nil { if item_2_x_SupportingInfo.Reference != nil { refVal := *item_2_x_SupportingInfo.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -44952,7 +44952,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.SupportingInfo != nil { for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo != nil { if item_2_x_SupportingInfo.Reference != nil { refVal := *item_2_x_SupportingInfo.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -44998,7 +44998,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.SupportingInfo != nil { for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo != nil { if item_2_x_SupportingInfo.Reference != nil { refVal := *item_2_x_SupportingInfo.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -45044,7 +45044,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.SupportingInfo != nil { for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo != nil { if item_2_x_SupportingInfo.Reference != nil { refVal := *item_2_x_SupportingInfo.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -45090,7 +45090,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.SupportingInfo != nil { for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo != nil { if item_2_x_SupportingInfo.Reference != nil { refVal := *item_2_x_SupportingInfo.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -45136,7 +45136,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Complication != nil { for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { + if item_3_x_Complication != nil { if item_3_x_Complication.Reference != nil { if item_3_x_Complication.Reference.Reference != nil { refVal := *item_3_x_Complication.Reference.Reference @@ -45184,7 +45184,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Complication != nil { for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { + if item_3_x_Complication != nil { if item_3_x_Complication.Reference != nil { if item_3_x_Complication.Reference.Reference != nil { refVal := *item_3_x_Complication.Reference.Reference @@ -45232,7 +45232,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Complication != nil { for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { + if item_3_x_Complication != nil { if item_3_x_Complication.Reference != nil { if item_3_x_Complication.Reference.Reference != nil { refVal := *item_3_x_Complication.Reference.Reference @@ -45280,7 +45280,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Complication != nil { for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { + if item_3_x_Complication != nil { if item_3_x_Complication.Reference != nil { if item_3_x_Complication.Reference.Reference != nil { refVal := *item_3_x_Complication.Reference.Reference @@ -45328,7 +45328,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Complication != nil { for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { + if item_3_x_Complication != nil { if item_3_x_Complication.Reference != nil { if item_3_x_Complication.Reference.Reference != nil { refVal := *item_3_x_Complication.Reference.Reference @@ -45376,7 +45376,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Complication != nil { for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { + if item_3_x_Complication != nil { if item_3_x_Complication.Reference != nil { if item_3_x_Complication.Reference.Reference != nil { refVal := *item_3_x_Complication.Reference.Reference @@ -45424,7 +45424,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Complication != nil { for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { + if item_3_x_Complication != nil { if item_3_x_Complication.Reference != nil { if item_3_x_Complication.Reference.Reference != nil { refVal := *item_3_x_Complication.Reference.Reference @@ -45472,7 +45472,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Complication != nil { for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { + if item_3_x_Complication != nil { if item_3_x_Complication.Reference != nil { if item_3_x_Complication.Reference.Reference != nil { refVal := *item_3_x_Complication.Reference.Reference @@ -45520,7 +45520,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Complication != nil { for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { + if item_3_x_Complication != nil { if item_3_x_Complication.Reference != nil { if item_3_x_Complication.Reference.Reference != nil { refVal := *item_3_x_Complication.Reference.Reference @@ -45568,7 +45568,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Complication != nil { for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { + if item_3_x_Complication != nil { if item_3_x_Complication.Reference != nil { if item_3_x_Complication.Reference.Reference != nil { refVal := *item_3_x_Complication.Reference.Reference @@ -45616,7 +45616,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Complication != nil { for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { + if item_3_x_Complication != nil { if item_3_x_Complication.Reference != nil { if item_3_x_Complication.Reference.Reference != nil { refVal := *item_3_x_Complication.Reference.Reference @@ -45664,7 +45664,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Complication != nil { for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { + if item_3_x_Complication != nil { if item_3_x_Complication.Reference != nil { if item_3_x_Complication.Reference.Reference != nil { refVal := *item_3_x_Complication.Reference.Reference @@ -45712,7 +45712,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Complication != nil { for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { + if item_3_x_Complication != nil { if item_3_x_Complication.Reference != nil { if item_3_x_Complication.Reference.Reference != nil { refVal := *item_3_x_Complication.Reference.Reference @@ -45760,7 +45760,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Complication != nil { for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { + if item_3_x_Complication != nil { if item_3_x_Complication.Reference != nil { if item_3_x_Complication.Reference.Reference != nil { refVal := *item_3_x_Complication.Reference.Reference @@ -45808,7 +45808,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Complication != nil { for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { + if item_3_x_Complication != nil { if item_3_x_Complication.Reference != nil { if item_3_x_Complication.Reference.Reference != nil { refVal := *item_3_x_Complication.Reference.Reference @@ -45856,7 +45856,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Complication != nil { for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { + if item_3_x_Complication != nil { if item_3_x_Complication.Reference != nil { if item_3_x_Complication.Reference.Reference != nil { refVal := *item_3_x_Complication.Reference.Reference @@ -45904,7 +45904,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Complication != nil { for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { + if item_3_x_Complication != nil { if item_3_x_Complication.Reference != nil { if item_3_x_Complication.Reference.Reference != nil { refVal := *item_3_x_Complication.Reference.Reference @@ -45952,7 +45952,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Complication != nil { for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { + if item_3_x_Complication != nil { if item_3_x_Complication.Reference != nil { if item_3_x_Complication.Reference.Reference != nil { refVal := *item_3_x_Complication.Reference.Reference @@ -46000,7 +46000,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Complication != nil { for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { + if item_3_x_Complication != nil { if item_3_x_Complication.Reference != nil { if item_3_x_Complication.Reference.Reference != nil { refVal := *item_3_x_Complication.Reference.Reference @@ -46048,7 +46048,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Complication != nil { for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { + if item_3_x_Complication != nil { if item_3_x_Complication.Reference != nil { if item_3_x_Complication.Reference.Reference != nil { refVal := *item_3_x_Complication.Reference.Reference @@ -46096,7 +46096,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Complication != nil { for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { + if item_3_x_Complication != nil { if item_3_x_Complication.Reference != nil { if item_3_x_Complication.Reference.Reference != nil { refVal := *item_3_x_Complication.Reference.Reference @@ -46144,7 +46144,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Complication != nil { for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { + if item_3_x_Complication != nil { if item_3_x_Complication.Reference != nil { if item_3_x_Complication.Reference.Reference != nil { refVal := *item_3_x_Complication.Reference.Reference @@ -46192,7 +46192,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Complication != nil { for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { + if item_3_x_Complication != nil { if item_3_x_Complication.Reference != nil { if item_3_x_Complication.Reference.Reference != nil { refVal := *item_3_x_Complication.Reference.Reference @@ -46240,7 +46240,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -46288,7 +46288,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -46336,7 +46336,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -46384,7 +46384,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -46432,7 +46432,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Performer != nil { for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { + if item_3_x_Performer != nil { if item_3_x_Performer.Actor != nil { if item_3_x_Performer.Actor.Reference != nil { refVal := *item_3_x_Performer.Actor.Reference @@ -46480,7 +46480,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Performer != nil { for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { + if item_3_x_Performer != nil { if item_3_x_Performer.Actor != nil { if item_3_x_Performer.Actor.Reference != nil { refVal := *item_3_x_Performer.Actor.Reference @@ -46528,7 +46528,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Performer != nil { for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { + if item_3_x_Performer != nil { if item_3_x_Performer.Actor != nil { if item_3_x_Performer.Actor.Reference != nil { refVal := *item_3_x_Performer.Actor.Reference @@ -46576,7 +46576,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Performer != nil { for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { + if item_3_x_Performer != nil { if item_3_x_Performer.Actor != nil { if item_3_x_Performer.Actor.Reference != nil { refVal := *item_3_x_Performer.Actor.Reference @@ -46624,7 +46624,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Performer != nil { for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { + if item_3_x_Performer != nil { if item_3_x_Performer.OnBehalfOf != nil { if item_3_x_Performer.OnBehalfOf.Reference != nil { refVal := *item_3_x_Performer.OnBehalfOf.Reference @@ -46672,7 +46672,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -46720,7 +46720,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -46768,7 +46768,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -46816,7 +46816,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -46864,7 +46864,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -46912,7 +46912,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -46960,7 +46960,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -47008,7 +47008,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -47056,7 +47056,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -47104,7 +47104,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -47152,7 +47152,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -47200,7 +47200,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -47248,7 +47248,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -47296,7 +47296,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -47344,7 +47344,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -47392,7 +47392,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -47440,7 +47440,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -47488,7 +47488,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -47536,7 +47536,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -47584,7 +47584,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -47632,7 +47632,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -47680,7 +47680,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -47728,7 +47728,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -47776,7 +47776,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Used != nil { for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { + if item_3_x_Used != nil { if item_3_x_Used.Reference != nil { if item_3_x_Used.Reference.Reference != nil { refVal := *item_3_x_Used.Reference.Reference @@ -47824,7 +47824,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Used != nil { for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { + if item_3_x_Used != nil { if item_3_x_Used.Reference != nil { if item_3_x_Used.Reference.Reference != nil { refVal := *item_3_x_Used.Reference.Reference @@ -47872,7 +47872,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Used != nil { for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { + if item_3_x_Used != nil { if item_3_x_Used.Reference != nil { if item_3_x_Used.Reference.Reference != nil { refVal := *item_3_x_Used.Reference.Reference @@ -47920,7 +47920,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Used != nil { for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { + if item_3_x_Used != nil { if item_3_x_Used.Reference != nil { if item_3_x_Used.Reference.Reference != nil { refVal := *item_3_x_Used.Reference.Reference @@ -47968,7 +47968,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Used != nil { for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { + if item_3_x_Used != nil { if item_3_x_Used.Reference != nil { if item_3_x_Used.Reference.Reference != nil { refVal := *item_3_x_Used.Reference.Reference @@ -48016,7 +48016,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Used != nil { for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { + if item_3_x_Used != nil { if item_3_x_Used.Reference != nil { if item_3_x_Used.Reference.Reference != nil { refVal := *item_3_x_Used.Reference.Reference @@ -48064,7 +48064,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Used != nil { for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { + if item_3_x_Used != nil { if item_3_x_Used.Reference != nil { if item_3_x_Used.Reference.Reference != nil { refVal := *item_3_x_Used.Reference.Reference @@ -48112,7 +48112,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Used != nil { for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { + if item_3_x_Used != nil { if item_3_x_Used.Reference != nil { if item_3_x_Used.Reference.Reference != nil { refVal := *item_3_x_Used.Reference.Reference @@ -48160,7 +48160,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Used != nil { for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { + if item_3_x_Used != nil { if item_3_x_Used.Reference != nil { if item_3_x_Used.Reference.Reference != nil { refVal := *item_3_x_Used.Reference.Reference @@ -48208,7 +48208,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Used != nil { for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { + if item_3_x_Used != nil { if item_3_x_Used.Reference != nil { if item_3_x_Used.Reference.Reference != nil { refVal := *item_3_x_Used.Reference.Reference @@ -48256,7 +48256,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Used != nil { for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { + if item_3_x_Used != nil { if item_3_x_Used.Reference != nil { if item_3_x_Used.Reference.Reference != nil { refVal := *item_3_x_Used.Reference.Reference @@ -48304,7 +48304,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Used != nil { for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { + if item_3_x_Used != nil { if item_3_x_Used.Reference != nil { if item_3_x_Used.Reference.Reference != nil { refVal := *item_3_x_Used.Reference.Reference @@ -48352,7 +48352,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Used != nil { for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { + if item_3_x_Used != nil { if item_3_x_Used.Reference != nil { if item_3_x_Used.Reference.Reference != nil { refVal := *item_3_x_Used.Reference.Reference @@ -48400,7 +48400,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Used != nil { for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { + if item_3_x_Used != nil { if item_3_x_Used.Reference != nil { if item_3_x_Used.Reference.Reference != nil { refVal := *item_3_x_Used.Reference.Reference @@ -48448,7 +48448,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Used != nil { for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { + if item_3_x_Used != nil { if item_3_x_Used.Reference != nil { if item_3_x_Used.Reference.Reference != nil { refVal := *item_3_x_Used.Reference.Reference @@ -48496,7 +48496,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Used != nil { for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { + if item_3_x_Used != nil { if item_3_x_Used.Reference != nil { if item_3_x_Used.Reference.Reference != nil { refVal := *item_3_x_Used.Reference.Reference @@ -48544,7 +48544,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Used != nil { for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { + if item_3_x_Used != nil { if item_3_x_Used.Reference != nil { if item_3_x_Used.Reference.Reference != nil { refVal := *item_3_x_Used.Reference.Reference @@ -48592,7 +48592,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Used != nil { for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { + if item_3_x_Used != nil { if item_3_x_Used.Reference != nil { if item_3_x_Used.Reference.Reference != nil { refVal := *item_3_x_Used.Reference.Reference @@ -48640,7 +48640,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Used != nil { for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { + if item_3_x_Used != nil { if item_3_x_Used.Reference != nil { if item_3_x_Used.Reference.Reference != nil { refVal := *item_3_x_Used.Reference.Reference @@ -48688,7 +48688,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Used != nil { for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { + if item_3_x_Used != nil { if item_3_x_Used.Reference != nil { if item_3_x_Used.Reference.Reference != nil { refVal := *item_3_x_Used.Reference.Reference @@ -48736,7 +48736,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Used != nil { for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { + if item_3_x_Used != nil { if item_3_x_Used.Reference != nil { if item_3_x_Used.Reference.Reference != nil { refVal := *item_3_x_Used.Reference.Reference @@ -48784,7 +48784,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Used != nil { for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { + if item_3_x_Used != nil { if item_3_x_Used.Reference != nil { if item_3_x_Used.Reference.Reference != nil { refVal := *item_3_x_Used.Reference.Reference @@ -48832,7 +48832,7 @@ func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Used != nil { for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { + if item_3_x_Used != nil { if item_3_x_Used.Reference != nil { if item_3_x_Used.Reference.Reference != nil { refVal := *item_3_x_Used.Reference.Reference @@ -50235,7 +50235,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.PartOf != nil { for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { + if item_2_x_PartOf != nil { if item_2_x_PartOf.Reference != nil { refVal := *item_2_x_PartOf.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -50281,7 +50281,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Result != nil { for _, item_2_x_Result := range x.Result { - if item_2_x_Result != nil { + if item_2_x_Result != nil { if item_2_x_Result.Reference != nil { refVal := *item_2_x_Result.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -50327,7 +50327,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Site != nil { for _, item_2_x_Site := range x.Site { - if item_2_x_Site != nil { + if item_2_x_Site != nil { if item_2_x_Site.Reference != nil { refVal := *item_2_x_Site.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -50373,7 +50373,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Site != nil { for _, item_2_x_Site := range x.Site { - if item_2_x_Site != nil { + if item_2_x_Site != nil { if item_2_x_Site.Reference != nil { refVal := *item_2_x_Site.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -50419,7 +50419,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.AssociatedParty != nil { for _, item_3_x_AssociatedParty := range x.AssociatedParty { - if item_3_x_AssociatedParty != nil { + if item_3_x_AssociatedParty != nil { if item_3_x_AssociatedParty.Party != nil { if item_3_x_AssociatedParty.Party.Reference != nil { refVal := *item_3_x_AssociatedParty.Party.Reference @@ -50467,7 +50467,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.AssociatedParty != nil { for _, item_3_x_AssociatedParty := range x.AssociatedParty { - if item_3_x_AssociatedParty != nil { + if item_3_x_AssociatedParty != nil { if item_3_x_AssociatedParty.Party != nil { if item_3_x_AssociatedParty.Party.Reference != nil { refVal := *item_3_x_AssociatedParty.Party.Reference @@ -50515,7 +50515,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.AssociatedParty != nil { for _, item_3_x_AssociatedParty := range x.AssociatedParty { - if item_3_x_AssociatedParty != nil { + if item_3_x_AssociatedParty != nil { if item_3_x_AssociatedParty.Party != nil { if item_3_x_AssociatedParty.Party.Reference != nil { refVal := *item_3_x_AssociatedParty.Party.Reference @@ -50563,7 +50563,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.ComparisonGroup != nil { for _, item_3_x_ComparisonGroup := range x.ComparisonGroup { - if item_3_x_ComparisonGroup != nil { + if item_3_x_ComparisonGroup != nil { if item_3_x_ComparisonGroup.ObservedGroup != nil { if item_3_x_ComparisonGroup.ObservedGroup.Reference != nil { refVal := *item_3_x_ComparisonGroup.ObservedGroup.Reference @@ -50611,7 +50611,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Focus != nil { for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { + if item_3_x_Focus != nil { if item_3_x_Focus.Reference != nil { if item_3_x_Focus.Reference.Reference != nil { refVal := *item_3_x_Focus.Reference.Reference @@ -50659,7 +50659,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Focus != nil { for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { + if item_3_x_Focus != nil { if item_3_x_Focus.Reference != nil { if item_3_x_Focus.Reference.Reference != nil { refVal := *item_3_x_Focus.Reference.Reference @@ -50707,7 +50707,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Focus != nil { for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { + if item_3_x_Focus != nil { if item_3_x_Focus.Reference != nil { if item_3_x_Focus.Reference.Reference != nil { refVal := *item_3_x_Focus.Reference.Reference @@ -50755,7 +50755,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Focus != nil { for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { + if item_3_x_Focus != nil { if item_3_x_Focus.Reference != nil { if item_3_x_Focus.Reference.Reference != nil { refVal := *item_3_x_Focus.Reference.Reference @@ -50803,7 +50803,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Focus != nil { for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { + if item_3_x_Focus != nil { if item_3_x_Focus.Reference != nil { if item_3_x_Focus.Reference.Reference != nil { refVal := *item_3_x_Focus.Reference.Reference @@ -50851,7 +50851,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Focus != nil { for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { + if item_3_x_Focus != nil { if item_3_x_Focus.Reference != nil { if item_3_x_Focus.Reference.Reference != nil { refVal := *item_3_x_Focus.Reference.Reference @@ -50899,7 +50899,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Focus != nil { for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { + if item_3_x_Focus != nil { if item_3_x_Focus.Reference != nil { if item_3_x_Focus.Reference.Reference != nil { refVal := *item_3_x_Focus.Reference.Reference @@ -50947,7 +50947,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Focus != nil { for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { + if item_3_x_Focus != nil { if item_3_x_Focus.Reference != nil { if item_3_x_Focus.Reference.Reference != nil { refVal := *item_3_x_Focus.Reference.Reference @@ -50995,7 +50995,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Focus != nil { for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { + if item_3_x_Focus != nil { if item_3_x_Focus.Reference != nil { if item_3_x_Focus.Reference.Reference != nil { refVal := *item_3_x_Focus.Reference.Reference @@ -51043,7 +51043,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Focus != nil { for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { + if item_3_x_Focus != nil { if item_3_x_Focus.Reference != nil { if item_3_x_Focus.Reference.Reference != nil { refVal := *item_3_x_Focus.Reference.Reference @@ -51091,7 +51091,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Focus != nil { for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { + if item_3_x_Focus != nil { if item_3_x_Focus.Reference != nil { if item_3_x_Focus.Reference.Reference != nil { refVal := *item_3_x_Focus.Reference.Reference @@ -51139,7 +51139,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Focus != nil { for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { + if item_3_x_Focus != nil { if item_3_x_Focus.Reference != nil { if item_3_x_Focus.Reference.Reference != nil { refVal := *item_3_x_Focus.Reference.Reference @@ -51187,7 +51187,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Focus != nil { for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { + if item_3_x_Focus != nil { if item_3_x_Focus.Reference != nil { if item_3_x_Focus.Reference.Reference != nil { refVal := *item_3_x_Focus.Reference.Reference @@ -51235,7 +51235,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Focus != nil { for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { + if item_3_x_Focus != nil { if item_3_x_Focus.Reference != nil { if item_3_x_Focus.Reference.Reference != nil { refVal := *item_3_x_Focus.Reference.Reference @@ -51283,7 +51283,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Focus != nil { for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { + if item_3_x_Focus != nil { if item_3_x_Focus.Reference != nil { if item_3_x_Focus.Reference.Reference != nil { refVal := *item_3_x_Focus.Reference.Reference @@ -51331,7 +51331,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Focus != nil { for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { + if item_3_x_Focus != nil { if item_3_x_Focus.Reference != nil { if item_3_x_Focus.Reference.Reference != nil { refVal := *item_3_x_Focus.Reference.Reference @@ -51379,7 +51379,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Focus != nil { for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { + if item_3_x_Focus != nil { if item_3_x_Focus.Reference != nil { if item_3_x_Focus.Reference.Reference != nil { refVal := *item_3_x_Focus.Reference.Reference @@ -51427,7 +51427,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Focus != nil { for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { + if item_3_x_Focus != nil { if item_3_x_Focus.Reference != nil { if item_3_x_Focus.Reference.Reference != nil { refVal := *item_3_x_Focus.Reference.Reference @@ -51475,7 +51475,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Focus != nil { for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { + if item_3_x_Focus != nil { if item_3_x_Focus.Reference != nil { if item_3_x_Focus.Reference.Reference != nil { refVal := *item_3_x_Focus.Reference.Reference @@ -51523,7 +51523,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Focus != nil { for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { + if item_3_x_Focus != nil { if item_3_x_Focus.Reference != nil { if item_3_x_Focus.Reference.Reference != nil { refVal := *item_3_x_Focus.Reference.Reference @@ -51571,7 +51571,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Focus != nil { for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { + if item_3_x_Focus != nil { if item_3_x_Focus.Reference != nil { if item_3_x_Focus.Reference.Reference != nil { refVal := *item_3_x_Focus.Reference.Reference @@ -51619,7 +51619,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Focus != nil { for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { + if item_3_x_Focus != nil { if item_3_x_Focus.Reference != nil { if item_3_x_Focus.Reference.Reference != nil { refVal := *item_3_x_Focus.Reference.Reference @@ -51667,7 +51667,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Focus != nil { for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { + if item_3_x_Focus != nil { if item_3_x_Focus.Reference != nil { if item_3_x_Focus.Reference.Reference != nil { refVal := *item_3_x_Focus.Reference.Reference @@ -51715,7 +51715,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -51763,7 +51763,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -51811,7 +51811,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -51859,7 +51859,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -51995,7 +51995,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.RelatedArtifact != nil { for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact != nil { if item_3_x_RelatedArtifact.ResourceReference != nil { if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference @@ -52043,7 +52043,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.RelatedArtifact != nil { for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact != nil { if item_3_x_RelatedArtifact.ResourceReference != nil { if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference @@ -52091,7 +52091,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.RelatedArtifact != nil { for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact != nil { if item_3_x_RelatedArtifact.ResourceReference != nil { if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference @@ -52139,7 +52139,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.RelatedArtifact != nil { for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact != nil { if item_3_x_RelatedArtifact.ResourceReference != nil { if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference @@ -52187,7 +52187,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.RelatedArtifact != nil { for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact != nil { if item_3_x_RelatedArtifact.ResourceReference != nil { if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference @@ -52235,7 +52235,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.RelatedArtifact != nil { for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact != nil { if item_3_x_RelatedArtifact.ResourceReference != nil { if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference @@ -52283,7 +52283,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.RelatedArtifact != nil { for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact != nil { if item_3_x_RelatedArtifact.ResourceReference != nil { if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference @@ -52331,7 +52331,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.RelatedArtifact != nil { for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact != nil { if item_3_x_RelatedArtifact.ResourceReference != nil { if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference @@ -52379,7 +52379,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.RelatedArtifact != nil { for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact != nil { if item_3_x_RelatedArtifact.ResourceReference != nil { if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference @@ -52427,7 +52427,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.RelatedArtifact != nil { for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact != nil { if item_3_x_RelatedArtifact.ResourceReference != nil { if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference @@ -52475,7 +52475,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.RelatedArtifact != nil { for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact != nil { if item_3_x_RelatedArtifact.ResourceReference != nil { if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference @@ -52523,7 +52523,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.RelatedArtifact != nil { for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact != nil { if item_3_x_RelatedArtifact.ResourceReference != nil { if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference @@ -52571,7 +52571,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.RelatedArtifact != nil { for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact != nil { if item_3_x_RelatedArtifact.ResourceReference != nil { if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference @@ -52619,7 +52619,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.RelatedArtifact != nil { for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact != nil { if item_3_x_RelatedArtifact.ResourceReference != nil { if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference @@ -52667,7 +52667,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.RelatedArtifact != nil { for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact != nil { if item_3_x_RelatedArtifact.ResourceReference != nil { if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference @@ -52715,7 +52715,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.RelatedArtifact != nil { for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact != nil { if item_3_x_RelatedArtifact.ResourceReference != nil { if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference @@ -52763,7 +52763,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.RelatedArtifact != nil { for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact != nil { if item_3_x_RelatedArtifact.ResourceReference != nil { if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference @@ -52811,7 +52811,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.RelatedArtifact != nil { for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact != nil { if item_3_x_RelatedArtifact.ResourceReference != nil { if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference @@ -52859,7 +52859,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.RelatedArtifact != nil { for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact != nil { if item_3_x_RelatedArtifact.ResourceReference != nil { if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference @@ -52907,7 +52907,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.RelatedArtifact != nil { for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact != nil { if item_3_x_RelatedArtifact.ResourceReference != nil { if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference @@ -52955,7 +52955,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.RelatedArtifact != nil { for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact != nil { if item_3_x_RelatedArtifact.ResourceReference != nil { if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference @@ -53003,7 +53003,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.RelatedArtifact != nil { for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact != nil { if item_3_x_RelatedArtifact.ResourceReference != nil { if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference @@ -53051,7 +53051,7 @@ func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) } if x.RelatedArtifact != nil { for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact != nil { if item_3_x_RelatedArtifact.ResourceReference != nil { if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference @@ -53500,11 +53500,11 @@ func (x *ResearchSubject) ExtractEdges(project string) ([]json.RawMessage, error edges = append(edges, buildEdgeRawJSON( forwardKey, collectionID(sourceType, id), - collectionID("study", targetID), + collectionID("ResearchStudy", targetID), "study", projectJSON, sourceType, - "study", + "ResearchStudy", )) } backrefKey := getEdgeUUID(id, targetID, "research_subject") @@ -54160,7 +54160,7 @@ func (x *Specimen) ExtractEdges(project string) ([]json.RawMessage, error) { _ = seen if x.Parent != nil { for _, item_2_x_Parent := range x.Parent { - if item_2_x_Parent != nil { + if item_2_x_Parent != nil { if item_2_x_Parent.Reference != nil { refVal := *item_2_x_Parent.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -54508,7 +54508,7 @@ func (x *Specimen) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -54556,7 +54556,7 @@ func (x *Specimen) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -54604,7 +54604,7 @@ func (x *Specimen) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -54652,7 +54652,7 @@ func (x *Specimen) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -54700,10 +54700,10 @@ func (x *Specimen) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Processing != nil { for _, item_4_x_Processing := range x.Processing { - if item_4_x_Processing != nil { + if item_4_x_Processing != nil { if item_4_x_Processing.Additive != nil { for _, item_2_item_4_x_Processing_Additive := range item_4_x_Processing.Additive { - if item_2_item_4_x_Processing_Additive != nil { + if item_2_item_4_x_Processing_Additive != nil { if item_2_item_4_x_Processing_Additive.Reference != nil { refVal := *item_2_item_4_x_Processing_Additive.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -57012,7 +57012,7 @@ func (x *SpecimenProcessing) ExtractEdges(project string) ([]json.RawMessage, er _ = seen if x.Additive != nil { for _, item_2_x_Additive := range x.Additive { - if item_2_x_Additive != nil { + if item_2_x_Additive != nil { if item_2_x_Additive.Reference != nil { refVal := *item_2_x_Additive.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -58087,7 +58087,7 @@ func (x *Substance) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Ingredient != nil { for _, item_3_x_Ingredient := range x.Ingredient { - if item_3_x_Ingredient != nil { + if item_3_x_Ingredient != nil { if item_3_x_Ingredient.SubstanceReference != nil { if item_3_x_Ingredient.SubstanceReference.Reference != nil { refVal := *item_3_x_Ingredient.SubstanceReference.Reference @@ -58152,7 +58152,7 @@ func (x *SubstanceDefinition) ExtractEdges(project string) ([]json.RawMessage, e _ = seen if x.Manufacturer != nil { for _, item_2_x_Manufacturer := range x.Manufacturer { - if item_2_x_Manufacturer != nil { + if item_2_x_Manufacturer != nil { if item_2_x_Manufacturer.Reference != nil { refVal := *item_2_x_Manufacturer.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -58198,7 +58198,7 @@ func (x *SubstanceDefinition) ExtractEdges(project string) ([]json.RawMessage, e } if x.Supplier != nil { for _, item_2_x_Supplier := range x.Supplier { - if item_2_x_Supplier != nil { + if item_2_x_Supplier != nil { if item_2_x_Supplier.Reference != nil { refVal := *item_2_x_Supplier.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -58244,10 +58244,10 @@ func (x *SubstanceDefinition) ExtractEdges(project string) ([]json.RawMessage, e } if x.Code != nil { for _, item_4_x_Code := range x.Code { - if item_4_x_Code != nil { + if item_4_x_Code != nil { if item_4_x_Code.Source != nil { for _, item_2_item_4_x_Code_Source := range item_4_x_Code.Source { - if item_2_item_4_x_Code_Source != nil { + if item_2_item_4_x_Code_Source != nil { if item_2_item_4_x_Code_Source.Reference != nil { refVal := *item_2_item_4_x_Code_Source.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -58296,10 +58296,10 @@ func (x *SubstanceDefinition) ExtractEdges(project string) ([]json.RawMessage, e } if x.Name != nil { for _, item_4_x_Name := range x.Name { - if item_4_x_Name != nil { + if item_4_x_Name != nil { if item_4_x_Name.Source != nil { for _, item_2_item_4_x_Name_Source := range item_4_x_Name.Source { - if item_2_item_4_x_Name_Source != nil { + if item_2_item_4_x_Name_Source != nil { if item_2_item_4_x_Name_Source.Reference != nil { refVal := *item_2_item_4_x_Name_Source.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -58348,7 +58348,7 @@ func (x *SubstanceDefinition) ExtractEdges(project string) ([]json.RawMessage, e } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -58396,7 +58396,7 @@ func (x *SubstanceDefinition) ExtractEdges(project string) ([]json.RawMessage, e } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -58444,7 +58444,7 @@ func (x *SubstanceDefinition) ExtractEdges(project string) ([]json.RawMessage, e } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -58492,7 +58492,7 @@ func (x *SubstanceDefinition) ExtractEdges(project string) ([]json.RawMessage, e } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -58540,10 +58540,10 @@ func (x *SubstanceDefinition) ExtractEdges(project string) ([]json.RawMessage, e } if x.Relationship != nil { for _, item_4_x_Relationship := range x.Relationship { - if item_4_x_Relationship != nil { + if item_4_x_Relationship != nil { if item_4_x_Relationship.Source != nil { for _, item_2_item_4_x_Relationship_Source := range item_4_x_Relationship.Source { - if item_2_item_4_x_Relationship_Source != nil { + if item_2_item_4_x_Relationship_Source != nil { if item_2_item_4_x_Relationship_Source.Reference != nil { refVal := *item_2_item_4_x_Relationship_Source.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -58592,7 +58592,7 @@ func (x *SubstanceDefinition) ExtractEdges(project string) ([]json.RawMessage, e } if x.Relationship != nil { for _, item_3_x_Relationship := range x.Relationship { - if item_3_x_Relationship != nil { + if item_3_x_Relationship != nil { if item_3_x_Relationship.SubstanceDefinitionReference != nil { if item_3_x_Relationship.SubstanceDefinitionReference.Reference != nil { refVal := *item_3_x_Relationship.SubstanceDefinitionReference.Reference @@ -58641,7 +58641,7 @@ func (x *SubstanceDefinition) ExtractEdges(project string) ([]json.RawMessage, e if x.Structure != nil { if x.Structure.SourceDocument != nil { for _, item_2_x_Structure_SourceDocument := range x.Structure.SourceDocument { - if item_2_x_Structure_SourceDocument != nil { + if item_2_x_Structure_SourceDocument != nil { if item_2_x_Structure_SourceDocument.Reference != nil { refVal := *item_2_x_Structure_SourceDocument.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -58722,7 +58722,7 @@ func (x *SubstanceDefinitionCode) ExtractEdges(project string) ([]json.RawMessag _ = seen if x.Source != nil { for _, item_2_x_Source := range x.Source { - if item_2_x_Source != nil { + if item_2_x_Source != nil { if item_2_x_Source.Reference != nil { refVal := *item_2_x_Source.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -58768,7 +58768,7 @@ func (x *SubstanceDefinitionCode) ExtractEdges(project string) ([]json.RawMessag } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -58816,7 +58816,7 @@ func (x *SubstanceDefinitionCode) ExtractEdges(project string) ([]json.RawMessag } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -58864,7 +58864,7 @@ func (x *SubstanceDefinitionCode) ExtractEdges(project string) ([]json.RawMessag } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -58912,7 +58912,7 @@ func (x *SubstanceDefinitionCode) ExtractEdges(project string) ([]json.RawMessag } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -59011,7 +59011,7 @@ func (x *SubstanceDefinitionName) ExtractEdges(project string) ([]json.RawMessag _ = seen if x.Source != nil { for _, item_2_x_Source := range x.Source { - if item_2_x_Source != nil { + if item_2_x_Source != nil { if item_2_x_Source.Reference != nil { refVal := *item_2_x_Source.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -59057,10 +59057,10 @@ func (x *SubstanceDefinitionName) ExtractEdges(project string) ([]json.RawMessag } if x.Synonym != nil { for _, item_4_x_Synonym := range x.Synonym { - if item_4_x_Synonym != nil { + if item_4_x_Synonym != nil { if item_4_x_Synonym.Source != nil { for _, item_2_item_4_x_Synonym_Source := range item_4_x_Synonym.Source { - if item_2_item_4_x_Synonym_Source != nil { + if item_2_item_4_x_Synonym_Source != nil { if item_2_item_4_x_Synonym_Source.Reference != nil { refVal := *item_2_item_4_x_Synonym_Source.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -59109,10 +59109,10 @@ func (x *SubstanceDefinitionName) ExtractEdges(project string) ([]json.RawMessag } if x.Translation != nil { for _, item_4_x_Translation := range x.Translation { - if item_4_x_Translation != nil { + if item_4_x_Translation != nil { if item_4_x_Translation.Source != nil { for _, item_2_item_4_x_Translation_Source := range item_4_x_Translation.Source { - if item_2_item_4_x_Translation_Source != nil { + if item_2_item_4_x_Translation_Source != nil { if item_2_item_4_x_Translation_Source.Reference != nil { refVal := *item_2_item_4_x_Translation_Source.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -59212,7 +59212,7 @@ func (x *SubstanceDefinitionRelationship) ExtractEdges(project string) ([]json.R _ = seen if x.Source != nil { for _, item_2_x_Source := range x.Source { - if item_2_x_Source != nil { + if item_2_x_Source != nil { if item_2_x_Source.Reference != nil { refVal := *item_2_x_Source.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -59334,7 +59334,7 @@ func (x *SubstanceDefinitionStructure) ExtractEdges(project string) ([]json.RawM _ = seen if x.SourceDocument != nil { for _, item_2_x_SourceDocument := range x.SourceDocument { - if item_2_x_SourceDocument != nil { + if item_2_x_SourceDocument != nil { if item_2_x_SourceDocument.Reference != nil { refVal := *item_2_x_SourceDocument.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -59380,7 +59380,7 @@ func (x *SubstanceDefinitionStructure) ExtractEdges(project string) ([]json.RawM } if x.Representation != nil { for _, item_3_x_Representation := range x.Representation { - if item_3_x_Representation != nil { + if item_3_x_Representation != nil { if item_3_x_Representation.Document != nil { if item_3_x_Representation.Document.Reference != nil { refVal := *item_3_x_Representation.Document.Reference @@ -59563,7 +59563,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { _ = seen if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -59609,7 +59609,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -59655,7 +59655,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -59701,7 +59701,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -59747,7 +59747,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -59793,7 +59793,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -59839,7 +59839,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -59885,7 +59885,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -59931,7 +59931,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -59977,7 +59977,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -60023,7 +60023,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -60069,7 +60069,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -60115,7 +60115,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -60161,7 +60161,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -60207,7 +60207,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -60253,7 +60253,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -60299,7 +60299,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -60345,7 +60345,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -60391,7 +60391,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -60437,7 +60437,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -60483,7 +60483,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -60529,7 +60529,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -60575,7 +60575,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.BasedOn != nil { for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { + if item_2_x_BasedOn != nil { if item_2_x_BasedOn.Reference != nil { refVal := *item_2_x_BasedOn.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -62721,7 +62721,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.PartOf != nil { for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { + if item_2_x_PartOf != nil { if item_2_x_PartOf.Reference != nil { refVal := *item_2_x_PartOf.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -62935,7 +62935,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Input != nil { for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { + if item_3_x_Input != nil { if item_3_x_Input.ValueReference != nil { if item_3_x_Input.ValueReference.Reference != nil { refVal := *item_3_x_Input.ValueReference.Reference @@ -62983,7 +62983,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Input != nil { for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { + if item_3_x_Input != nil { if item_3_x_Input.ValueReference != nil { if item_3_x_Input.ValueReference.Reference != nil { refVal := *item_3_x_Input.ValueReference.Reference @@ -63031,7 +63031,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Input != nil { for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { + if item_3_x_Input != nil { if item_3_x_Input.ValueReference != nil { if item_3_x_Input.ValueReference.Reference != nil { refVal := *item_3_x_Input.ValueReference.Reference @@ -63079,7 +63079,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Input != nil { for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { + if item_3_x_Input != nil { if item_3_x_Input.ValueReference != nil { if item_3_x_Input.ValueReference.Reference != nil { refVal := *item_3_x_Input.ValueReference.Reference @@ -63127,7 +63127,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Input != nil { for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { + if item_3_x_Input != nil { if item_3_x_Input.ValueReference != nil { if item_3_x_Input.ValueReference.Reference != nil { refVal := *item_3_x_Input.ValueReference.Reference @@ -63175,7 +63175,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Input != nil { for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { + if item_3_x_Input != nil { if item_3_x_Input.ValueReference != nil { if item_3_x_Input.ValueReference.Reference != nil { refVal := *item_3_x_Input.ValueReference.Reference @@ -63223,7 +63223,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Input != nil { for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { + if item_3_x_Input != nil { if item_3_x_Input.ValueReference != nil { if item_3_x_Input.ValueReference.Reference != nil { refVal := *item_3_x_Input.ValueReference.Reference @@ -63271,7 +63271,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Input != nil { for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { + if item_3_x_Input != nil { if item_3_x_Input.ValueReference != nil { if item_3_x_Input.ValueReference.Reference != nil { refVal := *item_3_x_Input.ValueReference.Reference @@ -63319,7 +63319,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Input != nil { for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { + if item_3_x_Input != nil { if item_3_x_Input.ValueReference != nil { if item_3_x_Input.ValueReference.Reference != nil { refVal := *item_3_x_Input.ValueReference.Reference @@ -63367,7 +63367,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Input != nil { for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { + if item_3_x_Input != nil { if item_3_x_Input.ValueReference != nil { if item_3_x_Input.ValueReference.Reference != nil { refVal := *item_3_x_Input.ValueReference.Reference @@ -63415,7 +63415,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Input != nil { for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { + if item_3_x_Input != nil { if item_3_x_Input.ValueReference != nil { if item_3_x_Input.ValueReference.Reference != nil { refVal := *item_3_x_Input.ValueReference.Reference @@ -63463,7 +63463,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Input != nil { for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { + if item_3_x_Input != nil { if item_3_x_Input.ValueReference != nil { if item_3_x_Input.ValueReference.Reference != nil { refVal := *item_3_x_Input.ValueReference.Reference @@ -63511,7 +63511,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Input != nil { for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { + if item_3_x_Input != nil { if item_3_x_Input.ValueReference != nil { if item_3_x_Input.ValueReference.Reference != nil { refVal := *item_3_x_Input.ValueReference.Reference @@ -63559,7 +63559,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Input != nil { for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { + if item_3_x_Input != nil { if item_3_x_Input.ValueReference != nil { if item_3_x_Input.ValueReference.Reference != nil { refVal := *item_3_x_Input.ValueReference.Reference @@ -63607,7 +63607,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Input != nil { for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { + if item_3_x_Input != nil { if item_3_x_Input.ValueReference != nil { if item_3_x_Input.ValueReference.Reference != nil { refVal := *item_3_x_Input.ValueReference.Reference @@ -63655,7 +63655,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Input != nil { for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { + if item_3_x_Input != nil { if item_3_x_Input.ValueReference != nil { if item_3_x_Input.ValueReference.Reference != nil { refVal := *item_3_x_Input.ValueReference.Reference @@ -63703,7 +63703,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Input != nil { for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { + if item_3_x_Input != nil { if item_3_x_Input.ValueReference != nil { if item_3_x_Input.ValueReference.Reference != nil { refVal := *item_3_x_Input.ValueReference.Reference @@ -63751,7 +63751,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Input != nil { for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { + if item_3_x_Input != nil { if item_3_x_Input.ValueReference != nil { if item_3_x_Input.ValueReference.Reference != nil { refVal := *item_3_x_Input.ValueReference.Reference @@ -63799,7 +63799,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Input != nil { for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { + if item_3_x_Input != nil { if item_3_x_Input.ValueReference != nil { if item_3_x_Input.ValueReference.Reference != nil { refVal := *item_3_x_Input.ValueReference.Reference @@ -63847,7 +63847,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Input != nil { for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { + if item_3_x_Input != nil { if item_3_x_Input.ValueReference != nil { if item_3_x_Input.ValueReference.Reference != nil { refVal := *item_3_x_Input.ValueReference.Reference @@ -63895,7 +63895,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Input != nil { for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { + if item_3_x_Input != nil { if item_3_x_Input.ValueReference != nil { if item_3_x_Input.ValueReference.Reference != nil { refVal := *item_3_x_Input.ValueReference.Reference @@ -63943,7 +63943,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Input != nil { for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { + if item_3_x_Input != nil { if item_3_x_Input.ValueReference != nil { if item_3_x_Input.ValueReference.Reference != nil { refVal := *item_3_x_Input.ValueReference.Reference @@ -63991,7 +63991,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Input != nil { for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { + if item_3_x_Input != nil { if item_3_x_Input.ValueReference != nil { if item_3_x_Input.ValueReference.Reference != nil { refVal := *item_3_x_Input.ValueReference.Reference @@ -64039,7 +64039,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -64087,7 +64087,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -64135,7 +64135,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -64183,7 +64183,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Note != nil { for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { + if item_3_x_Note != nil { if item_3_x_Note.AuthorReference != nil { if item_3_x_Note.AuthorReference.Reference != nil { refVal := *item_3_x_Note.AuthorReference.Reference @@ -64231,7 +64231,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Output != nil { for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { + if item_3_x_Output != nil { if item_3_x_Output.ValueReference != nil { if item_3_x_Output.ValueReference.Reference != nil { refVal := *item_3_x_Output.ValueReference.Reference @@ -64279,7 +64279,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Output != nil { for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { + if item_3_x_Output != nil { if item_3_x_Output.ValueReference != nil { if item_3_x_Output.ValueReference.Reference != nil { refVal := *item_3_x_Output.ValueReference.Reference @@ -64327,7 +64327,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Output != nil { for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { + if item_3_x_Output != nil { if item_3_x_Output.ValueReference != nil { if item_3_x_Output.ValueReference.Reference != nil { refVal := *item_3_x_Output.ValueReference.Reference @@ -64375,7 +64375,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Output != nil { for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { + if item_3_x_Output != nil { if item_3_x_Output.ValueReference != nil { if item_3_x_Output.ValueReference.Reference != nil { refVal := *item_3_x_Output.ValueReference.Reference @@ -64423,7 +64423,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Output != nil { for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { + if item_3_x_Output != nil { if item_3_x_Output.ValueReference != nil { if item_3_x_Output.ValueReference.Reference != nil { refVal := *item_3_x_Output.ValueReference.Reference @@ -64471,7 +64471,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Output != nil { for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { + if item_3_x_Output != nil { if item_3_x_Output.ValueReference != nil { if item_3_x_Output.ValueReference.Reference != nil { refVal := *item_3_x_Output.ValueReference.Reference @@ -64519,7 +64519,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Output != nil { for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { + if item_3_x_Output != nil { if item_3_x_Output.ValueReference != nil { if item_3_x_Output.ValueReference.Reference != nil { refVal := *item_3_x_Output.ValueReference.Reference @@ -64567,7 +64567,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Output != nil { for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { + if item_3_x_Output != nil { if item_3_x_Output.ValueReference != nil { if item_3_x_Output.ValueReference.Reference != nil { refVal := *item_3_x_Output.ValueReference.Reference @@ -64615,7 +64615,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Output != nil { for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { + if item_3_x_Output != nil { if item_3_x_Output.ValueReference != nil { if item_3_x_Output.ValueReference.Reference != nil { refVal := *item_3_x_Output.ValueReference.Reference @@ -64663,7 +64663,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Output != nil { for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { + if item_3_x_Output != nil { if item_3_x_Output.ValueReference != nil { if item_3_x_Output.ValueReference.Reference != nil { refVal := *item_3_x_Output.ValueReference.Reference @@ -64711,7 +64711,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Output != nil { for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { + if item_3_x_Output != nil { if item_3_x_Output.ValueReference != nil { if item_3_x_Output.ValueReference.Reference != nil { refVal := *item_3_x_Output.ValueReference.Reference @@ -64759,7 +64759,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Output != nil { for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { + if item_3_x_Output != nil { if item_3_x_Output.ValueReference != nil { if item_3_x_Output.ValueReference.Reference != nil { refVal := *item_3_x_Output.ValueReference.Reference @@ -64807,7 +64807,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Output != nil { for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { + if item_3_x_Output != nil { if item_3_x_Output.ValueReference != nil { if item_3_x_Output.ValueReference.Reference != nil { refVal := *item_3_x_Output.ValueReference.Reference @@ -64855,7 +64855,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Output != nil { for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { + if item_3_x_Output != nil { if item_3_x_Output.ValueReference != nil { if item_3_x_Output.ValueReference.Reference != nil { refVal := *item_3_x_Output.ValueReference.Reference @@ -64903,7 +64903,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Output != nil { for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { + if item_3_x_Output != nil { if item_3_x_Output.ValueReference != nil { if item_3_x_Output.ValueReference.Reference != nil { refVal := *item_3_x_Output.ValueReference.Reference @@ -64951,7 +64951,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Output != nil { for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { + if item_3_x_Output != nil { if item_3_x_Output.ValueReference != nil { if item_3_x_Output.ValueReference.Reference != nil { refVal := *item_3_x_Output.ValueReference.Reference @@ -64999,7 +64999,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Output != nil { for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { + if item_3_x_Output != nil { if item_3_x_Output.ValueReference != nil { if item_3_x_Output.ValueReference.Reference != nil { refVal := *item_3_x_Output.ValueReference.Reference @@ -65047,7 +65047,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Output != nil { for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { + if item_3_x_Output != nil { if item_3_x_Output.ValueReference != nil { if item_3_x_Output.ValueReference.Reference != nil { refVal := *item_3_x_Output.ValueReference.Reference @@ -65095,7 +65095,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Output != nil { for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { + if item_3_x_Output != nil { if item_3_x_Output.ValueReference != nil { if item_3_x_Output.ValueReference.Reference != nil { refVal := *item_3_x_Output.ValueReference.Reference @@ -65143,7 +65143,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Output != nil { for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { + if item_3_x_Output != nil { if item_3_x_Output.ValueReference != nil { if item_3_x_Output.ValueReference.Reference != nil { refVal := *item_3_x_Output.ValueReference.Reference @@ -65191,7 +65191,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Output != nil { for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { + if item_3_x_Output != nil { if item_3_x_Output.ValueReference != nil { if item_3_x_Output.ValueReference.Reference != nil { refVal := *item_3_x_Output.ValueReference.Reference @@ -65239,7 +65239,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Output != nil { for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { + if item_3_x_Output != nil { if item_3_x_Output.ValueReference != nil { if item_3_x_Output.ValueReference.Reference != nil { refVal := *item_3_x_Output.ValueReference.Reference @@ -65287,7 +65287,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Output != nil { for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { + if item_3_x_Output != nil { if item_3_x_Output.ValueReference != nil { if item_3_x_Output.ValueReference.Reference != nil { refVal := *item_3_x_Output.ValueReference.Reference @@ -65335,7 +65335,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Performer != nil { for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { + if item_3_x_Performer != nil { if item_3_x_Performer.Actor != nil { if item_3_x_Performer.Actor.Reference != nil { refVal := *item_3_x_Performer.Actor.Reference @@ -65383,7 +65383,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Performer != nil { for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { + if item_3_x_Performer != nil { if item_3_x_Performer.Actor != nil { if item_3_x_Performer.Actor.Reference != nil { refVal := *item_3_x_Performer.Actor.Reference @@ -65431,7 +65431,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Performer != nil { for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { + if item_3_x_Performer != nil { if item_3_x_Performer.Actor != nil { if item_3_x_Performer.Actor.Reference != nil { refVal := *item_3_x_Performer.Actor.Reference @@ -65479,7 +65479,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Performer != nil { for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { + if item_3_x_Performer != nil { if item_3_x_Performer.Actor != nil { if item_3_x_Performer.Actor.Reference != nil { refVal := *item_3_x_Performer.Actor.Reference @@ -65527,7 +65527,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -65575,7 +65575,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -65623,7 +65623,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -65671,7 +65671,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -65719,7 +65719,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -65767,7 +65767,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -65815,7 +65815,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -65863,7 +65863,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -65911,7 +65911,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -65959,7 +65959,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -66007,7 +66007,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -66055,7 +66055,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -66103,7 +66103,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -66151,7 +66151,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -66199,7 +66199,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -66247,7 +66247,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -66295,7 +66295,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -66343,7 +66343,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -66391,7 +66391,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -66439,7 +66439,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -66487,7 +66487,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -66535,7 +66535,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -66583,7 +66583,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.Reason != nil { for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { + if item_3_x_Reason != nil { if item_3_x_Reason.Reference != nil { if item_3_x_Reason.Reference.Reference != nil { refVal := *item_3_x_Reason.Reference.Reference @@ -66631,7 +66631,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.RequestedPerformer != nil { for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer != nil { if item_3_x_RequestedPerformer.Reference != nil { if item_3_x_RequestedPerformer.Reference.Reference != nil { refVal := *item_3_x_RequestedPerformer.Reference.Reference @@ -66679,7 +66679,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.RequestedPerformer != nil { for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer != nil { if item_3_x_RequestedPerformer.Reference != nil { if item_3_x_RequestedPerformer.Reference.Reference != nil { refVal := *item_3_x_RequestedPerformer.Reference.Reference @@ -66727,7 +66727,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.RequestedPerformer != nil { for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer != nil { if item_3_x_RequestedPerformer.Reference != nil { if item_3_x_RequestedPerformer.Reference.Reference != nil { refVal := *item_3_x_RequestedPerformer.Reference.Reference @@ -66775,7 +66775,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.RequestedPerformer != nil { for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer != nil { if item_3_x_RequestedPerformer.Reference != nil { if item_3_x_RequestedPerformer.Reference.Reference != nil { refVal := *item_3_x_RequestedPerformer.Reference.Reference @@ -66823,7 +66823,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.RequestedPerformer != nil { for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer != nil { if item_3_x_RequestedPerformer.Reference != nil { if item_3_x_RequestedPerformer.Reference.Reference != nil { refVal := *item_3_x_RequestedPerformer.Reference.Reference @@ -66871,7 +66871,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.RequestedPerformer != nil { for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer != nil { if item_3_x_RequestedPerformer.Reference != nil { if item_3_x_RequestedPerformer.Reference.Reference != nil { refVal := *item_3_x_RequestedPerformer.Reference.Reference @@ -66919,7 +66919,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.RequestedPerformer != nil { for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer != nil { if item_3_x_RequestedPerformer.Reference != nil { if item_3_x_RequestedPerformer.Reference.Reference != nil { refVal := *item_3_x_RequestedPerformer.Reference.Reference @@ -66967,7 +66967,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.RequestedPerformer != nil { for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer != nil { if item_3_x_RequestedPerformer.Reference != nil { if item_3_x_RequestedPerformer.Reference.Reference != nil { refVal := *item_3_x_RequestedPerformer.Reference.Reference @@ -67015,7 +67015,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.RequestedPerformer != nil { for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer != nil { if item_3_x_RequestedPerformer.Reference != nil { if item_3_x_RequestedPerformer.Reference.Reference != nil { refVal := *item_3_x_RequestedPerformer.Reference.Reference @@ -67063,7 +67063,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.RequestedPerformer != nil { for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer != nil { if item_3_x_RequestedPerformer.Reference != nil { if item_3_x_RequestedPerformer.Reference.Reference != nil { refVal := *item_3_x_RequestedPerformer.Reference.Reference @@ -67111,7 +67111,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.RequestedPerformer != nil { for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer != nil { if item_3_x_RequestedPerformer.Reference != nil { if item_3_x_RequestedPerformer.Reference.Reference != nil { refVal := *item_3_x_RequestedPerformer.Reference.Reference @@ -67159,7 +67159,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.RequestedPerformer != nil { for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer != nil { if item_3_x_RequestedPerformer.Reference != nil { if item_3_x_RequestedPerformer.Reference.Reference != nil { refVal := *item_3_x_RequestedPerformer.Reference.Reference @@ -67207,7 +67207,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.RequestedPerformer != nil { for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer != nil { if item_3_x_RequestedPerformer.Reference != nil { if item_3_x_RequestedPerformer.Reference.Reference != nil { refVal := *item_3_x_RequestedPerformer.Reference.Reference @@ -67255,7 +67255,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.RequestedPerformer != nil { for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer != nil { if item_3_x_RequestedPerformer.Reference != nil { if item_3_x_RequestedPerformer.Reference.Reference != nil { refVal := *item_3_x_RequestedPerformer.Reference.Reference @@ -67303,7 +67303,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.RequestedPerformer != nil { for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer != nil { if item_3_x_RequestedPerformer.Reference != nil { if item_3_x_RequestedPerformer.Reference.Reference != nil { refVal := *item_3_x_RequestedPerformer.Reference.Reference @@ -67351,7 +67351,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.RequestedPerformer != nil { for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer != nil { if item_3_x_RequestedPerformer.Reference != nil { if item_3_x_RequestedPerformer.Reference.Reference != nil { refVal := *item_3_x_RequestedPerformer.Reference.Reference @@ -67399,7 +67399,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.RequestedPerformer != nil { for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer != nil { if item_3_x_RequestedPerformer.Reference != nil { if item_3_x_RequestedPerformer.Reference.Reference != nil { refVal := *item_3_x_RequestedPerformer.Reference.Reference @@ -67447,7 +67447,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.RequestedPerformer != nil { for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer != nil { if item_3_x_RequestedPerformer.Reference != nil { if item_3_x_RequestedPerformer.Reference.Reference != nil { refVal := *item_3_x_RequestedPerformer.Reference.Reference @@ -67495,7 +67495,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.RequestedPerformer != nil { for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer != nil { if item_3_x_RequestedPerformer.Reference != nil { if item_3_x_RequestedPerformer.Reference.Reference != nil { refVal := *item_3_x_RequestedPerformer.Reference.Reference @@ -67543,7 +67543,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.RequestedPerformer != nil { for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer != nil { if item_3_x_RequestedPerformer.Reference != nil { if item_3_x_RequestedPerformer.Reference.Reference != nil { refVal := *item_3_x_RequestedPerformer.Reference.Reference @@ -67591,7 +67591,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.RequestedPerformer != nil { for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer != nil { if item_3_x_RequestedPerformer.Reference != nil { if item_3_x_RequestedPerformer.Reference.Reference != nil { refVal := *item_3_x_RequestedPerformer.Reference.Reference @@ -67639,7 +67639,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.RequestedPerformer != nil { for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer != nil { if item_3_x_RequestedPerformer.Reference != nil { if item_3_x_RequestedPerformer.Reference.Reference != nil { refVal := *item_3_x_RequestedPerformer.Reference.Reference @@ -67687,7 +67687,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { } if x.RequestedPerformer != nil { for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer != nil { if item_3_x_RequestedPerformer.Reference != nil { if item_3_x_RequestedPerformer.Reference.Reference != nil { refVal := *item_3_x_RequestedPerformer.Reference.Reference @@ -67736,7 +67736,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { if x.Restriction != nil { if x.Restriction.Recipient != nil { for _, item_2_x_Restriction_Recipient := range x.Restriction.Recipient { - if item_2_x_Restriction_Recipient != nil { + if item_2_x_Restriction_Recipient != nil { if item_2_x_Restriction_Recipient.Reference != nil { refVal := *item_2_x_Restriction_Recipient.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -67784,7 +67784,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { if x.Restriction != nil { if x.Restriction.Recipient != nil { for _, item_2_x_Restriction_Recipient := range x.Restriction.Recipient { - if item_2_x_Restriction_Recipient != nil { + if item_2_x_Restriction_Recipient != nil { if item_2_x_Restriction_Recipient.Reference != nil { refVal := *item_2_x_Restriction_Recipient.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -67832,7 +67832,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { if x.Restriction != nil { if x.Restriction.Recipient != nil { for _, item_2_x_Restriction_Recipient := range x.Restriction.Recipient { - if item_2_x_Restriction_Recipient != nil { + if item_2_x_Restriction_Recipient != nil { if item_2_x_Restriction_Recipient.Reference != nil { refVal := *item_2_x_Restriction_Recipient.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -67880,7 +67880,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { if x.Restriction != nil { if x.Restriction.Recipient != nil { for _, item_2_x_Restriction_Recipient := range x.Restriction.Recipient { - if item_2_x_Restriction_Recipient != nil { + if item_2_x_Restriction_Recipient != nil { if item_2_x_Restriction_Recipient.Reference != nil { refVal := *item_2_x_Restriction_Recipient.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -67928,7 +67928,7 @@ func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { if x.Restriction != nil { if x.Restriction.Recipient != nil { for _, item_2_x_Restriction_Recipient := range x.Restriction.Recipient { - if item_2_x_Restriction_Recipient != nil { + if item_2_x_Restriction_Recipient != nil { if item_2_x_Restriction_Recipient.Reference != nil { refVal := *item_2_x_Restriction_Recipient.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -76699,7 +76699,7 @@ func (x *TaskRestriction) ExtractEdges(project string) ([]json.RawMessage, error _ = seen if x.Recipient != nil { for _, item_2_x_Recipient := range x.Recipient { - if item_2_x_Recipient != nil { + if item_2_x_Recipient != nil { if item_2_x_Recipient.Reference != nil { refVal := *item_2_x_Recipient.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -76745,7 +76745,7 @@ func (x *TaskRestriction) ExtractEdges(project string) ([]json.RawMessage, error } if x.Recipient != nil { for _, item_2_x_Recipient := range x.Recipient { - if item_2_x_Recipient != nil { + if item_2_x_Recipient != nil { if item_2_x_Recipient.Reference != nil { refVal := *item_2_x_Recipient.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -76791,7 +76791,7 @@ func (x *TaskRestriction) ExtractEdges(project string) ([]json.RawMessage, error } if x.Recipient != nil { for _, item_2_x_Recipient := range x.Recipient { - if item_2_x_Recipient != nil { + if item_2_x_Recipient != nil { if item_2_x_Recipient.Reference != nil { refVal := *item_2_x_Recipient.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -76837,7 +76837,7 @@ func (x *TaskRestriction) ExtractEdges(project string) ([]json.RawMessage, error } if x.Recipient != nil { for _, item_2_x_Recipient := range x.Recipient { - if item_2_x_Recipient != nil { + if item_2_x_Recipient != nil { if item_2_x_Recipient.Reference != nil { refVal := *item_2_x_Recipient.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -76883,7 +76883,7 @@ func (x *TaskRestriction) ExtractEdges(project string) ([]json.RawMessage, error } if x.Recipient != nil { for _, item_2_x_Recipient := range x.Recipient { - if item_2_x_Recipient != nil { + if item_2_x_Recipient != nil { if item_2_x_Recipient.Reference != nil { refVal := *item_2_x_Recipient.Reference refType, targetID, ok := splitFHIRReference(refVal) @@ -76980,7 +76980,7 @@ func (x *TriggerDefinition) ExtractEdges(project string) ([]json.RawMessage, err _ = seen if x.Data != nil { for _, item_3_x_Data := range x.Data { - if item_3_x_Data != nil { + if item_3_x_Data != nil { if item_3_x_Data.SubjectReference != nil { if item_3_x_Data.SubjectReference.Reference != nil { refVal := *item_3_x_Data.SubjectReference.Reference diff --git a/internal/fhir/model.go b/internal/fhir/model.go index 82c7fab..b8164ba 100644 --- a/internal/fhir/model.go +++ b/internal/fhir/model.go @@ -3,3043 +3,3042 @@ package fhir // Address type Address struct { - XCity *FHIRPrimitiveExtension `json:"_city,omitempty"` - XCountry *FHIRPrimitiveExtension `json:"_country,omitempty"` - XDistrict *FHIRPrimitiveExtension `json:"_district,omitempty"` - XLine []*FHIRPrimitiveExtension `json:"_line,omitempty"` - XPostalCode *FHIRPrimitiveExtension `json:"_postalCode,omitempty"` - XState *FHIRPrimitiveExtension `json:"_state,omitempty"` - XText *FHIRPrimitiveExtension `json:"_text,omitempty"` - XType *FHIRPrimitiveExtension `json:"_type,omitempty"` - XUse *FHIRPrimitiveExtension `json:"_use,omitempty"` - City *string `json:"city,omitempty"` - Country *string `json:"country,omitempty"` - District *string `json:"district,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Line []string `json:"line,omitempty"` - Links [][]any `json:"links,omitempty"` - Period *Period `json:"period,omitempty"` - PostalCode *string `json:"postalCode,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - State *string `json:"state,omitempty"` - Text *string `json:"text,omitempty"` - Type *string `json:"type,omitempty"` - Use *string `json:"use,omitempty"` + XCity *FHIRPrimitiveExtension `json:"_city,omitempty"` + XCountry *FHIRPrimitiveExtension `json:"_country,omitempty"` + XDistrict *FHIRPrimitiveExtension `json:"_district,omitempty"` + XLine []*FHIRPrimitiveExtension `json:"_line,omitempty"` + XPostalCode *FHIRPrimitiveExtension `json:"_postalCode,omitempty"` + XState *FHIRPrimitiveExtension `json:"_state,omitempty"` + XText *FHIRPrimitiveExtension `json:"_text,omitempty"` + XType *FHIRPrimitiveExtension `json:"_type,omitempty"` + XUse *FHIRPrimitiveExtension `json:"_use,omitempty"` + City *string `json:"city,omitempty"` + Country *string `json:"country,omitempty"` + District *string `json:"district,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Line []string `json:"line,omitempty"` + Links [][]any `json:"links,omitempty"` + Period *Period `json:"period,omitempty"` + PostalCode *string `json:"postalCode,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + State *string `json:"state,omitempty"` + Text *string `json:"text,omitempty"` + Type *string `json:"type,omitempty"` + Use *string `json:"use,omitempty"` } // Age type Age struct { - XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` - XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` - XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` - XUnit *FHIRPrimitiveExtension `json:"_unit,omitempty"` - XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` - Code *string `json:"code,omitempty"` - Comparator *string `json:"comparator,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - System *string `json:"system,omitempty"` - Unit *string `json:"unit,omitempty"` - Value *float64 `json:"value,omitempty"` + XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` + XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` + XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` + XUnit *FHIRPrimitiveExtension `json:"_unit,omitempty"` + XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` + Code *string `json:"code,omitempty"` + Comparator *string `json:"comparator,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + System *string `json:"system,omitempty"` + Unit *string `json:"unit,omitempty"` + Value *float64 `json:"value,omitempty"` } // Annotation type Annotation struct { - XAuthorString *FHIRPrimitiveExtension `json:"_authorString,omitempty"` - XText *FHIRPrimitiveExtension `json:"_text,omitempty"` - XTime *FHIRPrimitiveExtension `json:"_time,omitempty"` - AuthorReference *Reference `json:"authorReference,omitempty"` - AuthorString *string `json:"authorString,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Text *string `json:"text,omitempty"` - Time *string `json:"time,omitempty"` + XAuthorString *FHIRPrimitiveExtension `json:"_authorString,omitempty"` + XText *FHIRPrimitiveExtension `json:"_text,omitempty"` + XTime *FHIRPrimitiveExtension `json:"_time,omitempty"` + AuthorReference *Reference `json:"authorReference,omitempty"` + AuthorString *string `json:"authorString,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Text *string `json:"text,omitempty"` + Time *string `json:"time,omitempty"` } // Attachment type Attachment struct { XContentType *FHIRPrimitiveExtension `json:"_contentType,omitempty"` - XCreation *FHIRPrimitiveExtension `json:"_creation,omitempty"` - XData *FHIRPrimitiveExtension `json:"_data,omitempty"` - XDuration *FHIRPrimitiveExtension `json:"_duration,omitempty"` - XFrames *FHIRPrimitiveExtension `json:"_frames,omitempty"` - XHash *FHIRPrimitiveExtension `json:"_hash,omitempty"` - XHeight *FHIRPrimitiveExtension `json:"_height,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XPages *FHIRPrimitiveExtension `json:"_pages,omitempty"` - XSize *FHIRPrimitiveExtension `json:"_size,omitempty"` - XTitle *FHIRPrimitiveExtension `json:"_title,omitempty"` - XURL *FHIRPrimitiveExtension `json:"_url,omitempty"` - XWidth *FHIRPrimitiveExtension `json:"_width,omitempty"` - ContentType *string `json:"contentType,omitempty"` - Creation *string `json:"creation,omitempty"` - Data *string `json:"data,omitempty"` - Duration *float64 `json:"duration,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Frames *int64 `json:"frames,omitempty"` - Hash *string `json:"hash,omitempty"` - Height *int64 `json:"height,omitempty"` - ID *string `json:"id,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Pages *int64 `json:"pages,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Size *int64 `json:"size,omitempty"` - Title *string `json:"title,omitempty"` - URL *string `json:"url,omitempty"` - Width *int64 `json:"width,omitempty"` + XCreation *FHIRPrimitiveExtension `json:"_creation,omitempty"` + XData *FHIRPrimitiveExtension `json:"_data,omitempty"` + XDuration *FHIRPrimitiveExtension `json:"_duration,omitempty"` + XFrames *FHIRPrimitiveExtension `json:"_frames,omitempty"` + XHash *FHIRPrimitiveExtension `json:"_hash,omitempty"` + XHeight *FHIRPrimitiveExtension `json:"_height,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XPages *FHIRPrimitiveExtension `json:"_pages,omitempty"` + XSize *FHIRPrimitiveExtension `json:"_size,omitempty"` + XTitle *FHIRPrimitiveExtension `json:"_title,omitempty"` + XURL *FHIRPrimitiveExtension `json:"_url,omitempty"` + XWidth *FHIRPrimitiveExtension `json:"_width,omitempty"` + ContentType *string `json:"contentType,omitempty"` + Creation *string `json:"creation,omitempty"` + Data *string `json:"data,omitempty"` + Duration *float64 `json:"duration,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Frames *int64 `json:"frames,omitempty"` + Hash *string `json:"hash,omitempty"` + Height *int64 `json:"height,omitempty"` + ID *string `json:"id,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Pages *int64 `json:"pages,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Size *int64 `json:"size,omitempty"` + Title *string `json:"title,omitempty"` + URL *string `json:"url,omitempty"` + Width *int64 `json:"width,omitempty"` } // Availability type Availability struct { - AvailableTime []*AvailabilityAvailableTime `json:"availableTime,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` + AvailableTime []*AvailabilityAvailableTime `json:"availableTime,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` NotAvailableTime []*AvailabilityNotAvailableTime `json:"notAvailableTime,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // AvailabilityAvailableTime type AvailabilityAvailableTime struct { - XAllDay *FHIRPrimitiveExtension `json:"_allDay,omitempty"` - XAvailableEndTime *FHIRPrimitiveExtension `json:"_availableEndTime,omitempty"` - XAvailableStartTime *FHIRPrimitiveExtension `json:"_availableStartTime,omitempty"` - XDaysOfWeek []*FHIRPrimitiveExtension `json:"_daysOfWeek,omitempty"` - AllDay *bool `json:"allDay,omitempty"` - AvailableEndTime *string `json:"availableEndTime,omitempty"` - AvailableStartTime *string `json:"availableStartTime,omitempty"` - DaysOfWeek []string `json:"daysOfWeek,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + XAllDay *FHIRPrimitiveExtension `json:"_allDay,omitempty"` + XAvailableEndTime *FHIRPrimitiveExtension `json:"_availableEndTime,omitempty"` + XAvailableStartTime *FHIRPrimitiveExtension `json:"_availableStartTime,omitempty"` + XDaysOfWeek []*FHIRPrimitiveExtension `json:"_daysOfWeek,omitempty"` + AllDay *bool `json:"allDay,omitempty"` + AvailableEndTime *string `json:"availableEndTime,omitempty"` + AvailableStartTime *string `json:"availableStartTime,omitempty"` + DaysOfWeek []string `json:"daysOfWeek,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // AvailabilityNotAvailableTime type AvailabilityNotAvailableTime struct { XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - Description *string `json:"description,omitempty"` - During *Period `json:"during,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + Description *string `json:"description,omitempty"` + During *Period `json:"during,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // BodyStructure type BodyStructure struct { - XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - Active *bool `json:"active,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Description *string `json:"description,omitempty"` + XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + Active *bool `json:"active,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Description *string `json:"description,omitempty"` ExcludedStructure []*BodyStructureIncludedStructure `json:"excludedStructure,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - Image []*Attachment `json:"image,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + Image []*Attachment `json:"image,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` IncludedStructure []*BodyStructureIncludedStructure `json:"includedStructure"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Morphology *CodeableConcept `json:"morphology,omitempty"` - Patient *Reference `json:"patient"` - ResourceType *string `json:"resourceType,omitempty"` - Text *Narrative `json:"text,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Morphology *CodeableConcept `json:"morphology,omitempty"` + Patient *Reference `json:"patient"` + ResourceType *string `json:"resourceType,omitempty"` + Text *Narrative `json:"text,omitempty"` } // BodyStructureIncludedStructure type BodyStructureIncludedStructure struct { BodyLandmarkOrientation []*BodyStructureIncludedStructureBodyLandmarkOrientation `json:"bodyLandmarkOrientation,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Laterality *CodeableConcept `json:"laterality,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Qualifier []*CodeableConcept `json:"qualifier,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SpatialReference []*Reference `json:"spatialReference,omitempty"` - Structure *CodeableConcept `json:"structure"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Laterality *CodeableConcept `json:"laterality,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Qualifier []*CodeableConcept `json:"qualifier,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SpatialReference []*Reference `json:"spatialReference,omitempty"` + Structure *CodeableConcept `json:"structure"` } // BodyStructureIncludedStructureBodyLandmarkOrientation type BodyStructureIncludedStructureBodyLandmarkOrientation struct { - ClockFacePosition []*CodeableConcept `json:"clockFacePosition,omitempty"` + ClockFacePosition []*CodeableConcept `json:"clockFacePosition,omitempty"` DistanceFromLandmark []*BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark `json:"distanceFromLandmark,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - LandmarkDescription []*CodeableConcept `json:"landmarkDescription,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SurfaceOrientation []*CodeableConcept `json:"surfaceOrientation,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + LandmarkDescription []*CodeableConcept `json:"landmarkDescription,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SurfaceOrientation []*CodeableConcept `json:"surfaceOrientation,omitempty"` } // BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark type BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark struct { - Device []*CodeableReference `json:"device,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Value []*Quantity `json:"value,omitempty"` + Device []*CodeableReference `json:"device,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Value []*Quantity `json:"value,omitempty"` } // CodeableConcept type CodeableConcept struct { - XText *FHIRPrimitiveExtension `json:"_text,omitempty"` - Coding []*Coding `json:"coding,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Text *string `json:"text,omitempty"` + XText *FHIRPrimitiveExtension `json:"_text,omitempty"` + Coding []*Coding `json:"coding,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Text *string `json:"text,omitempty"` } // CodeableReference type CodeableReference struct { - Concept *CodeableConcept `json:"concept,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Reference *Reference `json:"reference,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + Concept *CodeableConcept `json:"concept,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Reference *Reference `json:"reference,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // Coding type Coding struct { - XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` - XDisplay *FHIRPrimitiveExtension `json:"_display,omitempty"` - XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` + XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` + XDisplay *FHIRPrimitiveExtension `json:"_display,omitempty"` + XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` XUserSelected *FHIRPrimitiveExtension `json:"_userSelected,omitempty"` - XVersion *FHIRPrimitiveExtension `json:"_version,omitempty"` - Code *string `json:"code,omitempty"` - Display *string `json:"display,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - System *string `json:"system,omitempty"` - UserSelected *bool `json:"userSelected,omitempty"` - Version *string `json:"version,omitempty"` + XVersion *FHIRPrimitiveExtension `json:"_version,omitempty"` + Code *string `json:"code,omitempty"` + Display *string `json:"display,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + System *string `json:"system,omitempty"` + UserSelected *bool `json:"userSelected,omitempty"` + Version *string `json:"version,omitempty"` } // Condition type Condition struct { XAbatementDateTime *FHIRPrimitiveExtension `json:"_abatementDateTime,omitempty"` - XAbatementString *FHIRPrimitiveExtension `json:"_abatementString,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XOnsetDateTime *FHIRPrimitiveExtension `json:"_onsetDateTime,omitempty"` - XOnsetString *FHIRPrimitiveExtension `json:"_onsetString,omitempty"` - XRecordedDate *FHIRPrimitiveExtension `json:"_recordedDate,omitempty"` - AbatementAge *Age `json:"abatementAge,omitempty"` - AbatementDateTime *string `json:"abatementDateTime,omitempty"` - AbatementPeriod *Period `json:"abatementPeriod,omitempty"` - AbatementRange *Range `json:"abatementRange,omitempty"` - AbatementString *string `json:"abatementString,omitempty"` - BodySite []*CodeableConcept `json:"bodySite,omitempty"` - Category []*CodeableConcept `json:"category,omitempty"` - ClinicalStatus *CodeableConcept `json:"clinicalStatus"` - Code *CodeableConcept `json:"code,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Encounter *Reference `json:"encounter,omitempty"` - Evidence []*CodeableReference `json:"evidence,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - OnsetAge *Age `json:"onsetAge,omitempty"` - OnsetDateTime *string `json:"onsetDateTime,omitempty"` - OnsetPeriod *Period `json:"onsetPeriod,omitempty"` - OnsetRange *Range `json:"onsetRange,omitempty"` - OnsetString *string `json:"onsetString,omitempty"` - Participant []*ConditionParticipant `json:"participant,omitempty"` - RecordedDate *string `json:"recordedDate,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Severity *CodeableConcept `json:"severity,omitempty"` - Stage []*ConditionStage `json:"stage,omitempty"` - Subject *Reference `json:"subject"` - Text *Narrative `json:"text,omitempty"` - VerificationStatus *CodeableConcept `json:"verificationStatus,omitempty"` + XAbatementString *FHIRPrimitiveExtension `json:"_abatementString,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XOnsetDateTime *FHIRPrimitiveExtension `json:"_onsetDateTime,omitempty"` + XOnsetString *FHIRPrimitiveExtension `json:"_onsetString,omitempty"` + XRecordedDate *FHIRPrimitiveExtension `json:"_recordedDate,omitempty"` + AbatementAge *Age `json:"abatementAge,omitempty"` + AbatementDateTime *string `json:"abatementDateTime,omitempty"` + AbatementPeriod *Period `json:"abatementPeriod,omitempty"` + AbatementRange *Range `json:"abatementRange,omitempty"` + AbatementString *string `json:"abatementString,omitempty"` + BodySite []*CodeableConcept `json:"bodySite,omitempty"` + Category []*CodeableConcept `json:"category,omitempty"` + ClinicalStatus *CodeableConcept `json:"clinicalStatus"` + Code *CodeableConcept `json:"code,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Encounter *Reference `json:"encounter,omitempty"` + Evidence []*CodeableReference `json:"evidence,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + OnsetAge *Age `json:"onsetAge,omitempty"` + OnsetDateTime *string `json:"onsetDateTime,omitempty"` + OnsetPeriod *Period `json:"onsetPeriod,omitempty"` + OnsetRange *Range `json:"onsetRange,omitempty"` + OnsetString *string `json:"onsetString,omitempty"` + Participant []*ConditionParticipant `json:"participant,omitempty"` + RecordedDate *string `json:"recordedDate,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Severity *CodeableConcept `json:"severity,omitempty"` + Stage []*ConditionStage `json:"stage,omitempty"` + Subject *Reference `json:"subject"` + Text *Narrative `json:"text,omitempty"` + VerificationStatus *CodeableConcept `json:"verificationStatus,omitempty"` } // ConditionParticipant type ConditionParticipant struct { - Actor *Reference `json:"actor"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Function *CodeableConcept `json:"function,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + Actor *Reference `json:"actor"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Function *CodeableConcept `json:"function,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // ConditionStage type ConditionStage struct { - Assessment []*Reference `json:"assessment,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Summary *CodeableConcept `json:"summary,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` + Assessment []*Reference `json:"assessment,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Summary *CodeableConcept `json:"summary,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` } // ContactDetail type ContactDetail struct { - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Name *string `json:"name,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Telecom []*ContactPoint `json:"telecom,omitempty"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Name *string `json:"name,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Telecom []*ContactPoint `json:"telecom,omitempty"` } // ContactPoint type ContactPoint struct { - XRank *FHIRPrimitiveExtension `json:"_rank,omitempty"` - XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` - XUse *FHIRPrimitiveExtension `json:"_use,omitempty"` - XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Period *Period `json:"period,omitempty"` - Rank *int64 `json:"rank,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - System *string `json:"system,omitempty"` - Use *string `json:"use,omitempty"` - Value *string `json:"value,omitempty"` + XRank *FHIRPrimitiveExtension `json:"_rank,omitempty"` + XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` + XUse *FHIRPrimitiveExtension `json:"_use,omitempty"` + XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Period *Period `json:"period,omitempty"` + Rank *int64 `json:"rank,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + System *string `json:"system,omitempty"` + Use *string `json:"use,omitempty"` + Value *string `json:"value,omitempty"` } // Count type Count struct { - XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` - XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` - XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` - XUnit *FHIRPrimitiveExtension `json:"_unit,omitempty"` - XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` - Code *string `json:"code,omitempty"` - Comparator *string `json:"comparator,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - System *string `json:"system,omitempty"` - Unit *string `json:"unit,omitempty"` - Value *float64 `json:"value,omitempty"` + XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` + XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` + XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` + XUnit *FHIRPrimitiveExtension `json:"_unit,omitempty"` + XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` + Code *string `json:"code,omitempty"` + Comparator *string `json:"comparator,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + System *string `json:"system,omitempty"` + Unit *string `json:"unit,omitempty"` + Value *float64 `json:"value,omitempty"` } // DataRequirement type DataRequirement struct { - XLimit *FHIRPrimitiveExtension `json:"_limit,omitempty"` - XMustSupport []*FHIRPrimitiveExtension `json:"_mustSupport,omitempty"` - XProfile []*FHIRPrimitiveExtension `json:"_profile,omitempty"` - XType *FHIRPrimitiveExtension `json:"_type,omitempty"` - CodeFilter []*DataRequirementCodeFilter `json:"codeFilter,omitempty"` - DateFilter []*DataRequirementDateFilter `json:"dateFilter,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Limit *int64 `json:"limit,omitempty"` - Links [][]any `json:"links,omitempty"` - MustSupport []string `json:"mustSupport,omitempty"` - Profile []string `json:"profile,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Sort []*DataRequirementSort `json:"sort,omitempty"` - SubjectCodeableConcept *CodeableConcept `json:"subjectCodeableConcept,omitempty"` - SubjectReference *Reference `json:"subjectReference,omitempty"` - Type *string `json:"type,omitempty"` - ValueFilter []*DataRequirementValueFilter `json:"valueFilter,omitempty"` + XLimit *FHIRPrimitiveExtension `json:"_limit,omitempty"` + XMustSupport []*FHIRPrimitiveExtension `json:"_mustSupport,omitempty"` + XProfile []*FHIRPrimitiveExtension `json:"_profile,omitempty"` + XType *FHIRPrimitiveExtension `json:"_type,omitempty"` + CodeFilter []*DataRequirementCodeFilter `json:"codeFilter,omitempty"` + DateFilter []*DataRequirementDateFilter `json:"dateFilter,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Limit *int64 `json:"limit,omitempty"` + Links [][]any `json:"links,omitempty"` + MustSupport []string `json:"mustSupport,omitempty"` + Profile []string `json:"profile,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Sort []*DataRequirementSort `json:"sort,omitempty"` + SubjectCodeableConcept *CodeableConcept `json:"subjectCodeableConcept,omitempty"` + SubjectReference *Reference `json:"subjectReference,omitempty"` + Type *string `json:"type,omitempty"` + ValueFilter []*DataRequirementValueFilter `json:"valueFilter,omitempty"` } // DataRequirementCodeFilter type DataRequirementCodeFilter struct { - XPath *FHIRPrimitiveExtension `json:"_path,omitempty"` + XPath *FHIRPrimitiveExtension `json:"_path,omitempty"` XSearchParam *FHIRPrimitiveExtension `json:"_searchParam,omitempty"` - XValueSet *FHIRPrimitiveExtension `json:"_valueSet,omitempty"` - Code []*Coding `json:"code,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Path *string `json:"path,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SearchParam *string `json:"searchParam,omitempty"` - ValueSet *string `json:"valueSet,omitempty"` + XValueSet *FHIRPrimitiveExtension `json:"_valueSet,omitempty"` + Code []*Coding `json:"code,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Path *string `json:"path,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SearchParam *string `json:"searchParam,omitempty"` + ValueSet *string `json:"valueSet,omitempty"` } // DataRequirementDateFilter type DataRequirementDateFilter struct { - XPath *FHIRPrimitiveExtension `json:"_path,omitempty"` - XSearchParam *FHIRPrimitiveExtension `json:"_searchParam,omitempty"` + XPath *FHIRPrimitiveExtension `json:"_path,omitempty"` + XSearchParam *FHIRPrimitiveExtension `json:"_searchParam,omitempty"` XValueDateTime *FHIRPrimitiveExtension `json:"_valueDateTime,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Path *string `json:"path,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SearchParam *string `json:"searchParam,omitempty"` - ValueDateTime *string `json:"valueDateTime,omitempty"` - ValueDuration *Duration `json:"valueDuration,omitempty"` - ValuePeriod *Period `json:"valuePeriod,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Path *string `json:"path,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SearchParam *string `json:"searchParam,omitempty"` + ValueDateTime *string `json:"valueDateTime,omitempty"` + ValueDuration *Duration `json:"valueDuration,omitempty"` + ValuePeriod *Period `json:"valuePeriod,omitempty"` } // DataRequirementSort type DataRequirementSort struct { - XDirection *FHIRPrimitiveExtension `json:"_direction,omitempty"` - XPath *FHIRPrimitiveExtension `json:"_path,omitempty"` - Direction *string `json:"direction,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Path *string `json:"path,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + XDirection *FHIRPrimitiveExtension `json:"_direction,omitempty"` + XPath *FHIRPrimitiveExtension `json:"_path,omitempty"` + Direction *string `json:"direction,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Path *string `json:"path,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // DataRequirementValueFilter type DataRequirementValueFilter struct { - XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` - XPath *FHIRPrimitiveExtension `json:"_path,omitempty"` - XSearchParam *FHIRPrimitiveExtension `json:"_searchParam,omitempty"` + XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` + XPath *FHIRPrimitiveExtension `json:"_path,omitempty"` + XSearchParam *FHIRPrimitiveExtension `json:"_searchParam,omitempty"` XValueDateTime *FHIRPrimitiveExtension `json:"_valueDateTime,omitempty"` - Comparator *string `json:"comparator,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Path *string `json:"path,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SearchParam *string `json:"searchParam,omitempty"` - ValueDateTime *string `json:"valueDateTime,omitempty"` - ValueDuration *Duration `json:"valueDuration,omitempty"` - ValuePeriod *Period `json:"valuePeriod,omitempty"` + Comparator *string `json:"comparator,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Path *string `json:"path,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SearchParam *string `json:"searchParam,omitempty"` + ValueDateTime *string `json:"valueDateTime,omitempty"` + ValueDuration *Duration `json:"valueDuration,omitempty"` + ValuePeriod *Period `json:"valuePeriod,omitempty"` } // DiagnosticReport type DiagnosticReport struct { - XConclusion *FHIRPrimitiveExtension `json:"_conclusion,omitempty"` - XEffectiveDateTime *FHIRPrimitiveExtension `json:"_effectiveDateTime,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XIssued *FHIRPrimitiveExtension `json:"_issued,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - BasedOn []*Reference `json:"basedOn,omitempty"` - Category []*CodeableConcept `json:"category,omitempty"` - Code *CodeableConcept `json:"code"` - Composition *Reference `json:"composition,omitempty"` - Conclusion *string `json:"conclusion,omitempty"` - ConclusionCode []*CodeableConcept `json:"conclusionCode,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - EffectiveDateTime *string `json:"effectiveDateTime,omitempty"` - EffectivePeriod *Period `json:"effectivePeriod,omitempty"` - Encounter *Reference `json:"encounter,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Issued *string `json:"issued,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Media []*DiagnosticReportMedia `json:"media,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - Performer []*Reference `json:"performer,omitempty"` - PresentedForm []*Attachment `json:"presentedForm,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Result []*Reference `json:"result,omitempty"` - ResultsInterpreter []*Reference `json:"resultsInterpreter,omitempty"` - Specimen []*Reference `json:"specimen,omitempty"` - Status *string `json:"status,omitempty"` - Study []*Reference `json:"study,omitempty"` - Subject *Reference `json:"subject,omitempty"` - SupportingInfo []*DiagnosticReportSupportingInfo `json:"supportingInfo,omitempty"` - Text *Narrative `json:"text,omitempty"` + XConclusion *FHIRPrimitiveExtension `json:"_conclusion,omitempty"` + XEffectiveDateTime *FHIRPrimitiveExtension `json:"_effectiveDateTime,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XIssued *FHIRPrimitiveExtension `json:"_issued,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + BasedOn []*Reference `json:"basedOn,omitempty"` + Category []*CodeableConcept `json:"category,omitempty"` + Code *CodeableConcept `json:"code"` + Composition *Reference `json:"composition,omitempty"` + Conclusion *string `json:"conclusion,omitempty"` + ConclusionCode []*CodeableConcept `json:"conclusionCode,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + EffectiveDateTime *string `json:"effectiveDateTime,omitempty"` + EffectivePeriod *Period `json:"effectivePeriod,omitempty"` + Encounter *Reference `json:"encounter,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Issued *string `json:"issued,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Media []*DiagnosticReportMedia `json:"media,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + Performer []*Reference `json:"performer,omitempty"` + PresentedForm []*Attachment `json:"presentedForm,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Result []*Reference `json:"result,omitempty"` + ResultsInterpreter []*Reference `json:"resultsInterpreter,omitempty"` + Specimen []*Reference `json:"specimen,omitempty"` + Status *string `json:"status,omitempty"` + Study []*Reference `json:"study,omitempty"` + Subject *Reference `json:"subject,omitempty"` + SupportingInfo []*DiagnosticReportSupportingInfo `json:"supportingInfo,omitempty"` + Text *Narrative `json:"text,omitempty"` } // DiagnosticReportMedia type DiagnosticReportMedia struct { - XComment *FHIRPrimitiveExtension `json:"_comment,omitempty"` - Comment *string `json:"comment,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Link *Reference `json:"link"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + XComment *FHIRPrimitiveExtension `json:"_comment,omitempty"` + Comment *string `json:"comment,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Link *Reference `json:"link"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // DiagnosticReportSupportingInfo type DiagnosticReportSupportingInfo struct { - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Reference *Reference `json:"reference"` - ResourceType *string `json:"resourceType,omitempty"` - Type *CodeableConcept `json:"type"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Reference *Reference `json:"reference"` + ResourceType *string `json:"resourceType,omitempty"` + Type *CodeableConcept `json:"type"` } // Directory type Directory struct { - Child []*Reference `json:"child"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Name *string `json:"name"` - Path *string `json:"path,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + Child []*Reference `json:"child"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Name *string `json:"name"` + Path *string `json:"path,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // Distance type Distance struct { - XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` - XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` - XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` - XUnit *FHIRPrimitiveExtension `json:"_unit,omitempty"` - XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` - Code *string `json:"code,omitempty"` - Comparator *string `json:"comparator,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - System *string `json:"system,omitempty"` - Unit *string `json:"unit,omitempty"` - Value *float64 `json:"value,omitempty"` + XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` + XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` + XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` + XUnit *FHIRPrimitiveExtension `json:"_unit,omitempty"` + XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` + Code *string `json:"code,omitempty"` + Comparator *string `json:"comparator,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + System *string `json:"system,omitempty"` + Unit *string `json:"unit,omitempty"` + Value *float64 `json:"value,omitempty"` } // DocumentReference type DocumentReference struct { - XDate *FHIRPrimitiveExtension `json:"_date,omitempty"` - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XDocStatus *FHIRPrimitiveExtension `json:"_docStatus,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - XVersion *FHIRPrimitiveExtension `json:"_version,omitempty"` - Attester []*DocumentReferenceAttester `json:"attester,omitempty"` - Author []*Reference `json:"author,omitempty"` - BasedOn []*Reference `json:"basedOn,omitempty"` - BodySite []*CodeableReference `json:"bodySite,omitempty"` - Category []*CodeableConcept `json:"category,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Content []*DocumentReferenceContent `json:"content"` - Context []*Reference `json:"context,omitempty"` - Custodian *Reference `json:"custodian,omitempty"` - Date *string `json:"date,omitempty"` - Description *string `json:"description,omitempty"` - DocStatus *string `json:"docStatus,omitempty"` - Event []*CodeableReference `json:"event,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FacilityType *CodeableConcept `json:"facilityType,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - Modality []*CodeableConcept `json:"modality,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Period *Period `json:"period,omitempty"` - PracticeSetting *CodeableConcept `json:"practiceSetting,omitempty"` - RelatesTo []*DocumentReferenceRelatesTo `json:"relatesTo,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SecurityLabel []*CodeableConcept `json:"securityLabel,omitempty"` - Status *string `json:"status,omitempty"` - Subject *Reference `json:"subject,omitempty"` - Text *Narrative `json:"text,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` - Version *string `json:"version,omitempty"` + XDate *FHIRPrimitiveExtension `json:"_date,omitempty"` + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XDocStatus *FHIRPrimitiveExtension `json:"_docStatus,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + XVersion *FHIRPrimitiveExtension `json:"_version,omitempty"` + Attester []*DocumentReferenceAttester `json:"attester,omitempty"` + Author []*Reference `json:"author,omitempty"` + BasedOn []*Reference `json:"basedOn,omitempty"` + BodySite []*CodeableReference `json:"bodySite,omitempty"` + Category []*CodeableConcept `json:"category,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Content []*DocumentReferenceContent `json:"content"` + Context []*Reference `json:"context,omitempty"` + Custodian *Reference `json:"custodian,omitempty"` + Date *string `json:"date,omitempty"` + Description *string `json:"description,omitempty"` + DocStatus *string `json:"docStatus,omitempty"` + Event []*CodeableReference `json:"event,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FacilityType *CodeableConcept `json:"facilityType,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + Modality []*CodeableConcept `json:"modality,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Period *Period `json:"period,omitempty"` + PracticeSetting *CodeableConcept `json:"practiceSetting,omitempty"` + RelatesTo []*DocumentReferenceRelatesTo `json:"relatesTo,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SecurityLabel []*CodeableConcept `json:"securityLabel,omitempty"` + Status *string `json:"status,omitempty"` + Subject *Reference `json:"subject,omitempty"` + Text *Narrative `json:"text,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` + Version *string `json:"version,omitempty"` } // DocumentReferenceAttester type DocumentReferenceAttester struct { - XTime *FHIRPrimitiveExtension `json:"_time,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Mode *CodeableConcept `json:"mode"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Party *Reference `json:"party,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Time *string `json:"time,omitempty"` + XTime *FHIRPrimitiveExtension `json:"_time,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Mode *CodeableConcept `json:"mode"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Party *Reference `json:"party,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Time *string `json:"time,omitempty"` } // DocumentReferenceContent type DocumentReferenceContent struct { - Attachment *Attachment `json:"attachment"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Profile []*DocumentReferenceContentProfile `json:"profile,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + Attachment *Attachment `json:"attachment"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Profile []*DocumentReferenceContentProfile `json:"profile,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // DocumentReferenceContentProfile type DocumentReferenceContentProfile struct { - XValueCanonical *FHIRPrimitiveExtension `json:"_valueCanonical,omitempty"` - XValueURI *FHIRPrimitiveExtension `json:"_valueUri,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - ValueCanonical *string `json:"valueCanonical,omitempty"` - ValueCoding *Coding `json:"valueCoding,omitempty"` - ValueURI *string `json:"valueUri,omitempty"` + XValueCanonical *FHIRPrimitiveExtension `json:"_valueCanonical,omitempty"` + XValueURI *FHIRPrimitiveExtension `json:"_valueUri,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + ValueCanonical *string `json:"valueCanonical,omitempty"` + ValueCoding *Coding `json:"valueCoding,omitempty"` + ValueURI *string `json:"valueUri,omitempty"` } // DocumentReferenceRelatesTo type DocumentReferenceRelatesTo struct { - Code *CodeableConcept `json:"code"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Target *Reference `json:"target"` + Code *CodeableConcept `json:"code"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Target *Reference `json:"target"` } // Dosage type Dosage struct { - XAsNeeded *FHIRPrimitiveExtension `json:"_asNeeded,omitempty"` - XPatientInstruction *FHIRPrimitiveExtension `json:"_patientInstruction,omitempty"` - XSequence *FHIRPrimitiveExtension `json:"_sequence,omitempty"` - XText *FHIRPrimitiveExtension `json:"_text,omitempty"` - AdditionalInstruction []*CodeableConcept `json:"additionalInstruction,omitempty"` - AsNeeded *bool `json:"asNeeded,omitempty"` - AsNeededFor []*CodeableConcept `json:"asNeededFor,omitempty"` - DoseAndRate []*DosageDoseAndRate `json:"doseAndRate,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - MaxDosePerAdministration *Quantity `json:"maxDosePerAdministration,omitempty"` - MaxDosePerLifetime *Quantity `json:"maxDosePerLifetime,omitempty"` - MaxDosePerPeriod []*Ratio `json:"maxDosePerPeriod,omitempty"` - Method *CodeableConcept `json:"method,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - PatientInstruction *string `json:"patientInstruction,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Route *CodeableConcept `json:"route,omitempty"` - Sequence *int64 `json:"sequence,omitempty"` - Site *CodeableConcept `json:"site,omitempty"` - Text *string `json:"text,omitempty"` - Timing *Timing `json:"timing,omitempty"` + XAsNeeded *FHIRPrimitiveExtension `json:"_asNeeded,omitempty"` + XPatientInstruction *FHIRPrimitiveExtension `json:"_patientInstruction,omitempty"` + XSequence *FHIRPrimitiveExtension `json:"_sequence,omitempty"` + XText *FHIRPrimitiveExtension `json:"_text,omitempty"` + AdditionalInstruction []*CodeableConcept `json:"additionalInstruction,omitempty"` + AsNeeded *bool `json:"asNeeded,omitempty"` + AsNeededFor []*CodeableConcept `json:"asNeededFor,omitempty"` + DoseAndRate []*DosageDoseAndRate `json:"doseAndRate,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + MaxDosePerAdministration *Quantity `json:"maxDosePerAdministration,omitempty"` + MaxDosePerLifetime *Quantity `json:"maxDosePerLifetime,omitempty"` + MaxDosePerPeriod []*Ratio `json:"maxDosePerPeriod,omitempty"` + Method *CodeableConcept `json:"method,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + PatientInstruction *string `json:"patientInstruction,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Route *CodeableConcept `json:"route,omitempty"` + Sequence *int64 `json:"sequence,omitempty"` + Site *CodeableConcept `json:"site,omitempty"` + Text *string `json:"text,omitempty"` + Timing *Timing `json:"timing,omitempty"` } // DosageDoseAndRate type DosageDoseAndRate struct { - DoseQuantity *Quantity `json:"doseQuantity,omitempty"` - DoseRange *Range `json:"doseRange,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - RateQuantity *Quantity `json:"rateQuantity,omitempty"` - RateRange *Range `json:"rateRange,omitempty"` - RateRatio *Ratio `json:"rateRatio,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` + DoseQuantity *Quantity `json:"doseQuantity,omitempty"` + DoseRange *Range `json:"doseRange,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + RateQuantity *Quantity `json:"rateQuantity,omitempty"` + RateRange *Range `json:"rateRange,omitempty"` + RateRatio *Ratio `json:"rateRatio,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` } // Duration type Duration struct { - XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` - XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` - XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` - XUnit *FHIRPrimitiveExtension `json:"_unit,omitempty"` - XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` - Code *string `json:"code,omitempty"` - Comparator *string `json:"comparator,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - System *string `json:"system,omitempty"` - Unit *string `json:"unit,omitempty"` - Value *float64 `json:"value,omitempty"` + XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` + XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` + XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` + XUnit *FHIRPrimitiveExtension `json:"_unit,omitempty"` + XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` + Code *string `json:"code,omitempty"` + Comparator *string `json:"comparator,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + System *string `json:"system,omitempty"` + Unit *string `json:"unit,omitempty"` + Value *float64 `json:"value,omitempty"` } // Expression type Expression struct { XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XExpression *FHIRPrimitiveExtension `json:"_expression,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - XReference *FHIRPrimitiveExtension `json:"_reference,omitempty"` - Description *string `json:"description,omitempty"` - Expression *string `json:"expression,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Name *string `json:"name,omitempty"` - Reference *string `json:"reference,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + XExpression *FHIRPrimitiveExtension `json:"_expression,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + XReference *FHIRPrimitiveExtension `json:"_reference,omitempty"` + Description *string `json:"description,omitempty"` + Expression *string `json:"expression,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Name *string `json:"name,omitempty"` + Reference *string `json:"reference,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // ExtendedContactDetail type ExtendedContactDetail struct { - Address *Address `json:"address,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Name []*HumanName `json:"name,omitempty"` - Organization *Reference `json:"organization,omitempty"` - Period *Period `json:"period,omitempty"` - Purpose *CodeableConcept `json:"purpose,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Telecom []*ContactPoint `json:"telecom,omitempty"` + Address *Address `json:"address,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Name []*HumanName `json:"name,omitempty"` + Organization *Reference `json:"organization,omitempty"` + Period *Period `json:"period,omitempty"` + Purpose *CodeableConcept `json:"purpose,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Telecom []*ContactPoint `json:"telecom,omitempty"` } // Extension type Extension struct { - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - URL *string `json:"url,omitempty"` - ValueAddress *Address `json:"valueAddress,omitempty"` - ValueAge *Age `json:"valueAge,omitempty"` - ValueAnnotation *Annotation `json:"valueAnnotation,omitempty"` - ValueAttachment *Attachment `json:"valueAttachment,omitempty"` - ValueAvailability *Availability `json:"valueAvailability,omitempty"` - ValueBase64Binary *string `json:"valueBase64Binary,omitempty"` - ValueBoolean *bool `json:"valueBoolean,omitempty"` - ValueCanonical *string `json:"valueCanonical,omitempty"` - ValueCode *string `json:"valueCode,omitempty"` - ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` - ValueCodeableReference *CodeableReference `json:"valueCodeableReference,omitempty"` - ValueCoding *Coding `json:"valueCoding,omitempty"` - ValueContactDetail *ContactDetail `json:"valueContactDetail,omitempty"` - ValueContactPoint *ContactPoint `json:"valueContactPoint,omitempty"` - ValueCount *Count `json:"valueCount,omitempty"` - ValueDataRequirement *DataRequirement `json:"valueDataRequirement,omitempty"` - ValueDate *string `json:"valueDate,omitempty"` - ValueDateTime *string `json:"valueDateTime,omitempty"` - ValueDecimal *float64 `json:"valueDecimal,omitempty"` - ValueDistance *Distance `json:"valueDistance,omitempty"` - ValueDosage *Dosage `json:"valueDosage,omitempty"` - ValueDuration *Duration `json:"valueDuration,omitempty"` - ValueExpression *Expression `json:"valueExpression,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + URL *string `json:"url,omitempty"` + ValueAddress *Address `json:"valueAddress,omitempty"` + ValueAge *Age `json:"valueAge,omitempty"` + ValueAnnotation *Annotation `json:"valueAnnotation,omitempty"` + ValueAttachment *Attachment `json:"valueAttachment,omitempty"` + ValueAvailability *Availability `json:"valueAvailability,omitempty"` + ValueBase64Binary *string `json:"valueBase64Binary,omitempty"` + ValueBoolean *bool `json:"valueBoolean,omitempty"` + ValueCanonical *string `json:"valueCanonical,omitempty"` + ValueCode *string `json:"valueCode,omitempty"` + ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` + ValueCodeableReference *CodeableReference `json:"valueCodeableReference,omitempty"` + ValueCoding *Coding `json:"valueCoding,omitempty"` + ValueContactDetail *ContactDetail `json:"valueContactDetail,omitempty"` + ValueContactPoint *ContactPoint `json:"valueContactPoint,omitempty"` + ValueCount *Count `json:"valueCount,omitempty"` + ValueDataRequirement *DataRequirement `json:"valueDataRequirement,omitempty"` + ValueDate *string `json:"valueDate,omitempty"` + ValueDateTime *string `json:"valueDateTime,omitempty"` + ValueDecimal *float64 `json:"valueDecimal,omitempty"` + ValueDistance *Distance `json:"valueDistance,omitempty"` + ValueDosage *Dosage `json:"valueDosage,omitempty"` + ValueDuration *Duration `json:"valueDuration,omitempty"` + ValueExpression *Expression `json:"valueExpression,omitempty"` ValueExtendedContactDetail *ExtendedContactDetail `json:"valueExtendedContactDetail,omitempty"` - ValueHumanName *HumanName `json:"valueHumanName,omitempty"` - ValueID *string `json:"valueId,omitempty"` - ValueIDentifier *Identifier `json:"valueIdentifier,omitempty"` - ValueInstant *string `json:"valueInstant,omitempty"` - ValueInteger *int64 `json:"valueInteger,omitempty"` - ValueInteger64 *int64 `json:"valueInteger64,omitempty"` - ValueMarkdown *string `json:"valueMarkdown,omitempty"` - ValueMeta *Meta `json:"valueMeta,omitempty"` - ValueMoney *Money `json:"valueMoney,omitempty"` - ValueOid *string `json:"valueOid,omitempty"` - ValueParameterDefinition *ParameterDefinition `json:"valueParameterDefinition,omitempty"` - ValuePeriod *Period `json:"valuePeriod,omitempty"` - ValuePositiveInt *int64 `json:"valuePositiveInt,omitempty"` - ValueQuantity *Quantity `json:"valueQuantity,omitempty"` - ValueRange *Range `json:"valueRange,omitempty"` - ValueRatio *Ratio `json:"valueRatio,omitempty"` - ValueRatioRange *RatioRange `json:"valueRatioRange,omitempty"` - ValueReference *Reference `json:"valueReference,omitempty"` - ValueRelatedArtifact *RelatedArtifact `json:"valueRelatedArtifact,omitempty"` - ValueSampledData *SampledData `json:"valueSampledData,omitempty"` - ValueSignature *Signature `json:"valueSignature,omitempty"` - ValueString *string `json:"valueString,omitempty"` - ValueTime *string `json:"valueTime,omitempty"` - ValueTiming *Timing `json:"valueTiming,omitempty"` - ValueTriggerDefinition *TriggerDefinition `json:"valueTriggerDefinition,omitempty"` - ValueUnsignedInt *int64 `json:"valueUnsignedInt,omitempty"` - ValueURI *string `json:"valueUri,omitempty"` - ValueURL *string `json:"valueUrl,omitempty"` - ValueUsageContext *UsageContext `json:"valueUsageContext,omitempty"` - ValueUUID *string `json:"valueUuid,omitempty"` + ValueHumanName *HumanName `json:"valueHumanName,omitempty"` + ValueID *string `json:"valueId,omitempty"` + ValueIDentifier *Identifier `json:"valueIdentifier,omitempty"` + ValueInstant *string `json:"valueInstant,omitempty"` + ValueInteger *int64 `json:"valueInteger,omitempty"` + ValueInteger64 *int64 `json:"valueInteger64,omitempty"` + ValueMarkdown *string `json:"valueMarkdown,omitempty"` + ValueMeta *Meta `json:"valueMeta,omitempty"` + ValueMoney *Money `json:"valueMoney,omitempty"` + ValueOid *string `json:"valueOid,omitempty"` + ValueParameterDefinition *ParameterDefinition `json:"valueParameterDefinition,omitempty"` + ValuePeriod *Period `json:"valuePeriod,omitempty"` + ValuePositiveInt *int64 `json:"valuePositiveInt,omitempty"` + ValueQuantity *Quantity `json:"valueQuantity,omitempty"` + ValueRange *Range `json:"valueRange,omitempty"` + ValueRatio *Ratio `json:"valueRatio,omitempty"` + ValueRatioRange *RatioRange `json:"valueRatioRange,omitempty"` + ValueReference *Reference `json:"valueReference,omitempty"` + ValueRelatedArtifact *RelatedArtifact `json:"valueRelatedArtifact,omitempty"` + ValueSampledData *SampledData `json:"valueSampledData,omitempty"` + ValueSignature *Signature `json:"valueSignature,omitempty"` + ValueString *string `json:"valueString,omitempty"` + ValueTime *string `json:"valueTime,omitempty"` + ValueTiming *Timing `json:"valueTiming,omitempty"` + ValueTriggerDefinition *TriggerDefinition `json:"valueTriggerDefinition,omitempty"` + ValueUnsignedInt *int64 `json:"valueUnsignedInt,omitempty"` + ValueURI *string `json:"valueUri,omitempty"` + ValueURL *string `json:"valueUrl,omitempty"` + ValueUsageContext *UsageContext `json:"valueUsageContext,omitempty"` + ValueUUID *string `json:"valueUuid,omitempty"` } // FHIRPrimitiveExtension type FHIRPrimitiveExtension struct { - Extension []*Extension `json:"extension,omitempty"` + Extension []*Extension `json:"extension,omitempty"` FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // FamilyMemberHistory type FamilyMemberHistory struct { - XAgeString *FHIRPrimitiveExtension `json:"_ageString,omitempty"` - XBornDate *FHIRPrimitiveExtension `json:"_bornDate,omitempty"` - XBornString *FHIRPrimitiveExtension `json:"_bornString,omitempty"` - XDate *FHIRPrimitiveExtension `json:"_date,omitempty"` - XDeceasedBoolean *FHIRPrimitiveExtension `json:"_deceasedBoolean,omitempty"` - XDeceasedDate *FHIRPrimitiveExtension `json:"_deceasedDate,omitempty"` - XDeceasedString *FHIRPrimitiveExtension `json:"_deceasedString,omitempty"` - XEstimatedAge *FHIRPrimitiveExtension `json:"_estimatedAge,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XInstantiatesCanonical []*FHIRPrimitiveExtension `json:"_instantiatesCanonical,omitempty"` - XInstantiatesURI []*FHIRPrimitiveExtension `json:"_instantiatesUri,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - AgeAge *Age `json:"ageAge,omitempty"` - AgeRange *Range `json:"ageRange,omitempty"` - AgeString *string `json:"ageString,omitempty"` - BornDate *string `json:"bornDate,omitempty"` - BornPeriod *Period `json:"bornPeriod,omitempty"` - BornString *string `json:"bornString,omitempty"` - Condition []*FamilyMemberHistoryCondition `json:"condition,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - DataAbsentReason *CodeableConcept `json:"dataAbsentReason,omitempty"` - Date *string `json:"date,omitempty"` - DeceasedAge *Age `json:"deceasedAge,omitempty"` - DeceasedBoolean *bool `json:"deceasedBoolean,omitempty"` - DeceasedDate *string `json:"deceasedDate,omitempty"` - DeceasedRange *Range `json:"deceasedRange,omitempty"` - DeceasedString *string `json:"deceasedString,omitempty"` - EstimatedAge *bool `json:"estimatedAge,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - InstantiatesCanonical []string `json:"instantiatesCanonical,omitempty"` - InstantiatesURI []string `json:"instantiatesUri,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Name *string `json:"name,omitempty"` - Note []*Annotation `json:"note,omitempty"` - Participant []*FamilyMemberHistoryParticipant `json:"participant,omitempty"` - Patient *Reference `json:"patient"` - Procedure []*FamilyMemberHistoryProcedure `json:"procedure,omitempty"` - Reason []*CodeableReference `json:"reason,omitempty"` - Relationship *CodeableConcept `json:"relationship"` - ResourceType *string `json:"resourceType,omitempty"` - Sex *CodeableConcept `json:"sex,omitempty"` - Status *string `json:"status,omitempty"` - Text *Narrative `json:"text,omitempty"` + XAgeString *FHIRPrimitiveExtension `json:"_ageString,omitempty"` + XBornDate *FHIRPrimitiveExtension `json:"_bornDate,omitempty"` + XBornString *FHIRPrimitiveExtension `json:"_bornString,omitempty"` + XDate *FHIRPrimitiveExtension `json:"_date,omitempty"` + XDeceasedBoolean *FHIRPrimitiveExtension `json:"_deceasedBoolean,omitempty"` + XDeceasedDate *FHIRPrimitiveExtension `json:"_deceasedDate,omitempty"` + XDeceasedString *FHIRPrimitiveExtension `json:"_deceasedString,omitempty"` + XEstimatedAge *FHIRPrimitiveExtension `json:"_estimatedAge,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XInstantiatesCanonical []*FHIRPrimitiveExtension `json:"_instantiatesCanonical,omitempty"` + XInstantiatesURI []*FHIRPrimitiveExtension `json:"_instantiatesUri,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + AgeAge *Age `json:"ageAge,omitempty"` + AgeRange *Range `json:"ageRange,omitempty"` + AgeString *string `json:"ageString,omitempty"` + BornDate *string `json:"bornDate,omitempty"` + BornPeriod *Period `json:"bornPeriod,omitempty"` + BornString *string `json:"bornString,omitempty"` + Condition []*FamilyMemberHistoryCondition `json:"condition,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + DataAbsentReason *CodeableConcept `json:"dataAbsentReason,omitempty"` + Date *string `json:"date,omitempty"` + DeceasedAge *Age `json:"deceasedAge,omitempty"` + DeceasedBoolean *bool `json:"deceasedBoolean,omitempty"` + DeceasedDate *string `json:"deceasedDate,omitempty"` + DeceasedRange *Range `json:"deceasedRange,omitempty"` + DeceasedString *string `json:"deceasedString,omitempty"` + EstimatedAge *bool `json:"estimatedAge,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + InstantiatesCanonical []string `json:"instantiatesCanonical,omitempty"` + InstantiatesURI []string `json:"instantiatesUri,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Name *string `json:"name,omitempty"` + Note []*Annotation `json:"note,omitempty"` + Participant []*FamilyMemberHistoryParticipant `json:"participant,omitempty"` + Patient *Reference `json:"patient"` + Procedure []*FamilyMemberHistoryProcedure `json:"procedure,omitempty"` + Reason []*CodeableReference `json:"reason,omitempty"` + Relationship *CodeableConcept `json:"relationship"` + ResourceType *string `json:"resourceType,omitempty"` + Sex *CodeableConcept `json:"sex,omitempty"` + Status *string `json:"status,omitempty"` + Text *Narrative `json:"text,omitempty"` } // FamilyMemberHistoryCondition type FamilyMemberHistoryCondition struct { XContributedToDeath *FHIRPrimitiveExtension `json:"_contributedToDeath,omitempty"` - XOnsetString *FHIRPrimitiveExtension `json:"_onsetString,omitempty"` - Code *CodeableConcept `json:"code"` - ContributedToDeath *bool `json:"contributedToDeath,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - OnsetAge *Age `json:"onsetAge,omitempty"` - OnsetPeriod *Period `json:"onsetPeriod,omitempty"` - OnsetRange *Range `json:"onsetRange,omitempty"` - OnsetString *string `json:"onsetString,omitempty"` - Outcome *CodeableConcept `json:"outcome,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + XOnsetString *FHIRPrimitiveExtension `json:"_onsetString,omitempty"` + Code *CodeableConcept `json:"code"` + ContributedToDeath *bool `json:"contributedToDeath,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + OnsetAge *Age `json:"onsetAge,omitempty"` + OnsetPeriod *Period `json:"onsetPeriod,omitempty"` + OnsetRange *Range `json:"onsetRange,omitempty"` + OnsetString *string `json:"onsetString,omitempty"` + Outcome *CodeableConcept `json:"outcome,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // FamilyMemberHistoryParticipant type FamilyMemberHistoryParticipant struct { - Actor *Reference `json:"actor"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Function *CodeableConcept `json:"function,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + Actor *Reference `json:"actor"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Function *CodeableConcept `json:"function,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // FamilyMemberHistoryProcedure type FamilyMemberHistoryProcedure struct { XContributedToDeath *FHIRPrimitiveExtension `json:"_contributedToDeath,omitempty"` - XPerformedDateTime *FHIRPrimitiveExtension `json:"_performedDateTime,omitempty"` - XPerformedString *FHIRPrimitiveExtension `json:"_performedString,omitempty"` - Code *CodeableConcept `json:"code"` - ContributedToDeath *bool `json:"contributedToDeath,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - Outcome *CodeableConcept `json:"outcome,omitempty"` - PerformedAge *Age `json:"performedAge,omitempty"` - PerformedDateTime *string `json:"performedDateTime,omitempty"` - PerformedPeriod *Period `json:"performedPeriod,omitempty"` - PerformedRange *Range `json:"performedRange,omitempty"` - PerformedString *string `json:"performedString,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + XPerformedDateTime *FHIRPrimitiveExtension `json:"_performedDateTime,omitempty"` + XPerformedString *FHIRPrimitiveExtension `json:"_performedString,omitempty"` + Code *CodeableConcept `json:"code"` + ContributedToDeath *bool `json:"contributedToDeath,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + Outcome *CodeableConcept `json:"outcome,omitempty"` + PerformedAge *Age `json:"performedAge,omitempty"` + PerformedDateTime *string `json:"performedDateTime,omitempty"` + PerformedPeriod *Period `json:"performedPeriod,omitempty"` + PerformedRange *Range `json:"performedRange,omitempty"` + PerformedString *string `json:"performedString,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // Group type Group struct { - XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XMembership *FHIRPrimitiveExtension `json:"_membership,omitempty"` - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - XQuantity *FHIRPrimitiveExtension `json:"_quantity,omitempty"` - XType *FHIRPrimitiveExtension `json:"_type,omitempty"` - Active *bool `json:"active,omitempty"` - Characteristic []*GroupCharacteristic `json:"characteristic,omitempty"` - Code *CodeableConcept `json:"code,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Description *string `json:"description,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - ManagingEntity *Reference `json:"managingEntity,omitempty"` - Member []*GroupMember `json:"member,omitempty"` - Membership *string `json:"membership,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Name *string `json:"name,omitempty"` - Quantity *int64 `json:"quantity,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Text *Narrative `json:"text,omitempty"` - Type *string `json:"type,omitempty"` + XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XMembership *FHIRPrimitiveExtension `json:"_membership,omitempty"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + XQuantity *FHIRPrimitiveExtension `json:"_quantity,omitempty"` + XType *FHIRPrimitiveExtension `json:"_type,omitempty"` + Active *bool `json:"active,omitempty"` + Characteristic []*GroupCharacteristic `json:"characteristic,omitempty"` + Code *CodeableConcept `json:"code,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Description *string `json:"description,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + ManagingEntity *Reference `json:"managingEntity,omitempty"` + Member []*GroupMember `json:"member,omitempty"` + Membership *string `json:"membership,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Name *string `json:"name,omitempty"` + Quantity *int64 `json:"quantity,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Text *Narrative `json:"text,omitempty"` + Type *string `json:"type,omitempty"` } // GroupCharacteristic type GroupCharacteristic struct { - XExclude *FHIRPrimitiveExtension `json:"_exclude,omitempty"` - XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` - Code *CodeableConcept `json:"code"` - Exclude *bool `json:"exclude,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Period *Period `json:"period,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - ValueBoolean *bool `json:"valueBoolean,omitempty"` - ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` - ValueQuantity *Quantity `json:"valueQuantity,omitempty"` - ValueRange *Range `json:"valueRange,omitempty"` - ValueReference *Reference `json:"valueReference,omitempty"` + XExclude *FHIRPrimitiveExtension `json:"_exclude,omitempty"` + XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` + Code *CodeableConcept `json:"code"` + Exclude *bool `json:"exclude,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Period *Period `json:"period,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + ValueBoolean *bool `json:"valueBoolean,omitempty"` + ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` + ValueQuantity *Quantity `json:"valueQuantity,omitempty"` + ValueRange *Range `json:"valueRange,omitempty"` + ValueReference *Reference `json:"valueReference,omitempty"` } // GroupMember type GroupMember struct { - XInactive *FHIRPrimitiveExtension `json:"_inactive,omitempty"` - Entity *Reference `json:"entity"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Inactive *bool `json:"inactive,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Period *Period `json:"period,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + XInactive *FHIRPrimitiveExtension `json:"_inactive,omitempty"` + Entity *Reference `json:"entity"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Inactive *bool `json:"inactive,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Period *Period `json:"period,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // HumanName type HumanName struct { - XFamily *FHIRPrimitiveExtension `json:"_family,omitempty"` - XGiven []*FHIRPrimitiveExtension `json:"_given,omitempty"` - XPrefix []*FHIRPrimitiveExtension `json:"_prefix,omitempty"` - XSuffix []*FHIRPrimitiveExtension `json:"_suffix,omitempty"` - XText *FHIRPrimitiveExtension `json:"_text,omitempty"` - XUse *FHIRPrimitiveExtension `json:"_use,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - Family *string `json:"family,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Given []string `json:"given,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Period *Period `json:"period,omitempty"` - Prefix []string `json:"prefix,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Suffix []string `json:"suffix,omitempty"` - Text *string `json:"text,omitempty"` - Use *string `json:"use,omitempty"` + XFamily *FHIRPrimitiveExtension `json:"_family,omitempty"` + XGiven []*FHIRPrimitiveExtension `json:"_given,omitempty"` + XPrefix []*FHIRPrimitiveExtension `json:"_prefix,omitempty"` + XSuffix []*FHIRPrimitiveExtension `json:"_suffix,omitempty"` + XText *FHIRPrimitiveExtension `json:"_text,omitempty"` + XUse *FHIRPrimitiveExtension `json:"_use,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + Family *string `json:"family,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Given []string `json:"given,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Period *Period `json:"period,omitempty"` + Prefix []string `json:"prefix,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Suffix []string `json:"suffix,omitempty"` + Text *string `json:"text,omitempty"` + Use *string `json:"use,omitempty"` } // Identifier type Identifier struct { - XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` - XUse *FHIRPrimitiveExtension `json:"_use,omitempty"` - XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` - Assigner *Reference `json:"assigner,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Period *Period `json:"period,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - System *string `json:"system,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` - Use *string `json:"use,omitempty"` - Value *string `json:"value,omitempty"` + XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` + XUse *FHIRPrimitiveExtension `json:"_use,omitempty"` + XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` + Assigner *Reference `json:"assigner,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Period *Period `json:"period,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + System *string `json:"system,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` + Use *string `json:"use,omitempty"` + Value *string `json:"value,omitempty"` } // ImagingStudy type ImagingStudy struct { - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` XNumberOfInstances *FHIRPrimitiveExtension `json:"_numberOfInstances,omitempty"` - XNumberOfSeries *FHIRPrimitiveExtension `json:"_numberOfSeries,omitempty"` - XStarted *FHIRPrimitiveExtension `json:"_started,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - BasedOn []*Reference `json:"basedOn,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Description *string `json:"description,omitempty"` - Encounter *Reference `json:"encounter,omitempty"` - Endpoint []*Reference `json:"endpoint,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Location *Reference `json:"location,omitempty"` - Meta *Meta `json:"meta,omitempty"` - Modality []*CodeableConcept `json:"modality,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - NumberOfInstances *int64 `json:"numberOfInstances,omitempty"` - NumberOfSeries *int64 `json:"numberOfSeries,omitempty"` - PartOf []*Reference `json:"partOf,omitempty"` - Procedure []*CodeableReference `json:"procedure,omitempty"` - Reason []*CodeableReference `json:"reason,omitempty"` - Referrer *Reference `json:"referrer,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Series []*ImagingStudySeries `json:"series,omitempty"` - Started *string `json:"started,omitempty"` - Status *string `json:"status,omitempty"` - Subject *Reference `json:"subject"` - Text *Narrative `json:"text,omitempty"` + XNumberOfSeries *FHIRPrimitiveExtension `json:"_numberOfSeries,omitempty"` + XStarted *FHIRPrimitiveExtension `json:"_started,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + BasedOn []*Reference `json:"basedOn,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Description *string `json:"description,omitempty"` + Encounter *Reference `json:"encounter,omitempty"` + Endpoint []*Reference `json:"endpoint,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Location *Reference `json:"location,omitempty"` + Meta *Meta `json:"meta,omitempty"` + Modality []*CodeableConcept `json:"modality,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + NumberOfInstances *int64 `json:"numberOfInstances,omitempty"` + NumberOfSeries *int64 `json:"numberOfSeries,omitempty"` + PartOf []*Reference `json:"partOf,omitempty"` + Procedure []*CodeableReference `json:"procedure,omitempty"` + Reason []*CodeableReference `json:"reason,omitempty"` + Referrer *Reference `json:"referrer,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Series []*ImagingStudySeries `json:"series,omitempty"` + Started *string `json:"started,omitempty"` + Status *string `json:"status,omitempty"` + Subject *Reference `json:"subject"` + Text *Narrative `json:"text,omitempty"` } // ImagingStudySeries type ImagingStudySeries struct { - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XNumber *FHIRPrimitiveExtension `json:"_number,omitempty"` - XNumberOfInstances *FHIRPrimitiveExtension `json:"_numberOfInstances,omitempty"` - XStarted *FHIRPrimitiveExtension `json:"_started,omitempty"` - XUid *FHIRPrimitiveExtension `json:"_uid,omitempty"` - BodySite *CodeableReference `json:"bodySite,omitempty"` - Description *string `json:"description,omitempty"` - Endpoint []*Reference `json:"endpoint,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Instance []*ImagingStudySeriesInstance `json:"instance,omitempty"` - Laterality *CodeableConcept `json:"laterality,omitempty"` - Links [][]any `json:"links,omitempty"` - Modality *CodeableConcept `json:"modality"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Number *int64 `json:"number,omitempty"` - NumberOfInstances *int64 `json:"numberOfInstances,omitempty"` - Performer []*ImagingStudySeriesPerformer `json:"performer,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Specimen []*Reference `json:"specimen,omitempty"` - Started *string `json:"started,omitempty"` - Uid *string `json:"uid,omitempty"` + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XNumber *FHIRPrimitiveExtension `json:"_number,omitempty"` + XNumberOfInstances *FHIRPrimitiveExtension `json:"_numberOfInstances,omitempty"` + XStarted *FHIRPrimitiveExtension `json:"_started,omitempty"` + XUid *FHIRPrimitiveExtension `json:"_uid,omitempty"` + BodySite *CodeableReference `json:"bodySite,omitempty"` + Description *string `json:"description,omitempty"` + Endpoint []*Reference `json:"endpoint,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Instance []*ImagingStudySeriesInstance `json:"instance,omitempty"` + Laterality *CodeableConcept `json:"laterality,omitempty"` + Links [][]any `json:"links,omitempty"` + Modality *CodeableConcept `json:"modality"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Number *int64 `json:"number,omitempty"` + NumberOfInstances *int64 `json:"numberOfInstances,omitempty"` + Performer []*ImagingStudySeriesPerformer `json:"performer,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Specimen []*Reference `json:"specimen,omitempty"` + Started *string `json:"started,omitempty"` + Uid *string `json:"uid,omitempty"` } // ImagingStudySeriesInstance type ImagingStudySeriesInstance struct { - XNumber *FHIRPrimitiveExtension `json:"_number,omitempty"` - XTitle *FHIRPrimitiveExtension `json:"_title,omitempty"` - XUid *FHIRPrimitiveExtension `json:"_uid,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Number *int64 `json:"number,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SopClass *Coding `json:"sopClass"` - Title *string `json:"title,omitempty"` - Uid *string `json:"uid,omitempty"` + XNumber *FHIRPrimitiveExtension `json:"_number,omitempty"` + XTitle *FHIRPrimitiveExtension `json:"_title,omitempty"` + XUid *FHIRPrimitiveExtension `json:"_uid,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Number *int64 `json:"number,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SopClass *Coding `json:"sopClass"` + Title *string `json:"title,omitempty"` + Uid *string `json:"uid,omitempty"` } // ImagingStudySeriesPerformer type ImagingStudySeriesPerformer struct { - Actor *Reference `json:"actor"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Function *CodeableConcept `json:"function,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + Actor *Reference `json:"actor"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Function *CodeableConcept `json:"function,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // Medication type Medication struct { - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - Batch *MedicationBatch `json:"batch,omitempty"` - Code *CodeableConcept `json:"code,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Definition *Reference `json:"definition,omitempty"` - DoseForm *CodeableConcept `json:"doseForm,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Ingredient []*MedicationIngredient `json:"ingredient,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - MarketingAuthorizationHolder *Reference `json:"marketingAuthorizationHolder,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Status *string `json:"status,omitempty"` - Text *Narrative `json:"text,omitempty"` - TotalVolume *Quantity `json:"totalVolume,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + Batch *MedicationBatch `json:"batch,omitempty"` + Code *CodeableConcept `json:"code,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Definition *Reference `json:"definition,omitempty"` + DoseForm *CodeableConcept `json:"doseForm,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Ingredient []*MedicationIngredient `json:"ingredient,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + MarketingAuthorizationHolder *Reference `json:"marketingAuthorizationHolder,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Status *string `json:"status,omitempty"` + Text *Narrative `json:"text,omitempty"` + TotalVolume *Quantity `json:"totalVolume,omitempty"` } // MedicationAdministration type MedicationAdministration struct { - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XIsSubPotent *FHIRPrimitiveExtension `json:"_isSubPotent,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XOccurenceDateTime *FHIRPrimitiveExtension `json:"_occurenceDateTime,omitempty"` - XRecorded *FHIRPrimitiveExtension `json:"_recorded,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - BasedOn []*Reference `json:"basedOn,omitempty"` - Category []*CodeableConcept `json:"category,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Device []*CodeableReference `json:"device,omitempty"` - Dosage *MedicationAdministrationDosage `json:"dosage,omitempty"` - Encounter *Reference `json:"encounter,omitempty"` - EventHistory []*Reference `json:"eventHistory,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - IsSubPotent *bool `json:"isSubPotent,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Medication *CodeableReference `json:"medication"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - OccurenceDateTime *string `json:"occurenceDateTime,omitempty"` - OccurencePeriod *Period `json:"occurencePeriod,omitempty"` - OccurenceTiming *Timing `json:"occurenceTiming,omitempty"` - PartOf []*Reference `json:"partOf,omitempty"` - Performer []*MedicationAdministrationPerformer `json:"performer,omitempty"` - Reason []*CodeableReference `json:"reason,omitempty"` - Recorded *string `json:"recorded,omitempty"` - Request *Reference `json:"request,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Status *string `json:"status,omitempty"` - StatusReason []*CodeableConcept `json:"statusReason,omitempty"` - SubPotentReason []*CodeableConcept `json:"subPotentReason,omitempty"` - Subject *Reference `json:"subject"` - SupportingInformation []*Reference `json:"supportingInformation,omitempty"` - Text *Narrative `json:"text,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XIsSubPotent *FHIRPrimitiveExtension `json:"_isSubPotent,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XOccurenceDateTime *FHIRPrimitiveExtension `json:"_occurenceDateTime,omitempty"` + XRecorded *FHIRPrimitiveExtension `json:"_recorded,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + BasedOn []*Reference `json:"basedOn,omitempty"` + Category []*CodeableConcept `json:"category,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Device []*CodeableReference `json:"device,omitempty"` + Dosage *MedicationAdministrationDosage `json:"dosage,omitempty"` + Encounter *Reference `json:"encounter,omitempty"` + EventHistory []*Reference `json:"eventHistory,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + IsSubPotent *bool `json:"isSubPotent,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Medication *CodeableReference `json:"medication"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + OccurenceDateTime *string `json:"occurenceDateTime,omitempty"` + OccurencePeriod *Period `json:"occurencePeriod,omitempty"` + OccurenceTiming *Timing `json:"occurenceTiming,omitempty"` + PartOf []*Reference `json:"partOf,omitempty"` + Performer []*MedicationAdministrationPerformer `json:"performer,omitempty"` + Reason []*CodeableReference `json:"reason,omitempty"` + Recorded *string `json:"recorded,omitempty"` + Request *Reference `json:"request,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Status *string `json:"status,omitempty"` + StatusReason []*CodeableConcept `json:"statusReason,omitempty"` + SubPotentReason []*CodeableConcept `json:"subPotentReason,omitempty"` + Subject *Reference `json:"subject"` + SupportingInformation []*Reference `json:"supportingInformation,omitempty"` + Text *Narrative `json:"text,omitempty"` } // MedicationAdministrationDosage type MedicationAdministrationDosage struct { - XText *FHIRPrimitiveExtension `json:"_text,omitempty"` - Dose *Quantity `json:"dose,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Method *CodeableConcept `json:"method,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - RateQuantity *Quantity `json:"rateQuantity,omitempty"` - RateRatio *Ratio `json:"rateRatio,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Route *CodeableConcept `json:"route,omitempty"` - Site *CodeableConcept `json:"site,omitempty"` - Text *string `json:"text,omitempty"` + XText *FHIRPrimitiveExtension `json:"_text,omitempty"` + Dose *Quantity `json:"dose,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Method *CodeableConcept `json:"method,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + RateQuantity *Quantity `json:"rateQuantity,omitempty"` + RateRatio *Ratio `json:"rateRatio,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Route *CodeableConcept `json:"route,omitempty"` + Site *CodeableConcept `json:"site,omitempty"` + Text *string `json:"text,omitempty"` } // MedicationAdministrationPerformer type MedicationAdministrationPerformer struct { - Actor *CodeableReference `json:"actor"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Function *CodeableConcept `json:"function,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + Actor *CodeableReference `json:"actor"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Function *CodeableConcept `json:"function,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // MedicationBatch type MedicationBatch struct { - XExpirationDate *FHIRPrimitiveExtension `json:"_expirationDate,omitempty"` - XLotNumber *FHIRPrimitiveExtension `json:"_lotNumber,omitempty"` - ExpirationDate *string `json:"expirationDate,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - LotNumber *string `json:"lotNumber,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + XExpirationDate *FHIRPrimitiveExtension `json:"_expirationDate,omitempty"` + XLotNumber *FHIRPrimitiveExtension `json:"_lotNumber,omitempty"` + ExpirationDate *string `json:"expirationDate,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + LotNumber *string `json:"lotNumber,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // MedicationIngredient type MedicationIngredient struct { - XIsActive *FHIRPrimitiveExtension `json:"_isActive,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IsActive *bool `json:"isActive,omitempty"` - Item *CodeableReference `json:"item"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - StrengthCodeableConcept *CodeableConcept `json:"strengthCodeableConcept,omitempty"` - StrengthQuantity *Quantity `json:"strengthQuantity,omitempty"` - StrengthRatio *Ratio `json:"strengthRatio,omitempty"` + XIsActive *FHIRPrimitiveExtension `json:"_isActive,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IsActive *bool `json:"isActive,omitempty"` + Item *CodeableReference `json:"item"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + StrengthCodeableConcept *CodeableConcept `json:"strengthCodeableConcept,omitempty"` + StrengthQuantity *Quantity `json:"strengthQuantity,omitempty"` + StrengthRatio *Ratio `json:"strengthRatio,omitempty"` } // MedicationRequest type MedicationRequest struct { - XAuthoredOn *FHIRPrimitiveExtension `json:"_authoredOn,omitempty"` - XDoNotPerform *FHIRPrimitiveExtension `json:"_doNotPerform,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XIntent *FHIRPrimitiveExtension `json:"_intent,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XPriority *FHIRPrimitiveExtension `json:"_priority,omitempty"` - XRenderedDosageInstruction *FHIRPrimitiveExtension `json:"_renderedDosageInstruction,omitempty"` - XReported *FHIRPrimitiveExtension `json:"_reported,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - XStatusChanged *FHIRPrimitiveExtension `json:"_statusChanged,omitempty"` - AuthoredOn *string `json:"authoredOn,omitempty"` - BasedOn []*Reference `json:"basedOn,omitempty"` - Category []*CodeableConcept `json:"category,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - CourseOfTherapyType *CodeableConcept `json:"courseOfTherapyType,omitempty"` - Device []*CodeableReference `json:"device,omitempty"` - DispenseRequest *MedicationRequestDispenseRequest `json:"dispenseRequest,omitempty"` - DoNotPerform *bool `json:"doNotPerform,omitempty"` - DosageInstruction []*Dosage `json:"dosageInstruction,omitempty"` - EffectiveDosePeriod *Period `json:"effectiveDosePeriod,omitempty"` - Encounter *Reference `json:"encounter,omitempty"` - EventHistory []*Reference `json:"eventHistory,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - GroupIDentifier *Identifier `json:"groupIdentifier,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - InformationSource []*Reference `json:"informationSource,omitempty"` - Insurance []*Reference `json:"insurance,omitempty"` - Intent *string `json:"intent,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Medication *CodeableReference `json:"medication"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - Performer []*Reference `json:"performer,omitempty"` - PerformerType *CodeableConcept `json:"performerType,omitempty"` - PriorPrescription *Reference `json:"priorPrescription,omitempty"` - Priority *string `json:"priority,omitempty"` - Reason []*CodeableReference `json:"reason,omitempty"` - Recorder *Reference `json:"recorder,omitempty"` - RenderedDosageInstruction *string `json:"renderedDosageInstruction,omitempty"` - Reported *bool `json:"reported,omitempty"` - Requester *Reference `json:"requester,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Status *string `json:"status,omitempty"` - StatusChanged *string `json:"statusChanged,omitempty"` - StatusReason *CodeableConcept `json:"statusReason,omitempty"` - Subject *Reference `json:"subject"` - Substitution *MedicationRequestSubstitution `json:"substitution,omitempty"` - SupportingInformation []*Reference `json:"supportingInformation,omitempty"` - Text *Narrative `json:"text,omitempty"` + XAuthoredOn *FHIRPrimitiveExtension `json:"_authoredOn,omitempty"` + XDoNotPerform *FHIRPrimitiveExtension `json:"_doNotPerform,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XIntent *FHIRPrimitiveExtension `json:"_intent,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XPriority *FHIRPrimitiveExtension `json:"_priority,omitempty"` + XRenderedDosageInstruction *FHIRPrimitiveExtension `json:"_renderedDosageInstruction,omitempty"` + XReported *FHIRPrimitiveExtension `json:"_reported,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + XStatusChanged *FHIRPrimitiveExtension `json:"_statusChanged,omitempty"` + AuthoredOn *string `json:"authoredOn,omitempty"` + BasedOn []*Reference `json:"basedOn,omitempty"` + Category []*CodeableConcept `json:"category,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + CourseOfTherapyType *CodeableConcept `json:"courseOfTherapyType,omitempty"` + Device []*CodeableReference `json:"device,omitempty"` + DispenseRequest *MedicationRequestDispenseRequest `json:"dispenseRequest,omitempty"` + DoNotPerform *bool `json:"doNotPerform,omitempty"` + DosageInstruction []*Dosage `json:"dosageInstruction,omitempty"` + EffectiveDosePeriod *Period `json:"effectiveDosePeriod,omitempty"` + Encounter *Reference `json:"encounter,omitempty"` + EventHistory []*Reference `json:"eventHistory,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + GroupIDentifier *Identifier `json:"groupIdentifier,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + InformationSource []*Reference `json:"informationSource,omitempty"` + Insurance []*Reference `json:"insurance,omitempty"` + Intent *string `json:"intent,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Medication *CodeableReference `json:"medication"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + Performer []*Reference `json:"performer,omitempty"` + PerformerType *CodeableConcept `json:"performerType,omitempty"` + PriorPrescription *Reference `json:"priorPrescription,omitempty"` + Priority *string `json:"priority,omitempty"` + Reason []*CodeableReference `json:"reason,omitempty"` + Recorder *Reference `json:"recorder,omitempty"` + RenderedDosageInstruction *string `json:"renderedDosageInstruction,omitempty"` + Reported *bool `json:"reported,omitempty"` + Requester *Reference `json:"requester,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Status *string `json:"status,omitempty"` + StatusChanged *string `json:"statusChanged,omitempty"` + StatusReason *CodeableConcept `json:"statusReason,omitempty"` + Subject *Reference `json:"subject"` + Substitution *MedicationRequestSubstitution `json:"substitution,omitempty"` + SupportingInformation []*Reference `json:"supportingInformation,omitempty"` + Text *Narrative `json:"text,omitempty"` } // MedicationRequestDispenseRequest type MedicationRequestDispenseRequest struct { - XNumberOfRepeatsAllowed *FHIRPrimitiveExtension `json:"_numberOfRepeatsAllowed,omitempty"` - DispenseInterval *Duration `json:"dispenseInterval,omitempty"` - Dispenser *Reference `json:"dispenser,omitempty"` - DispenserInstruction []*Annotation `json:"dispenserInstruction,omitempty"` - DoseAdministrationAid *CodeableConcept `json:"doseAdministrationAid,omitempty"` - ExpectedSupplyDuration *Duration `json:"expectedSupplyDuration,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - InitialFill *MedicationRequestDispenseRequestInitialFill `json:"initialFill,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - NumberOfRepeatsAllowed *int64 `json:"numberOfRepeatsAllowed,omitempty"` - Quantity *Quantity `json:"quantity,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - ValidityPeriod *Period `json:"validityPeriod,omitempty"` + XNumberOfRepeatsAllowed *FHIRPrimitiveExtension `json:"_numberOfRepeatsAllowed,omitempty"` + DispenseInterval *Duration `json:"dispenseInterval,omitempty"` + Dispenser *Reference `json:"dispenser,omitempty"` + DispenserInstruction []*Annotation `json:"dispenserInstruction,omitempty"` + DoseAdministrationAid *CodeableConcept `json:"doseAdministrationAid,omitempty"` + ExpectedSupplyDuration *Duration `json:"expectedSupplyDuration,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + InitialFill *MedicationRequestDispenseRequestInitialFill `json:"initialFill,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + NumberOfRepeatsAllowed *int64 `json:"numberOfRepeatsAllowed,omitempty"` + Quantity *Quantity `json:"quantity,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + ValidityPeriod *Period `json:"validityPeriod,omitempty"` } // MedicationRequestDispenseRequestInitialFill type MedicationRequestDispenseRequestInitialFill struct { - Duration *Duration `json:"duration,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` + Duration *Duration `json:"duration,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Quantity *Quantity `json:"quantity,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + Quantity *Quantity `json:"quantity,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // MedicationRequestSubstitution type MedicationRequestSubstitution struct { - XAllowedBoolean *FHIRPrimitiveExtension `json:"_allowedBoolean,omitempty"` - AllowedBoolean *bool `json:"allowedBoolean,omitempty"` - AllowedCodeableConcept *CodeableConcept `json:"allowedCodeableConcept,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Reason *CodeableConcept `json:"reason,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + XAllowedBoolean *FHIRPrimitiveExtension `json:"_allowedBoolean,omitempty"` + AllowedBoolean *bool `json:"allowedBoolean,omitempty"` + AllowedCodeableConcept *CodeableConcept `json:"allowedCodeableConcept,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Reason *CodeableConcept `json:"reason,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // MedicationStatement type MedicationStatement struct { - XDateAsserted *FHIRPrimitiveExtension `json:"_dateAsserted,omitempty"` - XEffectiveDateTime *FHIRPrimitiveExtension `json:"_effectiveDateTime,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XRenderedDosageInstruction *FHIRPrimitiveExtension `json:"_renderedDosageInstruction,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - Adherence *MedicationStatementAdherence `json:"adherence,omitempty"` - Category []*CodeableConcept `json:"category,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - DateAsserted *string `json:"dateAsserted,omitempty"` - DerivedFrom []*Reference `json:"derivedFrom,omitempty"` - Dosage []*Dosage `json:"dosage,omitempty"` - EffectiveDateTime *string `json:"effectiveDateTime,omitempty"` - EffectivePeriod *Period `json:"effectivePeriod,omitempty"` - EffectiveTiming *Timing `json:"effectiveTiming,omitempty"` - Encounter *Reference `json:"encounter,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - InformationSource []*Reference `json:"informationSource,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Medication *CodeableReference `json:"medication"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - PartOf []*Reference `json:"partOf,omitempty"` - Reason []*CodeableReference `json:"reason,omitempty"` - RelatedClinicalInformation []*Reference `json:"relatedClinicalInformation,omitempty"` - RenderedDosageInstruction *string `json:"renderedDosageInstruction,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Status *string `json:"status,omitempty"` - Subject *Reference `json:"subject"` - Text *Narrative `json:"text,omitempty"` + XDateAsserted *FHIRPrimitiveExtension `json:"_dateAsserted,omitempty"` + XEffectiveDateTime *FHIRPrimitiveExtension `json:"_effectiveDateTime,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XRenderedDosageInstruction *FHIRPrimitiveExtension `json:"_renderedDosageInstruction,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + Adherence *MedicationStatementAdherence `json:"adherence,omitempty"` + Category []*CodeableConcept `json:"category,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + DateAsserted *string `json:"dateAsserted,omitempty"` + DerivedFrom []*Reference `json:"derivedFrom,omitempty"` + Dosage []*Dosage `json:"dosage,omitempty"` + EffectiveDateTime *string `json:"effectiveDateTime,omitempty"` + EffectivePeriod *Period `json:"effectivePeriod,omitempty"` + EffectiveTiming *Timing `json:"effectiveTiming,omitempty"` + Encounter *Reference `json:"encounter,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + InformationSource []*Reference `json:"informationSource,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Medication *CodeableReference `json:"medication"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + PartOf []*Reference `json:"partOf,omitempty"` + Reason []*CodeableReference `json:"reason,omitempty"` + RelatedClinicalInformation []*Reference `json:"relatedClinicalInformation,omitempty"` + RenderedDosageInstruction *string `json:"renderedDosageInstruction,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Status *string `json:"status,omitempty"` + Subject *Reference `json:"subject"` + Text *Narrative `json:"text,omitempty"` } // MedicationStatementAdherence type MedicationStatementAdherence struct { - Code *CodeableConcept `json:"code"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Reason *CodeableConcept `json:"reason,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + Code *CodeableConcept `json:"code"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Reason *CodeableConcept `json:"reason,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // Meta type Meta struct { - XLastUpdated *FHIRPrimitiveExtension `json:"_lastUpdated,omitempty"` - XProfile []*FHIRPrimitiveExtension `json:"_profile,omitempty"` - XSource *FHIRPrimitiveExtension `json:"_source,omitempty"` - XVersionID *FHIRPrimitiveExtension `json:"_versionId,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - LastUpdated *string `json:"lastUpdated,omitempty"` - Links [][]any `json:"links,omitempty"` - Profile []string `json:"profile,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Security []*Coding `json:"security,omitempty"` - Source *string `json:"source,omitempty"` - Tag []*Coding `json:"tag,omitempty"` - VersionID *string `json:"versionId,omitempty"` + XLastUpdated *FHIRPrimitiveExtension `json:"_lastUpdated,omitempty"` + XProfile []*FHIRPrimitiveExtension `json:"_profile,omitempty"` + XSource *FHIRPrimitiveExtension `json:"_source,omitempty"` + XVersionID *FHIRPrimitiveExtension `json:"_versionId,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + LastUpdated *string `json:"lastUpdated,omitempty"` + Links [][]any `json:"links,omitempty"` + Profile []string `json:"profile,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Security []*Coding `json:"security,omitempty"` + Source *string `json:"source,omitempty"` + Tag []*Coding `json:"tag,omitempty"` + VersionID *string `json:"versionId,omitempty"` } // Money type Money struct { - XCurrency *FHIRPrimitiveExtension `json:"_currency,omitempty"` - XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` - Currency *string `json:"currency,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Value *float64 `json:"value,omitempty"` + XCurrency *FHIRPrimitiveExtension `json:"_currency,omitempty"` + XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` + Currency *string `json:"currency,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Value *float64 `json:"value,omitempty"` } // Narrative type Narrative struct { - XDiv *FHIRPrimitiveExtension `json:"_div,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - Div *string `json:"div,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Status *string `json:"status,omitempty"` + XDiv *FHIRPrimitiveExtension `json:"_div,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + Div *string `json:"div,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Status *string `json:"status,omitempty"` } // Observation type Observation struct { - XEffectiveDateTime *FHIRPrimitiveExtension `json:"_effectiveDateTime,omitempty"` - XEffectiveInstant *FHIRPrimitiveExtension `json:"_effectiveInstant,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XInstantiatesCanonical *FHIRPrimitiveExtension `json:"_instantiatesCanonical,omitempty"` - XIssued *FHIRPrimitiveExtension `json:"_issued,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` - XValueDateTime *FHIRPrimitiveExtension `json:"_valueDateTime,omitempty"` - XValueInteger *FHIRPrimitiveExtension `json:"_valueInteger,omitempty"` - XValueString *FHIRPrimitiveExtension `json:"_valueString,omitempty"` - XValueTime *FHIRPrimitiveExtension `json:"_valueTime,omitempty"` - BasedOn []*Reference `json:"basedOn,omitempty"` - BodySite *CodeableConcept `json:"bodySite,omitempty"` - BodyStructure *Reference `json:"bodyStructure,omitempty"` - Category []*CodeableConcept `json:"category,omitempty"` - Code *CodeableConcept `json:"code"` - Component []*ObservationComponent `json:"component,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - DataAbsentReason *CodeableConcept `json:"dataAbsentReason,omitempty"` - DerivedFrom []*Reference `json:"derivedFrom,omitempty"` - Device *Reference `json:"device,omitempty"` - EffectiveDateTime *string `json:"effectiveDateTime,omitempty"` - EffectiveInstant *string `json:"effectiveInstant,omitempty"` - EffectivePeriod *Period `json:"effectivePeriod,omitempty"` - EffectiveTiming *Timing `json:"effectiveTiming,omitempty"` - Encounter *Reference `json:"encounter,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Focus []*Reference `json:"focus,omitempty"` - HasMember []*Reference `json:"hasMember,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - InstantiatesCanonical *string `json:"instantiatesCanonical,omitempty"` - InstantiatesReference *Reference `json:"instantiatesReference,omitempty"` - Interpretation []*CodeableConcept `json:"interpretation,omitempty"` - Issued *string `json:"issued,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - Method *CodeableConcept `json:"method,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - PartOf []*Reference `json:"partOf,omitempty"` - Performer []*Reference `json:"performer,omitempty"` - ReferenceRange []*ObservationReferenceRange `json:"referenceRange,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Specimen *Reference `json:"specimen,omitempty"` - Status *string `json:"status,omitempty"` - Subject *Reference `json:"subject,omitempty"` - Text *Narrative `json:"text,omitempty"` - TriggeredBy []*ObservationTriggeredBy `json:"triggeredBy,omitempty"` - ValueAttachment *Attachment `json:"valueAttachment,omitempty"` - ValueBoolean *bool `json:"valueBoolean,omitempty"` - ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` - ValueDateTime *string `json:"valueDateTime,omitempty"` - ValueInteger *int64 `json:"valueInteger,omitempty"` - ValuePeriod *Period `json:"valuePeriod,omitempty"` - ValueQuantity *Quantity `json:"valueQuantity,omitempty"` - ValueRange *Range `json:"valueRange,omitempty"` - ValueRatio *Ratio `json:"valueRatio,omitempty"` - ValueReference *Reference `json:"valueReference,omitempty"` - ValueSampledData *SampledData `json:"valueSampledData,omitempty"` - ValueString *string `json:"valueString,omitempty"` - ValueTime *string `json:"valueTime,omitempty"` + XEffectiveDateTime *FHIRPrimitiveExtension `json:"_effectiveDateTime,omitempty"` + XEffectiveInstant *FHIRPrimitiveExtension `json:"_effectiveInstant,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XInstantiatesCanonical *FHIRPrimitiveExtension `json:"_instantiatesCanonical,omitempty"` + XIssued *FHIRPrimitiveExtension `json:"_issued,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` + XValueDateTime *FHIRPrimitiveExtension `json:"_valueDateTime,omitempty"` + XValueInteger *FHIRPrimitiveExtension `json:"_valueInteger,omitempty"` + XValueString *FHIRPrimitiveExtension `json:"_valueString,omitempty"` + XValueTime *FHIRPrimitiveExtension `json:"_valueTime,omitempty"` + BasedOn []*Reference `json:"basedOn,omitempty"` + BodySite *CodeableConcept `json:"bodySite,omitempty"` + BodyStructure *Reference `json:"bodyStructure,omitempty"` + Category []*CodeableConcept `json:"category,omitempty"` + Code *CodeableConcept `json:"code"` + Component []*ObservationComponent `json:"component,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + DataAbsentReason *CodeableConcept `json:"dataAbsentReason,omitempty"` + DerivedFrom []*Reference `json:"derivedFrom,omitempty"` + Device *Reference `json:"device,omitempty"` + EffectiveDateTime *string `json:"effectiveDateTime,omitempty"` + EffectiveInstant *string `json:"effectiveInstant,omitempty"` + EffectivePeriod *Period `json:"effectivePeriod,omitempty"` + EffectiveTiming *Timing `json:"effectiveTiming,omitempty"` + Encounter *Reference `json:"encounter,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Focus []*Reference `json:"focus,omitempty"` + HasMember []*Reference `json:"hasMember,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + InstantiatesCanonical *string `json:"instantiatesCanonical,omitempty"` + InstantiatesReference *Reference `json:"instantiatesReference,omitempty"` + Interpretation []*CodeableConcept `json:"interpretation,omitempty"` + Issued *string `json:"issued,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + Method *CodeableConcept `json:"method,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + PartOf []*Reference `json:"partOf,omitempty"` + Performer []*Reference `json:"performer,omitempty"` + ReferenceRange []*ObservationReferenceRange `json:"referenceRange,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Specimen *Reference `json:"specimen,omitempty"` + Status *string `json:"status,omitempty"` + Subject *Reference `json:"subject,omitempty"` + Text *Narrative `json:"text,omitempty"` + TriggeredBy []*ObservationTriggeredBy `json:"triggeredBy,omitempty"` + ValueAttachment *Attachment `json:"valueAttachment,omitempty"` + ValueBoolean *bool `json:"valueBoolean,omitempty"` + ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` + ValueDateTime *string `json:"valueDateTime,omitempty"` + ValueInteger *int64 `json:"valueInteger,omitempty"` + ValuePeriod *Period `json:"valuePeriod,omitempty"` + ValueQuantity *Quantity `json:"valueQuantity,omitempty"` + ValueRange *Range `json:"valueRange,omitempty"` + ValueRatio *Ratio `json:"valueRatio,omitempty"` + ValueReference *Reference `json:"valueReference,omitempty"` + ValueSampledData *SampledData `json:"valueSampledData,omitempty"` + ValueString *string `json:"valueString,omitempty"` + ValueTime *string `json:"valueTime,omitempty"` } // ObservationComponent type ObservationComponent struct { - XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` - XValueDateTime *FHIRPrimitiveExtension `json:"_valueDateTime,omitempty"` - XValueInteger *FHIRPrimitiveExtension `json:"_valueInteger,omitempty"` - XValueString *FHIRPrimitiveExtension `json:"_valueString,omitempty"` - XValueTime *FHIRPrimitiveExtension `json:"_valueTime,omitempty"` - Code *CodeableConcept `json:"code"` - DataAbsentReason *CodeableConcept `json:"dataAbsentReason,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Interpretation []*CodeableConcept `json:"interpretation,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ReferenceRange []*ObservationReferenceRange `json:"referenceRange,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - ValueAttachment *Attachment `json:"valueAttachment,omitempty"` - ValueBoolean *bool `json:"valueBoolean,omitempty"` - ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` - ValueDateTime *string `json:"valueDateTime,omitempty"` - ValueInteger *int64 `json:"valueInteger,omitempty"` - ValuePeriod *Period `json:"valuePeriod,omitempty"` - ValueQuantity *Quantity `json:"valueQuantity,omitempty"` - ValueRange *Range `json:"valueRange,omitempty"` - ValueRatio *Ratio `json:"valueRatio,omitempty"` - ValueReference *Reference `json:"valueReference,omitempty"` - ValueSampledData *SampledData `json:"valueSampledData,omitempty"` - ValueString *string `json:"valueString,omitempty"` - ValueTime *string `json:"valueTime,omitempty"` + XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` + XValueDateTime *FHIRPrimitiveExtension `json:"_valueDateTime,omitempty"` + XValueInteger *FHIRPrimitiveExtension `json:"_valueInteger,omitempty"` + XValueString *FHIRPrimitiveExtension `json:"_valueString,omitempty"` + XValueTime *FHIRPrimitiveExtension `json:"_valueTime,omitempty"` + Code *CodeableConcept `json:"code"` + DataAbsentReason *CodeableConcept `json:"dataAbsentReason,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Interpretation []*CodeableConcept `json:"interpretation,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ReferenceRange []*ObservationReferenceRange `json:"referenceRange,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + ValueAttachment *Attachment `json:"valueAttachment,omitempty"` + ValueBoolean *bool `json:"valueBoolean,omitempty"` + ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` + ValueDateTime *string `json:"valueDateTime,omitempty"` + ValueInteger *int64 `json:"valueInteger,omitempty"` + ValuePeriod *Period `json:"valuePeriod,omitempty"` + ValueQuantity *Quantity `json:"valueQuantity,omitempty"` + ValueRange *Range `json:"valueRange,omitempty"` + ValueRatio *Ratio `json:"valueRatio,omitempty"` + ValueReference *Reference `json:"valueReference,omitempty"` + ValueSampledData *SampledData `json:"valueSampledData,omitempty"` + ValueString *string `json:"valueString,omitempty"` + ValueTime *string `json:"valueTime,omitempty"` } // ObservationReferenceRange type ObservationReferenceRange struct { - XText *FHIRPrimitiveExtension `json:"_text,omitempty"` - Age *Range `json:"age,omitempty"` - AppliesTo []*CodeableConcept `json:"appliesTo,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - High *Quantity `json:"high,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Low *Quantity `json:"low,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - NormalValue *CodeableConcept `json:"normalValue,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Text *string `json:"text,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` + XText *FHIRPrimitiveExtension `json:"_text,omitempty"` + Age *Range `json:"age,omitempty"` + AppliesTo []*CodeableConcept `json:"appliesTo,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + High *Quantity `json:"high,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Low *Quantity `json:"low,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + NormalValue *CodeableConcept `json:"normalValue,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Text *string `json:"text,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` } // ObservationTriggeredBy type ObservationTriggeredBy struct { - XReason *FHIRPrimitiveExtension `json:"_reason,omitempty"` - XType *FHIRPrimitiveExtension `json:"_type,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Observation *Reference `json:"observation"` - Reason *string `json:"reason,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *string `json:"type,omitempty"` + XReason *FHIRPrimitiveExtension `json:"_reason,omitempty"` + XType *FHIRPrimitiveExtension `json:"_type,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Observation *Reference `json:"observation"` + Reason *string `json:"reason,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *string `json:"type,omitempty"` } // Organization type Organization struct { - XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` - XAlias []*FHIRPrimitiveExtension `json:"_alias,omitempty"` - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - Active *bool `json:"active,omitempty"` - Alias []string `json:"alias,omitempty"` - Contact []*ExtendedContactDetail `json:"contact,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Description *string `json:"description,omitempty"` - Endpoint []*Reference `json:"endpoint,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Name *string `json:"name,omitempty"` - PartOf *Reference `json:"partOf,omitempty"` - Qualification []*OrganizationQualification `json:"qualification,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Text *Narrative `json:"text,omitempty"` - Type []*CodeableConcept `json:"type,omitempty"` + XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` + XAlias []*FHIRPrimitiveExtension `json:"_alias,omitempty"` + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + Active *bool `json:"active,omitempty"` + Alias []string `json:"alias,omitempty"` + Contact []*ExtendedContactDetail `json:"contact,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Description *string `json:"description,omitempty"` + Endpoint []*Reference `json:"endpoint,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Name *string `json:"name,omitempty"` + PartOf *Reference `json:"partOf,omitempty"` + Qualification []*OrganizationQualification `json:"qualification,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Text *Narrative `json:"text,omitempty"` + Type []*CodeableConcept `json:"type,omitempty"` } // OrganizationQualification type OrganizationQualification struct { - Code *CodeableConcept `json:"code"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - Issuer *Reference `json:"issuer,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Period *Period `json:"period,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + Code *CodeableConcept `json:"code"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + Issuer *Reference `json:"issuer,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Period *Period `json:"period,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // ParameterDefinition type ParameterDefinition struct { XDocumentation *FHIRPrimitiveExtension `json:"_documentation,omitempty"` - XMax *FHIRPrimitiveExtension `json:"_max,omitempty"` - XMin *FHIRPrimitiveExtension `json:"_min,omitempty"` - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - XProfile *FHIRPrimitiveExtension `json:"_profile,omitempty"` - XType *FHIRPrimitiveExtension `json:"_type,omitempty"` - XUse *FHIRPrimitiveExtension `json:"_use,omitempty"` - Documentation *string `json:"documentation,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Max *string `json:"max,omitempty"` - Min *int64 `json:"min,omitempty"` - Name *string `json:"name,omitempty"` - Profile *string `json:"profile,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *string `json:"type,omitempty"` - Use *string `json:"use,omitempty"` + XMax *FHIRPrimitiveExtension `json:"_max,omitempty"` + XMin *FHIRPrimitiveExtension `json:"_min,omitempty"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + XProfile *FHIRPrimitiveExtension `json:"_profile,omitempty"` + XType *FHIRPrimitiveExtension `json:"_type,omitempty"` + XUse *FHIRPrimitiveExtension `json:"_use,omitempty"` + Documentation *string `json:"documentation,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Max *string `json:"max,omitempty"` + Min *int64 `json:"min,omitempty"` + Name *string `json:"name,omitempty"` + Profile *string `json:"profile,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *string `json:"type,omitempty"` + Use *string `json:"use,omitempty"` } // Patient type Patient struct { - XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` - XBirthDate *FHIRPrimitiveExtension `json:"_birthDate,omitempty"` - XDeceasedBoolean *FHIRPrimitiveExtension `json:"_deceasedBoolean,omitempty"` - XDeceasedDateTime *FHIRPrimitiveExtension `json:"_deceasedDateTime,omitempty"` - XGender *FHIRPrimitiveExtension `json:"_gender,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` + XBirthDate *FHIRPrimitiveExtension `json:"_birthDate,omitempty"` + XDeceasedBoolean *FHIRPrimitiveExtension `json:"_deceasedBoolean,omitempty"` + XDeceasedDateTime *FHIRPrimitiveExtension `json:"_deceasedDateTime,omitempty"` + XGender *FHIRPrimitiveExtension `json:"_gender,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` XMultipleBirthBoolean *FHIRPrimitiveExtension `json:"_multipleBirthBoolean,omitempty"` XMultipleBirthInteger *FHIRPrimitiveExtension `json:"_multipleBirthInteger,omitempty"` - Active *bool `json:"active,omitempty"` - Address []*Address `json:"address,omitempty"` - BirthDate *string `json:"birthDate,omitempty"` - Communication []*PatientCommunication `json:"communication,omitempty"` - Contact []*PatientContact `json:"contact,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - DeceasedBoolean *bool `json:"deceasedBoolean,omitempty"` - DeceasedDateTime *string `json:"deceasedDateTime,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Gender *string `json:"gender,omitempty"` - GeneralPractitioner []*Reference `json:"generalPractitioner,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Language *string `json:"language,omitempty"` - Link []*PatientLink `json:"link,omitempty"` - Links [][]any `json:"links,omitempty"` - ManagingOrganization *Reference `json:"managingOrganization,omitempty"` - MaritalStatus *CodeableConcept `json:"maritalStatus,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - MultipleBirthBoolean *bool `json:"multipleBirthBoolean,omitempty"` - MultipleBirthInteger *int64 `json:"multipleBirthInteger,omitempty"` - Name []*HumanName `json:"name,omitempty"` - Photo []*Attachment `json:"photo,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Telecom []*ContactPoint `json:"telecom,omitempty"` - Text *Narrative `json:"text,omitempty"` + Active *bool `json:"active,omitempty"` + Address []*Address `json:"address,omitempty"` + BirthDate *string `json:"birthDate,omitempty"` + Communication []*PatientCommunication `json:"communication,omitempty"` + Contact []*PatientContact `json:"contact,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + DeceasedBoolean *bool `json:"deceasedBoolean,omitempty"` + DeceasedDateTime *string `json:"deceasedDateTime,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Gender *string `json:"gender,omitempty"` + GeneralPractitioner []*Reference `json:"generalPractitioner,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Language *string `json:"language,omitempty"` + Link []*PatientLink `json:"link,omitempty"` + Links [][]any `json:"links,omitempty"` + ManagingOrganization *Reference `json:"managingOrganization,omitempty"` + MaritalStatus *CodeableConcept `json:"maritalStatus,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + MultipleBirthBoolean *bool `json:"multipleBirthBoolean,omitempty"` + MultipleBirthInteger *int64 `json:"multipleBirthInteger,omitempty"` + Name []*HumanName `json:"name,omitempty"` + Photo []*Attachment `json:"photo,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Telecom []*ContactPoint `json:"telecom,omitempty"` + Text *Narrative `json:"text,omitempty"` } // PatientCommunication type PatientCommunication struct { - XPreferred *FHIRPrimitiveExtension `json:"_preferred,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Language *CodeableConcept `json:"language"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Preferred *bool `json:"preferred,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + XPreferred *FHIRPrimitiveExtension `json:"_preferred,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Language *CodeableConcept `json:"language"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Preferred *bool `json:"preferred,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // PatientContact type PatientContact struct { - XGender *FHIRPrimitiveExtension `json:"_gender,omitempty"` - Address *Address `json:"address,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Gender *string `json:"gender,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Name *HumanName `json:"name,omitempty"` - Organization *Reference `json:"organization,omitempty"` - Period *Period `json:"period,omitempty"` - Relationship []*CodeableConcept `json:"relationship,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Telecom []*ContactPoint `json:"telecom,omitempty"` + XGender *FHIRPrimitiveExtension `json:"_gender,omitempty"` + Address *Address `json:"address,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Gender *string `json:"gender,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Name *HumanName `json:"name,omitempty"` + Organization *Reference `json:"organization,omitempty"` + Period *Period `json:"period,omitempty"` + Relationship []*CodeableConcept `json:"relationship,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Telecom []*ContactPoint `json:"telecom,omitempty"` } // PatientLink type PatientLink struct { - XType *FHIRPrimitiveExtension `json:"_type,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Other *Reference `json:"other"` - ResourceType *string `json:"resourceType,omitempty"` - Type *string `json:"type,omitempty"` + XType *FHIRPrimitiveExtension `json:"_type,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Other *Reference `json:"other"` + ResourceType *string `json:"resourceType,omitempty"` + Type *string `json:"type,omitempty"` } // Period type Period struct { - XEnd *FHIRPrimitiveExtension `json:"_end,omitempty"` - XStart *FHIRPrimitiveExtension `json:"_start,omitempty"` - End *string `json:"end,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Start *string `json:"start,omitempty"` + XEnd *FHIRPrimitiveExtension `json:"_end,omitempty"` + XStart *FHIRPrimitiveExtension `json:"_start,omitempty"` + End *string `json:"end,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Start *string `json:"start,omitempty"` } // Practitioner type Practitioner struct { - XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` - XBirthDate *FHIRPrimitiveExtension `json:"_birthDate,omitempty"` - XDeceasedBoolean *FHIRPrimitiveExtension `json:"_deceasedBoolean,omitempty"` - XDeceasedDateTime *FHIRPrimitiveExtension `json:"_deceasedDateTime,omitempty"` - XGender *FHIRPrimitiveExtension `json:"_gender,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - Active *bool `json:"active,omitempty"` - Address []*Address `json:"address,omitempty"` - BirthDate *string `json:"birthDate,omitempty"` - Communication []*PractitionerCommunication `json:"communication,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - DeceasedBoolean *bool `json:"deceasedBoolean,omitempty"` - DeceasedDateTime *string `json:"deceasedDateTime,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Gender *string `json:"gender,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Name []*HumanName `json:"name,omitempty"` - Photo []*Attachment `json:"photo,omitempty"` - Qualification []*PractitionerQualification `json:"qualification,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Telecom []*ContactPoint `json:"telecom,omitempty"` - Text *Narrative `json:"text,omitempty"` + XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` + XBirthDate *FHIRPrimitiveExtension `json:"_birthDate,omitempty"` + XDeceasedBoolean *FHIRPrimitiveExtension `json:"_deceasedBoolean,omitempty"` + XDeceasedDateTime *FHIRPrimitiveExtension `json:"_deceasedDateTime,omitempty"` + XGender *FHIRPrimitiveExtension `json:"_gender,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + Active *bool `json:"active,omitempty"` + Address []*Address `json:"address,omitempty"` + BirthDate *string `json:"birthDate,omitempty"` + Communication []*PractitionerCommunication `json:"communication,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + DeceasedBoolean *bool `json:"deceasedBoolean,omitempty"` + DeceasedDateTime *string `json:"deceasedDateTime,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Gender *string `json:"gender,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Name []*HumanName `json:"name,omitempty"` + Photo []*Attachment `json:"photo,omitempty"` + Qualification []*PractitionerQualification `json:"qualification,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Telecom []*ContactPoint `json:"telecom,omitempty"` + Text *Narrative `json:"text,omitempty"` } // PractitionerCommunication type PractitionerCommunication struct { - XPreferred *FHIRPrimitiveExtension `json:"_preferred,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Language *CodeableConcept `json:"language"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Preferred *bool `json:"preferred,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + XPreferred *FHIRPrimitiveExtension `json:"_preferred,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Language *CodeableConcept `json:"language"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Preferred *bool `json:"preferred,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // PractitionerQualification type PractitionerQualification struct { - Code *CodeableConcept `json:"code"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - Issuer *Reference `json:"issuer,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Period *Period `json:"period,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + Code *CodeableConcept `json:"code"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + Issuer *Reference `json:"issuer,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Period *Period `json:"period,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // PractitionerRole type PractitionerRole struct { - XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - Active *bool `json:"active,omitempty"` - Availability []*Availability `json:"availability,omitempty"` - Characteristic []*CodeableConcept `json:"characteristic,omitempty"` - Code []*CodeableConcept `json:"code,omitempty"` - Communication []*CodeableConcept `json:"communication,omitempty"` - Contact []*ExtendedContactDetail `json:"contact,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Endpoint []*Reference `json:"endpoint,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - HealthcareService []*Reference `json:"healthcareService,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Location []*Reference `json:"location,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Organization *Reference `json:"organization,omitempty"` - Period *Period `json:"period,omitempty"` - Practitioner *Reference `json:"practitioner,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Specialty []*CodeableConcept `json:"specialty,omitempty"` - Text *Narrative `json:"text,omitempty"` + XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + Active *bool `json:"active,omitempty"` + Availability []*Availability `json:"availability,omitempty"` + Characteristic []*CodeableConcept `json:"characteristic,omitempty"` + Code []*CodeableConcept `json:"code,omitempty"` + Communication []*CodeableConcept `json:"communication,omitempty"` + Contact []*ExtendedContactDetail `json:"contact,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Endpoint []*Reference `json:"endpoint,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + HealthcareService []*Reference `json:"healthcareService,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Location []*Reference `json:"location,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Organization *Reference `json:"organization,omitempty"` + Period *Period `json:"period,omitempty"` + Practitioner *Reference `json:"practitioner,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Specialty []*CodeableConcept `json:"specialty,omitempty"` + Text *Narrative `json:"text,omitempty"` } // Procedure type Procedure struct { - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` XInstantiatesCanonical []*FHIRPrimitiveExtension `json:"_instantiatesCanonical,omitempty"` - XInstantiatesURI []*FHIRPrimitiveExtension `json:"_instantiatesUri,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XOccurrenceDateTime *FHIRPrimitiveExtension `json:"_occurrenceDateTime,omitempty"` - XOccurrenceString *FHIRPrimitiveExtension `json:"_occurrenceString,omitempty"` - XRecorded *FHIRPrimitiveExtension `json:"_recorded,omitempty"` - XReportedBoolean *FHIRPrimitiveExtension `json:"_reportedBoolean,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - BasedOn []*Reference `json:"basedOn,omitempty"` - BodySite []*CodeableConcept `json:"bodySite,omitempty"` - Category []*CodeableConcept `json:"category,omitempty"` - Code *CodeableConcept `json:"code,omitempty"` - Complication []*CodeableReference `json:"complication,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Encounter *Reference `json:"encounter,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - FocalDevice []*ProcedureFocalDevice `json:"focalDevice,omitempty"` - Focus *Reference `json:"focus,omitempty"` - FollowUp []*CodeableConcept `json:"followUp,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - InstantiatesCanonical []string `json:"instantiatesCanonical,omitempty"` - InstantiatesURI []string `json:"instantiatesUri,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Location *Reference `json:"location,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - OccurrenceAge *Age `json:"occurrenceAge,omitempty"` - OccurrenceDateTime *string `json:"occurrenceDateTime,omitempty"` - OccurrencePeriod *Period `json:"occurrencePeriod,omitempty"` - OccurrenceRange *Range `json:"occurrenceRange,omitempty"` - OccurrenceString *string `json:"occurrenceString,omitempty"` - OccurrenceTiming *Timing `json:"occurrenceTiming,omitempty"` - Outcome *CodeableConcept `json:"outcome,omitempty"` - PartOf []*Reference `json:"partOf,omitempty"` - Performer []*ProcedurePerformer `json:"performer,omitempty"` - Reason []*CodeableReference `json:"reason,omitempty"` - Recorded *string `json:"recorded,omitempty"` - Recorder *Reference `json:"recorder,omitempty"` - Report []*Reference `json:"report,omitempty"` - ReportedBoolean *bool `json:"reportedBoolean,omitempty"` - ReportedReference *Reference `json:"reportedReference,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Status *string `json:"status,omitempty"` - StatusReason *CodeableConcept `json:"statusReason,omitempty"` - Subject *Reference `json:"subject"` - SupportingInfo []*Reference `json:"supportingInfo,omitempty"` - Text *Narrative `json:"text,omitempty"` - Used []*CodeableReference `json:"used,omitempty"` + XInstantiatesURI []*FHIRPrimitiveExtension `json:"_instantiatesUri,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XOccurrenceDateTime *FHIRPrimitiveExtension `json:"_occurrenceDateTime,omitempty"` + XOccurrenceString *FHIRPrimitiveExtension `json:"_occurrenceString,omitempty"` + XRecorded *FHIRPrimitiveExtension `json:"_recorded,omitempty"` + XReportedBoolean *FHIRPrimitiveExtension `json:"_reportedBoolean,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + BasedOn []*Reference `json:"basedOn,omitempty"` + BodySite []*CodeableConcept `json:"bodySite,omitempty"` + Category []*CodeableConcept `json:"category,omitempty"` + Code *CodeableConcept `json:"code,omitempty"` + Complication []*CodeableReference `json:"complication,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Encounter *Reference `json:"encounter,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + FocalDevice []*ProcedureFocalDevice `json:"focalDevice,omitempty"` + Focus *Reference `json:"focus,omitempty"` + FollowUp []*CodeableConcept `json:"followUp,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + InstantiatesCanonical []string `json:"instantiatesCanonical,omitempty"` + InstantiatesURI []string `json:"instantiatesUri,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Location *Reference `json:"location,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + OccurrenceAge *Age `json:"occurrenceAge,omitempty"` + OccurrenceDateTime *string `json:"occurrenceDateTime,omitempty"` + OccurrencePeriod *Period `json:"occurrencePeriod,omitempty"` + OccurrenceRange *Range `json:"occurrenceRange,omitempty"` + OccurrenceString *string `json:"occurrenceString,omitempty"` + OccurrenceTiming *Timing `json:"occurrenceTiming,omitempty"` + Outcome *CodeableConcept `json:"outcome,omitempty"` + PartOf []*Reference `json:"partOf,omitempty"` + Performer []*ProcedurePerformer `json:"performer,omitempty"` + Reason []*CodeableReference `json:"reason,omitempty"` + Recorded *string `json:"recorded,omitempty"` + Recorder *Reference `json:"recorder,omitempty"` + Report []*Reference `json:"report,omitempty"` + ReportedBoolean *bool `json:"reportedBoolean,omitempty"` + ReportedReference *Reference `json:"reportedReference,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Status *string `json:"status,omitempty"` + StatusReason *CodeableConcept `json:"statusReason,omitempty"` + Subject *Reference `json:"subject"` + SupportingInfo []*Reference `json:"supportingInfo,omitempty"` + Text *Narrative `json:"text,omitempty"` + Used []*CodeableReference `json:"used,omitempty"` } // ProcedureFocalDevice type ProcedureFocalDevice struct { - Action *CodeableConcept `json:"action,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Manipulated *Reference `json:"manipulated"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + Action *CodeableConcept `json:"action,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Manipulated *Reference `json:"manipulated"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // ProcedurePerformer type ProcedurePerformer struct { - Actor *Reference `json:"actor"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Function *CodeableConcept `json:"function,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - OnBehalfOf *Reference `json:"onBehalfOf,omitempty"` - Period *Period `json:"period,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + Actor *Reference `json:"actor"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Function *CodeableConcept `json:"function,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + OnBehalfOf *Reference `json:"onBehalfOf,omitempty"` + Period *Period `json:"period,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // Quantity type Quantity struct { - XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` - XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` - XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` - XUnit *FHIRPrimitiveExtension `json:"_unit,omitempty"` - XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` - Code *string `json:"code,omitempty"` - Comparator *string `json:"comparator,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - System *string `json:"system,omitempty"` - Unit *string `json:"unit,omitempty"` - Value *float64 `json:"value,omitempty"` + XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` + XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` + XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` + XUnit *FHIRPrimitiveExtension `json:"_unit,omitempty"` + XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` + Code *string `json:"code,omitempty"` + Comparator *string `json:"comparator,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + System *string `json:"system,omitempty"` + Unit *string `json:"unit,omitempty"` + Value *float64 `json:"value,omitempty"` } // Range type Range struct { - Extension []*Extension `json:"extension,omitempty"` + Extension []*Extension `json:"extension,omitempty"` FhirComments FHIRComments `json:"fhir_comments,omitempty"` - High *Quantity `json:"high,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Low *Quantity `json:"low,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + High *Quantity `json:"high,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Low *Quantity `json:"low,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // Ratio type Ratio struct { - Denominator *Quantity `json:"denominator,omitempty"` - Extension []*Extension `json:"extension,omitempty"` + Denominator *Quantity `json:"denominator,omitempty"` + Extension []*Extension `json:"extension,omitempty"` FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Numerator *Quantity `json:"numerator,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Numerator *Quantity `json:"numerator,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // RatioRange type RatioRange struct { - Denominator *Quantity `json:"denominator,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - HighNumerator *Quantity `json:"highNumerator,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - LowNumerator *Quantity `json:"lowNumerator,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + Denominator *Quantity `json:"denominator,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + HighNumerator *Quantity `json:"highNumerator,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + LowNumerator *Quantity `json:"lowNumerator,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // Reference type Reference struct { - XDisplay *FHIRPrimitiveExtension `json:"_display,omitempty"` - XReference *FHIRPrimitiveExtension `json:"_reference,omitempty"` - XType *FHIRPrimitiveExtension `json:"_type,omitempty"` - Display *string `json:"display,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier *Identifier `json:"identifier,omitempty"` - Links [][]any `json:"links,omitempty"` - Reference *string `json:"reference,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *string `json:"type,omitempty"` + XDisplay *FHIRPrimitiveExtension `json:"_display,omitempty"` + XReference *FHIRPrimitiveExtension `json:"_reference,omitempty"` + XType *FHIRPrimitiveExtension `json:"_type,omitempty"` + Display *string `json:"display,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier *Identifier `json:"identifier,omitempty"` + Links [][]any `json:"links,omitempty"` + Reference *string `json:"reference,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *string `json:"type,omitempty"` } // RelatedArtifact type RelatedArtifact struct { - XCitation *FHIRPrimitiveExtension `json:"_citation,omitempty"` - XDisplay *FHIRPrimitiveExtension `json:"_display,omitempty"` - XLabel *FHIRPrimitiveExtension `json:"_label,omitempty"` - XPublicationDate *FHIRPrimitiveExtension `json:"_publicationDate,omitempty"` + XCitation *FHIRPrimitiveExtension `json:"_citation,omitempty"` + XDisplay *FHIRPrimitiveExtension `json:"_display,omitempty"` + XLabel *FHIRPrimitiveExtension `json:"_label,omitempty"` + XPublicationDate *FHIRPrimitiveExtension `json:"_publicationDate,omitempty"` XPublicationStatus *FHIRPrimitiveExtension `json:"_publicationStatus,omitempty"` - XResource *FHIRPrimitiveExtension `json:"_resource,omitempty"` - XType *FHIRPrimitiveExtension `json:"_type,omitempty"` - Citation *string `json:"citation,omitempty"` - Classifier []*CodeableConcept `json:"classifier,omitempty"` - Display *string `json:"display,omitempty"` - Document *Attachment `json:"document,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Label *string `json:"label,omitempty"` - Links [][]any `json:"links,omitempty"` - PublicationDate *string `json:"publicationDate,omitempty"` - PublicationStatus *string `json:"publicationStatus,omitempty"` - Resource *string `json:"resource,omitempty"` - ResourceReference *Reference `json:"resourceReference,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *string `json:"type,omitempty"` + XResource *FHIRPrimitiveExtension `json:"_resource,omitempty"` + XType *FHIRPrimitiveExtension `json:"_type,omitempty"` + Citation *string `json:"citation,omitempty"` + Classifier []*CodeableConcept `json:"classifier,omitempty"` + Display *string `json:"display,omitempty"` + Document *Attachment `json:"document,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Label *string `json:"label,omitempty"` + Links [][]any `json:"links,omitempty"` + PublicationDate *string `json:"publicationDate,omitempty"` + PublicationStatus *string `json:"publicationStatus,omitempty"` + Resource *string `json:"resource,omitempty"` + ResourceReference *Reference `json:"resourceReference,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *string `json:"type,omitempty"` } // ResearchStudy type ResearchStudy struct { - XDate *FHIRPrimitiveExtension `json:"_date,omitempty"` - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XDescriptionSummary *FHIRPrimitiveExtension `json:"_descriptionSummary,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - XTitle *FHIRPrimitiveExtension `json:"_title,omitempty"` - XURL *FHIRPrimitiveExtension `json:"_url,omitempty"` - XVersion *FHIRPrimitiveExtension `json:"_version,omitempty"` - AssociatedParty []*ResearchStudyAssociatedParty `json:"associatedParty,omitempty"` - Classifier []*CodeableConcept `json:"classifier,omitempty"` - ComparisonGroup []*ResearchStudyComparisonGroup `json:"comparisonGroup,omitempty"` - Condition []*CodeableConcept `json:"condition,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Date *string `json:"date,omitempty"` - Description *string `json:"description,omitempty"` - DescriptionSummary *string `json:"descriptionSummary,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Focus []*CodeableReference `json:"focus,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Keyword []*CodeableConcept `json:"keyword,omitempty"` - Label []*ResearchStudyLabel `json:"label,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Name *string `json:"name,omitempty"` - Note []*Annotation `json:"note,omitempty"` - Objective []*ResearchStudyObjective `json:"objective,omitempty"` - OutcomeMeasure []*ResearchStudyOutcomeMeasure `json:"outcomeMeasure,omitempty"` - PartOf []*Reference `json:"partOf,omitempty"` - Period *Period `json:"period,omitempty"` - Phase *CodeableConcept `json:"phase,omitempty"` - PrimaryPurposeType *CodeableConcept `json:"primaryPurposeType,omitempty"` - ProgressStatus []*ResearchStudyProgressStatus `json:"progressStatus,omitempty"` - Protocol []*Reference `json:"protocol,omitempty"` - Recruitment *ResearchStudyRecruitment `json:"recruitment,omitempty"` - Region []*CodeableConcept `json:"region,omitempty"` - RelatedArtifact []*RelatedArtifact `json:"relatedArtifact,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Result []*Reference `json:"result,omitempty"` - RootDir *Reference `json:"rootDir,omitempty"` - Site []*Reference `json:"site,omitempty"` - Status *string `json:"status,omitempty"` - StudyDesign []*CodeableConcept `json:"studyDesign,omitempty"` - Text *Narrative `json:"text,omitempty"` - Title *string `json:"title,omitempty"` - URL *string `json:"url,omitempty"` - Version *string `json:"version,omitempty"` - WhyStopped *CodeableConcept `json:"whyStopped,omitempty"` + XDate *FHIRPrimitiveExtension `json:"_date,omitempty"` + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XDescriptionSummary *FHIRPrimitiveExtension `json:"_descriptionSummary,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + XTitle *FHIRPrimitiveExtension `json:"_title,omitempty"` + XURL *FHIRPrimitiveExtension `json:"_url,omitempty"` + XVersion *FHIRPrimitiveExtension `json:"_version,omitempty"` + AssociatedParty []*ResearchStudyAssociatedParty `json:"associatedParty,omitempty"` + Classifier []*CodeableConcept `json:"classifier,omitempty"` + ComparisonGroup []*ResearchStudyComparisonGroup `json:"comparisonGroup,omitempty"` + Condition []*CodeableConcept `json:"condition,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Date *string `json:"date,omitempty"` + Description *string `json:"description,omitempty"` + DescriptionSummary *string `json:"descriptionSummary,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Focus []*CodeableReference `json:"focus,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Keyword []*CodeableConcept `json:"keyword,omitempty"` + Label []*ResearchStudyLabel `json:"label,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Name *string `json:"name,omitempty"` + Note []*Annotation `json:"note,omitempty"` + Objective []*ResearchStudyObjective `json:"objective,omitempty"` + OutcomeMeasure []*ResearchStudyOutcomeMeasure `json:"outcomeMeasure,omitempty"` + PartOf []*Reference `json:"partOf,omitempty"` + Period *Period `json:"period,omitempty"` + Phase *CodeableConcept `json:"phase,omitempty"` + PrimaryPurposeType *CodeableConcept `json:"primaryPurposeType,omitempty"` + ProgressStatus []*ResearchStudyProgressStatus `json:"progressStatus,omitempty"` + Protocol []*Reference `json:"protocol,omitempty"` + Recruitment *ResearchStudyRecruitment `json:"recruitment,omitempty"` + Region []*CodeableConcept `json:"region,omitempty"` + RelatedArtifact []*RelatedArtifact `json:"relatedArtifact,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Result []*Reference `json:"result,omitempty"` + RootDir *Reference `json:"rootDir,omitempty"` + Site []*Reference `json:"site,omitempty"` + Status *string `json:"status,omitempty"` + StudyDesign []*CodeableConcept `json:"studyDesign,omitempty"` + Text *Narrative `json:"text,omitempty"` + Title *string `json:"title,omitempty"` + URL *string `json:"url,omitempty"` + Version *string `json:"version,omitempty"` + WhyStopped *CodeableConcept `json:"whyStopped,omitempty"` } // ResearchStudyAssociatedParty type ResearchStudyAssociatedParty struct { - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - Classifier []*CodeableConcept `json:"classifier,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Name *string `json:"name,omitempty"` - Party *Reference `json:"party,omitempty"` - Period []*Period `json:"period,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Role *CodeableConcept `json:"role"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + Classifier []*CodeableConcept `json:"classifier,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Name *string `json:"name,omitempty"` + Party *Reference `json:"party,omitempty"` + Period []*Period `json:"period,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Role *CodeableConcept `json:"role"` } // ResearchStudyComparisonGroup type ResearchStudyComparisonGroup struct { - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XLinkID *FHIRPrimitiveExtension `json:"_linkId,omitempty"` - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - Description *string `json:"description,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IntendedExposure []*Reference `json:"intendedExposure,omitempty"` - LinkID *string `json:"linkId,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Name *string `json:"name,omitempty"` - ObservedGroup *Reference `json:"observedGroup,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XLinkID *FHIRPrimitiveExtension `json:"_linkId,omitempty"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + Description *string `json:"description,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IntendedExposure []*Reference `json:"intendedExposure,omitempty"` + LinkID *string `json:"linkId,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Name *string `json:"name,omitempty"` + ObservedGroup *Reference `json:"observedGroup,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` } // ResearchStudyLabel type ResearchStudyLabel struct { - XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` - Value *string `json:"value,omitempty"` + XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` + Value *string `json:"value,omitempty"` } // ResearchStudyObjective type ResearchStudyObjective struct { - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - Description *string `json:"description,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Name *string `json:"name,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + Description *string `json:"description,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Name *string `json:"name,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` } // ResearchStudyOutcomeMeasure type ResearchStudyOutcomeMeasure struct { - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - Description *string `json:"description,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Name *string `json:"name,omitempty"` - Reference *Reference `json:"reference,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type []*CodeableConcept `json:"type,omitempty"` + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + Description *string `json:"description,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Name *string `json:"name,omitempty"` + Reference *Reference `json:"reference,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type []*CodeableConcept `json:"type,omitempty"` } // ResearchStudyProgressStatus type ResearchStudyProgressStatus struct { - XActual *FHIRPrimitiveExtension `json:"_actual,omitempty"` - Actual *bool `json:"actual,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Period *Period `json:"period,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - State *CodeableConcept `json:"state"` + XActual *FHIRPrimitiveExtension `json:"_actual,omitempty"` + Actual *bool `json:"actual,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Period *Period `json:"period,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + State *CodeableConcept `json:"state"` } // ResearchStudyRecruitment type ResearchStudyRecruitment struct { - XActualNumber *FHIRPrimitiveExtension `json:"_actualNumber,omitempty"` - XTargetNumber *FHIRPrimitiveExtension `json:"_targetNumber,omitempty"` - ActualGroup *Reference `json:"actualGroup,omitempty"` - ActualNumber *int64 `json:"actualNumber,omitempty"` - Eligibility *Reference `json:"eligibility,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - TargetNumber *int64 `json:"targetNumber,omitempty"` + XActualNumber *FHIRPrimitiveExtension `json:"_actualNumber,omitempty"` + XTargetNumber *FHIRPrimitiveExtension `json:"_targetNumber,omitempty"` + ActualGroup *Reference `json:"actualGroup,omitempty"` + ActualNumber *int64 `json:"actualNumber,omitempty"` + Eligibility *Reference `json:"eligibility,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + TargetNumber *int64 `json:"targetNumber,omitempty"` } // ResearchSubject type ResearchSubject struct { - XActualComparisonGroup *FHIRPrimitiveExtension `json:"_actualComparisonGroup,omitempty"` - XAssignedComparisonGroup *FHIRPrimitiveExtension `json:"_assignedComparisonGroup,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - ActualComparisonGroup *string `json:"actualComparisonGroup,omitempty"` - AssignedComparisonGroup *string `json:"assignedComparisonGroup,omitempty"` - Consent []*Reference `json:"consent,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Period *Period `json:"period,omitempty"` - Progress []*ResearchSubjectProgress `json:"progress,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Status *string `json:"status,omitempty"` - Study *Reference `json:"study"` - Subject *Reference `json:"subject"` - Text *Narrative `json:"text,omitempty"` + XActualComparisonGroup *FHIRPrimitiveExtension `json:"_actualComparisonGroup,omitempty"` + XAssignedComparisonGroup *FHIRPrimitiveExtension `json:"_assignedComparisonGroup,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + ActualComparisonGroup *string `json:"actualComparisonGroup,omitempty"` + AssignedComparisonGroup *string `json:"assignedComparisonGroup,omitempty"` + Consent []*Reference `json:"consent,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Period *Period `json:"period,omitempty"` + Progress []*ResearchSubjectProgress `json:"progress,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Status *string `json:"status,omitempty"` + Study *Reference `json:"study"` + Subject *Reference `json:"subject"` + Text *Narrative `json:"text,omitempty"` } // ResearchSubjectProgress type ResearchSubjectProgress struct { - XEndDate *FHIRPrimitiveExtension `json:"_endDate,omitempty"` - XStartDate *FHIRPrimitiveExtension `json:"_startDate,omitempty"` - EndDate *string `json:"endDate,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Milestone *CodeableConcept `json:"milestone,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Reason *CodeableConcept `json:"reason,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - StartDate *string `json:"startDate,omitempty"` - SubjectState *CodeableConcept `json:"subjectState,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` + XEndDate *FHIRPrimitiveExtension `json:"_endDate,omitempty"` + XStartDate *FHIRPrimitiveExtension `json:"_startDate,omitempty"` + EndDate *string `json:"endDate,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Milestone *CodeableConcept `json:"milestone,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Reason *CodeableConcept `json:"reason,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + StartDate *string `json:"startDate,omitempty"` + SubjectState *CodeableConcept `json:"subjectState,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` } // Resource type Resource struct { XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // SampledData type SampledData struct { - XCodeMap *FHIRPrimitiveExtension `json:"_codeMap,omitempty"` - XData *FHIRPrimitiveExtension `json:"_data,omitempty"` - XDimensions *FHIRPrimitiveExtension `json:"_dimensions,omitempty"` - XFactor *FHIRPrimitiveExtension `json:"_factor,omitempty"` - XInterval *FHIRPrimitiveExtension `json:"_interval,omitempty"` + XCodeMap *FHIRPrimitiveExtension `json:"_codeMap,omitempty"` + XData *FHIRPrimitiveExtension `json:"_data,omitempty"` + XDimensions *FHIRPrimitiveExtension `json:"_dimensions,omitempty"` + XFactor *FHIRPrimitiveExtension `json:"_factor,omitempty"` + XInterval *FHIRPrimitiveExtension `json:"_interval,omitempty"` XIntervalUnit *FHIRPrimitiveExtension `json:"_intervalUnit,omitempty"` - XLowerLimit *FHIRPrimitiveExtension `json:"_lowerLimit,omitempty"` - XOffsets *FHIRPrimitiveExtension `json:"_offsets,omitempty"` - XUpperLimit *FHIRPrimitiveExtension `json:"_upperLimit,omitempty"` - CodeMap *string `json:"codeMap,omitempty"` - Data *string `json:"data,omitempty"` - Dimensions *int64 `json:"dimensions,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - Factor *float64 `json:"factor,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Interval *float64 `json:"interval,omitempty"` - IntervalUnit *string `json:"intervalUnit,omitempty"` - Links [][]any `json:"links,omitempty"` - LowerLimit *float64 `json:"lowerLimit,omitempty"` - Offsets *string `json:"offsets,omitempty"` - Origin *Quantity `json:"origin"` - ResourceType *string `json:"resourceType,omitempty"` - UpperLimit *float64 `json:"upperLimit,omitempty"` + XLowerLimit *FHIRPrimitiveExtension `json:"_lowerLimit,omitempty"` + XOffsets *FHIRPrimitiveExtension `json:"_offsets,omitempty"` + XUpperLimit *FHIRPrimitiveExtension `json:"_upperLimit,omitempty"` + CodeMap *string `json:"codeMap,omitempty"` + Data *string `json:"data,omitempty"` + Dimensions *int64 `json:"dimensions,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + Factor *float64 `json:"factor,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Interval *float64 `json:"interval,omitempty"` + IntervalUnit *string `json:"intervalUnit,omitempty"` + Links [][]any `json:"links,omitempty"` + LowerLimit *float64 `json:"lowerLimit,omitempty"` + Offsets *string `json:"offsets,omitempty"` + Origin *Quantity `json:"origin"` + ResourceType *string `json:"resourceType,omitempty"` + UpperLimit *float64 `json:"upperLimit,omitempty"` } // Signature type Signature struct { - XData *FHIRPrimitiveExtension `json:"_data,omitempty"` - XSigFormat *FHIRPrimitiveExtension `json:"_sigFormat,omitempty"` + XData *FHIRPrimitiveExtension `json:"_data,omitempty"` + XSigFormat *FHIRPrimitiveExtension `json:"_sigFormat,omitempty"` XTargetFormat *FHIRPrimitiveExtension `json:"_targetFormat,omitempty"` - XWhen *FHIRPrimitiveExtension `json:"_when,omitempty"` - Data *string `json:"data,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - OnBehalfOf *Reference `json:"onBehalfOf,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SigFormat *string `json:"sigFormat,omitempty"` - TargetFormat *string `json:"targetFormat,omitempty"` - Type []*Coding `json:"type,omitempty"` - When *string `json:"when,omitempty"` - Who *Reference `json:"who,omitempty"` + XWhen *FHIRPrimitiveExtension `json:"_when,omitempty"` + Data *string `json:"data,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + OnBehalfOf *Reference `json:"onBehalfOf,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SigFormat *string `json:"sigFormat,omitempty"` + TargetFormat *string `json:"targetFormat,omitempty"` + Type []*Coding `json:"type,omitempty"` + When *string `json:"when,omitempty"` + Who *Reference `json:"who,omitempty"` } // Specimen type Specimen struct { - XCombined *FHIRPrimitiveExtension `json:"_combined,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XReceivedTime *FHIRPrimitiveExtension `json:"_receivedTime,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - AccessionIDentifier *Identifier `json:"accessionIdentifier,omitempty"` - Collection *SpecimenCollection `json:"collection,omitempty"` - Combined *string `json:"combined,omitempty"` - Condition []*CodeableConcept `json:"condition,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Container []*SpecimenContainer `json:"container,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - Feature []*SpecimenFeature `json:"feature,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - Parent []*Reference `json:"parent,omitempty"` - Processing []*SpecimenProcessing `json:"processing,omitempty"` - ReceivedTime *string `json:"receivedTime,omitempty"` - Request []*Reference `json:"request,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Role []*CodeableConcept `json:"role,omitempty"` - Status *string `json:"status,omitempty"` - Subject *Reference `json:"subject,omitempty"` - Text *Narrative `json:"text,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` + XCombined *FHIRPrimitiveExtension `json:"_combined,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XReceivedTime *FHIRPrimitiveExtension `json:"_receivedTime,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + AccessionIDentifier *Identifier `json:"accessionIdentifier,omitempty"` + Collection *SpecimenCollection `json:"collection,omitempty"` + Combined *string `json:"combined,omitempty"` + Condition []*CodeableConcept `json:"condition,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Container []*SpecimenContainer `json:"container,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + Feature []*SpecimenFeature `json:"feature,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + Parent []*Reference `json:"parent,omitempty"` + Processing []*SpecimenProcessing `json:"processing,omitempty"` + ReceivedTime *string `json:"receivedTime,omitempty"` + Request []*Reference `json:"request,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Role []*CodeableConcept `json:"role,omitempty"` + Status *string `json:"status,omitempty"` + Subject *Reference `json:"subject,omitempty"` + Text *Narrative `json:"text,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` } // SpecimenCollection type SpecimenCollection struct { - XCollectedDateTime *FHIRPrimitiveExtension `json:"_collectedDateTime,omitempty"` - BodySite *CodeableReference `json:"bodySite,omitempty"` - CollectedDateTime *string `json:"collectedDateTime,omitempty"` - CollectedPeriod *Period `json:"collectedPeriod,omitempty"` - Collector *Reference `json:"collector,omitempty"` - Device *CodeableReference `json:"device,omitempty"` - Duration *Duration `json:"duration,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FastingStatusCodeableConcept *CodeableConcept `json:"fastingStatusCodeableConcept,omitempty"` - FastingStatusDuration *Duration `json:"fastingStatusDuration,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Method *CodeableConcept `json:"method,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Procedure *Reference `json:"procedure,omitempty"` - Quantity *Quantity `json:"quantity,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + XCollectedDateTime *FHIRPrimitiveExtension `json:"_collectedDateTime,omitempty"` + BodySite *CodeableReference `json:"bodySite,omitempty"` + CollectedDateTime *string `json:"collectedDateTime,omitempty"` + CollectedPeriod *Period `json:"collectedPeriod,omitempty"` + Collector *Reference `json:"collector,omitempty"` + Device *CodeableReference `json:"device,omitempty"` + Duration *Duration `json:"duration,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FastingStatusCodeableConcept *CodeableConcept `json:"fastingStatusCodeableConcept,omitempty"` + FastingStatusDuration *Duration `json:"fastingStatusDuration,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Method *CodeableConcept `json:"method,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Procedure *Reference `json:"procedure,omitempty"` + Quantity *Quantity `json:"quantity,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // SpecimenContainer type SpecimenContainer struct { - Device *Reference `json:"device"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Location *Reference `json:"location,omitempty"` + Device *Reference `json:"device"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Location *Reference `json:"location,omitempty"` ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SpecimenQuantity *Quantity `json:"specimenQuantity,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SpecimenQuantity *Quantity `json:"specimenQuantity,omitempty"` } // SpecimenFeature type SpecimenFeature struct { - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - Description *string `json:"description,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *CodeableConcept `json:"type"` + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + Description *string `json:"description,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *CodeableConcept `json:"type"` } // SpecimenProcessing type SpecimenProcessing struct { - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XTimeDateTime *FHIRPrimitiveExtension `json:"_timeDateTime,omitempty"` - Additive []*Reference `json:"additive,omitempty"` - Description *string `json:"description,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Method *CodeableConcept `json:"method,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - TimeDateTime *string `json:"timeDateTime,omitempty"` - TimePeriod *Period `json:"timePeriod,omitempty"` + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XTimeDateTime *FHIRPrimitiveExtension `json:"_timeDateTime,omitempty"` + Additive []*Reference `json:"additive,omitempty"` + Description *string `json:"description,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Method *CodeableConcept `json:"method,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + TimeDateTime *string `json:"timeDateTime,omitempty"` + TimePeriod *Period `json:"timePeriod,omitempty"` } // Substance type Substance struct { - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XExpiry *FHIRPrimitiveExtension `json:"_expiry,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XInstance *FHIRPrimitiveExtension `json:"_instance,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - Category []*CodeableConcept `json:"category,omitempty"` - Code *CodeableReference `json:"code"` - Contained []*Resource `json:"contained,omitempty"` - Description *string `json:"description,omitempty"` - Expiry *string `json:"expiry,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Ingredient []*SubstanceIngredient `json:"ingredient,omitempty"` - Instance *bool `json:"instance,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Quantity *Quantity `json:"quantity,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Status *string `json:"status,omitempty"` - Text *Narrative `json:"text,omitempty"` + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XExpiry *FHIRPrimitiveExtension `json:"_expiry,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XInstance *FHIRPrimitiveExtension `json:"_instance,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + Category []*CodeableConcept `json:"category,omitempty"` + Code *CodeableReference `json:"code"` + Contained []*Resource `json:"contained,omitempty"` + Description *string `json:"description,omitempty"` + Expiry *string `json:"expiry,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Ingredient []*SubstanceIngredient `json:"ingredient,omitempty"` + Instance *bool `json:"instance,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Quantity *Quantity `json:"quantity,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Status *string `json:"status,omitempty"` + Text *Narrative `json:"text,omitempty"` } // SubstanceDefinition type SubstanceDefinition struct { - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XVersion *FHIRPrimitiveExtension `json:"_version,omitempty"` - Characterization []*SubstanceDefinitionCharacterization `json:"characterization,omitempty"` - Classification []*CodeableConcept `json:"classification,omitempty"` - Code []*SubstanceDefinitionCode `json:"code,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Description *string `json:"description,omitempty"` - Domain *CodeableConcept `json:"domain,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Grade []*CodeableConcept `json:"grade,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - InformationSource []*Reference `json:"informationSource,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Manufacturer []*Reference `json:"manufacturer,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Moiety []*SubstanceDefinitionMoiety `json:"moiety,omitempty"` - MolecularWeight []*SubstanceDefinitionMolecularWeight `json:"molecularWeight,omitempty"` - Name []*SubstanceDefinitionName `json:"name,omitempty"` - Note []*Annotation `json:"note,omitempty"` - NucleicAcid *Reference `json:"nucleicAcid,omitempty"` - Polymer *Reference `json:"polymer,omitempty"` - Property []*SubstanceDefinitionProperty `json:"property,omitempty"` - Protein *Reference `json:"protein,omitempty"` - ReferenceInformation *Reference `json:"referenceInformation,omitempty"` - Relationship []*SubstanceDefinitionRelationship `json:"relationship,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SourceMaterial *SubstanceDefinitionSourceMaterial `json:"sourceMaterial,omitempty"` - Status *CodeableConcept `json:"status,omitempty"` - Structure *SubstanceDefinitionStructure `json:"structure,omitempty"` - Supplier []*Reference `json:"supplier,omitempty"` - Text *Narrative `json:"text,omitempty"` - Version *string `json:"version,omitempty"` + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XVersion *FHIRPrimitiveExtension `json:"_version,omitempty"` + Characterization []*SubstanceDefinitionCharacterization `json:"characterization,omitempty"` + Classification []*CodeableConcept `json:"classification,omitempty"` + Code []*SubstanceDefinitionCode `json:"code,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Description *string `json:"description,omitempty"` + Domain *CodeableConcept `json:"domain,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Grade []*CodeableConcept `json:"grade,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + InformationSource []*Reference `json:"informationSource,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Manufacturer []*Reference `json:"manufacturer,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Moiety []*SubstanceDefinitionMoiety `json:"moiety,omitempty"` + MolecularWeight []*SubstanceDefinitionMolecularWeight `json:"molecularWeight,omitempty"` + Name []*SubstanceDefinitionName `json:"name,omitempty"` + Note []*Annotation `json:"note,omitempty"` + NucleicAcid *Reference `json:"nucleicAcid,omitempty"` + Polymer *Reference `json:"polymer,omitempty"` + Property []*SubstanceDefinitionProperty `json:"property,omitempty"` + Protein *Reference `json:"protein,omitempty"` + ReferenceInformation *Reference `json:"referenceInformation,omitempty"` + Relationship []*SubstanceDefinitionRelationship `json:"relationship,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SourceMaterial *SubstanceDefinitionSourceMaterial `json:"sourceMaterial,omitempty"` + Status *CodeableConcept `json:"status,omitempty"` + Structure *SubstanceDefinitionStructure `json:"structure,omitempty"` + Supplier []*Reference `json:"supplier,omitempty"` + Text *Narrative `json:"text,omitempty"` + Version *string `json:"version,omitempty"` } // SubstanceDefinitionCharacterization type SubstanceDefinitionCharacterization struct { - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - Description *string `json:"description,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - File []*Attachment `json:"file,omitempty"` - Form *CodeableConcept `json:"form,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Technique *CodeableConcept `json:"technique,omitempty"` + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + Description *string `json:"description,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + File []*Attachment `json:"file,omitempty"` + Form *CodeableConcept `json:"form,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Technique *CodeableConcept `json:"technique,omitempty"` } // SubstanceDefinitionCode type SubstanceDefinitionCode struct { - XStatusDate *FHIRPrimitiveExtension `json:"_statusDate,omitempty"` - Code *CodeableConcept `json:"code,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Source []*Reference `json:"source,omitempty"` - Status *CodeableConcept `json:"status,omitempty"` - StatusDate *string `json:"statusDate,omitempty"` + XStatusDate *FHIRPrimitiveExtension `json:"_statusDate,omitempty"` + Code *CodeableConcept `json:"code,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Source []*Reference `json:"source,omitempty"` + Status *CodeableConcept `json:"status,omitempty"` + StatusDate *string `json:"statusDate,omitempty"` } // SubstanceDefinitionMoiety type SubstanceDefinitionMoiety struct { - XAmountString *FHIRPrimitiveExtension `json:"_amountString,omitempty"` + XAmountString *FHIRPrimitiveExtension `json:"_amountString,omitempty"` XMolecularFormula *FHIRPrimitiveExtension `json:"_molecularFormula,omitempty"` - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - AmountQuantity *Quantity `json:"amountQuantity,omitempty"` - AmountString *string `json:"amountString,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier *Identifier `json:"identifier,omitempty"` - Links [][]any `json:"links,omitempty"` - MeasurementType *CodeableConcept `json:"measurementType,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - MolecularFormula *string `json:"molecularFormula,omitempty"` - Name *string `json:"name,omitempty"` - OpticalActivity *CodeableConcept `json:"opticalActivity,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Role *CodeableConcept `json:"role,omitempty"` - Stereochemistry *CodeableConcept `json:"stereochemistry,omitempty"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + AmountQuantity *Quantity `json:"amountQuantity,omitempty"` + AmountString *string `json:"amountString,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier *Identifier `json:"identifier,omitempty"` + Links [][]any `json:"links,omitempty"` + MeasurementType *CodeableConcept `json:"measurementType,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + MolecularFormula *string `json:"molecularFormula,omitempty"` + Name *string `json:"name,omitempty"` + OpticalActivity *CodeableConcept `json:"opticalActivity,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Role *CodeableConcept `json:"role,omitempty"` + Stereochemistry *CodeableConcept `json:"stereochemistry,omitempty"` } // SubstanceDefinitionMolecularWeight type SubstanceDefinitionMolecularWeight struct { - Amount *Quantity `json:"amount"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Method *CodeableConcept `json:"method,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` + Amount *Quantity `json:"amount"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Method *CodeableConcept `json:"method,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` } // SubstanceDefinitionName type SubstanceDefinitionName struct { - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - XPreferred *FHIRPrimitiveExtension `json:"_preferred,omitempty"` - Domain []*CodeableConcept `json:"domain,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Jurisdiction []*CodeableConcept `json:"jurisdiction,omitempty"` - Language []*CodeableConcept `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Name *string `json:"name,omitempty"` - Official []*SubstanceDefinitionNameOfficial `json:"official,omitempty"` - Preferred *bool `json:"preferred,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Source []*Reference `json:"source,omitempty"` - Status *CodeableConcept `json:"status,omitempty"` - Synonym []*SubstanceDefinitionName `json:"synonym,omitempty"` - Translation []*SubstanceDefinitionName `json:"translation,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + XPreferred *FHIRPrimitiveExtension `json:"_preferred,omitempty"` + Domain []*CodeableConcept `json:"domain,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Jurisdiction []*CodeableConcept `json:"jurisdiction,omitempty"` + Language []*CodeableConcept `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Name *string `json:"name,omitempty"` + Official []*SubstanceDefinitionNameOfficial `json:"official,omitempty"` + Preferred *bool `json:"preferred,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Source []*Reference `json:"source,omitempty"` + Status *CodeableConcept `json:"status,omitempty"` + Synonym []*SubstanceDefinitionName `json:"synonym,omitempty"` + Translation []*SubstanceDefinitionName `json:"translation,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` } // SubstanceDefinitionNameOfficial type SubstanceDefinitionNameOfficial struct { - XDate *FHIRPrimitiveExtension `json:"_date,omitempty"` - Authority *CodeableConcept `json:"authority,omitempty"` - Date *string `json:"date,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Status *CodeableConcept `json:"status,omitempty"` + XDate *FHIRPrimitiveExtension `json:"_date,omitempty"` + Authority *CodeableConcept `json:"authority,omitempty"` + Date *string `json:"date,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Status *CodeableConcept `json:"status,omitempty"` } // SubstanceDefinitionProperty type SubstanceDefinitionProperty struct { - XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` - XValueDate *FHIRPrimitiveExtension `json:"_valueDate,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *CodeableConcept `json:"type"` - ValueAttachment *Attachment `json:"valueAttachment,omitempty"` - ValueBoolean *bool `json:"valueBoolean,omitempty"` - ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` - ValueDate *string `json:"valueDate,omitempty"` - ValueQuantity *Quantity `json:"valueQuantity,omitempty"` + XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` + XValueDate *FHIRPrimitiveExtension `json:"_valueDate,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *CodeableConcept `json:"type"` + ValueAttachment *Attachment `json:"valueAttachment,omitempty"` + ValueBoolean *bool `json:"valueBoolean,omitempty"` + ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` + ValueDate *string `json:"valueDate,omitempty"` + ValueQuantity *Quantity `json:"valueQuantity,omitempty"` } // SubstanceDefinitionRelationship type SubstanceDefinitionRelationship struct { - XAmountString *FHIRPrimitiveExtension `json:"_amountString,omitempty"` - XIsDefining *FHIRPrimitiveExtension `json:"_isDefining,omitempty"` - AmountQuantity *Quantity `json:"amountQuantity,omitempty"` - AmountRatio *Ratio `json:"amountRatio,omitempty"` - AmountString *string `json:"amountString,omitempty"` - Comparator *CodeableConcept `json:"comparator,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IsDefining *bool `json:"isDefining,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - RatioHighLimitAmount *Ratio `json:"ratioHighLimitAmount,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Source []*Reference `json:"source,omitempty"` - SubstanceDefinitionCodeableConcept *CodeableConcept `json:"substanceDefinitionCodeableConcept,omitempty"` - SubstanceDefinitionReference *Reference `json:"substanceDefinitionReference,omitempty"` - Type *CodeableConcept `json:"type"` + XAmountString *FHIRPrimitiveExtension `json:"_amountString,omitempty"` + XIsDefining *FHIRPrimitiveExtension `json:"_isDefining,omitempty"` + AmountQuantity *Quantity `json:"amountQuantity,omitempty"` + AmountRatio *Ratio `json:"amountRatio,omitempty"` + AmountString *string `json:"amountString,omitempty"` + Comparator *CodeableConcept `json:"comparator,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IsDefining *bool `json:"isDefining,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + RatioHighLimitAmount *Ratio `json:"ratioHighLimitAmount,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Source []*Reference `json:"source,omitempty"` + SubstanceDefinitionCodeableConcept *CodeableConcept `json:"substanceDefinitionCodeableConcept,omitempty"` + SubstanceDefinitionReference *Reference `json:"substanceDefinitionReference,omitempty"` + Type *CodeableConcept `json:"type"` } // SubstanceDefinitionSourceMaterial type SubstanceDefinitionSourceMaterial struct { - CountryOfOrigin []*CodeableConcept `json:"countryOfOrigin,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Genus *CodeableConcept `json:"genus,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Part *CodeableConcept `json:"part,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Species *CodeableConcept `json:"species,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` + CountryOfOrigin []*CodeableConcept `json:"countryOfOrigin,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Genus *CodeableConcept `json:"genus,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Part *CodeableConcept `json:"part,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Species *CodeableConcept `json:"species,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` } // SubstanceDefinitionStructure type SubstanceDefinitionStructure struct { - XMolecularFormula *FHIRPrimitiveExtension `json:"_molecularFormula,omitempty"` - XMolecularFormulaByMoiety *FHIRPrimitiveExtension `json:"_molecularFormulaByMoiety,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - MolecularFormula *string `json:"molecularFormula,omitempty"` - MolecularFormulaByMoiety *string `json:"molecularFormulaByMoiety,omitempty"` - MolecularWeight *SubstanceDefinitionMolecularWeight `json:"molecularWeight,omitempty"` - OpticalActivity *CodeableConcept `json:"opticalActivity,omitempty"` - Representation []*SubstanceDefinitionStructureRepresentation `json:"representation,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SourceDocument []*Reference `json:"sourceDocument,omitempty"` - Stereochemistry *CodeableConcept `json:"stereochemistry,omitempty"` - Technique []*CodeableConcept `json:"technique,omitempty"` + XMolecularFormula *FHIRPrimitiveExtension `json:"_molecularFormula,omitempty"` + XMolecularFormulaByMoiety *FHIRPrimitiveExtension `json:"_molecularFormulaByMoiety,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + MolecularFormula *string `json:"molecularFormula,omitempty"` + MolecularFormulaByMoiety *string `json:"molecularFormulaByMoiety,omitempty"` + MolecularWeight *SubstanceDefinitionMolecularWeight `json:"molecularWeight,omitempty"` + OpticalActivity *CodeableConcept `json:"opticalActivity,omitempty"` + Representation []*SubstanceDefinitionStructureRepresentation `json:"representation,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SourceDocument []*Reference `json:"sourceDocument,omitempty"` + Stereochemistry *CodeableConcept `json:"stereochemistry,omitempty"` + Technique []*CodeableConcept `json:"technique,omitempty"` } // SubstanceDefinitionStructureRepresentation type SubstanceDefinitionStructureRepresentation struct { - XRepresentation *FHIRPrimitiveExtension `json:"_representation,omitempty"` - Document *Reference `json:"document,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Format *CodeableConcept `json:"format,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Representation *string `json:"representation,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` + XRepresentation *FHIRPrimitiveExtension `json:"_representation,omitempty"` + Document *Reference `json:"document,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Format *CodeableConcept `json:"format,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Representation *string `json:"representation,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` } // SubstanceIngredient type SubstanceIngredient struct { - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Quantity *Ratio `json:"quantity,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Quantity *Ratio `json:"quantity,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` SubstanceCodeableConcept *CodeableConcept `json:"substanceCodeableConcept,omitempty"` - SubstanceReference *Reference `json:"substanceReference,omitempty"` + SubstanceReference *Reference `json:"substanceReference,omitempty"` } // Task type Task struct { - XAuthoredOn *FHIRPrimitiveExtension `json:"_authoredOn,omitempty"` - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XDoNotPerform *FHIRPrimitiveExtension `json:"_doNotPerform,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XAuthoredOn *FHIRPrimitiveExtension `json:"_authoredOn,omitempty"` + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XDoNotPerform *FHIRPrimitiveExtension `json:"_doNotPerform,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` XInstantiatesCanonical *FHIRPrimitiveExtension `json:"_instantiatesCanonical,omitempty"` - XInstantiatesURI *FHIRPrimitiveExtension `json:"_instantiatesUri,omitempty"` - XIntent *FHIRPrimitiveExtension `json:"_intent,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XLastModified *FHIRPrimitiveExtension `json:"_lastModified,omitempty"` - XPriority *FHIRPrimitiveExtension `json:"_priority,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - AuthoredOn *string `json:"authoredOn,omitempty"` - BasedOn []*Reference `json:"basedOn,omitempty"` - BusinessStatus *CodeableConcept `json:"businessStatus,omitempty"` - Code *CodeableConcept `json:"code,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Description *string `json:"description,omitempty"` - DoNotPerform *bool `json:"doNotPerform,omitempty"` - Encounter *Reference `json:"encounter,omitempty"` - ExecutionPeriod *Period `json:"executionPeriod,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Focus *Reference `json:"focus,omitempty"` - ForFhir *Reference `json:"for_fhir,omitempty"` - GroupIDentifier *Identifier `json:"groupIdentifier,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Input []*TaskInput `json:"input,omitempty"` - InstantiatesCanonical *string `json:"instantiatesCanonical,omitempty"` - InstantiatesURI *string `json:"instantiatesUri,omitempty"` - Insurance []*Reference `json:"insurance,omitempty"` - Intent *string `json:"intent,omitempty"` - Language *string `json:"language,omitempty"` - LastModified *string `json:"lastModified,omitempty"` - Links [][]any `json:"links,omitempty"` - Location *Reference `json:"location,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - Output []*TaskOutput `json:"output,omitempty"` - Owner *Reference `json:"owner,omitempty"` - PartOf []*Reference `json:"partOf,omitempty"` - Performer []*TaskPerformer `json:"performer,omitempty"` - Priority *string `json:"priority,omitempty"` - Reason []*CodeableReference `json:"reason,omitempty"` - RelevantHistory []*Reference `json:"relevantHistory,omitempty"` - RequestedPerformer []*CodeableReference `json:"requestedPerformer,omitempty"` - RequestedPeriod *Period `json:"requestedPeriod,omitempty"` - Requester *Reference `json:"requester,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Restriction *TaskRestriction `json:"restriction,omitempty"` - Status *string `json:"status,omitempty"` - StatusReason *CodeableReference `json:"statusReason,omitempty"` - Text *Narrative `json:"text,omitempty"` + XInstantiatesURI *FHIRPrimitiveExtension `json:"_instantiatesUri,omitempty"` + XIntent *FHIRPrimitiveExtension `json:"_intent,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XLastModified *FHIRPrimitiveExtension `json:"_lastModified,omitempty"` + XPriority *FHIRPrimitiveExtension `json:"_priority,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + AuthoredOn *string `json:"authoredOn,omitempty"` + BasedOn []*Reference `json:"basedOn,omitempty"` + BusinessStatus *CodeableConcept `json:"businessStatus,omitempty"` + Code *CodeableConcept `json:"code,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Description *string `json:"description,omitempty"` + DoNotPerform *bool `json:"doNotPerform,omitempty"` + Encounter *Reference `json:"encounter,omitempty"` + ExecutionPeriod *Period `json:"executionPeriod,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Focus *Reference `json:"focus,omitempty"` + ForFhir *Reference `json:"for_fhir,omitempty"` + GroupIDentifier *Identifier `json:"groupIdentifier,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Input []*TaskInput `json:"input,omitempty"` + InstantiatesCanonical *string `json:"instantiatesCanonical,omitempty"` + InstantiatesURI *string `json:"instantiatesUri,omitempty"` + Insurance []*Reference `json:"insurance,omitempty"` + Intent *string `json:"intent,omitempty"` + Language *string `json:"language,omitempty"` + LastModified *string `json:"lastModified,omitempty"` + Links [][]any `json:"links,omitempty"` + Location *Reference `json:"location,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + Output []*TaskOutput `json:"output,omitempty"` + Owner *Reference `json:"owner,omitempty"` + PartOf []*Reference `json:"partOf,omitempty"` + Performer []*TaskPerformer `json:"performer,omitempty"` + Priority *string `json:"priority,omitempty"` + Reason []*CodeableReference `json:"reason,omitempty"` + RelevantHistory []*Reference `json:"relevantHistory,omitempty"` + RequestedPerformer []*CodeableReference `json:"requestedPerformer,omitempty"` + RequestedPeriod *Period `json:"requestedPeriod,omitempty"` + Requester *Reference `json:"requester,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Restriction *TaskRestriction `json:"restriction,omitempty"` + Status *string `json:"status,omitempty"` + StatusReason *CodeableReference `json:"statusReason,omitempty"` + Text *Narrative `json:"text,omitempty"` } // TaskInput type TaskInput struct { - XValueBase64Binary *FHIRPrimitiveExtension `json:"_valueBase64Binary,omitempty"` - XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` - XValueCanonical *FHIRPrimitiveExtension `json:"_valueCanonical,omitempty"` - XValueCode *FHIRPrimitiveExtension `json:"_valueCode,omitempty"` - XValueDate *FHIRPrimitiveExtension `json:"_valueDate,omitempty"` - XValueDateTime *FHIRPrimitiveExtension `json:"_valueDateTime,omitempty"` - XValueDecimal *FHIRPrimitiveExtension `json:"_valueDecimal,omitempty"` - XValueID *FHIRPrimitiveExtension `json:"_valueId,omitempty"` - XValueInstant *FHIRPrimitiveExtension `json:"_valueInstant,omitempty"` - XValueInteger *FHIRPrimitiveExtension `json:"_valueInteger,omitempty"` - XValueInteger64 *FHIRPrimitiveExtension `json:"_valueInteger64,omitempty"` - XValueMarkdown *FHIRPrimitiveExtension `json:"_valueMarkdown,omitempty"` - XValueOid *FHIRPrimitiveExtension `json:"_valueOid,omitempty"` - XValuePositiveInt *FHIRPrimitiveExtension `json:"_valuePositiveInt,omitempty"` - XValueString *FHIRPrimitiveExtension `json:"_valueString,omitempty"` - XValueTime *FHIRPrimitiveExtension `json:"_valueTime,omitempty"` - XValueUnsignedInt *FHIRPrimitiveExtension `json:"_valueUnsignedInt,omitempty"` - XValueURI *FHIRPrimitiveExtension `json:"_valueUri,omitempty"` - XValueURL *FHIRPrimitiveExtension `json:"_valueUrl,omitempty"` - XValueUUID *FHIRPrimitiveExtension `json:"_valueUuid,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *CodeableConcept `json:"type"` - ValueAddress *Address `json:"valueAddress,omitempty"` - ValueAge *Age `json:"valueAge,omitempty"` - ValueAnnotation *Annotation `json:"valueAnnotation,omitempty"` - ValueAttachment *Attachment `json:"valueAttachment,omitempty"` - ValueAvailability *Availability `json:"valueAvailability,omitempty"` - ValueBase64Binary *string `json:"valueBase64Binary,omitempty"` - ValueBoolean *bool `json:"valueBoolean,omitempty"` - ValueCanonical *string `json:"valueCanonical,omitempty"` - ValueCode *string `json:"valueCode,omitempty"` - ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` - ValueCodeableReference *CodeableReference `json:"valueCodeableReference,omitempty"` - ValueCoding *Coding `json:"valueCoding,omitempty"` - ValueContactDetail *ContactDetail `json:"valueContactDetail,omitempty"` - ValueContactPoint *ContactPoint `json:"valueContactPoint,omitempty"` - ValueCount *Count `json:"valueCount,omitempty"` - ValueDataRequirement *DataRequirement `json:"valueDataRequirement,omitempty"` - ValueDate *string `json:"valueDate,omitempty"` - ValueDateTime *string `json:"valueDateTime,omitempty"` - ValueDecimal *float64 `json:"valueDecimal,omitempty"` - ValueDistance *Distance `json:"valueDistance,omitempty"` - ValueDosage *Dosage `json:"valueDosage,omitempty"` - ValueDuration *Duration `json:"valueDuration,omitempty"` - ValueExpression *Expression `json:"valueExpression,omitempty"` - ValueExtendedContactDetail *ExtendedContactDetail `json:"valueExtendedContactDetail,omitempty"` - ValueHumanName *HumanName `json:"valueHumanName,omitempty"` - ValueID *string `json:"valueId,omitempty"` - ValueIDentifier *Identifier `json:"valueIdentifier,omitempty"` - ValueInstant *string `json:"valueInstant,omitempty"` - ValueInteger *int64 `json:"valueInteger,omitempty"` - ValueInteger64 *int64 `json:"valueInteger64,omitempty"` - ValueMarkdown *string `json:"valueMarkdown,omitempty"` - ValueMeta *Meta `json:"valueMeta,omitempty"` - ValueMoney *Money `json:"valueMoney,omitempty"` - ValueOid *string `json:"valueOid,omitempty"` - ValueParameterDefinition *ParameterDefinition `json:"valueParameterDefinition,omitempty"` - ValuePeriod *Period `json:"valuePeriod,omitempty"` - ValuePositiveInt *int64 `json:"valuePositiveInt,omitempty"` - ValueQuantity *Quantity `json:"valueQuantity,omitempty"` - ValueRange *Range `json:"valueRange,omitempty"` - ValueRatio *Ratio `json:"valueRatio,omitempty"` - ValueRatioRange *RatioRange `json:"valueRatioRange,omitempty"` - ValueReference *Reference `json:"valueReference,omitempty"` - ValueRelatedArtifact *RelatedArtifact `json:"valueRelatedArtifact,omitempty"` - ValueSampledData *SampledData `json:"valueSampledData,omitempty"` - ValueSignature *Signature `json:"valueSignature,omitempty"` - ValueString *string `json:"valueString,omitempty"` - ValueTime *string `json:"valueTime,omitempty"` - ValueTiming *Timing `json:"valueTiming,omitempty"` - ValueTriggerDefinition *TriggerDefinition `json:"valueTriggerDefinition,omitempty"` - ValueUnsignedInt *int64 `json:"valueUnsignedInt,omitempty"` - ValueURI *string `json:"valueUri,omitempty"` - ValueURL *string `json:"valueUrl,omitempty"` - ValueUsageContext *UsageContext `json:"valueUsageContext,omitempty"` - ValueUUID *string `json:"valueUuid,omitempty"` + XValueBase64Binary *FHIRPrimitiveExtension `json:"_valueBase64Binary,omitempty"` + XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` + XValueCanonical *FHIRPrimitiveExtension `json:"_valueCanonical,omitempty"` + XValueCode *FHIRPrimitiveExtension `json:"_valueCode,omitempty"` + XValueDate *FHIRPrimitiveExtension `json:"_valueDate,omitempty"` + XValueDateTime *FHIRPrimitiveExtension `json:"_valueDateTime,omitempty"` + XValueDecimal *FHIRPrimitiveExtension `json:"_valueDecimal,omitempty"` + XValueID *FHIRPrimitiveExtension `json:"_valueId,omitempty"` + XValueInstant *FHIRPrimitiveExtension `json:"_valueInstant,omitempty"` + XValueInteger *FHIRPrimitiveExtension `json:"_valueInteger,omitempty"` + XValueInteger64 *FHIRPrimitiveExtension `json:"_valueInteger64,omitempty"` + XValueMarkdown *FHIRPrimitiveExtension `json:"_valueMarkdown,omitempty"` + XValueOid *FHIRPrimitiveExtension `json:"_valueOid,omitempty"` + XValuePositiveInt *FHIRPrimitiveExtension `json:"_valuePositiveInt,omitempty"` + XValueString *FHIRPrimitiveExtension `json:"_valueString,omitempty"` + XValueTime *FHIRPrimitiveExtension `json:"_valueTime,omitempty"` + XValueUnsignedInt *FHIRPrimitiveExtension `json:"_valueUnsignedInt,omitempty"` + XValueURI *FHIRPrimitiveExtension `json:"_valueUri,omitempty"` + XValueURL *FHIRPrimitiveExtension `json:"_valueUrl,omitempty"` + XValueUUID *FHIRPrimitiveExtension `json:"_valueUuid,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *CodeableConcept `json:"type"` + ValueAddress *Address `json:"valueAddress,omitempty"` + ValueAge *Age `json:"valueAge,omitempty"` + ValueAnnotation *Annotation `json:"valueAnnotation,omitempty"` + ValueAttachment *Attachment `json:"valueAttachment,omitempty"` + ValueAvailability *Availability `json:"valueAvailability,omitempty"` + ValueBase64Binary *string `json:"valueBase64Binary,omitempty"` + ValueBoolean *bool `json:"valueBoolean,omitempty"` + ValueCanonical *string `json:"valueCanonical,omitempty"` + ValueCode *string `json:"valueCode,omitempty"` + ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` + ValueCodeableReference *CodeableReference `json:"valueCodeableReference,omitempty"` + ValueCoding *Coding `json:"valueCoding,omitempty"` + ValueContactDetail *ContactDetail `json:"valueContactDetail,omitempty"` + ValueContactPoint *ContactPoint `json:"valueContactPoint,omitempty"` + ValueCount *Count `json:"valueCount,omitempty"` + ValueDataRequirement *DataRequirement `json:"valueDataRequirement,omitempty"` + ValueDate *string `json:"valueDate,omitempty"` + ValueDateTime *string `json:"valueDateTime,omitempty"` + ValueDecimal *float64 `json:"valueDecimal,omitempty"` + ValueDistance *Distance `json:"valueDistance,omitempty"` + ValueDosage *Dosage `json:"valueDosage,omitempty"` + ValueDuration *Duration `json:"valueDuration,omitempty"` + ValueExpression *Expression `json:"valueExpression,omitempty"` + ValueExtendedContactDetail *ExtendedContactDetail `json:"valueExtendedContactDetail,omitempty"` + ValueHumanName *HumanName `json:"valueHumanName,omitempty"` + ValueID *string `json:"valueId,omitempty"` + ValueIDentifier *Identifier `json:"valueIdentifier,omitempty"` + ValueInstant *string `json:"valueInstant,omitempty"` + ValueInteger *int64 `json:"valueInteger,omitempty"` + ValueInteger64 *int64 `json:"valueInteger64,omitempty"` + ValueMarkdown *string `json:"valueMarkdown,omitempty"` + ValueMeta *Meta `json:"valueMeta,omitempty"` + ValueMoney *Money `json:"valueMoney,omitempty"` + ValueOid *string `json:"valueOid,omitempty"` + ValueParameterDefinition *ParameterDefinition `json:"valueParameterDefinition,omitempty"` + ValuePeriod *Period `json:"valuePeriod,omitempty"` + ValuePositiveInt *int64 `json:"valuePositiveInt,omitempty"` + ValueQuantity *Quantity `json:"valueQuantity,omitempty"` + ValueRange *Range `json:"valueRange,omitempty"` + ValueRatio *Ratio `json:"valueRatio,omitempty"` + ValueRatioRange *RatioRange `json:"valueRatioRange,omitempty"` + ValueReference *Reference `json:"valueReference,omitempty"` + ValueRelatedArtifact *RelatedArtifact `json:"valueRelatedArtifact,omitempty"` + ValueSampledData *SampledData `json:"valueSampledData,omitempty"` + ValueSignature *Signature `json:"valueSignature,omitempty"` + ValueString *string `json:"valueString,omitempty"` + ValueTime *string `json:"valueTime,omitempty"` + ValueTiming *Timing `json:"valueTiming,omitempty"` + ValueTriggerDefinition *TriggerDefinition `json:"valueTriggerDefinition,omitempty"` + ValueUnsignedInt *int64 `json:"valueUnsignedInt,omitempty"` + ValueURI *string `json:"valueUri,omitempty"` + ValueURL *string `json:"valueUrl,omitempty"` + ValueUsageContext *UsageContext `json:"valueUsageContext,omitempty"` + ValueUUID *string `json:"valueUuid,omitempty"` } // TaskOutput type TaskOutput struct { - XValueBase64Binary *FHIRPrimitiveExtension `json:"_valueBase64Binary,omitempty"` - XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` - XValueCanonical *FHIRPrimitiveExtension `json:"_valueCanonical,omitempty"` - XValueCode *FHIRPrimitiveExtension `json:"_valueCode,omitempty"` - XValueDate *FHIRPrimitiveExtension `json:"_valueDate,omitempty"` - XValueDateTime *FHIRPrimitiveExtension `json:"_valueDateTime,omitempty"` - XValueDecimal *FHIRPrimitiveExtension `json:"_valueDecimal,omitempty"` - XValueID *FHIRPrimitiveExtension `json:"_valueId,omitempty"` - XValueInstant *FHIRPrimitiveExtension `json:"_valueInstant,omitempty"` - XValueInteger *FHIRPrimitiveExtension `json:"_valueInteger,omitempty"` - XValueInteger64 *FHIRPrimitiveExtension `json:"_valueInteger64,omitempty"` - XValueMarkdown *FHIRPrimitiveExtension `json:"_valueMarkdown,omitempty"` - XValueOid *FHIRPrimitiveExtension `json:"_valueOid,omitempty"` - XValuePositiveInt *FHIRPrimitiveExtension `json:"_valuePositiveInt,omitempty"` - XValueString *FHIRPrimitiveExtension `json:"_valueString,omitempty"` - XValueTime *FHIRPrimitiveExtension `json:"_valueTime,omitempty"` - XValueUnsignedInt *FHIRPrimitiveExtension `json:"_valueUnsignedInt,omitempty"` - XValueURI *FHIRPrimitiveExtension `json:"_valueUri,omitempty"` - XValueURL *FHIRPrimitiveExtension `json:"_valueUrl,omitempty"` - XValueUUID *FHIRPrimitiveExtension `json:"_valueUuid,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *CodeableConcept `json:"type"` - ValueAddress *Address `json:"valueAddress,omitempty"` - ValueAge *Age `json:"valueAge,omitempty"` - ValueAnnotation *Annotation `json:"valueAnnotation,omitempty"` - ValueAttachment *Attachment `json:"valueAttachment,omitempty"` - ValueAvailability *Availability `json:"valueAvailability,omitempty"` - ValueBase64Binary *string `json:"valueBase64Binary,omitempty"` - ValueBoolean *bool `json:"valueBoolean,omitempty"` - ValueCanonical *string `json:"valueCanonical,omitempty"` - ValueCode *string `json:"valueCode,omitempty"` - ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` - ValueCodeableReference *CodeableReference `json:"valueCodeableReference,omitempty"` - ValueCoding *Coding `json:"valueCoding,omitempty"` - ValueContactDetail *ContactDetail `json:"valueContactDetail,omitempty"` - ValueContactPoint *ContactPoint `json:"valueContactPoint,omitempty"` - ValueCount *Count `json:"valueCount,omitempty"` - ValueDataRequirement *DataRequirement `json:"valueDataRequirement,omitempty"` - ValueDate *string `json:"valueDate,omitempty"` - ValueDateTime *string `json:"valueDateTime,omitempty"` - ValueDecimal *float64 `json:"valueDecimal,omitempty"` - ValueDistance *Distance `json:"valueDistance,omitempty"` - ValueDosage *Dosage `json:"valueDosage,omitempty"` - ValueDuration *Duration `json:"valueDuration,omitempty"` - ValueExpression *Expression `json:"valueExpression,omitempty"` - ValueExtendedContactDetail *ExtendedContactDetail `json:"valueExtendedContactDetail,omitempty"` - ValueHumanName *HumanName `json:"valueHumanName,omitempty"` - ValueID *string `json:"valueId,omitempty"` - ValueIDentifier *Identifier `json:"valueIdentifier,omitempty"` - ValueInstant *string `json:"valueInstant,omitempty"` - ValueInteger *int64 `json:"valueInteger,omitempty"` - ValueInteger64 *int64 `json:"valueInteger64,omitempty"` - ValueMarkdown *string `json:"valueMarkdown,omitempty"` - ValueMeta *Meta `json:"valueMeta,omitempty"` - ValueMoney *Money `json:"valueMoney,omitempty"` - ValueOid *string `json:"valueOid,omitempty"` - ValueParameterDefinition *ParameterDefinition `json:"valueParameterDefinition,omitempty"` - ValuePeriod *Period `json:"valuePeriod,omitempty"` - ValuePositiveInt *int64 `json:"valuePositiveInt,omitempty"` - ValueQuantity *Quantity `json:"valueQuantity,omitempty"` - ValueRange *Range `json:"valueRange,omitempty"` - ValueRatio *Ratio `json:"valueRatio,omitempty"` - ValueRatioRange *RatioRange `json:"valueRatioRange,omitempty"` - ValueReference *Reference `json:"valueReference,omitempty"` - ValueRelatedArtifact *RelatedArtifact `json:"valueRelatedArtifact,omitempty"` - ValueSampledData *SampledData `json:"valueSampledData,omitempty"` - ValueSignature *Signature `json:"valueSignature,omitempty"` - ValueString *string `json:"valueString,omitempty"` - ValueTime *string `json:"valueTime,omitempty"` - ValueTiming *Timing `json:"valueTiming,omitempty"` - ValueTriggerDefinition *TriggerDefinition `json:"valueTriggerDefinition,omitempty"` - ValueUnsignedInt *int64 `json:"valueUnsignedInt,omitempty"` - ValueURI *string `json:"valueUri,omitempty"` - ValueURL *string `json:"valueUrl,omitempty"` - ValueUsageContext *UsageContext `json:"valueUsageContext,omitempty"` - ValueUUID *string `json:"valueUuid,omitempty"` + XValueBase64Binary *FHIRPrimitiveExtension `json:"_valueBase64Binary,omitempty"` + XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` + XValueCanonical *FHIRPrimitiveExtension `json:"_valueCanonical,omitempty"` + XValueCode *FHIRPrimitiveExtension `json:"_valueCode,omitempty"` + XValueDate *FHIRPrimitiveExtension `json:"_valueDate,omitempty"` + XValueDateTime *FHIRPrimitiveExtension `json:"_valueDateTime,omitempty"` + XValueDecimal *FHIRPrimitiveExtension `json:"_valueDecimal,omitempty"` + XValueID *FHIRPrimitiveExtension `json:"_valueId,omitempty"` + XValueInstant *FHIRPrimitiveExtension `json:"_valueInstant,omitempty"` + XValueInteger *FHIRPrimitiveExtension `json:"_valueInteger,omitempty"` + XValueInteger64 *FHIRPrimitiveExtension `json:"_valueInteger64,omitempty"` + XValueMarkdown *FHIRPrimitiveExtension `json:"_valueMarkdown,omitempty"` + XValueOid *FHIRPrimitiveExtension `json:"_valueOid,omitempty"` + XValuePositiveInt *FHIRPrimitiveExtension `json:"_valuePositiveInt,omitempty"` + XValueString *FHIRPrimitiveExtension `json:"_valueString,omitempty"` + XValueTime *FHIRPrimitiveExtension `json:"_valueTime,omitempty"` + XValueUnsignedInt *FHIRPrimitiveExtension `json:"_valueUnsignedInt,omitempty"` + XValueURI *FHIRPrimitiveExtension `json:"_valueUri,omitempty"` + XValueURL *FHIRPrimitiveExtension `json:"_valueUrl,omitempty"` + XValueUUID *FHIRPrimitiveExtension `json:"_valueUuid,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *CodeableConcept `json:"type"` + ValueAddress *Address `json:"valueAddress,omitempty"` + ValueAge *Age `json:"valueAge,omitempty"` + ValueAnnotation *Annotation `json:"valueAnnotation,omitempty"` + ValueAttachment *Attachment `json:"valueAttachment,omitempty"` + ValueAvailability *Availability `json:"valueAvailability,omitempty"` + ValueBase64Binary *string `json:"valueBase64Binary,omitempty"` + ValueBoolean *bool `json:"valueBoolean,omitempty"` + ValueCanonical *string `json:"valueCanonical,omitempty"` + ValueCode *string `json:"valueCode,omitempty"` + ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` + ValueCodeableReference *CodeableReference `json:"valueCodeableReference,omitempty"` + ValueCoding *Coding `json:"valueCoding,omitempty"` + ValueContactDetail *ContactDetail `json:"valueContactDetail,omitempty"` + ValueContactPoint *ContactPoint `json:"valueContactPoint,omitempty"` + ValueCount *Count `json:"valueCount,omitempty"` + ValueDataRequirement *DataRequirement `json:"valueDataRequirement,omitempty"` + ValueDate *string `json:"valueDate,omitempty"` + ValueDateTime *string `json:"valueDateTime,omitempty"` + ValueDecimal *float64 `json:"valueDecimal,omitempty"` + ValueDistance *Distance `json:"valueDistance,omitempty"` + ValueDosage *Dosage `json:"valueDosage,omitempty"` + ValueDuration *Duration `json:"valueDuration,omitempty"` + ValueExpression *Expression `json:"valueExpression,omitempty"` + ValueExtendedContactDetail *ExtendedContactDetail `json:"valueExtendedContactDetail,omitempty"` + ValueHumanName *HumanName `json:"valueHumanName,omitempty"` + ValueID *string `json:"valueId,omitempty"` + ValueIDentifier *Identifier `json:"valueIdentifier,omitempty"` + ValueInstant *string `json:"valueInstant,omitempty"` + ValueInteger *int64 `json:"valueInteger,omitempty"` + ValueInteger64 *int64 `json:"valueInteger64,omitempty"` + ValueMarkdown *string `json:"valueMarkdown,omitempty"` + ValueMeta *Meta `json:"valueMeta,omitempty"` + ValueMoney *Money `json:"valueMoney,omitempty"` + ValueOid *string `json:"valueOid,omitempty"` + ValueParameterDefinition *ParameterDefinition `json:"valueParameterDefinition,omitempty"` + ValuePeriod *Period `json:"valuePeriod,omitempty"` + ValuePositiveInt *int64 `json:"valuePositiveInt,omitempty"` + ValueQuantity *Quantity `json:"valueQuantity,omitempty"` + ValueRange *Range `json:"valueRange,omitempty"` + ValueRatio *Ratio `json:"valueRatio,omitempty"` + ValueRatioRange *RatioRange `json:"valueRatioRange,omitempty"` + ValueReference *Reference `json:"valueReference,omitempty"` + ValueRelatedArtifact *RelatedArtifact `json:"valueRelatedArtifact,omitempty"` + ValueSampledData *SampledData `json:"valueSampledData,omitempty"` + ValueSignature *Signature `json:"valueSignature,omitempty"` + ValueString *string `json:"valueString,omitempty"` + ValueTime *string `json:"valueTime,omitempty"` + ValueTiming *Timing `json:"valueTiming,omitempty"` + ValueTriggerDefinition *TriggerDefinition `json:"valueTriggerDefinition,omitempty"` + ValueUnsignedInt *int64 `json:"valueUnsignedInt,omitempty"` + ValueURI *string `json:"valueUri,omitempty"` + ValueURL *string `json:"valueUrl,omitempty"` + ValueUsageContext *UsageContext `json:"valueUsageContext,omitempty"` + ValueUUID *string `json:"valueUuid,omitempty"` } // TaskPerformer type TaskPerformer struct { - Actor *Reference `json:"actor"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Function *CodeableConcept `json:"function,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + Actor *Reference `json:"actor"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Function *CodeableConcept `json:"function,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // TaskRestriction type TaskRestriction struct { - XRepetitions *FHIRPrimitiveExtension `json:"_repetitions,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Period *Period `json:"period,omitempty"` - Recipient []*Reference `json:"recipient,omitempty"` - Repetitions *int64 `json:"repetitions,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + XRepetitions *FHIRPrimitiveExtension `json:"_repetitions,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Period *Period `json:"period,omitempty"` + Recipient []*Reference `json:"recipient,omitempty"` + Repetitions *int64 `json:"repetitions,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // Timing type Timing struct { - XEvent []*FHIRPrimitiveExtension `json:"_event,omitempty"` - Code *CodeableConcept `json:"code,omitempty"` - Event []string `json:"event,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Repeat *TimingRepeat `json:"repeat,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + XEvent []*FHIRPrimitiveExtension `json:"_event,omitempty"` + Code *CodeableConcept `json:"code,omitempty"` + Event []string `json:"event,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Repeat *TimingRepeat `json:"repeat,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` } // TimingRepeat type TimingRepeat struct { - XCount *FHIRPrimitiveExtension `json:"_count,omitempty"` - XCountMax *FHIRPrimitiveExtension `json:"_countMax,omitempty"` - XDayOfWeek []*FHIRPrimitiveExtension `json:"_dayOfWeek,omitempty"` - XDuration *FHIRPrimitiveExtension `json:"_duration,omitempty"` - XDurationMax *FHIRPrimitiveExtension `json:"_durationMax,omitempty"` - XDurationUnit *FHIRPrimitiveExtension `json:"_durationUnit,omitempty"` - XFrequency *FHIRPrimitiveExtension `json:"_frequency,omitempty"` - XFrequencyMax *FHIRPrimitiveExtension `json:"_frequencyMax,omitempty"` - XOffset *FHIRPrimitiveExtension `json:"_offset,omitempty"` - XPeriod *FHIRPrimitiveExtension `json:"_period,omitempty"` - XPeriodMax *FHIRPrimitiveExtension `json:"_periodMax,omitempty"` - XPeriodUnit *FHIRPrimitiveExtension `json:"_periodUnit,omitempty"` - XTimeOfDay []*FHIRPrimitiveExtension `json:"_timeOfDay,omitempty"` - XWhen []*FHIRPrimitiveExtension `json:"_when,omitempty"` - BoundsDuration *Duration `json:"boundsDuration,omitempty"` - BoundsPeriod *Period `json:"boundsPeriod,omitempty"` - BoundsRange *Range `json:"boundsRange,omitempty"` - Count *int64 `json:"count,omitempty"` - CountMax *int64 `json:"countMax,omitempty"` - DayOfWeek []string `json:"dayOfWeek,omitempty"` - Duration *float64 `json:"duration,omitempty"` - DurationMax *float64 `json:"durationMax,omitempty"` - DurationUnit *string `json:"durationUnit,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Frequency *int64 `json:"frequency,omitempty"` - FrequencyMax *int64 `json:"frequencyMax,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Offset *int64 `json:"offset,omitempty"` - Period *float64 `json:"period,omitempty"` - PeriodMax *float64 `json:"periodMax,omitempty"` - PeriodUnit *string `json:"periodUnit,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - TimeOfDay []string `json:"timeOfDay,omitempty"` - When []string `json:"when,omitempty"` + XCount *FHIRPrimitiveExtension `json:"_count,omitempty"` + XCountMax *FHIRPrimitiveExtension `json:"_countMax,omitempty"` + XDayOfWeek []*FHIRPrimitiveExtension `json:"_dayOfWeek,omitempty"` + XDuration *FHIRPrimitiveExtension `json:"_duration,omitempty"` + XDurationMax *FHIRPrimitiveExtension `json:"_durationMax,omitempty"` + XDurationUnit *FHIRPrimitiveExtension `json:"_durationUnit,omitempty"` + XFrequency *FHIRPrimitiveExtension `json:"_frequency,omitempty"` + XFrequencyMax *FHIRPrimitiveExtension `json:"_frequencyMax,omitempty"` + XOffset *FHIRPrimitiveExtension `json:"_offset,omitempty"` + XPeriod *FHIRPrimitiveExtension `json:"_period,omitempty"` + XPeriodMax *FHIRPrimitiveExtension `json:"_periodMax,omitempty"` + XPeriodUnit *FHIRPrimitiveExtension `json:"_periodUnit,omitempty"` + XTimeOfDay []*FHIRPrimitiveExtension `json:"_timeOfDay,omitempty"` + XWhen []*FHIRPrimitiveExtension `json:"_when,omitempty"` + BoundsDuration *Duration `json:"boundsDuration,omitempty"` + BoundsPeriod *Period `json:"boundsPeriod,omitempty"` + BoundsRange *Range `json:"boundsRange,omitempty"` + Count *int64 `json:"count,omitempty"` + CountMax *int64 `json:"countMax,omitempty"` + DayOfWeek []string `json:"dayOfWeek,omitempty"` + Duration *float64 `json:"duration,omitempty"` + DurationMax *float64 `json:"durationMax,omitempty"` + DurationUnit *string `json:"durationUnit,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Frequency *int64 `json:"frequency,omitempty"` + FrequencyMax *int64 `json:"frequencyMax,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Offset *int64 `json:"offset,omitempty"` + Period *float64 `json:"period,omitempty"` + PeriodMax *float64 `json:"periodMax,omitempty"` + PeriodUnit *string `json:"periodUnit,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + TimeOfDay []string `json:"timeOfDay,omitempty"` + When []string `json:"when,omitempty"` } // TriggerDefinition type TriggerDefinition struct { - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` XSubscriptionTopic *FHIRPrimitiveExtension `json:"_subscriptionTopic,omitempty"` - XTimingDate *FHIRPrimitiveExtension `json:"_timingDate,omitempty"` - XTimingDateTime *FHIRPrimitiveExtension `json:"_timingDateTime,omitempty"` - XType *FHIRPrimitiveExtension `json:"_type,omitempty"` - Code *CodeableConcept `json:"code,omitempty"` - Condition *Expression `json:"condition,omitempty"` - Data []*DataRequirement `json:"data,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Name *string `json:"name,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SubscriptionTopic *string `json:"subscriptionTopic,omitempty"` - TimingDate *string `json:"timingDate,omitempty"` - TimingDateTime *string `json:"timingDateTime,omitempty"` - TimingReference *Reference `json:"timingReference,omitempty"` - TimingTiming *Timing `json:"timingTiming,omitempty"` - Type *string `json:"type,omitempty"` + XTimingDate *FHIRPrimitiveExtension `json:"_timingDate,omitempty"` + XTimingDateTime *FHIRPrimitiveExtension `json:"_timingDateTime,omitempty"` + XType *FHIRPrimitiveExtension `json:"_type,omitempty"` + Code *CodeableConcept `json:"code,omitempty"` + Condition *Expression `json:"condition,omitempty"` + Data []*DataRequirement `json:"data,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Name *string `json:"name,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SubscriptionTopic *string `json:"subscriptionTopic,omitempty"` + TimingDate *string `json:"timingDate,omitempty"` + TimingDateTime *string `json:"timingDateTime,omitempty"` + TimingReference *Reference `json:"timingReference,omitempty"` + TimingTiming *Timing `json:"timingTiming,omitempty"` + Type *string `json:"type,omitempty"` } // UsageContext type UsageContext struct { - Code *Coding `json:"code"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` + Code *Coding `json:"code"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` - ValueQuantity *Quantity `json:"valueQuantity,omitempty"` - ValueRange *Range `json:"valueRange,omitempty"` - ValueReference *Reference `json:"valueReference,omitempty"` + ValueQuantity *Quantity `json:"valueQuantity,omitempty"` + ValueRange *Range `json:"valueRange,omitempty"` + ValueReference *Reference `json:"valueReference,omitempty"` } - diff --git a/internal/fhir/validate.go b/internal/fhir/validate.go index 90acafb..2af3296 100644 --- a/internal/fhir/validate.go +++ b/internal/fhir/validate.go @@ -9,159 +9,159 @@ import ( // Pre-compiled regular expressions for pattern validation var ( - rx_Address_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Address_Use = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Age_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Age_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Annotation_Text = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_Attachment_ContentType = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Attachment_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_AvailabilityAvailableTime_DaysOfWeek_items = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_BodyStructure_Description = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_BodyStructure_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_BodyStructure_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Coding_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Condition_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Condition_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ContactPoint_System = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ContactPoint_Use = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Count_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Count_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_DataRequirement_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_DataRequirementSort_Direction = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_DataRequirementValueFilter_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_DiagnosticReport_Conclusion = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_DiagnosticReport_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_DiagnosticReport_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_DiagnosticReport_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Directory_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Distance_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Distance_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_DocumentReference_Description = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_DocumentReference_DocStatus = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_DocumentReference_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_DocumentReference_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_DocumentReference_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Duration_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Duration_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Expression_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Expression_Name = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Extension_ValueCode = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Extension_ValueID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Extension_ValueMarkdown = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_Extension_ValueOid = regexp.MustCompile("^urn:oid:[0-2](\\.(0|[1-9][0-9]*))+$") - rx_FamilyMemberHistory_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_FamilyMemberHistory_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_FamilyMemberHistory_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Group_Description = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_Group_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Group_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Group_Membership = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Group_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_HumanName_Use = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Identifier_Use = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ImagingStudy_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_ImagingStudy_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ImagingStudy_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ImagingStudySeries_Uid = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_ImagingStudySeriesInstance_Uid = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Medication_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Medication_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Medication_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_MedicationAdministration_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_MedicationAdministration_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_MedicationAdministration_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_MedicationRequest_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_MedicationRequest_Intent = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_MedicationRequest_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_MedicationRequest_Priority = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_MedicationRequest_RenderedDosageInstruction = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_MedicationRequest_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_MedicationStatement_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_MedicationStatement_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_MedicationStatement_RenderedDosageInstruction = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_MedicationStatement_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Meta_VersionID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Money_Currency = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Narrative_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Observation_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Observation_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Observation_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ObservationReferenceRange_Text = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_ObservationTriggeredBy_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Organization_Description = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_Organization_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Organization_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ParameterDefinition_Name = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ParameterDefinition_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ParameterDefinition_Use = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Patient_Gender = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Patient_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Patient_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_PatientContact_Gender = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_PatientLink_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Practitioner_Gender = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Practitioner_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Practitioner_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_PractitionerRole_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_PractitionerRole_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Procedure_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Procedure_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Procedure_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Quantity_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Quantity_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_RelatedArtifact_Citation = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_RelatedArtifact_PublicationStatus = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_RelatedArtifact_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ResearchStudy_Description = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_ResearchStudy_DescriptionSummary = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_ResearchStudy_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_ResearchStudy_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ResearchStudy_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ResearchStudyComparisonGroup_Description = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_ResearchStudyComparisonGroup_LinkID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_ResearchStudyObjective_Description = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_ResearchStudyOutcomeMeasure_Description = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_ResearchSubject_ActualComparisonGroup = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_ResearchSubject_AssignedComparisonGroup = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_ResearchSubject_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_ResearchSubject_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ResearchSubject_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Resource_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Resource_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_SampledData_IntervalUnit = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Signature_SigFormat = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Signature_TargetFormat = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Specimen_Combined = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Specimen_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Specimen_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Specimen_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Substance_Description = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_Substance_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Substance_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Substance_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_SubstanceDefinition_Description = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_SubstanceDefinition_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_SubstanceDefinition_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Address_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Address_Use = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Age_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Age_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Annotation_Text = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_Attachment_ContentType = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Attachment_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_AvailabilityAvailableTime_DaysOfWeek_items = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_BodyStructure_Description = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_BodyStructure_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_BodyStructure_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Coding_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Condition_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Condition_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ContactPoint_System = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ContactPoint_Use = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Count_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Count_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_DataRequirement_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_DataRequirementSort_Direction = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_DataRequirementValueFilter_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_DiagnosticReport_Conclusion = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_DiagnosticReport_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_DiagnosticReport_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_DiagnosticReport_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Directory_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Distance_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Distance_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_DocumentReference_Description = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_DocumentReference_DocStatus = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_DocumentReference_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_DocumentReference_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_DocumentReference_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Duration_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Duration_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Expression_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Expression_Name = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Extension_ValueCode = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Extension_ValueID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Extension_ValueMarkdown = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_Extension_ValueOid = regexp.MustCompile("^urn:oid:[0-2](\\.(0|[1-9][0-9]*))+$") + rx_FamilyMemberHistory_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_FamilyMemberHistory_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_FamilyMemberHistory_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Group_Description = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_Group_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Group_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Group_Membership = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Group_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_HumanName_Use = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Identifier_Use = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ImagingStudy_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_ImagingStudy_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ImagingStudy_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ImagingStudySeries_Uid = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_ImagingStudySeriesInstance_Uid = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Medication_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Medication_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Medication_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_MedicationAdministration_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_MedicationAdministration_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_MedicationAdministration_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_MedicationRequest_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_MedicationRequest_Intent = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_MedicationRequest_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_MedicationRequest_Priority = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_MedicationRequest_RenderedDosageInstruction = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_MedicationRequest_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_MedicationStatement_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_MedicationStatement_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_MedicationStatement_RenderedDosageInstruction = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_MedicationStatement_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Meta_VersionID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Money_Currency = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Narrative_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Observation_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Observation_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Observation_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ObservationReferenceRange_Text = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_ObservationTriggeredBy_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Organization_Description = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_Organization_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Organization_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ParameterDefinition_Name = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ParameterDefinition_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ParameterDefinition_Use = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Patient_Gender = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Patient_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Patient_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_PatientContact_Gender = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_PatientLink_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Practitioner_Gender = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Practitioner_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Practitioner_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_PractitionerRole_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_PractitionerRole_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Procedure_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Procedure_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Procedure_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Quantity_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Quantity_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_RelatedArtifact_Citation = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_RelatedArtifact_PublicationStatus = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_RelatedArtifact_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ResearchStudy_Description = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_ResearchStudy_DescriptionSummary = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_ResearchStudy_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_ResearchStudy_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ResearchStudy_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ResearchStudyComparisonGroup_Description = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_ResearchStudyComparisonGroup_LinkID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_ResearchStudyObjective_Description = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_ResearchStudyOutcomeMeasure_Description = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_ResearchSubject_ActualComparisonGroup = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_ResearchSubject_AssignedComparisonGroup = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_ResearchSubject_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_ResearchSubject_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ResearchSubject_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Resource_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Resource_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_SampledData_IntervalUnit = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Signature_SigFormat = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Signature_TargetFormat = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Specimen_Combined = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Specimen_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Specimen_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Specimen_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Substance_Description = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_Substance_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Substance_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Substance_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_SubstanceDefinition_Description = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_SubstanceDefinition_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_SubstanceDefinition_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") rx_SubstanceDefinitionCharacterization_Description = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_Task_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Task_Intent = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Task_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Task_Priority = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Task_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_TaskInput_ValueCode = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_TaskInput_ValueID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_TaskInput_ValueMarkdown = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_TaskInput_ValueOid = regexp.MustCompile("^urn:oid:[0-2](\\.(0|[1-9][0-9]*))+$") - rx_TaskOutput_ValueCode = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_TaskOutput_ValueID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_TaskOutput_ValueMarkdown = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_TaskOutput_ValueOid = regexp.MustCompile("^urn:oid:[0-2](\\.(0|[1-9][0-9]*))+$") - rx_TimingRepeat_DayOfWeek_items = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_TimingRepeat_DurationUnit = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_TimingRepeat_PeriodUnit = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_TimingRepeat_When_items = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_TriggerDefinition_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Task_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Task_Intent = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Task_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Task_Priority = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Task_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_TaskInput_ValueCode = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_TaskInput_ValueID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_TaskInput_ValueMarkdown = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_TaskInput_ValueOid = regexp.MustCompile("^urn:oid:[0-2](\\.(0|[1-9][0-9]*))+$") + rx_TaskOutput_ValueCode = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_TaskOutput_ValueID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_TaskOutput_ValueMarkdown = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_TaskOutput_ValueOid = regexp.MustCompile("^urn:oid:[0-2](\\.(0|[1-9][0-9]*))+$") + rx_TimingRepeat_DayOfWeek_items = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_TimingRepeat_DurationUnit = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_TimingRepeat_PeriodUnit = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_TimingRepeat_When_items = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_TriggerDefinition_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") ) // Validate validates a Address struct against its schema constraints. @@ -14862,4 +14862,3 @@ func (x *UsageContext) Validate() error { } return nil } - diff --git a/internal/fhirschema/compiler_semantics.go b/internal/fhirschema/compiler_semantics.go new file mode 100644 index 0000000..4827194 --- /dev/null +++ b/internal/fhirschema/compiler_semantics.go @@ -0,0 +1,185 @@ +package fhirschema + +import ( + "fmt" + "sort" + "strings" +) + +// FieldKind is the compiler-facing shape of a FHIR field. It deliberately +// hides the generated schema representation so callers do not depend on +// generator-private types. +type FieldKind string + +const ( + FieldKindUnknown FieldKind = "unknown" + FieldKindScalar FieldKind = "scalar" + FieldKindObject FieldKind = "object" + FieldKindArray FieldKind = "array" +) + +// FieldSemantics describes the terminal field at a canonical FHIR path. +// ElementKind and Reference are populated for arrays and objects when the +// generated metadata provides that information. +type FieldSemantics struct { + Kind FieldKind + ElementKind FieldKind + Reference string +} + +// TraversalDirection is the FHIR reference direction declared by generated +// graph metadata. It is not automatically the physical AQL direction: the +// stored fhir_edge layout and catalog traversal contract decide that lowering +// concern. +type TraversalDirection string + +const ( + TraversalOutbound TraversalDirection = "OUTBOUND" + TraversalInbound TraversalDirection = "INBOUND" + TraversalAny TraversalDirection = "ANY" +) + +// TraversalMultiplicity describes whether one source may resolve to one or +// multiple targets. Unknown generated values are rejected rather than guessed. +type TraversalMultiplicity string + +const ( + TraversalOne TraversalMultiplicity = "ONE" + TraversalMany TraversalMultiplicity = "MANY" +) + +// CompilerTraversal is an immutable compiler-facing traversal description. +type CompilerTraversal struct { + FromType string + EdgeLabel string + ToType string + Direction TraversalDirection + Multiplicity TraversalMultiplicity +} + +// ResourceTypes returns a sorted copy of the generated FHIR resource types. +func ResourceTypes() []string { + out := append([]string(nil), generatedResourceTypes...) + sort.Strings(out) + return out +} + +// HasResource reports whether resourceType is a generated FHIR resource type. +func HasResource(resourceType string) bool { + resourceType = strings.TrimSpace(resourceType) + if resourceType == "" { + return false + } + index := sort.SearchStrings(generatedResourceTypes, resourceType) + return index < len(generatedResourceTypes) && generatedResourceTypes[index] == resourceType +} + +// ResourceExists is the explicit predicate form of HasResource. +func ResourceExists(resourceType string) bool { return HasResource(resourceType) } + +// ResolveFieldSemantics resolves a canonical path using generated schema +// metadata and returns only stable, compiler-safe values. +func ResolveFieldSemantics(resourceType, canonicalPath string) (FieldSemantics, bool) { + resolved, ok := ResolvePath(resourceType, canonicalPath) + if !ok { + return FieldSemantics{}, false + } + property := resolved.Property + semantics := FieldSemantics{Kind: normalizeFieldKind(property.Kind)} + switch semantics.Kind { + case FieldKindObject: + semantics.Reference = property.Ref + case FieldKindArray: + semantics.ElementKind = normalizeFieldKind(property.ItemKind) + semantics.Reference = property.ItemRef + } + return semantics, true +} + +// ResolveCompilerTraversal looks up and normalizes generated traversal +// metadata. Conflicting or unknown generated values return an error so the +// compiler cannot silently choose unsafe graph semantics. +func ResolveCompilerTraversal(fromType, edgeLabel, toType string) (CompilerTraversal, bool, error) { + spec, ok := LookupTraversal(fromType, edgeLabel, toType) + if !ok { + return CompilerTraversal{}, false, nil + } + direction, err := normalizeTraversalDirection(spec.Direction) + if err != nil { + return CompilerTraversal{}, true, err + } + multiplicity, err := normalizeTraversalMultiplicity(spec.Multiplicity) + if err != nil { + return CompilerTraversal{}, true, err + } + return CompilerTraversal{ + FromType: spec.FromType, + EdgeLabel: spec.EdgeLabel, + ToType: spec.ToType, + Direction: direction, + Multiplicity: multiplicity, + }, true, nil +} + +func normalizeFieldKind(kind string) FieldKind { + switch strings.ToLower(strings.TrimSpace(kind)) { + case "object": + return FieldKindObject + case "array": + return FieldKindArray + case "", "null": + return FieldKindUnknown + default: + return FieldKindScalar + } +} + +func normalizeTraversalDirection(values []string) (TraversalDirection, error) { + seen := map[TraversalDirection]bool{} + for _, value := range values { + switch strings.ToLower(strings.TrimSpace(value)) { + case "outbound", "out": + seen[TraversalOutbound] = true + case "inbound", "in": + seen[TraversalInbound] = true + case "any", "both": + seen[TraversalAny] = true + case "": + default: + return "", fmt.Errorf("unsupported traversal direction %q", value) + } + } + if seen[TraversalAny] || (seen[TraversalOutbound] && seen[TraversalInbound]) { + return TraversalAny, nil + } + if seen[TraversalOutbound] { + return TraversalOutbound, nil + } + if seen[TraversalInbound] { + return TraversalInbound, nil + } + return "", fmt.Errorf("traversal direction is missing") +} + +func normalizeTraversalMultiplicity(values []string) (TraversalMultiplicity, error) { + seenOne := false + seenMany := false + for _, value := range values { + switch strings.ToLower(strings.TrimSpace(value)) { + case "has_one", "one", "0..1", "1..1": + seenOne = true + case "has_many", "many", "0..*", "1..*", "*": + seenMany = true + case "": + default: + return "", fmt.Errorf("unsupported traversal multiplicity %q", value) + } + } + if seenMany { + return TraversalMany, nil + } + if seenOne { + return TraversalOne, nil + } + return "", fmt.Errorf("traversal multiplicity is missing") +} diff --git a/internal/fhirschema/compiler_semantics_test.go b/internal/fhirschema/compiler_semantics_test.go new file mode 100644 index 0000000..699e02b --- /dev/null +++ b/internal/fhirschema/compiler_semantics_test.go @@ -0,0 +1,68 @@ +package fhirschema + +import "testing" + +func TestResourceTypesAreSortedDefensiveCopy(t *testing.T) { + resources := ResourceTypes() + if len(resources) == 0 || !HasResource("Patient") || HasResource("UnknownResource") { + t.Fatalf("unexpected generated resource inventory: %#v", resources) + } + for i := 1; i < len(resources); i++ { + if resources[i-1] >= resources[i] { + t.Fatalf("resource inventory is not sorted and unique: %#v", resources) + } + } + resources[0] = "mutated" + if ResourceTypes()[0] == "mutated" { + t.Fatal("ResourceTypes exposed generated storage") + } +} + +func TestResolveFieldSemanticsFromGeneratedMetadata(t *testing.T) { + tests := []struct { + path string + want FieldSemantics + }{ + {"gender", FieldSemantics{Kind: FieldKindScalar}}, + {"name", FieldSemantics{Kind: FieldKindArray, ElementKind: FieldKindObject, Reference: "HumanName"}}, + {"name[].family", FieldSemantics{Kind: FieldKindScalar}}, + {"managingOrganization", FieldSemantics{Kind: FieldKindObject, Reference: "Reference"}}, + } + for _, test := range tests { + got, ok := ResolveFieldSemantics("Patient", test.path) + if !ok || got != test.want { + t.Errorf("ResolveFieldSemantics(Patient, %q) = %#v, %v; want %#v, true", test.path, got, ok, test.want) + } + } + if _, ok := ResolveFieldSemantics("Patient", "doesNotExist"); ok { + t.Fatal("unknown path resolved") + } +} + +func TestResolveCompilerTraversalFromGeneratedMetadata(t *testing.T) { + got, ok, err := ResolveCompilerTraversal("Patient", "subject_Patient", "Specimen") + if err != nil || !ok { + t.Fatalf("ResolveCompilerTraversal() = %#v, %v, %v", got, ok, err) + } + if got.Direction != TraversalOutbound || got.Multiplicity != TraversalOne { + t.Fatalf("unexpected normalized traversal: %#v", got) + } + if _, ok, err := ResolveCompilerTraversal("Patient", "missing", "Specimen"); err != nil || ok { + t.Fatalf("missing traversal = ok %v, err %v", ok, err) + } +} + +func TestTraversalNormalizationRejectsUnknownAndCombinesSafeValues(t *testing.T) { + if got, err := normalizeTraversalDirection([]string{"outbound", "inbound"}); err != nil || got != TraversalAny { + t.Fatalf("combined direction = %q, %v", got, err) + } + if _, err := normalizeTraversalDirection([]string{"sideways"}); err == nil { + t.Fatal("unknown direction accepted") + } + if got, err := normalizeTraversalMultiplicity([]string{"has_one", "has_many"}); err != nil || got != TraversalMany { + t.Fatalf("combined multiplicity = %q, %v", got, err) + } + if _, err := normalizeTraversalMultiplicity([]string{"sometimes"}); err == nil { + t.Fatal("unknown multiplicity accepted") + } +} diff --git a/internal/fhirschema/generated.go b/internal/fhirschema/generated.go index bbd4ab8..8dd4d82 100644 --- a/internal/fhirschema/generated.go +++ b/internal/fhirschema/generated.go @@ -4,18 +4,27 @@ package fhirschema var generatedResourceTypes = []string{ "BodyStructure", "Condition", + "DiagnosticReport", "DocumentReference", + "FamilyMemberHistory", "Group", "ImagingStudy", "Medication", "MedicationAdministration", + "MedicationRequest", + "MedicationStatement", "Observation", "Organization", "Patient", "Practitioner", + "PractitionerRole", + "Procedure", "ResearchStudy", "ResearchSubject", "Specimen", + "Substance", + "SubstanceDefinition", + "Task", } var generatedDefinitions = map[string]generatedDefinition{ @@ -263,8 +272,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "time", - Kind: "string", + Name: "time", + Kind: "string", + Format: "date-time", }, }, }, @@ -340,12 +350,14 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "creation", - Kind: "string", + Name: "creation", + Kind: "string", + Format: "date-time", }, { - Name: "data", - Kind: "string", + Name: "data", + Kind: "string", + Format: "binary", }, { Name: "duration", @@ -366,8 +378,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "integer", }, { - Name: "hash", - Kind: "string", + Name: "hash", + Kind: "string", + Format: "binary", }, { Name: "height", @@ -404,8 +417,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "url", - Kind: "string", + Name: "url", + Kind: "string", + Format: "uri", }, { Name: "width", @@ -481,12 +495,14 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "boolean", }, { - Name: "availableEndTime", - Kind: "string", + Name: "availableEndTime", + Kind: "string", + Format: "time", }, { - Name: "availableStartTime", - Kind: "string", + Name: "availableStartTime", + Kind: "string", + Format: "time", }, { Name: "daysOfWeek", @@ -1044,8 +1060,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "Age", }, { - Name: "abatementDateTime", - Kind: "string", + Name: "abatementDateTime", + Kind: "string", + Format: "date-time", }, { Name: "abatementPeriod", @@ -1157,8 +1174,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "Age", }, { - Name: "onsetDateTime", - Kind: "string", + Name: "onsetDateTime", + Kind: "string", + Format: "date-time", }, { Name: "onsetPeriod", @@ -1181,8 +1199,9 @@ var generatedDefinitions = map[string]generatedDefinition{ ItemRef: "ConditionParticipant", }, { - Name: "recordedDate", - Kind: "string", + Name: "recordedDate", + Kind: "string", + Format: "date-time", }, { Name: "resourceType", @@ -1708,8 +1727,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "valueDateTime", - Kind: "string", + Name: "valueDateTime", + Kind: "string", + Format: "date-time", }, { Name: "valueDuration", @@ -1828,8 +1848,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "valueDateTime", - Kind: "string", + Name: "valueDateTime", + Kind: "string", + Format: "date-time", }, { Name: "valueDuration", @@ -1914,8 +1935,9 @@ var generatedDefinitions = map[string]generatedDefinition{ ItemRef: "Resource", }, { - Name: "effectiveDateTime", - Kind: "string", + Name: "effectiveDateTime", + Kind: "string", + Format: "date-time", }, { Name: "effectivePeriod", @@ -1952,8 +1974,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "issued", - Kind: "string", + Name: "issued", + Kind: "string", + Format: "date-time", }, { Name: "language", @@ -2338,8 +2361,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "Reference", }, { - Name: "date", - Kind: "string", + Name: "date", + Kind: "string", + Format: "date-time", }, { Name: "description", @@ -2510,8 +2534,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "time", - Kind: "string", + Name: "time", + Kind: "string", + Format: "date-time", }, }, }, @@ -3105,8 +3130,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "Availability", }, { - Name: "valueBase64Binary", - Kind: "string", + Name: "valueBase64Binary", + Kind: "string", + Format: "binary", }, { Name: "valueBoolean", @@ -3156,12 +3182,14 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "DataRequirement", }, { - Name: "valueDate", - Kind: "string", + Name: "valueDate", + Kind: "string", + Format: "date", }, { - Name: "valueDateTime", - Kind: "string", + Name: "valueDateTime", + Kind: "string", + Format: "date-time", }, { Name: "valueDecimal", @@ -3207,8 +3235,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "Identifier", }, { - Name: "valueInstant", - Kind: "string", + Name: "valueInstant", + Kind: "string", + Format: "date-time", }, { Name: "valueInteger", @@ -3295,8 +3324,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "valueTime", - Kind: "string", + Name: "valueTime", + Kind: "string", + Format: "time", }, { Name: "valueTiming", @@ -3317,8 +3347,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "valueUrl", - Kind: "string", + Name: "valueUrl", + Kind: "string", + Format: "uri", }, { Name: "valueUsageContext", @@ -3326,8 +3357,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "UsageContext", }, { - Name: "valueUuid", - Kind: "string", + Name: "valueUuid", + Kind: "string", + Format: "uuid", }, }, }, @@ -3448,8 +3480,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "bornDate", - Kind: "string", + Name: "bornDate", + Kind: "string", + Format: "date", }, { Name: "bornPeriod", @@ -3478,8 +3511,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "CodeableConcept", }, { - Name: "date", - Kind: "string", + Name: "date", + Kind: "string", + Format: "date-time", }, { Name: "deceasedAge", @@ -3491,8 +3525,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "boolean", }, { - Name: "deceasedDate", - Kind: "string", + Name: "deceasedDate", + Kind: "string", + Format: "date", }, { Name: "deceasedRange", @@ -3816,8 +3851,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "Age", }, { - Name: "performedDateTime", - Kind: "string", + Name: "performedDateTime", + Kind: "string", + Format: "date-time", }, { Name: "performedPeriod", @@ -4455,8 +4491,9 @@ var generatedDefinitions = map[string]generatedDefinition{ ItemRef: "ImagingStudySeries", }, { - Name: "started", - Kind: "string", + Name: "started", + Kind: "string", + Format: "date-time", }, { Name: "status", @@ -4583,8 +4620,9 @@ var generatedDefinitions = map[string]generatedDefinition{ ItemRef: "Reference", }, { - Name: "started", - Kind: "string", + Name: "started", + Kind: "string", + Format: "date-time", }, { Name: "uid", @@ -4954,8 +4992,9 @@ var generatedDefinitions = map[string]generatedDefinition{ ItemRef: "Annotation", }, { - Name: "occurenceDateTime", - Kind: "string", + Name: "occurenceDateTime", + Kind: "string", + Format: "date-time", }, { Name: "occurencePeriod", @@ -4986,8 +5025,9 @@ var generatedDefinitions = map[string]generatedDefinition{ ItemRef: "CodeableReference", }, { - Name: "recorded", - Kind: "string", + Name: "recorded", + Kind: "string", + Format: "date-time", }, { Name: "request", @@ -5162,8 +5202,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "FHIRPrimitiveExtension", }, { - Name: "expirationDate", - Kind: "string", + Name: "expirationDate", + Kind: "string", + Format: "date-time", }, { Name: "extension", @@ -5317,8 +5358,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "FHIRPrimitiveExtension", }, { - Name: "authoredOn", - Kind: "string", + Name: "authoredOn", + Kind: "string", + Format: "date-time", }, { Name: "basedOn", @@ -5510,8 +5552,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "statusChanged", - Kind: "string", + Name: "statusChanged", + Kind: "string", + Format: "date-time", }, { Name: "statusReason", @@ -5772,8 +5815,9 @@ var generatedDefinitions = map[string]generatedDefinition{ ItemRef: "Resource", }, { - Name: "dateAsserted", - Kind: "string", + Name: "dateAsserted", + Kind: "string", + Format: "date-time", }, { Name: "derivedFrom", @@ -5788,8 +5832,9 @@ var generatedDefinitions = map[string]generatedDefinition{ ItemRef: "Dosage", }, { - Name: "effectiveDateTime", - Kind: "string", + Name: "effectiveDateTime", + Kind: "string", + Format: "date-time", }, { Name: "effectivePeriod", @@ -5992,8 +6037,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "lastUpdated", - Kind: "string", + Name: "lastUpdated", + Kind: "string", + Format: "date-time", }, { Name: "links", @@ -6242,12 +6288,14 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "Reference", }, { - Name: "effectiveDateTime", - Kind: "string", + Name: "effectiveDateTime", + Kind: "string", + Format: "date-time", }, { - Name: "effectiveInstant", - Kind: "string", + Name: "effectiveInstant", + Kind: "string", + Format: "date-time", }, { Name: "effectivePeriod", @@ -6316,8 +6364,9 @@ var generatedDefinitions = map[string]generatedDefinition{ ItemRef: "CodeableConcept", }, { - Name: "issued", - Kind: "string", + Name: "issued", + Kind: "string", + Format: "date-time", }, { Name: "language", @@ -6413,8 +6462,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "CodeableConcept", }, { - Name: "valueDateTime", - Kind: "string", + Name: "valueDateTime", + Kind: "string", + Format: "date-time", }, { Name: "valueInteger", @@ -6455,8 +6505,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "valueTime", - Kind: "string", + Name: "valueTime", + Kind: "string", + Format: "time", }, }, }, @@ -6554,8 +6605,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "CodeableConcept", }, { - Name: "valueDateTime", - Kind: "string", + Name: "valueDateTime", + Kind: "string", + Format: "date-time", }, { Name: "valueInteger", @@ -6596,8 +6648,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "valueTime", - Kind: "string", + Name: "valueTime", + Kind: "string", + Format: "time", }, }, }, @@ -7077,8 +7130,9 @@ var generatedDefinitions = map[string]generatedDefinition{ ItemRef: "Address", }, { - Name: "birthDate", - Kind: "string", + Name: "birthDate", + Kind: "string", + Format: "date", }, { Name: "communication", @@ -7103,8 +7157,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "boolean", }, { - Name: "deceasedDateTime", - Kind: "string", + Name: "deceasedDateTime", + Kind: "string", + Format: "date-time", }, { Name: "extension", @@ -7398,8 +7453,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "FHIRPrimitiveExtension", }, { - Name: "end", - Kind: "string", + Name: "end", + Kind: "string", + Format: "date-time", }, { Name: "extension", @@ -7426,8 +7482,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "start", - Kind: "string", + Name: "start", + Kind: "string", + Format: "date-time", }, }, }, @@ -7479,8 +7536,9 @@ var generatedDefinitions = map[string]generatedDefinition{ ItemRef: "Address", }, { - Name: "birthDate", - Kind: "string", + Name: "birthDate", + Kind: "string", + Format: "date", }, { Name: "communication", @@ -7499,8 +7557,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "boolean", }, { - Name: "deceasedDateTime", - Kind: "string", + Name: "deceasedDateTime", + Kind: "string", + Format: "date-time", }, { Name: "extension", @@ -8019,8 +8078,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "Age", }, { - Name: "occurrenceDateTime", - Kind: "string", + Name: "occurrenceDateTime", + Kind: "string", + Format: "date-time", }, { Name: "occurrencePeriod", @@ -8065,8 +8125,9 @@ var generatedDefinitions = map[string]generatedDefinition{ ItemRef: "CodeableReference", }, { - Name: "recorded", - Kind: "string", + Name: "recorded", + Kind: "string", + Format: "date-time", }, { Name: "recorder", @@ -8556,8 +8617,9 @@ var generatedDefinitions = map[string]generatedDefinition{ ItemRef: "links", }, { - Name: "publicationDate", - Kind: "string", + Name: "publicationDate", + Kind: "string", + Format: "date", }, { Name: "publicationStatus", @@ -8665,8 +8727,9 @@ var generatedDefinitions = map[string]generatedDefinition{ ItemRef: "Resource", }, { - Name: "date", - Kind: "string", + Name: "date", + Kind: "string", + Format: "date-time", }, { Name: "description", @@ -9432,8 +9495,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "FHIRPrimitiveExtension", }, { - Name: "endDate", - Kind: "string", + Name: "endDate", + Kind: "string", + Format: "date-time", }, { Name: "extension", @@ -9476,8 +9540,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "startDate", - Kind: "string", + Name: "startDate", + Kind: "string", + Format: "date-time", }, { Name: "subjectState", @@ -9673,8 +9738,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "FHIRPrimitiveExtension", }, { - Name: "data", - Kind: "string", + Name: "data", + Kind: "string", + Format: "binary", }, { Name: "extension", @@ -9720,8 +9786,9 @@ var generatedDefinitions = map[string]generatedDefinition{ ItemRef: "Coding", }, { - Name: "when", - Kind: "string", + Name: "when", + Kind: "string", + Format: "date-time", }, { Name: "who", @@ -9859,8 +9926,9 @@ var generatedDefinitions = map[string]generatedDefinition{ ItemRef: "SpecimenProcessing", }, { - Name: "receivedTime", - Kind: "string", + Name: "receivedTime", + Kind: "string", + Format: "date-time", }, { Name: "request", @@ -9912,8 +9980,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "CodeableReference", }, { - Name: "collectedDateTime", - Kind: "string", + Name: "collectedDateTime", + Kind: "string", + Format: "date-time", }, { Name: "collectedPeriod", @@ -10147,8 +10216,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "timeDateTime", - Kind: "string", + Name: "timeDateTime", + Kind: "string", + Format: "date-time", }, { Name: "timePeriod", @@ -10211,8 +10281,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "expiry", - Kind: "string", + Name: "expiry", + Kind: "string", + Format: "date-time", }, { Name: "extension", @@ -10618,8 +10689,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "CodeableConcept", }, { - Name: "statusDate", - Kind: "string", + Name: "statusDate", + Kind: "string", + Format: "date-time", }, }, }, @@ -10880,8 +10952,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "CodeableConcept", }, { - Name: "date", - Kind: "string", + Name: "date", + Kind: "string", + Format: "date-time", }, { Name: "extension", @@ -10982,8 +11055,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "CodeableConcept", }, { - Name: "valueDate", - Kind: "string", + Name: "valueDate", + Kind: "string", + Format: "date", }, { Name: "valueQuantity", @@ -11395,8 +11469,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "FHIRPrimitiveExtension", }, { - Name: "authoredOn", - Kind: "string", + Name: "authoredOn", + Kind: "string", + Format: "date-time", }, { Name: "basedOn", @@ -11506,8 +11581,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "lastModified", - Kind: "string", + Name: "lastModified", + Kind: "string", + Format: "date-time", }, { Name: "links", @@ -11780,8 +11856,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "Availability", }, { - Name: "valueBase64Binary", - Kind: "string", + Name: "valueBase64Binary", + Kind: "string", + Format: "binary", }, { Name: "valueBoolean", @@ -11831,12 +11908,14 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "DataRequirement", }, { - Name: "valueDate", - Kind: "string", + Name: "valueDate", + Kind: "string", + Format: "date", }, { - Name: "valueDateTime", - Kind: "string", + Name: "valueDateTime", + Kind: "string", + Format: "date-time", }, { Name: "valueDecimal", @@ -11882,8 +11961,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "Identifier", }, { - Name: "valueInstant", - Kind: "string", + Name: "valueInstant", + Kind: "string", + Format: "date-time", }, { Name: "valueInteger", @@ -11970,8 +12050,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "valueTime", - Kind: "string", + Name: "valueTime", + Kind: "string", + Format: "time", }, { Name: "valueTiming", @@ -11992,8 +12073,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "valueUrl", - Kind: "string", + Name: "valueUrl", + Kind: "string", + Format: "uri", }, { Name: "valueUsageContext", @@ -12001,8 +12083,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "UsageContext", }, { - Name: "valueUuid", - Kind: "string", + Name: "valueUuid", + Kind: "string", + Format: "uuid", }, }, }, @@ -12169,8 +12252,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "Availability", }, { - Name: "valueBase64Binary", - Kind: "string", + Name: "valueBase64Binary", + Kind: "string", + Format: "binary", }, { Name: "valueBoolean", @@ -12220,12 +12304,14 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "DataRequirement", }, { - Name: "valueDate", - Kind: "string", + Name: "valueDate", + Kind: "string", + Format: "date", }, { - Name: "valueDateTime", - Kind: "string", + Name: "valueDateTime", + Kind: "string", + Format: "date-time", }, { Name: "valueDecimal", @@ -12271,8 +12357,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "Identifier", }, { - Name: "valueInstant", - Kind: "string", + Name: "valueInstant", + Kind: "string", + Format: "date-time", }, { Name: "valueInteger", @@ -12359,8 +12446,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "valueTime", - Kind: "string", + Name: "valueTime", + Kind: "string", + Format: "time", }, { Name: "valueTiming", @@ -12381,8 +12469,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "valueUrl", - Kind: "string", + Name: "valueUrl", + Kind: "string", + Format: "uri", }, { Name: "valueUsageContext", @@ -12390,8 +12479,9 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "UsageContext", }, { - Name: "valueUuid", - Kind: "string", + Name: "valueUuid", + Kind: "string", + Format: "uuid", }, }, }, @@ -12507,9 +12597,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Ref: "CodeableConcept", }, { - Name: "event", - Kind: "array", - ItemKind: "string", + Name: "event", + Kind: "array", + ItemKind: "string", + ItemFormat: "date-time", }, { Name: "extension", @@ -12712,9 +12803,10 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "timeOfDay", - Kind: "array", - ItemKind: "string", + Name: "timeOfDay", + Kind: "array", + ItemKind: "string", + ItemFormat: "time", }, { Name: "when", @@ -12799,12 +12891,14 @@ var generatedDefinitions = map[string]generatedDefinition{ Kind: "string", }, { - Name: "timingDate", - Kind: "string", + Name: "timingDate", + Kind: "string", + Format: "date", }, { - Name: "timingDateTime", - Kind: "string", + Name: "timingDateTime", + Kind: "string", + Format: "date-time", }, { Name: "timingReference", diff --git a/internal/fhirschema/root_resources_test.go b/internal/fhirschema/root_resources_test.go new file mode 100644 index 0000000..90d442b --- /dev/null +++ b/internal/fhirschema/root_resources_test.go @@ -0,0 +1,22 @@ +package fhirschema + +import "testing" + +func TestResourceTypesExposeSchemaDerivedConcreteRootsOnly(t *testing.T) { + for _, resourceType := range []string{ + "DiagnosticReport", + "MedicationRequest", + "MedicationStatement", + "Procedure", + "Task", + } { + if !HasResource(resourceType) { + t.Errorf("HasResource(%q) = false; concrete schema root is missing", resourceType) + } + } + for _, definition := range []string{"Address", "PatientContact", "Resource"} { + if HasResource(definition) { + t.Errorf("HasResource(%q) = true; backbone or abstract definition must not be a compiler root", definition) + } + } +} diff --git a/internal/fhirschema/schema.go b/internal/fhirschema/schema.go index aaffde5..f157162 100644 --- a/internal/fhirschema/schema.go +++ b/internal/fhirschema/schema.go @@ -80,9 +80,11 @@ type generatedDefinition struct { type generatedProperty struct { Name string Kind string + Format string Ref string Properties []generatedProperty ItemKind string + ItemFormat string ItemRef string ItemProperties []generatedProperty } diff --git a/internal/fhirschema/terminal_metadata.go b/internal/fhirschema/terminal_metadata.go new file mode 100644 index 0000000..e212c8a --- /dev/null +++ b/internal/fhirschema/terminal_metadata.go @@ -0,0 +1,76 @@ +package fhirschema + +import "strings" + +// PrimitiveKind is the primitive shape reliably represented by generated +// schema metadata. Date and date-time are exposed only when the source graph +// schema declares the corresponding JSON Schema format; code semantics remain +// distinct from arbitrary generated strings. +type PrimitiveKind string + +const ( + PrimitiveUnknown PrimitiveKind = "unknown" + PrimitiveString PrimitiveKind = "string" + PrimitiveBoolean PrimitiveKind = "boolean" + PrimitiveInteger PrimitiveKind = "integer" + PrimitiveDecimal PrimitiveKind = "decimal" + PrimitiveDate PrimitiveKind = "date" + PrimitiveDateTime PrimitiveKind = "date_time" +) + +// TerminalScalarMetadata describes the terminal property of a canonical FHIR +// path without exposing generator-private property types. Primitive is unknown +// when the terminal is an object or an array of objects. +type TerminalScalarMetadata struct { + Primitive PrimitiveKind + Repeated bool +} + +// ResolveTerminalScalarMetadata resolves compiler-facing primitive and +// repetition facts from the active generated definition. +func ResolveTerminalScalarMetadata(resourceType, canonicalPath string) (TerminalScalarMetadata, bool) { + canonicalPath = CanonicalizePath(canonicalPath) + resolved, ok := ResolvePath(resourceType, canonicalPath) + if !ok { + return TerminalScalarMetadata{}, false + } + // A scalar below any repeated parent can yield more than one value per + // resource. Looking at only the terminal generated property would classify + // component[].valueInteger as scalar, which would let the compiler apply an + // incorrect scalar filter or projection. + repeated := strings.Contains(canonicalPath, "[]") + property := resolved.Property + if property.Kind == "array" { + return TerminalScalarMetadata{ + Primitive: primitiveKind(property.ItemKind, property.ItemFormat), + Repeated: true, + }, true + } + return TerminalScalarMetadata{ + Primitive: primitiveKind(property.Kind, property.Format), + Repeated: repeated, + }, true +} + +func primitiveKind(kind, format string) PrimitiveKind { + if kind == "string" { + switch format { + case "date": + return PrimitiveDate + case "date-time": + return PrimitiveDateTime + } + } + switch kind { + case "string": + return PrimitiveString + case "boolean": + return PrimitiveBoolean + case "integer": + return PrimitiveInteger + case "number": + return PrimitiveDecimal + default: + return PrimitiveUnknown + } +} diff --git a/internal/fhirschema/terminal_metadata_test.go b/internal/fhirschema/terminal_metadata_test.go new file mode 100644 index 0000000..058c9b1 --- /dev/null +++ b/internal/fhirschema/terminal_metadata_test.go @@ -0,0 +1,98 @@ +package fhirschema + +import "testing" + +func TestResolveTerminalScalarMetadata(t *testing.T) { + tests := []struct { + name string + resourceType string + path string + want TerminalScalarMetadata + }{ + { + name: "string primitive", + resourceType: "Patient", + path: "gender", + want: TerminalScalarMetadata{Primitive: PrimitiveString}, + }, + { + name: "integer primitive", + resourceType: "Observation", + path: "valueInteger", + want: TerminalScalarMetadata{Primitive: PrimitiveInteger}, + }, + { + name: "decimal primitive", + resourceType: "Observation", + path: "valueQuantity.value", + want: TerminalScalarMetadata{Primitive: PrimitiveDecimal}, + }, + { + name: "boolean primitive", + resourceType: "Observation", + path: "valueBoolean", + want: TerminalScalarMetadata{Primitive: PrimitiveBoolean}, + }, + { + name: "repeated object terminal", + resourceType: "Observation", + path: "component[]", + want: TerminalScalarMetadata{Primitive: PrimitiveUnknown, Repeated: true}, + }, + { + name: "scalar below repeated object", + resourceType: "Observation", + path: "component[].valueInteger", + want: TerminalScalarMetadata{Primitive: PrimitiveInteger, Repeated: true}, + }, + { + name: "date time format is generated metadata", + resourceType: "Observation", + path: "valueDateTime", + want: TerminalScalarMetadata{Primitive: PrimitiveDateTime}, + }, + { + name: "date format is generated metadata", + resourceType: "Patient", + path: "birthDate", + want: TerminalScalarMetadata{Primitive: PrimitiveDate}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, ok := ResolveTerminalScalarMetadata(tt.resourceType, tt.path) + if !ok { + t.Fatalf("ResolveTerminalScalarMetadata(%q, %q) did not resolve", tt.resourceType, tt.path) + } + if got != tt.want { + t.Fatalf("metadata = %#v, want %#v", got, tt.want) + } + }) + } +} + +func TestResolveTerminalScalarMetadataRejectsUnknownPath(t *testing.T) { + if got, ok := ResolveTerminalScalarMetadata("Patient", "notARealField"); ok { + t.Fatalf("unexpected metadata for unknown path: %#v", got) + } + if got, ok := ResolveTerminalScalarMetadata("NotAResource", "id"); ok { + t.Fatalf("unexpected metadata for unknown resource: %#v", got) + } + // The active generated Observation definition does not advertise + // valueDecimal, so the semantic API must not infer it from another FHIR + // version or an external model. + if got, ok := ResolveTerminalScalarMetadata("Observation", "valueDecimal"); ok { + t.Fatalf("unexpected metadata for unadvertised Observation.valueDecimal: %#v", got) + } +} + +func TestResolveTerminalScalarMetadataRepeatedPrimitive(t *testing.T) { + got, ok := ResolveTerminalScalarMetadata("Patient", "name[]") + if !ok { + t.Fatal("Patient.name[] did not resolve") + } + if !got.Repeated || got.Primitive != PrimitiveUnknown { + t.Fatalf("Patient.name[] metadata = %#v, want repeated object", got) + } +} diff --git a/internal/graphqlapi/http_integration_test.go b/internal/graphqlapi/http_integration_test.go index c387b11..84fd815 100644 --- a/internal/graphqlapi/http_integration_test.go +++ b/internal/graphqlapi/http_integration_test.go @@ -214,8 +214,8 @@ func TestGraphQLRunDataframeMutation(t *testing.T) { return []catalog.PopulatedReference{}, nil }, ExecuteRows: func(ctx context.Context, opts dataframe.ExecuteQueryOptions, query string, bindVars map[string]any, visit func(map[string]any) error) error { - if !strings.Contains(query, "LET root_patient_neighbor_set") || !strings.Contains(query, "LET patient_condition_set") { - t.Fatalf("expected advanced lowered query, got:\n%s", query) + if !strings.Contains(query, "LET generic_root_subject_Patient_neighbors_set") || !strings.Contains(query, "LET generic_condition_set") { + t.Fatalf("expected generic lowered query, got:\n%s", query) } return visit(map[string]any{"_key": "p1", "gender": "female", "condition__condition_count": 1}) }, @@ -336,8 +336,8 @@ func TestGraphQLRunDataframeTraversalBuilder(t *testing.T) { return []catalog.PopulatedReference{}, nil }, ExecuteRows: func(ctx context.Context, opts dataframe.ExecuteQueryOptions, query string, bindVars map[string]any, visit func(map[string]any) error) error { - if !strings.Contains(query, "LET root_patient_neighbor_set") || !strings.Contains(query, "LET patient_specimen_set") { - t.Fatalf("expected advanced lowered query, got:\n%s", query) + if !strings.Contains(query, "LET generic_root_subject_Patient_neighbors_set") || !strings.Contains(query, "LET generic_specimen_set") { + t.Fatalf("expected generic lowered query, got:\n%s", query) } return visit(map[string]any{ "_key": "p1", diff --git a/internal/graphqlapi/output_mapping.go b/internal/graphqlapi/output_mapping.go index 8637f48..356eeb1 100644 --- a/internal/graphqlapi/output_mapping.go +++ b/internal/graphqlapi/output_mapping.go @@ -150,13 +150,6 @@ func cloneStrings(in []string) []string { return append([]string(nil), in...) } -func cloneTraversals(in []catalog.PopulatedReference) []catalog.PopulatedReference { - if len(in) == 0 { - return []catalog.PopulatedReference{} - } - return append([]catalog.PopulatedReference(nil), in...) -} - func optionalString(in string) *string { in = strings.TrimSpace(in) if in == "" { diff --git a/internal/graphqlapi/scalars.go b/internal/graphqlapi/scalars.go index 0a8c8b7..e15bea7 100644 --- a/internal/graphqlapi/scalars.go +++ b/internal/graphqlapi/scalars.go @@ -15,12 +15,8 @@ func MarshalJSON(v json.RawMessage) graphql.Marshaler { }) } -func UnmarshalJSON(v any) (json.RawMessage, error) { - return json.Marshal(v) -} - func (ec *executionContext) unmarshalInputJSON(ctx context.Context, v any) (json.RawMessage, error) { - return UnmarshalJSON(v) + return json.Marshal(v) } func (ec *executionContext) _JSON(ctx context.Context, sel ast.SelectionSet, v json.RawMessage) graphql.Marshaler { diff --git a/internal/ingest/backend.go b/internal/ingest/backend.go index 25f5ba7..e84fbfc 100644 --- a/internal/ingest/backend.go +++ b/internal/ingest/backend.go @@ -4,26 +4,39 @@ import ( "context" "encoding/json" + "github.com/calypr/loom/internal/datasetstore" arangostore "github.com/calypr/loom/internal/store/arango" ) const EdgeCollection = "fhir_edge" -const PatientFileRollupCollection = "patient_file_rollup" -const ScalarIndexCollection = "fhir_scalar_index" func openBackend(ctx context.Context, opts arangostore.ConnectionOptions) (*arangostore.Client, error) { return arangostore.Open(ctx, opts.URL, opts.Database) } func bootstrapSpecWithReporter(resourceTypes []string, truncate bool, reporter EventSink) arangostore.BootstrapSpec { - collections := make([]arangostore.CollectionSpec, 0, len(resourceTypes)+3) + collections := make([]arangostore.CollectionSpec, 0, len(resourceTypes)+2) for _, name := range resourceTypes { - indexes := [][]string{{"project"}, {"id"}, {"project", "id"}, {"project", "auth_resource_path"}} - if name == "Patient" { - indexes = append(indexes, []string{"project", "_key"}, []string{"project", "auth_resource_path", "_key"}) - } - if name == "DocumentReference" { - indexes = append(indexes, []string{"project", "auth_resource_path", "_key"}) + // Every generated FHIR resource is a possible dataframe root. The + // compiler applies project and optional authorization scope before a + // stable _key sort/limit, so these are not Patient-specific indexes. + // Without the _key suffix Arango can choose the primary index only to + // satisfy SORT root._key, then scan an entire resource collection before + // it finds a project's first preview rows. + indexes := [][]string{ + {"project"}, + {"id"}, + {"project", "id"}, + {"project", "_key"}, + {"project", "auth_resource_path"}, + {"project", "auth_resource_path", "_key"}, + // Dataset generations use immutable, hashed physical keys. These + // indexes support the compiler's mandatory project/generation scope + // before stable key or FHIR-id lookup without changing legacy plans. + {"project", "dataset_generation", "_key"}, + {"project", "dataset_generation", "auth_resource_path", "_key"}, + {"project", "dataset_generation", "id"}, + {"project", "dataset_generation", "auth_resource_path", "id"}, } collections = append(collections, arangostore.CollectionSpec{ Name: name, @@ -40,6 +53,20 @@ func bootstrapSpecWithReporter(resourceTypes []string, truncate bool, reporter E {"project", "label"}, {"project", "from_type", "label"}, {"project", "to_type", "label"}, + {"project", "dataset_generation", "from_type", "label"}, + {"project", "dataset_generation", "to_type", "label"}, + {"project", "dataset_generation", "auth_resource_path", "from_type", "label"}, + {"project", "dataset_generation", "auth_resource_path", "to_type", "label"}, + // These are vertex-centric persistent indexes. A dataframe + // traversal always starts at one known root/parent endpoint and + // applies exact project, generation, label, and target-type + // predicates. The default Arango edge index can locate the + // endpoint but must inspect every adjacent edge; these compound + // indexes let the optimizer restrict the adjacency list before + // materializing candidate edges. Keep the endpoint first: `_to` + // is INBOUND and `_from` is OUTBOUND. + {"_to", "project", "dataset_generation", "label", "from_type"}, + {"_from", "project", "dataset_generation", "label", "to_type"}, }, }, arangostore.CollectionSpec{ @@ -51,14 +78,12 @@ func bootstrapSpecWithReporter(resourceTypes []string, truncate bool, reporter E {"project", "resource_type", "path"}, {"project", "auth_resource_path", "resource_type", "path"}, {"project", "resource_type", "pivot_candidate"}, - }, - }, - arangostore.CollectionSpec{ - Name: PatientFileRollupCollection, - Truncate: truncate, - Indexes: [][]string{ - {"project", "patient_key"}, - {"project", "auth_resource_path", "patient_key"}, + {"project", "dataset_generation", "resource_type"}, + {"project", "dataset_generation", "auth_resource_path", "resource_type"}, + {"project", "dataset_generation", "resource_type", "path"}, + {"project", "dataset_generation", "auth_resource_path", "resource_type", "path"}, + {"project", "dataset_generation", "resource_type", "pivot_candidate"}, + {"project", "dataset_generation", "auth_resource_path", "resource_type", "pivot_candidate"}, }, }, ) @@ -70,6 +95,18 @@ func bootstrapSpecWithReporter(resourceTypes []string, truncate bool, reporter E } } +// lifecycleBootstrapSpecWithReporter keeps generation manifests outside the +// truncation-oriented FHIR bootstrap. Load invokes this spec first when a +// caller explicitly selects immutable dataset-generation mode. +func lifecycleBootstrapSpecWithReporter(reporter EventSink) arangostore.BootstrapSpec { + return arangostore.BootstrapSpec{ + Collections: datasetstore.CollectionSpecs(), + Reporter: func(event string, fields map[string]any) { + emitEvent(reporter, event, fields) + }, + } +} + func insertRawDocuments(ctx context.Context, backend *arangostore.Client, collection string, docs []json.RawMessage, overwrite bool, writeAPI string) error { return backend.InsertBatchRaw(ctx, collection, docs, overwrite, writeAPI) } diff --git a/internal/ingest/backend_test.go b/internal/ingest/backend_test.go new file mode 100644 index 0000000..2859303 --- /dev/null +++ b/internal/ingest/backend_test.go @@ -0,0 +1,108 @@ +package ingest + +import ( + "reflect" + "testing" + + arangostore "github.com/calypr/loom/internal/store/arango" +) + +func TestBootstrapSpecAddsRootPreviewIndexesForEveryFHIRCollection(t *testing.T) { + resources := []string{"Patient", "Specimen", "Observation", "DocumentReference"} + spec := bootstrapSpecWithReporter(resources, false, nil) + for _, resource := range resources { + collection, found := bootstrapCollection(spec, resource) + if !found { + t.Fatalf("bootstrap collection %q is missing", resource) + } + for _, required := range [][]string{ + {"project", "_key"}, + {"project", "auth_resource_path", "_key"}, + } { + if !containsIndex(collection.Indexes, required) { + t.Fatalf("collection %q indexes %#v do not include required preview index %#v", resource, collection.Indexes, required) + } + } + } +} + +func TestBootstrapSpecAddsGenerationScopedIndexesWithoutTraversalSpeculation(t *testing.T) { + spec := bootstrapSpecWithReporter([]string{"Patient"}, true, nil) + patient, found := bootstrapCollection(spec, "Patient") + if !found { + t.Fatal("Patient bootstrap collection is missing") + } + for _, required := range [][]string{ + {"project", "dataset_generation", "_key"}, + {"project", "dataset_generation", "auth_resource_path", "_key"}, + {"project", "dataset_generation", "id"}, + {"project", "dataset_generation", "auth_resource_path", "id"}, + } { + if !containsIndex(patient.Indexes, required) { + t.Fatalf("Patient indexes %#v do not include generation index %#v", patient.Indexes, required) + } + } + + edges, found := bootstrapCollection(spec, EdgeCollection) + if !found { + t.Fatal("edge bootstrap collection is missing") + } + for _, required := range [][]string{ + {"project", "dataset_generation", "from_type", "label"}, + {"project", "dataset_generation", "to_type", "label"}, + {"project", "dataset_generation", "auth_resource_path", "from_type", "label"}, + {"project", "dataset_generation", "auth_resource_path", "to_type", "label"}, + {"_to", "project", "dataset_generation", "label", "from_type"}, + {"_from", "project", "dataset_generation", "label", "to_type"}, + } { + if !containsIndex(edges.Indexes, required) { + t.Fatalf("edge indexes %#v do not include generation index %#v", edges.Indexes, required) + } + } + + catalog, found := bootstrapCollection(spec, "fhir_field_catalog") + if !found { + t.Fatal("field catalog bootstrap collection is missing") + } + for _, required := range [][]string{ + {"project", "dataset_generation", "resource_type"}, + {"project", "dataset_generation", "auth_resource_path", "resource_type"}, + {"project", "dataset_generation", "resource_type", "path"}, + {"project", "dataset_generation", "auth_resource_path", "resource_type", "path"}, + {"project", "dataset_generation", "resource_type", "pivot_candidate"}, + {"project", "dataset_generation", "auth_resource_path", "resource_type", "pivot_candidate"}, + } { + if !containsIndex(catalog.Indexes, required) { + t.Fatalf("catalog indexes %#v do not include generation index %#v", catalog.Indexes, required) + } + } + +} + +func TestLifecycleBootstrapNeverTruncatesMetadata(t *testing.T) { + spec := lifecycleBootstrapSpecWithReporter(nil) + if len(spec.Collections) != 1 { + t.Fatalf("lifecycle collection count = %d, want 1", len(spec.Collections)) + } + if spec.Collections[0].Truncate { + t.Fatalf("lifecycle collection %#v requests truncation", spec.Collections[0]) + } +} + +func bootstrapCollection(spec arangostore.BootstrapSpec, name string) (arangostore.CollectionSpec, bool) { + for _, collection := range spec.Collections { + if collection.Name == name { + return collection, true + } + } + return arangostore.CollectionSpec{}, false +} + +func containsIndex(indexes [][]string, want []string) bool { + for _, index := range indexes { + if reflect.DeepEqual(index, want) { + return true + } + } + return false +} diff --git a/internal/ingest/generated_load.go b/internal/ingest/generated_load.go index 212d606..722d823 100644 --- a/internal/ingest/generated_load.go +++ b/internal/ingest/generated_load.go @@ -11,6 +11,20 @@ import ( "github.com/bytedance/sonic" ) +// supportsGeneratedLoad reports whether the optimized generated-loader +// dispatcher has a concrete fast-path case for this resource. The generated +// FHIR model can contain more types than this dispatcher; Load uses the +// generic schema-backed builder for active graph-schema roots outside the fast +// switch rather than rejecting an otherwise valid file. +func supportsGeneratedLoad(resourceType string) bool { + switch resourceType { + case "BodyStructure", "Condition", "DocumentReference", "Group", "ImagingStudy", "Medication", "MedicationAdministration", "Observation", "Organization", "Patient", "Practitioner", "ResearchStudy", "ResearchSubject", "Specimen": + return true + default: + return false + } +} + func loadRowGenerated(resourceType string, line []byte, project string, stageSeconds map[string]float64) (jsgarango.VertexDocument, []json.RawMessage, error) { switch resourceType { case "BodyStructure": diff --git a/internal/ingest/generated_load_test.go b/internal/ingest/generated_load_test.go new file mode 100644 index 0000000..581f7c2 --- /dev/null +++ b/internal/ingest/generated_load_test.go @@ -0,0 +1,61 @@ +package ingest + +import ( + "encoding/json" + "testing" + + "github.com/calypr/loom/internal/fhir" +) + +func TestGeneratedLoadCapabilityFallsBackForSchemaOnlyRoots(t *testing.T) { + for _, resourceType := range []string{"Patient", "Specimen", "Observation"} { + if !supportsGeneratedLoad(resourceType) { + t.Fatalf("generated fast path unexpectedly unavailable for %s", resourceType) + } + } + for _, resourceType := range []string{"DiagnosticReport", "MedicationRequest", "MedicationStatement", "Procedure", "Task"} { + if supportsGeneratedLoad(resourceType) { + t.Fatalf("schema-only root %s should use generic loader fallback", resourceType) + } + } +} + +func TestGeneratedResearchSubjectStudyEdgeTargetsResearchStudy(t *testing.T) { + _, edges, err := loadRowGenerated("ResearchSubject", []byte(`{ + "resourceType": "ResearchSubject", + "id": "research-subject-1", + "status": "active", + "study": {"reference": "ResearchStudy/study-1"}, + "subject": {"reference": "Patient/patient-1"} +}`), "project-1", map[string]float64{}) + if err != nil { + t.Fatalf("loadRowGenerated(ResearchSubject): %v", err) + } + + var studyEdge *fhir.EdgeDocument + for _, raw := range edges { + var edge fhir.EdgeDocument + if err := json.Unmarshal(raw, &edge); err != nil { + t.Fatalf("decode generated edge: %v", err) + } + if edge.Label == "study" { + studyEdge = &edge + break + } + } + if studyEdge == nil { + t.Fatalf("generated ResearchSubject edges do not contain study: %#v", edges) + } + if got, want := studyEdge.From, "ResearchSubject/research-subject-1"; got != want { + t.Fatalf("study edge _from = %q, want %q", got, want) + } + if got, want := studyEdge.To, "ResearchStudy/study-1"; got != want { + t.Fatalf("study edge _to = %q, want %q", got, want) + } + if got, want := studyEdge.FromType, "ResearchSubject"; got != want { + t.Fatalf("study edge from_type = %q, want %q", got, want) + } + if got, want := studyEdge.ToType, "ResearchStudy"; got != want { + t.Fatalf("study edge to_type = %q, want %q", got, want) + } +} diff --git a/internal/ingest/generation_identity.go b/internal/ingest/generation_identity.go new file mode 100644 index 0000000..a8e3d1d --- /dev/null +++ b/internal/ingest/generation_identity.go @@ -0,0 +1,227 @@ +package ingest + +import ( + "crypto/sha256" + "encoding/hex" + "encoding/json" + "fmt" + "strings" +) + +// generationIdentityField is deliberately distinct from the resource payload +// and from the loader's error-generation counters. It identifies the immutable +// Loom dataset generation that owns a persisted graph document. +const generationIdentityField = "dataset_generation" + +// logicalKeyField preserves the pre-generation Arango key for operational +// diagnostics and future stable external-ID policy. It is not used for graph +// traversal: _key, _from, and _to are all generation-qualified below. +const logicalKeyField = "logical_key" + +// generationRowBuilder is the one identity boundary shared by the generated +// and generic FHIR row builders. Keeping it here avoids a second FHIR model or +// a generator-wide change: both builders first produce the established Loom +// vertex/edge representation, then this wrapper qualifies its physical graph +// identity for one immutable dataset generation. +// +// It is intentionally not selected by Load until the dataset lifecycle owns +// manifest creation and active-generation reads. Writing qualified identities +// without generation-qualified readers would be an incomplete migration. +type generationRowBuilder struct { + delegate RowBuilder + project string + datasetGeneration string +} + +func newGenerationRowBuilder(delegate RowBuilder, project, datasetGeneration string) (*generationRowBuilder, error) { + if delegate == nil { + return nil, fmt.Errorf("generation row builder requires a delegate") + } + project = strings.TrimSpace(project) + datasetGeneration = strings.TrimSpace(datasetGeneration) + if project == "" { + return nil, fmt.Errorf("generation row builder requires a project") + } + if datasetGeneration == "" { + return nil, fmt.Errorf("generation row builder requires a dataset generation") + } + return &generationRowBuilder{ + delegate: delegate, + project: project, + datasetGeneration: datasetGeneration, + }, nil +} + +func (b *generationRowBuilder) Build(resourceType string, line []byte, stageSeconds map[string]float64) (rowBuildResult, rowErrorType, error) { + result, errType, err := b.delegate.Build(resourceType, line, stageSeconds) + if err != nil { + return rowBuildResult{}, errType, err + } + namespaced, err := namespaceRowBuildResult(result, b.project, b.datasetGeneration, resourceType) + if err != nil { + return rowBuildResult{}, rowErrorGeneration, err + } + return namespaced, "", nil +} + +// namespaceRowBuildResult rewrites one generated or generic result into a +// generation-isolated graph identity. The original logical FHIR ID remains in +// the existing top-level id field; logical_key captures the original Arango +// key. Hashing is necessary because keys are global to a collection, while +// both resource IDs and generated edge IDs are otherwise reused by later +// project loads and dataset generations. +func namespaceRowBuildResult(result rowBuildResult, project, datasetGeneration, resourceType string) (rowBuildResult, error) { + project = strings.TrimSpace(project) + datasetGeneration = strings.TrimSpace(datasetGeneration) + resourceType = strings.TrimSpace(resourceType) + if project == "" || datasetGeneration == "" || resourceType == "" { + return rowBuildResult{}, fmt.Errorf("namespace row result requires project, dataset generation, and resource type") + } + + vertex, logicalVertexKey, err := namespaceVertexDocument(result.vertex, project, datasetGeneration, resourceType) + if err != nil { + return rowBuildResult{}, err + } + edges := make([]json.RawMessage, len(result.edges)) + for index, edge := range result.edges { + namespaced, err := namespaceEdgeDocument(edge, project, datasetGeneration) + if err != nil { + return rowBuildResult{}, fmt.Errorf("namespace edge %d for %s/%s: %w", index, resourceType, logicalVertexKey, err) + } + edges[index] = namespaced + } + return rowBuildResult{ + vertex: vertex, + edges: edges, + payload: result.payload, + }, nil +} + +func namespaceVertexDocument(raw json.RawMessage, project, datasetGeneration, resourceType string) (json.RawMessage, string, error) { + document, err := decodeTopLevelDocument(raw) + if err != nil { + return nil, "", err + } + logicalKey, err := requiredDocumentString(document, "_key") + if err != nil { + return nil, "", fmt.Errorf("vertex: %w", err) + } + if err := requireProject(document, project); err != nil { + return nil, "", fmt.Errorf("vertex: %w", err) + } + document[logicalKeyField] = json.RawMessage(strconvQuote(logicalKey)) + document[generationIdentityField] = json.RawMessage(strconvQuote(datasetGeneration)) + document["_key"] = json.RawMessage(strconvQuote(generationDocumentKey(project, datasetGeneration, resourceType, logicalKey))) + encoded, err := json.Marshal(document) + if err != nil { + return nil, "", fmt.Errorf("marshal namespaced vertex: %w", err) + } + return json.RawMessage(encoded), logicalKey, nil +} + +func namespaceEdgeDocument(raw json.RawMessage, project, datasetGeneration string) (json.RawMessage, error) { + document, err := decodeTopLevelDocument(raw) + if err != nil { + return nil, err + } + logicalKey, err := requiredDocumentString(document, "_key") + if err != nil { + return nil, fmt.Errorf("edge: %w", err) + } + if err := requireProject(document, project); err != nil { + return nil, fmt.Errorf("edge: %w", err) + } + from, err := requiredDocumentString(document, "_from") + if err != nil { + return nil, fmt.Errorf("edge: %w", err) + } + to, err := requiredDocumentString(document, "_to") + if err != nil { + return nil, fmt.Errorf("edge: %w", err) + } + namespacedFrom, err := generationDocumentID(project, datasetGeneration, from) + if err != nil { + return nil, fmt.Errorf("edge _from: %w", err) + } + namespacedTo, err := generationDocumentID(project, datasetGeneration, to) + if err != nil { + return nil, fmt.Errorf("edge _to: %w", err) + } + document[logicalKeyField] = json.RawMessage(strconvQuote(logicalKey)) + document[generationIdentityField] = json.RawMessage(strconvQuote(datasetGeneration)) + document["_key"] = json.RawMessage(strconvQuote(generationEdgeKey(project, datasetGeneration, logicalKey, from, to))) + document["_from"] = json.RawMessage(strconvQuote(namespacedFrom)) + document["_to"] = json.RawMessage(strconvQuote(namespacedTo)) + encoded, err := json.Marshal(document) + if err != nil { + return nil, fmt.Errorf("marshal namespaced edge: %w", err) + } + return json.RawMessage(encoded), nil +} + +func decodeTopLevelDocument(raw json.RawMessage) (map[string]json.RawMessage, error) { + if len(raw) == 0 { + return nil, fmt.Errorf("empty document") + } + var document map[string]json.RawMessage + if err := json.Unmarshal(raw, &document); err != nil { + return nil, fmt.Errorf("decode document: %w", err) + } + if document == nil { + return nil, fmt.Errorf("document must be an object") + } + return document, nil +} + +func requiredDocumentString(document map[string]json.RawMessage, field string) (string, error) { + raw, ok := document[field] + if !ok { + return "", fmt.Errorf("missing %s", field) + } + var value string + if err := json.Unmarshal(raw, &value); err != nil || strings.TrimSpace(value) == "" { + return "", fmt.Errorf("%s must be a non-empty string", field) + } + return value, nil +} + +func requireProject(document map[string]json.RawMessage, project string) error { + documentProject, err := requiredDocumentString(document, "project") + if err != nil { + return err + } + if documentProject != project { + return fmt.Errorf("project %q does not match expected project %q", documentProject, project) + } + return nil +} + +func generationDocumentID(project, datasetGeneration, documentID string) (string, error) { + collection, logicalKey, ok := strings.Cut(documentID, "/") + if !ok || strings.TrimSpace(collection) == "" || strings.TrimSpace(logicalKey) == "" || strings.Contains(logicalKey, "/") { + return "", fmt.Errorf("document ID %q must be collection/key", documentID) + } + return collection + "/" + generationDocumentKey(project, datasetGeneration, collection, logicalKey), nil +} + +func generationDocumentKey(project, datasetGeneration, collection, logicalKey string) string { + return "g_" + generationHash("vertex", project, datasetGeneration, collection, logicalKey) +} + +func generationEdgeKey(project, datasetGeneration, logicalKey, from, to string) string { + return "g_" + generationHash("edge", project, datasetGeneration, logicalKey, from, to) +} + +func generationHash(parts ...string) string { + hash := sha256.New() + for _, part := range parts { + _, _ = hash.Write([]byte(part)) + _, _ = hash.Write([]byte{0}) + } + return hex.EncodeToString(hash.Sum(nil)) +} + +func strconvQuote(value string) string { + encoded, _ := json.Marshal(value) + return string(encoded) +} diff --git a/internal/ingest/generation_identity_test.go b/internal/ingest/generation_identity_test.go new file mode 100644 index 0000000..5145d13 --- /dev/null +++ b/internal/ingest/generation_identity_test.go @@ -0,0 +1,257 @@ +package ingest + +import ( + "encoding/json" + "os" + "path/filepath" + "reflect" + "runtime" + "sort" + "strings" + "testing" + + "github.com/bmeg/jsonschemagraph/graph" +) + +func TestNamespaceRowBuildResultKeepsLogicalFHIRIdentityAndQualifiesGraphIdentity(t *testing.T) { + result := rowBuildResult{ + vertex: json.RawMessage(`{"_key":"patient-1","id":"patient-1","project":"project-a","resourceType":"Patient","payload":{"resourceType":"Patient","id":"patient-1"}}`), + edges: []json.RawMessage{ + json.RawMessage(`{"_key":"subject-edge","_from":"Observation/obs-1","_to":"Patient/patient-1","label":"subject_Patient","project":"project-a","from_type":"Observation","to_type":"Patient"}`), + }, + payload: map[string]any{"resourceType": "Patient", "id": "patient-1"}, + } + + namespaced, err := namespaceRowBuildResult(result, "project-a", "generation-1", "Patient") + if err != nil { + t.Fatalf("namespaceRowBuildResult() error = %v", err) + } + vertex := decodeIdentityDocument(t, namespaced.vertex) + if got, want := documentString(t, vertex, "id"), "patient-1"; got != want { + t.Fatalf("vertex id = %q, want %q", got, want) + } + if got, want := documentString(t, vertex, logicalKeyField), "patient-1"; got != want { + t.Fatalf("vertex logical key = %q, want %q", got, want) + } + if got, want := documentString(t, vertex, generationIdentityField), "generation-1"; got != want { + t.Fatalf("vertex dataset generation = %q, want %q", got, want) + } + vertexKey := documentString(t, vertex, "_key") + if vertexKey == "patient-1" || len(vertexKey) != len("g_")+64 { + t.Fatalf("vertex physical key = %q, want generation-qualified hash", vertexKey) + } + if got, want := string(vertex["payload"]), `{"resourceType":"Patient","id":"patient-1"}`; got != want { + t.Fatalf("payload changed\ngot: %s\nwant: %s", got, want) + } + + if got, want := len(namespaced.edges), 1; got != want { + t.Fatalf("edge count = %d, want %d", got, want) + } + edge := decodeIdentityDocument(t, namespaced.edges[0]) + if got, want := documentString(t, edge, logicalKeyField), "subject-edge"; got != want { + t.Fatalf("edge logical key = %q, want %q", got, want) + } + if got, want := documentString(t, edge, generationIdentityField), "generation-1"; got != want { + t.Fatalf("edge dataset generation = %q, want %q", got, want) + } + if got, want := documentString(t, edge, "_from"), generationDocumentIDMust(t, "project-a", "generation-1", "Observation/obs-1"); got != want { + t.Fatalf("edge _from = %q, want %q", got, want) + } + if got, want := documentString(t, edge, "_to"), "Patient/"+vertexKey; got != want { + t.Fatalf("edge _to = %q, want %q", got, want) + } + if key := documentString(t, edge, "_key"); key == "subject-edge" || len(key) != len("g_")+64 { + t.Fatalf("edge physical key = %q, want generation-qualified hash", key) + } + if !reflect.DeepEqual(namespaced.payload, result.payload) { + t.Fatalf("payload map changed\ngot: %#v\nwant: %#v", namespaced.payload, result.payload) + } +} + +func TestNamespaceRowBuildResultSeparatesProjectsAndGenerationsWithSameFHIRID(t *testing.T) { + result := rowBuildResult{ + vertex: json.RawMessage(`{"_key":"same-id","id":"same-id","project":"project-a","resourceType":"Patient"}`), + payload: map[string]any{"id": "same-id"}, + } + first, err := namespaceRowBuildResult(result, "project-a", "generation-a", "Patient") + if err != nil { + t.Fatal(err) + } + second, err := namespaceRowBuildResult(result, "project-a", "generation-b", "Patient") + if err != nil { + t.Fatal(err) + } + otherProject := result + otherProject.vertex = json.RawMessage(`{"_key":"same-id","id":"same-id","project":"project-b","resourceType":"Patient"}`) + third, err := namespaceRowBuildResult(otherProject, "project-b", "generation-a", "Patient") + if err != nil { + t.Fatal(err) + } + keys := []string{ + documentString(t, decodeIdentityDocument(t, first.vertex), "_key"), + documentString(t, decodeIdentityDocument(t, second.vertex), "_key"), + documentString(t, decodeIdentityDocument(t, third.vertex), "_key"), + } + if keys[0] == keys[1] || keys[0] == keys[2] || keys[1] == keys[2] { + t.Fatalf("namespaced keys collide: %#v", keys) + } +} + +func TestNamespaceRowBuildResultRejectsMalformedOrCrossProjectDocuments(t *testing.T) { + tests := []struct { + name string + result rowBuildResult + }{ + { + name: "missing vertex key", + result: rowBuildResult{vertex: json.RawMessage(`{"project":"project-a"}`)}, + }, + { + name: "project mismatch", + result: rowBuildResult{vertex: json.RawMessage(`{"_key":"one","project":"project-b"}`)}, + }, + { + name: "malformed edge endpoint", + result: rowBuildResult{ + vertex: json.RawMessage(`{"_key":"one","project":"project-a"}`), + edges: []json.RawMessage{json.RawMessage(`{"_key":"edge","_from":"not-a-document-id","_to":"Patient/one","project":"project-a"}`)}, + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + if _, err := namespaceRowBuildResult(test.result, "project-a", "generation-a", "Patient"); err == nil { + t.Fatal("namespaceRowBuildResult() error = nil, want validation failure") + } + }) + } +} + +func TestGenerationRowBuilderTurnsIdentityFailureIntoGenerationError(t *testing.T) { + delegate := rowBuilderFunc(func(resourceType string, line []byte, stageSeconds map[string]float64) (rowBuildResult, rowErrorType, error) { + return rowBuildResult{vertex: json.RawMessage(`{"project":"project-a"}`)}, "", nil + }) + builder, err := newGenerationRowBuilder(delegate, "project-a", "generation-a") + if err != nil { + t.Fatal(err) + } + _, kind, err := builder.Build("Patient", []byte(`{}`), map[string]float64{}) + if err == nil || kind != rowErrorGeneration { + t.Fatalf("Build() = kind %q err %v, want generation error", kind, err) + } +} + +func TestGeneratedAndGenericBuildersShareGenerationQualifiedIdentityForMETA(t *testing.T) { + line := metaFixtureLine(t, "Specimen.ndjson") + schema, err := graph.Load(filepath.Join(repoRoot(t), "schemas", "graph-fhir.json")) + if err != nil { + t.Fatalf("graph.Load: %v", err) + } + class := schema.GetClass("Specimen") + if class == nil { + t.Fatal("Specimen class is absent from checked-in graph schema") + } + + generated, err := newGenerationRowBuilder(NewGeneratedRowBuilder("meta-baseline", ""), "meta-baseline", "generation-a") + if err != nil { + t.Fatal(err) + } + generic, err := newGenerationRowBuilder(NewGenericRowBuilder("meta-baseline", class, schema, nil), "meta-baseline", "generation-a") + if err != nil { + t.Fatal(err) + } + + generatedResult, generatedKind, err := generated.Build("Specimen", line, map[string]float64{}) + if err != nil { + t.Fatalf("generated Build() kind %q: %v", generatedKind, err) + } + genericResult, genericKind, err := generic.Build("Specimen", line, map[string]float64{}) + if err != nil { + t.Fatalf("generic Build() kind %q: %v", genericKind, err) + } + + if got, want := documentString(t, decodeIdentityDocument(t, generatedResult.vertex), "_key"), documentString(t, decodeIdentityDocument(t, genericResult.vertex), "_key"); got != want { + t.Fatalf("generation-qualified vertex keys differ\ngenerated: %q\ngeneric: %q", got, want) + } + if got, want := documentString(t, decodeIdentityDocument(t, generatedResult.vertex), logicalKeyField), documentString(t, decodeIdentityDocument(t, genericResult.vertex), logicalKeyField); got != want { + t.Fatalf("logical vertex keys differ\ngenerated: %q\ngeneric: %q", got, want) + } + if got, want := edgeIdentityTuples(t, generatedResult.edges), edgeIdentityTuples(t, genericResult.edges); !reflect.DeepEqual(got, want) { + t.Fatalf("generation-qualified edge identities differ\ngenerated: %#v\ngeneric: %#v", got, want) + } +} + +type rowBuilderFunc func(string, []byte, map[string]float64) (rowBuildResult, rowErrorType, error) + +func (f rowBuilderFunc) Build(resourceType string, line []byte, stageSeconds map[string]float64) (rowBuildResult, rowErrorType, error) { + return f(resourceType, line, stageSeconds) +} + +func decodeIdentityDocument(t *testing.T, raw json.RawMessage) map[string]json.RawMessage { + t.Helper() + var document map[string]json.RawMessage + if err := json.Unmarshal(raw, &document); err != nil { + t.Fatalf("decode document %s: %v", raw, err) + } + return document +} + +func documentString(t *testing.T, document map[string]json.RawMessage, field string) string { + t.Helper() + var value string + if raw, ok := document[field]; ok { + _ = json.Unmarshal(raw, &value) + } + return value +} + +func generationDocumentIDMust(t *testing.T, project, generation, documentID string) string { + t.Helper() + value, err := generationDocumentID(project, generation, documentID) + if err != nil { + t.Fatal(err) + } + return value +} + +func edgeIdentityTuples(t *testing.T, edges []json.RawMessage) []string { + t.Helper() + tuples := make([]string, 0, len(edges)) + for _, raw := range edges { + document := decodeIdentityDocument(t, raw) + tuples = append(tuples, strings.Join([]string{ + documentString(t, document, "_key"), + documentString(t, document, "_from"), + documentString(t, document, "_to"), + documentString(t, document, "label"), + documentString(t, document, generationIdentityField), + }, "\x00")) + } + sort.Strings(tuples) + return tuples +} + +func metaFixtureLine(t *testing.T, filename string) []byte { + t.Helper() + data, err := os.ReadFile(filepath.Join(repoRoot(t), "META", filename)) + if err != nil { + t.Fatalf("read META fixture %s: %v", filename, err) + } + for _, line := range strings.Split(string(data), "\n") { + line = strings.TrimSpace(line) + if line != "" { + return []byte(line) + } + } + t.Fatalf("META fixture %s has no NDJSON row", filename) + return nil +} + +func repoRoot(t *testing.T) string { + t.Helper() + _, source, _, ok := runtime.Caller(0) + if !ok { + t.Fatal("resolve ingest test source") + } + return filepath.Clean(filepath.Join(filepath.Dir(source), "..", "..")) +} diff --git a/internal/ingest/generation_load.go b/internal/ingest/generation_load.go new file mode 100644 index 0000000..3892fb9 --- /dev/null +++ b/internal/ingest/generation_load.go @@ -0,0 +1,669 @@ +package ingest + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "path/filepath" + "sort" + "strings" + "sync" + "sync/atomic" + "time" + + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/dataset" + "github.com/calypr/loom/internal/datasetstore" + "github.com/calypr/loom/internal/schemaidentity" + arangostore "github.com/calypr/loom/internal/store/arango" + + "github.com/bmeg/jsonschemagraph/graph" +) + +// Load selects the legacy loader only when no immutable Dataset reference was +// supplied. Dataset mode is a separate write contract: every physical graph +// document, catalog row, and lifecycle operation is bound to one generation. +func Load(ctx context.Context, opts LoadOptions) (LoadSummary, error) { + if opts.Dataset == nil { + return loadLegacy(ctx, opts) + } + return loadGeneration(ctx, opts) +} + +func loadGeneration(ctx context.Context, opts LoadOptions) (summary LoadSummary, err error) { + if opts.BatchSize <= 0 { + opts.BatchSize = 5000 + } + if opts.ProgressEvery <= 0 { + opts.ProgressEvery = 50000 + } + if opts.WriterCount <= 0 { + opts.WriterCount = 8 + } + if opts.WriteAPI == "" { + opts.WriteAPI = "import" + } + + start := time.Now() + files, err := DiscoverNDJSON(opts.MetaDir) + if err != nil { + return LoadSummary{}, err + } + summary = LoadSummary{ + Files: len(files), + Resources: map[string]int{}, + BatchCounts: map[string]int{}, + StageSeconds: map[string]float64{}, + } + + // Keep the existing ordered evidence path: discover staged files, parse the + // graph with its authoritative loader, capture identity from the same file, + // then preflight every staged payload before contacting Arango. + schema, err := graph.Load(opts.Schema) + if err != nil { + return summary, err + } + schemaIdentity, err := schemaidentity.Load(opts.Schema) + if err != nil { + return summary, err + } + summary.SchemaIdentity = &schemaIdentity + preflightSampleRows := opts.PreflightSampleRows + if preflightSampleRows <= 0 { + preflightSampleRows = defaultPreflightSampleRows + } + emitEvent(opts.EventSink, "go_preflight_start", map[string]any{ + "files": len(files), + "sampleRows": preflightSampleRows, + "schemaSha256": schemaIdentity.SchemaSHA256(), + "generatedRootCount": len(schemaIdentity.GeneratedResourceTypes()), + }) + preflightStart := time.Now() + preflight, err := PreflightFiles(files, schema, preflightSampleRows) + summary.Preflight = preflight + summary.StageSeconds["preflight"] = time.Since(preflightStart).Seconds() + emitEvent(opts.EventSink, "go_preflight_complete", map[string]any{ + "files": len(files), + "resources": len(preflight.Resources), + "issues": len(preflight.Issues), + "seconds": summary.StageSeconds["preflight"], + }) + if err != nil { + return summary, err + } + + plan, err := newGenerationLoadPlan(opts, files, schemaIdentity) + if err != nil { + return summary, err + } + // Load dispatch guarantees a plan, but retaining this check makes the + // generation-only helper safe if it is called directly in a future test. + if plan == nil { + return summary, fmt.Errorf("dataset generation plan is required") + } + datasetRef := plan.Dataset + summary.Dataset = &datasetRef + if err := ctx.Err(); err != nil { + return summary, err + } + + resourceTypes := make([]string, 0, len(preflight.Resources)) + for _, resource := range preflight.Resources { + resourceTypes = append(resourceTypes, resource.ResourceType) + } + + emitEvent(opts.EventSink, "go_backend_connect_start", map[string]any{ + "backend": "arango", + "url": opts.URL, + "database": opts.Database, + }) + connectStart := time.Now() + client, err := openBackend(ctx, opts.ConnectionOptions) + if err != nil { + return summary, err + } + defer func() { _ = client.Close(context.WithoutCancel(ctx)) }() + emitEvent(opts.EventSink, "go_backend_connect_complete", map[string]any{ + "backend": "arango", + "url": opts.URL, + "database": opts.Database, + "seconds": time.Since(connectStart).Seconds(), + }) + + bootstrapStart := time.Now() + // Metadata comes first and never truncates. This order means a failed + // graph bootstrap cannot delete lifecycle history from a prior generation. + emitEvent(opts.EventSink, "go_bootstrap_start", map[string]any{ + "database": opts.Database, + "resources": 0, + "truncate": false, + "collections": "dataset_lifecycle", + }) + if err = client.Bootstrap(ctx, lifecycleBootstrapSpecWithReporter(opts.EventSink)); err != nil { + return summary, err + } + emitEvent(opts.EventSink, "go_bootstrap_start", map[string]any{ + "database": opts.Database, + "resources": len(resourceTypes), + "truncate": false, + }) + if err = client.Bootstrap(ctx, bootstrapSpecWithReporter(resourceTypes, false, opts.EventSink)); err != nil { + return summary, err + } + summary.StageSeconds["bootstrap"] = time.Since(bootstrapStart).Seconds() + + lifecycleStore, err := datasetstore.New(client) + if err != nil { + return summary, err + } + manifest, err := lifecycleStore.CreateManifest(ctx, plan.Manifest) + if err != nil { + return summary, err + } + manifestReady := false + defer func() { + if err == nil || manifestReady { + return + } + // A canceled request must not strand a PRE-FLIGHT/LOADING/ANALYZING + // manifest. Once READY is persisted we deliberately leave it alone, + // because an activation error is an unknown outcome rather than proof + // that the generation failed. + _, cleanupErr := lifecycleStore.TransitionManifest( + context.WithoutCancel(ctx), + manifest, + dataset.ManifestStateFailed, + ) + if cleanupErr != nil { + err = errors.Join(err, fmt.Errorf("mark dataset generation %s/%s failed: %w", plan.Dataset.Project, plan.Dataset.Generation, cleanupErr)) + } + }() + loadingManifest, transitionErr := lifecycleStore.TransitionManifest(ctx, manifest, dataset.ManifestStateLoading) + if transitionErr != nil { + return summary, transitionErr + } + manifest = loadingManifest + + catalogs := make(map[generationCatalogKey]*catalog.Profiler) + for _, file := range files { + if err = ctx.Err(); err != nil { + return summary, err + } + fileStart := time.Now() + resourceType := ResourceTypeFromPath(file) + emitEvent(opts.EventSink, "go_load_file_start", map[string]any{"file": file, "resource": resourceType}) + + result, fileErr := loadGenerationFile( + ctx, + opts, + client, + schema, + file, + plan.Dataset.Generation, + start, + summary.VerticesInserted, + summary.EdgesInserted, + ) + if fileErr != nil { + return summary, fileErr + } + + summary.VerticesInserted += result.VerticesInserted + summary.EdgesInserted += result.EdgesInserted + summary.ValidationErrors += result.ValidationErrors + summary.GenerationErrors += result.GenerationErrors + summary.EdgeErrors += result.EdgeErrors + summary.Resources[result.ResourceType] += result.Rows + summary.BatchCounts["vertex_insert"] += result.VertexBatches + summary.BatchCounts["edge_insert"] += result.EdgeBatches + for name, seconds := range result.StageSeconds { + summary.StageSeconds[name] += seconds + } + + key := generationCatalogKey{ + project: opts.Project, + datasetGeneration: plan.Dataset.Generation, + authResourcePath: opts.AuthResourcePath, + resourceType: result.ResourceType, + } + merged := catalogs[key] + if merged == nil { + merged = catalog.NewProfilerForGeneration( + key.project, + key.datasetGeneration, + key.authResourcePath, + key.resourceType, + catalog.NewShapePlanCache(), + ) + catalogs[key] = merged + } + if err = merged.Merge(result.Catalog); err != nil { + return summary, fmt.Errorf("merge catalog for dataset generation %s/%s %s: %w", plan.Dataset.Project, plan.Dataset.Generation, result.ResourceType, err) + } + + emitEvent(opts.EventSink, "go_load_file_complete", map[string]any{ + "file": filepath.Base(file), + "resource": result.ResourceType, + "file_rows": result.Rows, + "file_vertices": result.VerticesBuilt, + "file_edges": result.EdgesBuilt, + "seconds": time.Since(fileStart).Seconds(), + }) + } + + if summary.ValidationErrors != 0 || summary.GenerationErrors != 0 || summary.EdgeErrors != 0 { + return summary, &GenerationLoadIncompleteError{ + Dataset: plan.Dataset, + ValidationErrors: summary.ValidationErrors, + GenerationErrors: summary.GenerationErrors, + EdgeErrors: summary.EdgeErrors, + } + } + if err = ctx.Err(); err != nil { + return summary, err + } + + // ANALYZING is intentionally limited to catalog finalization in this + // packet. No synthetic analysis version is attached; a later analysis owner + // can add one without changing the load/activation contract. + analyzingManifest, transitionErr := lifecycleStore.TransitionManifest(ctx, manifest, dataset.ManifestStateAnalyzing) + if transitionErr != nil { + return summary, transitionErr + } + manifest = analyzingManifest + for _, key := range sortedGenerationCatalogKeys(catalogs) { + if err = ctx.Err(); err != nil { + return summary, err + } + if err = catalog.WriteFieldCatalog( + ctx, + client, + catalog.FieldCatalogCollection, + catalogs[key].Documents(), + opts.BatchSize, + false, + opts.WriteAPI, + summary.StageSeconds, + ); err != nil { + return summary, err + } + } + if err = ctx.Err(); err != nil { + return summary, err + } + readyManifest, transitionErr := lifecycleStore.TransitionManifest(ctx, manifest, dataset.ManifestStateReady) + if transitionErr != nil { + return summary, transitionErr + } + manifest = readyManifest + manifestReady = true + if _, activationErr := lifecycleStore.Activate(ctx, manifest); activationErr != nil { + return summary, &ActivationOutcomeError{Dataset: plan.Dataset, Err: activationErr} + } + + emitEvent(opts.EventSink, "go_load_complete", map[string]any{ + "files": summary.Files, + "vertices_inserted": summary.VerticesInserted, + "edges_inserted": summary.EdgesInserted, + "validation_errors": summary.ValidationErrors, + "generation_errors": summary.GenerationErrors, + "edge_errors": summary.EdgeErrors, + "dataset_generation": plan.Dataset.Generation, + "seconds": SecondsSince(start), + }) + return summary, nil +} + +type generationCatalogKey struct { + project string + datasetGeneration string + authResourcePath string + resourceType string +} + +func sortedGenerationCatalogKeys(catalogs map[generationCatalogKey]*catalog.Profiler) []generationCatalogKey { + keys := make([]generationCatalogKey, 0, len(catalogs)) + for key := range catalogs { + keys = append(keys, key) + } + sort.Slice(keys, func(left, right int) bool { + if keys[left].project != keys[right].project { + return keys[left].project < keys[right].project + } + if keys[left].datasetGeneration != keys[right].datasetGeneration { + return keys[left].datasetGeneration < keys[right].datasetGeneration + } + if keys[left].authResourcePath != keys[right].authResourcePath { + return keys[left].authResourcePath < keys[right].authResourcePath + } + return keys[left].resourceType < keys[right].resourceType + }) + return keys +} + +type generationFileResult struct { + ResourceType string + Rows int + VerticesBuilt int + EdgesBuilt int + VerticesInserted int + EdgesInserted int + ValidationErrors int + GenerationErrors int + EdgeErrors int + VertexBatches int + EdgeBatches int + StageSeconds map[string]float64 + Catalog *catalog.Profiler +} + +type generationWriteTask struct { + collection string + docs []json.RawMessage +} + +// loadGenerationFile owns one scanner and closes it with a defer before it +// returns. This keeps file descriptors bounded for large staged directories, +// including failures from worker, writer, or scanner goroutines. +func loadGenerationFile( + ctx context.Context, + opts LoadOptions, + client *arangostore.Client, + schema *graph.GraphSchema, + file string, + datasetGeneration string, + start time.Time, + priorVertices int, + priorEdges int, +) (result generationFileResult, err error) { + resourceType := ResourceTypeFromPath(file) + result.ResourceType = resourceType + class := schema.GetClass(resourceType) + if class == nil { + return result, fmt.Errorf("%s: class %q not found in graph schema", filepath.Base(file), resourceType) + } + + scanner, closeFn, err := OpenLineScanner(file) + if err != nil { + return result, err + } + defer func() { + if closeErr := closeFn(); closeErr != nil && err == nil { + err = closeErr + } + }() + + var rowBuilder RowBuilder + if opts.UseGeneric || !supportsGeneratedLoad(resourceType) { + rowBuilder = NewGenericRowBuilder(opts.Project, class, schema, graphExtraArgs(opts.AuthResourcePath)) + } else { + rowBuilder = NewGeneratedRowBuilder(opts.Project, opts.AuthResourcePath) + } + rowBuilder, err = newGenerationRowBuilder(rowBuilder, opts.Project, datasetGeneration) + if err != nil { + return result, err + } + + linesChan := make(chan string, 10000) + writeChan := make(chan generationWriteTask, 100) + fileCtx, cancel := context.WithCancel(ctx) + defer cancel() + + var pipelineErr error + var pipelineErrMu sync.Mutex + var errOnce sync.Once + setPipelineErr := func(value error) { + errOnce.Do(func() { + pipelineErrMu.Lock() + pipelineErr = value + pipelineErrMu.Unlock() + cancel() + }) + } + + go func() { + defer close(linesChan) + for scanner.Scan() { + select { + case <-fileCtx.Done(): + return + default: + } + line := strings.TrimSpace(scanner.Text()) + if line == "" { + continue + } + select { + case linesChan <- line: + case <-fileCtx.Done(): + return + } + } + if scanErr := scanner.Err(); scanErr != nil { + setPipelineErr(scanErr) + } + }() + + const workerCount = 8 + var workersWG sync.WaitGroup + workerTimingsChan := make(chan map[string]float64, workerCount) + workerCatalogsChan := make(chan *catalog.Profiler, workerCount) + + var fileRows int64 + var fileVertices int64 + var fileEdges int64 + var verticesInserted int64 + var edgesInserted int64 + var validationErrors int64 + var generationErrors int64 + var edgeErrors int64 + + for worker := 0; worker < workerCount; worker++ { + workersWG.Add(1) + go func() { + defer workersWG.Done() + localTimings := make(map[string]float64) + localCatalog := catalog.NewProfilerForGeneration(opts.Project, datasetGeneration, opts.AuthResourcePath, resourceType, catalog.NewShapePlanCache()) + lineCounter := 0 + vertexBatch := make([]json.RawMessage, 0, opts.BatchSize) + edgeBatch := make([]json.RawMessage, 0, opts.BatchSize) + + flushVertexBatch := func() bool { + if len(vertexBatch) == 0 { + return true + } + waitStart := time.Now() + select { + case writeChan <- generationWriteTask{collection: resourceType, docs: vertexBatch}: + localTimings["vertex_queue_wait"] += time.Since(waitStart).Seconds() + localTimings["vertex_batches"]++ + vertexBatch = make([]json.RawMessage, 0, opts.BatchSize) + return true + case <-fileCtx.Done(): + localTimings["vertex_queue_wait"] += time.Since(waitStart).Seconds() + return false + } + } + flushEdgeBatch := func() bool { + if len(edgeBatch) == 0 { + return true + } + waitStart := time.Now() + select { + case writeChan <- generationWriteTask{collection: EdgeCollection, docs: edgeBatch}: + localTimings["edge_queue_wait"] += time.Since(waitStart).Seconds() + localTimings["edge_batches"]++ + edgeBatch = make([]json.RawMessage, 0, opts.BatchSize) + return true + case <-fileCtx.Done(): + localTimings["edge_queue_wait"] += time.Since(waitStart).Seconds() + return false + } + } + + for { + select { + case <-fileCtx.Done(): + return + case line, open := <-linesChan: + if !open { + if !flushVertexBatch() || !flushEdgeBatch() { + return + } + select { + case workerTimingsChan <- localTimings: + case <-ctx.Done(): + } + select { + case workerCatalogsChan <- localCatalog: + case <-ctx.Done(): + } + return + } + lineCounter++ + built, errorType, buildErr := rowBuilder.Build(resourceType, []byte(line), localTimings) + if buildErr != nil { + if opts.FailFast { + setPipelineErr(fmt.Errorf("%s %s row %d: %w", filepath.Base(file), resourceType, lineCounter, buildErr)) + return + } + switch errorType { + case rowErrorValidation: + atomic.AddInt64(&validationErrors, 1) + case rowErrorGeneration: + atomic.AddInt64(&generationErrors, 1) + case rowErrorEdge: + atomic.AddInt64(&edgeErrors, 1) + } + continue + } + + localCatalog.ObservePayload(built.payload, localTimings) + vertexBatch = append(vertexBatch, built.vertex) + atomic.AddInt64(&fileVertices, 1) + if len(vertexBatch) >= opts.BatchSize && !flushVertexBatch() { + return + } + for _, edge := range built.edges { + edgeBatch = append(edgeBatch, edge) + atomic.AddInt64(&fileEdges, 1) + if len(edgeBatch) >= opts.BatchSize && !flushEdgeBatch() { + return + } + } + + currentRows := atomic.AddInt64(&fileRows, 1) + if currentRows%int64(opts.ProgressEvery) == 0 { + emitEvent(opts.EventSink, "go_load_progress", map[string]any{ + "file": filepath.Base(file), + "resource": resourceType, + "file_rows": currentRows, + "file_vertices": atomic.LoadInt64(&fileVertices), + "file_edges": atomic.LoadInt64(&fileEdges), + "vertices_inserted": priorVertices + int(atomic.LoadInt64(&verticesInserted)), + "edges_inserted": priorEdges + int(atomic.LoadInt64(&edgesInserted)), + "seconds": SecondsSince(start), + }) + } + } + } + }() + } + + go func() { + workersWG.Wait() + close(writeChan) + close(workerTimingsChan) + close(workerCatalogsChan) + }() + + var writersWG sync.WaitGroup + writerTimingsChan := make(chan map[string]float64, opts.WriterCount) + for writer := 0; writer < opts.WriterCount; writer++ { + writersWG.Add(1) + go func() { + defer writersWG.Done() + localTimings := make(map[string]float64) + for { + select { + case <-fileCtx.Done(): + return + case task, open := <-writeChan: + if !open { + select { + case writerTimingsChan <- localTimings: + case <-ctx.Done(): + } + return + } + insertStart := time.Now() + // A generation never overwrites a physical graph or catalog + // document. Collisions are evidence of a non-immutable load. + if insertErr := insertRawDocuments(fileCtx, client, task.collection, task.docs, false, opts.WriteAPI); insertErr != nil { + setPipelineErr(insertErr) + return + } + elapsed := time.Since(insertStart).Seconds() + if task.collection == EdgeCollection { + localTimings["edge_insert"] += elapsed + atomic.AddInt64(&edgesInserted, int64(len(task.docs))) + } else { + localTimings["vertex_insert"] += elapsed + atomic.AddInt64(&verticesInserted, int64(len(task.docs))) + } + } + } + }() + } + go func() { + writersWG.Wait() + close(writerTimingsChan) + }() + + writersWG.Wait() + pipelineErrMu.Lock() + currentPipelineErr := pipelineErr + pipelineErrMu.Unlock() + if currentPipelineErr != nil { + return result, currentPipelineErr + } + if err := ctx.Err(); err != nil { + return result, err + } + + result.Rows = int(atomic.LoadInt64(&fileRows)) + result.VerticesBuilt = int(atomic.LoadInt64(&fileVertices)) + result.EdgesBuilt = int(atomic.LoadInt64(&fileEdges)) + result.VerticesInserted = int(atomic.LoadInt64(&verticesInserted)) + result.EdgesInserted = int(atomic.LoadInt64(&edgesInserted)) + result.ValidationErrors = int(atomic.LoadInt64(&validationErrors)) + result.GenerationErrors = int(atomic.LoadInt64(&generationErrors)) + result.EdgeErrors = int(atomic.LoadInt64(&edgeErrors)) + result.StageSeconds = make(map[string]float64) + mergedCatalog := catalog.NewProfilerForGeneration(opts.Project, datasetGeneration, opts.AuthResourcePath, resourceType, catalog.NewShapePlanCache()) + for timings := range workerTimingsChan { + for key, value := range timings { + switch key { + case "vertex_batches": + result.VertexBatches += int(value) + case "edge_batches": + result.EdgeBatches += int(value) + default: + result.StageSeconds[key] += value + } + } + } + for workerCatalog := range workerCatalogsChan { + if mergeErr := mergedCatalog.Merge(workerCatalog); mergeErr != nil { + return result, fmt.Errorf("merge worker field catalog for %s: %w", resourceType, mergeErr) + } + } + for timings := range writerTimingsChan { + for key, value := range timings { + result.StageSeconds[key] += value + } + } + result.Catalog = mergedCatalog + return result, nil +} diff --git a/internal/ingest/generation_load_test.go b/internal/ingest/generation_load_test.go new file mode 100644 index 0000000..35c7f18 --- /dev/null +++ b/internal/ingest/generation_load_test.go @@ -0,0 +1,203 @@ +package ingest + +import ( + "context" + "errors" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/dataset" + "github.com/calypr/loom/internal/schemaidentity" + arangostore "github.com/calypr/loom/internal/store/arango" +) + +func TestNewGenerationLoadPlanRejectsUnsafeOrIncompleteInputs(t *testing.T) { + identity := loadGenerationSchemaIdentity(t) + dir := t.TempDir() + file := filepath.Join(dir, "Patient.ndjson") + if err := os.WriteFile(file, []byte(`{"resourceType":"Patient"}`+"\n"), 0o644); err != nil { + t.Fatalf("write staged file: %v", err) + } + validRef, err := dataset.NewDatasetRef("project-a", "generation-a") + if err != nil { + t.Fatal(err) + } + + tests := []struct { + name string + opts LoadOptions + files []string + want error + }{ + { + name: "invalid dataset reference", + opts: LoadOptions{MetaDir: dir, Project: "project-a", Dataset: &dataset.DatasetRef{Project: "project-a"}}, + files: []string{file}, + want: dataset.ErrInvalidDatasetRef, + }, + { + name: "project mismatch", + opts: LoadOptions{MetaDir: dir, Project: "project-b", Dataset: &validRef}, + files: []string{file}, + want: ErrGenerationDatasetProjectMismatch, + }, + { + name: "truncate forbidden", + opts: LoadOptions{MetaDir: dir, Project: "project-a", Dataset: &validRef, Truncate: true}, + files: []string{file}, + want: ErrGenerationLoadTruncateForbidden, + }, + { + name: "file is not directory", + opts: LoadOptions{MetaDir: file, Project: "project-a", Dataset: &validRef}, + files: []string{file}, + want: ErrGenerationLoadRequiresDirectory, + }, + { + name: "empty staged directory", + opts: LoadOptions{MetaDir: t.TempDir(), Project: "project-a", Dataset: &validRef}, + files: nil, + want: ErrGenerationLoadRequiresFiles, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + if _, err := newGenerationLoadPlan(test.opts, test.files, identity); !errors.Is(err, test.want) { + t.Fatalf("newGenerationLoadPlan() error = %v, want %v", err, test.want) + } + }) + } +} + +func TestNewGenerationLoadPlanSnapshotsDatasetAndSchemaBeforeBackend(t *testing.T) { + identity := loadGenerationSchemaIdentity(t) + dir := t.TempDir() + file := filepath.Join(dir, "Patient.ndjson") + if err := os.WriteFile(file, []byte(`{"resourceType":"Patient"}`+"\n"), 0o644); err != nil { + t.Fatalf("write staged file: %v", err) + } + ref, err := dataset.NewDatasetRef("project-a", "generation-a") + if err != nil { + t.Fatal(err) + } + plan, err := newGenerationLoadPlan(LoadOptions{MetaDir: dir, Project: ref.Project, Dataset: &ref}, []string{file}, identity) + if err != nil { + t.Fatalf("newGenerationLoadPlan: %v", err) + } + if !plan.Dataset.Equal(ref) || !plan.Manifest.Dataset.Equal(ref) { + t.Fatalf("generation plan dataset = %#v manifest = %#v, want %v", plan.Dataset, plan.Manifest.Dataset, ref) + } + if got, want := plan.Manifest.State, dataset.ManifestStatePreflight; got != want { + t.Fatalf("generation manifest state = %q, want %q", got, want) + } + if got, want := plan.Manifest.SchemaIdentity.SchemaSHA256(), identity.SchemaSHA256(); got != want { + t.Fatalf("generation schema digest = %q, want %q", got, want) + } +} + +func TestGenerationLoadPreflightRunsBeforeOptionRejectionOrBackend(t *testing.T) { + dir := t.TempDir() + writePreflightFixture(t, dir, "Unknown.ndjson", `{"resourceType":"Unknown"}`+"\n") + ref, err := dataset.NewDatasetRef("project-a", "generation-a") + if err != nil { + t.Fatal(err) + } + var events []string + summary, err := Load(context.Background(), LoadOptions{ + Schema: repoPath(t, "schemas", "graph-fhir.json"), + MetaDir: dir, + Project: ref.Project, + Dataset: &ref, + Truncate: true, // would be rejected only after preflight succeeds. + ConnectionOptions: arangostore.ConnectionOptions{ + URL: "http://127.0.0.1:1", + Database: "generation_preflight_must_not_connect", + }, + EventSink: func(event string, fields map[string]any) { + events = append(events, event) + }, + }) + var preflightErr *PreflightError + if !errors.As(err, &preflightErr) { + t.Fatalf("Load() error = %T %v, want PreflightError", err, err) + } + if summary.SchemaIdentity == nil || summary.Preflight.Valid() { + t.Fatalf("Load() summary = %#v, want schema evidence and invalid preflight", summary) + } + for _, event := range events { + if strings.HasPrefix(event, "go_backend_") || event == "go_bootstrap_start" { + t.Fatalf("Load() emitted %q before generation preflight passed; events = %v", event, events) + } + } +} + +func TestGenerationLoadEmptyDirectoryDoesNotOpenBackend(t *testing.T) { + dir := t.TempDir() + ref, err := dataset.NewDatasetRef("project-a", "generation-a") + if err != nil { + t.Fatal(err) + } + var events []string + summary, err := Load(context.Background(), LoadOptions{ + Schema: repoPath(t, "schemas", "graph-fhir.json"), + MetaDir: dir, + Project: ref.Project, + Dataset: &ref, + ConnectionOptions: arangostore.ConnectionOptions{ + URL: "http://127.0.0.1:1", + Database: "empty_generation_must_not_connect", + }, + EventSink: func(event string, fields map[string]any) { + events = append(events, event) + }, + }) + if !errors.Is(err, ErrGenerationLoadRequiresFiles) { + t.Fatalf("Load() error = %v, want %v", err, ErrGenerationLoadRequiresFiles) + } + if summary.SchemaIdentity == nil || !summary.Preflight.Valid() { + t.Fatalf("Load() summary = %#v, want schema evidence and valid empty preflight", summary) + } + for _, event := range events { + if strings.HasPrefix(event, "go_backend_") || event == "go_bootstrap_start" { + t.Fatalf("Load() emitted %q for empty generation input; events = %v", event, events) + } + } +} + +func TestSingleResourceImportsRejectDatasetGenerationBeforeFileOrTempIO(t *testing.T) { + ref, err := dataset.NewDatasetRef("project-a", "generation-a") + if err != nil { + t.Fatal(err) + } + opts := LoadOptions{Dataset: &ref} + if _, err := LoadSingleResourceReader(context.Background(), opts, "Patient", strings.NewReader(`{"resourceType":"Patient"}`), false); !errors.Is(err, ErrGenerationSingleResourceUnsupported) { + t.Fatalf("LoadSingleResourceReader() error = %v, want %v", err, ErrGenerationSingleResourceUnsupported) + } + if _, err := LoadSingleResourceFile(context.Background(), opts, "Patient", filepath.Join(t.TempDir(), "missing.ndjson")); !errors.Is(err, ErrGenerationSingleResourceUnsupported) { + t.Fatalf("LoadSingleResourceFile() error = %v, want %v", err, ErrGenerationSingleResourceUnsupported) + } +} + +func TestSortedGenerationCatalogKeysKeepFullIdentityDistinct(t *testing.T) { + cache := catalog.NewShapePlanCache() + keys := map[generationCatalogKey]*catalog.Profiler{ + {project: "project-a", datasetGeneration: "generation-b", authResourcePath: "scope-b", resourceType: "Patient"}: catalog.NewProfilerForGeneration("project-a", "generation-b", "scope-b", "Patient", cache), + {project: "project-a", datasetGeneration: "generation-a", authResourcePath: "scope-a", resourceType: "Patient"}: catalog.NewProfilerForGeneration("project-a", "generation-a", "scope-a", "Patient", cache), + } + sorted := sortedGenerationCatalogKeys(keys) + if len(sorted) != 2 || sorted[0].datasetGeneration != "generation-a" || sorted[1].datasetGeneration != "generation-b" { + t.Fatalf("sorted generation catalog keys = %#v", sorted) + } +} + +func loadGenerationSchemaIdentity(t *testing.T) schemaidentity.Identity { + t.Helper() + identity, err := schemaidentity.Load(repoPath(t, "schemas", "graph-fhir.json")) + if err != nil { + t.Fatalf("load schema identity: %v", err) + } + return identity +} diff --git a/internal/ingest/integration_test.go b/internal/ingest/integration_test.go index 18bff1f..18e0992 100644 --- a/internal/ingest/integration_test.go +++ b/internal/ingest/integration_test.go @@ -89,18 +89,6 @@ func TestLoadAndQueryFixture(t *testing.T) { } } - outputPath := filepath.Join(t.TempDir(), "query.ndjson") - rows, err := runFixtureQuery(ctx, arangostore.ConnectionOptions{ - URL: "http://127.0.0.1:8529", - Database: database, - }, repoPath(t, "queries", "gdc_case_assay_matrix_arango_rows.aql"), outputPath, "ARANGO_PROTO_TEST") - if err != nil { - t.Fatalf("query fixture: %v", err) - } - if rows != 1 { - t.Fatalf("query rows = %d, want 1", rows) - } - fields, err := catalog.DiscoverPopulatedFields(ctx, catalog.PopulatedFieldOptions{ ConnectionOptions: arangostore.ConnectionOptions{ URL: "http://127.0.0.1:8529", @@ -151,42 +139,3 @@ func repoPath(t *testing.T, elems ...string) string { base := filepath.Clean(filepath.Join(filepath.Dir(file), "..", "..")) return filepath.Join(append([]string{base}, elems...)...) } - -func runFixtureQuery(ctx context.Context, connOpts arangostore.ConnectionOptions, queryPath, outputPath, project string) (int, error) { - queryBytes, err := os.ReadFile(queryPath) - if err != nil { - return 0, err - } - out, err := os.Create(outputPath) - if err != nil { - return 0, err - } - defer out.Close() - writer := bufio.NewWriter(out) - defer writer.Flush() - - client, err := arangostore.Open(ctx, connOpts.URL, connOpts.Database) - if err != nil { - return 0, err - } - defer client.Close(ctx) - - rows := 0 - err = client.QueryRows(ctx, string(queryBytes), 100, map[string]any{ - "project": project, - "auth_resource_paths": []string(nil), - "auth_resource_paths_unrestricted": true, - "auth_resource_path": nil, - }, func(row map[string]any) error { - rows++ - data, err := sonic.ConfigFastest.Marshal(row) - if err != nil { - return err - } - if _, err := writer.Write(data); err != nil { - return err - } - return writer.WriteByte('\n') - }) - return rows, err -} diff --git a/internal/ingest/load.go b/internal/ingest/load.go index ffa988d..186e9c5 100644 --- a/internal/ingest/load.go +++ b/internal/ingest/load.go @@ -3,6 +3,7 @@ package ingest import ( "context" "encoding/json" + "errors" "fmt" "io" "os" @@ -13,6 +14,8 @@ import ( "time" "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/dataset" + "github.com/calypr/loom/internal/schemaidentity" arangostore "github.com/calypr/loom/internal/store/arango" "github.com/bmeg/jsonschema/v6" @@ -34,6 +37,16 @@ type LoadOptions struct { UseGeneric bool WriteAPI string EventSink EventSink + // Dataset selects immutable generation mode. A nil value preserves the + // original unversioned loader behavior. A non-nil value requires a complete + // directory import, writes generation-qualified graph identities, and only + // activates the generation after every graph file and catalog finalization + // succeeds. + Dataset *dataset.DatasetRef + // PreflightSampleRows bounds the number of payloads inspected from every + // staged file before Loom opens or mutates Arango. Zero uses the safe + // default; full row validation still happens in the loader. + PreflightSampleRows int } type LoadSummary struct { @@ -46,9 +59,132 @@ type LoadSummary struct { BatchCounts map[string]int `json:"batch_counts,omitempty"` Resources map[string]int `json:"resources"` StageSeconds map[string]float64 `json:"stage_seconds"` + Preflight PreflightReport `json:"preflight"` + // SchemaIdentity is the exact configured graph-schema evidence used for + // this load. It remains nil when Loom cannot load the configured schema, so + // an early failure never looks like a successful schema observation. + SchemaIdentity *schemaidentity.Identity `json:"schema_identity,omitempty"` + // Dataset is the immutable target when this was a generation load. It is + // present even on a failed generation load so callers can identify the + // inactive manifest that needs operational inspection. + Dataset *dataset.DatasetRef `json:"dataset,omitempty"` } -func Load(ctx context.Context, opts LoadOptions) (LoadSummary, error) { +var ( + // ErrGenerationLoadRequiresDirectory prevents a one-file or arbitrary-file + // load from being mistaken for a complete immutable dataset snapshot. + ErrGenerationLoadRequiresDirectory = errors.New("dataset generation load requires a directory") + // ErrGenerationLoadRequiresFiles prevents an empty staged directory from + // becoming an active but meaningless generation. + ErrGenerationLoadRequiresFiles = errors.New("dataset generation load requires at least one NDJSON file") + // ErrGenerationLoadTruncateForbidden prevents a new generation from + // deleting active or historical graph data. + ErrGenerationLoadTruncateForbidden = errors.New("dataset generation load cannot truncate collections") + // ErrGenerationDatasetProjectMismatch prevents graph documents and their + // lifecycle manifest from being scoped to different projects. + ErrGenerationDatasetProjectMismatch = errors.New("dataset generation project does not match load project") + // ErrGenerationSingleResourceUnsupported makes the legacy HTTP one-file + // path explicitly unavailable in immutable snapshot mode. + ErrGenerationSingleResourceUnsupported = errors.New("single-resource imports cannot create a dataset generation") +) + +// ActivationOutcomeError means the generation reached READY but Loom could +// not prove that the active-generation pointer was updated. READY is kept for +// an operator to reconcile; it must never be downgraded to FAILED because the +// activation request may have committed before its error reached the caller. +type ActivationOutcomeError struct { + Dataset dataset.DatasetRef + Err error +} + +func (e *ActivationOutcomeError) Error() string { + if e == nil { + return "dataset generation activation outcome is unknown" + } + return fmt.Sprintf("activate dataset generation %s/%s: %v", e.Dataset.Project, e.Dataset.Generation, e.Err) +} + +func (e *ActivationOutcomeError) Unwrap() error { + if e == nil { + return nil + } + return e.Err +} + +// GenerationLoadIncompleteError means row-level validation, generation, or +// edge construction failures were observed while FailFast was disabled. The +// graph may contain partial immutable documents, but the lifecycle manifest is +// deliberately left FAILED and cannot be selected for reads. +type GenerationLoadIncompleteError struct { + Dataset dataset.DatasetRef + ValidationErrors int + GenerationErrors int + EdgeErrors int +} + +func (e *GenerationLoadIncompleteError) Error() string { + if e == nil { + return "dataset generation load is incomplete" + } + return fmt.Sprintf( + "dataset generation %s/%s is incomplete: validation_errors=%d generation_errors=%d edge_errors=%d", + e.Dataset.Project, + e.Dataset.Generation, + e.ValidationErrors, + e.GenerationErrors, + e.EdgeErrors, + ) +} + +type generationLoadPlan struct { + Dataset dataset.DatasetRef + Manifest dataset.Manifest +} + +// newGenerationLoadPlan validates and snapshots all immutable information +// after input preflight and before a database connection is opened. Nil keeps +// the legacy loader path exactly unversioned. +func newGenerationLoadPlan(opts LoadOptions, files []string, identity schemaidentity.Identity) (*generationLoadPlan, error) { + if opts.Dataset == nil { + return nil, nil + } + + ref := *opts.Dataset + if err := ref.Validate(); err != nil { + return nil, err + } + if ref.Project != opts.Project { + return nil, fmt.Errorf("%w: dataset project %q, load project %q", ErrGenerationDatasetProjectMismatch, ref.Project, opts.Project) + } + if opts.Truncate { + return nil, ErrGenerationLoadTruncateForbidden + } + info, err := os.Stat(opts.MetaDir) + if err != nil { + return nil, fmt.Errorf("inspect dataset generation directory: %w", err) + } + if !info.IsDir() { + return nil, fmt.Errorf("%w: %q", ErrGenerationLoadRequiresDirectory, opts.MetaDir) + } + if len(files) == 0 { + return nil, fmt.Errorf("%w: %q", ErrGenerationLoadRequiresFiles, opts.MetaDir) + } + + schemaSnapshot, err := dataset.SnapshotSchemaIdentity(identity) + if err != nil { + return nil, fmt.Errorf("snapshot dataset generation schema identity: %w", err) + } + manifest, err := dataset.NewManifest(ref, schemaSnapshot) + if err != nil { + return nil, fmt.Errorf("create dataset generation manifest: %w", err) + } + return &generationLoadPlan{Dataset: ref, Manifest: manifest}, nil +} + +// loadLegacy is the original unversioned loader. Load dispatches to it only +// when Dataset is nil so existing import/API behavior and physical identities +// remain unchanged while generation mode evolves independently. +func loadLegacy(ctx context.Context, opts LoadOptions) (LoadSummary, error) { if opts.BatchSize <= 0 { opts.BatchSize = 5000 } @@ -66,9 +202,47 @@ func Load(ctx context.Context, opts LoadOptions) (LoadSummary, error) { if err != nil { return LoadSummary{}, err } - resourceTypes := make([]string, 0, len(files)) - for _, file := range files { - resourceTypes = append(resourceTypes, ResourceTypeFromPath(file)) + summary := LoadSummary{Files: len(files), Resources: map[string]int{}, BatchCounts: map[string]int{}, StageSeconds: map[string]float64{}} + schema, err := graph.Load(opts.Schema) + if err != nil { + return summary, err + } + // Keep graph.Load as the authoritative graph parser so its established + // validation and error behavior remain unchanged. Identity records evidence + // for the same configured file once graph loading succeeds. + schemaIdentity, err := schemaidentity.Load(opts.Schema) + if err != nil { + return summary, err + } + summary.SchemaIdentity = &schemaIdentity + preflightSampleRows := opts.PreflightSampleRows + if preflightSampleRows <= 0 { + preflightSampleRows = defaultPreflightSampleRows + } + emitEvent(opts.EventSink, "go_preflight_start", map[string]any{ + "files": len(files), + "sampleRows": preflightSampleRows, + "schemaSha256": schemaIdentity.SchemaSHA256(), + "generatedRootCount": len(schemaIdentity.GeneratedResourceTypes()), + }) + preflightStart := time.Now() + preflight, err := PreflightFiles(files, schema, preflightSampleRows) + summary.Preflight = preflight + summary.StageSeconds["preflight"] = time.Since(preflightStart).Seconds() + emitEvent(opts.EventSink, "go_preflight_complete", map[string]any{ + "files": len(files), + "resources": len(preflight.Resources), + "issues": len(preflight.Issues), + "seconds": summary.StageSeconds["preflight"], + }) + if err != nil { + return summary, err + } + // Preflight groups staged files by resource type, which prevents duplicate + // collection bootstrap specs when callers stage multiple files for one type. + resourceTypes := make([]string, 0, len(preflight.Resources)) + for _, resource := range preflight.Resources { + resourceTypes = append(resourceTypes, resource.ResourceType) } emitEvent(opts.EventSink, "go_backend_connect_start", map[string]any{ "backend": "arango", @@ -78,7 +252,7 @@ func Load(ctx context.Context, opts LoadOptions) (LoadSummary, error) { connectStart := time.Now() client, err := openBackend(ctx, opts.ConnectionOptions) if err != nil { - return LoadSummary{}, err + return summary, err } defer client.Close(ctx) emitEvent(opts.EventSink, "go_backend_connect_complete", map[string]any{ @@ -94,13 +268,8 @@ func Load(ctx context.Context, opts LoadOptions) (LoadSummary, error) { }) bootstrapStart := time.Now() if err := client.Bootstrap(ctx, bootstrapSpecWithReporter(resourceTypes, opts.Truncate, opts.EventSink)); err != nil { - return LoadSummary{}, err + return summary, err } - schema, err := graph.Load(opts.Schema) - if err != nil { - return LoadSummary{}, err - } - summary := LoadSummary{Files: len(files), Resources: map[string]int{}, BatchCounts: map[string]int{}, StageSeconds: map[string]float64{}} summary.StageSeconds["bootstrap"] = time.Since(bootstrapStart).Seconds() extraArgs := graphExtraArgs(opts.AuthResourcePath) @@ -117,7 +286,7 @@ func Load(ctx context.Context, opts LoadOptions) (LoadSummary, error) { fileStart := time.Now() emitEvent(opts.EventSink, "go_load_file_start", map[string]any{"file": file, "resource": resourceType}) var rowBuilder RowBuilder - if opts.UseGeneric { + if opts.UseGeneric || !supportsGeneratedLoad(resourceType) { rowBuilder = NewGenericRowBuilder(opts.Project, class, schema, extraArgs) } else { rowBuilder = NewGeneratedRowBuilder(opts.Project, opts.AuthResourcePath) @@ -447,6 +616,9 @@ func graphExtraArgs(authResourcePath string) map[string]any { } func LoadSingleResourceReader(ctx context.Context, opts LoadOptions, resourceType string, reader io.Reader, compressed bool) (LoadSummary, error) { + if opts.Dataset != nil { + return LoadSummary{}, ErrGenerationSingleResourceUnsupported + } dir, err := os.MkdirTemp("", "arango-fhir-single-resource-*") if err != nil { return LoadSummary{}, err @@ -476,6 +648,9 @@ func LoadSingleResourceReader(ctx context.Context, opts LoadOptions, resourceTyp } func LoadSingleResourceFile(ctx context.Context, opts LoadOptions, resourceType, path string) (LoadSummary, error) { + if opts.Dataset != nil { + return LoadSummary{}, ErrGenerationSingleResourceUnsupported + } file, err := os.Open(path) if err != nil { return LoadSummary{}, err diff --git a/internal/ingest/preflight.go b/internal/ingest/preflight.go new file mode 100644 index 0000000..e5fc805 --- /dev/null +++ b/internal/ingest/preflight.go @@ -0,0 +1,196 @@ +package ingest + +import ( + "encoding/json" + "fmt" + "path/filepath" + "sort" + "strings" + + "github.com/bmeg/jsonschemagraph/graph" +) + +const defaultPreflightSampleRows = 10 + +// IngestionMode describes the loader selected for a resource type after +// checking the active graph schema. Generated is a fast path; Generic remains +// the supported schema-backed path for resources outside that optimized +// switch. +type IngestionMode string + +const ( + IngestionModeGenerated IngestionMode = "generated" + IngestionModeGeneric IngestionMode = "generic" + IngestionModeUnsupported IngestionMode = "unsupported" +) + +// PreflightResource is a deterministic per-resource report. Resource types +// come from the staged file names because that is the load contract; sampled +// payload resourceType values are checked below before any database mutation. +type PreflightResource struct { + ResourceType string `json:"resourceType"` + Files []string `json:"files"` + SampledRows int `json:"sampledRows"` + GraphSchemaSupported bool `json:"graphSchemaSupported"` + GeneratedLoaderSupported bool `json:"generatedLoaderSupported"` + Mode IngestionMode `json:"mode"` +} + +// PreflightIssue is intentionally structured so an HTTP or CLI caller can +// present every actionable issue rather than leaving a partially loaded +// project behind after the first invalid file. +type PreflightIssue struct { + Code string `json:"code"` + File string `json:"file"` + ResourceType string `json:"resourceType"` + Row int `json:"row,omitempty"` + Message string `json:"message"` +} + +type PreflightReport struct { + Resources []PreflightResource `json:"resources"` + Issues []PreflightIssue `json:"issues"` +} + +func (r PreflightReport) Valid() bool { + return len(r.Issues) == 0 +} + +// PreflightError preserves the complete report for callers while retaining a +// compact Error implementation for the existing synchronous Load API. +type PreflightError struct { + Report PreflightReport +} + +func (e *PreflightError) Error() string { + if len(e.Report.Issues) == 0 { + return "ingestion preflight failed" + } + issue := e.Report.Issues[0] + return fmt.Sprintf("ingestion preflight failed: %s", issue.Message) +} + +// PreflightFiles validates the staged filename-to-resource contract and +// chooses the generated or generic loader for every active graph-schema class. +// It samples a bounded number of records per file; full validation remains in +// the streaming loader so large imports are not read twice. +func PreflightFiles(files []string, schema *graph.GraphSchema, sampleRows int) (PreflightReport, error) { + if schema == nil { + return PreflightReport{}, fmt.Errorf("graph schema is required") + } + if sampleRows <= 0 { + sampleRows = defaultPreflightSampleRows + } + + grouped := make(map[string][]string, len(files)) + for _, file := range files { + resourceType := ResourceTypeFromPath(file) + grouped[resourceType] = append(grouped[resourceType], file) + } + resourceTypes := make([]string, 0, len(grouped)) + for resourceType := range grouped { + resourceTypes = append(resourceTypes, resourceType) + } + sort.Strings(resourceTypes) + + report := PreflightReport{ + Resources: make([]PreflightResource, 0, len(resourceTypes)), + Issues: []PreflightIssue{}, + } + for _, resourceType := range resourceTypes { + resourceFiles := append([]string(nil), grouped[resourceType]...) + sort.Strings(resourceFiles) + classSupported := schema.GetClass(resourceType) != nil + generatedSupported := supportsGeneratedLoad(resourceType) + mode := IngestionModeGeneric + if !classSupported { + mode = IngestionModeUnsupported + } else if generatedSupported { + mode = IngestionModeGenerated + } + resource := PreflightResource{ + ResourceType: resourceType, + Files: resourceFiles, + GraphSchemaSupported: classSupported, + GeneratedLoaderSupported: generatedSupported, + Mode: mode, + } + if !classSupported { + report.Issues = append(report.Issues, PreflightIssue{ + Code: "unsupported_graph_schema_resource", + File: filepath.Base(resourceFiles[0]), + ResourceType: resourceType, + Message: fmt.Sprintf("resource type %q is not represented by the active graph schema", resourceType), + }) + } + + for _, file := range resourceFiles { + sampled, issues, err := sampleFileResourceTypes(file, resourceType, sampleRows) + if err != nil { + return PreflightReport{}, err + } + resource.SampledRows += sampled + report.Issues = append(report.Issues, issues...) + } + report.Resources = append(report.Resources, resource) + } + if !report.Valid() { + return report, &PreflightError{Report: report} + } + return report, nil +} + +func sampleFileResourceTypes(file string, expectedResourceType string, sampleRows int) (int, []PreflightIssue, error) { + scanner, closeFn, err := OpenLineScanner(file) + if err != nil { + return 0, nil, err + } + defer closeFn() + + issues := []PreflightIssue{} + sampled := 0 + row := 0 + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + if line == "" { + continue + } + row++ + sampled++ + var envelope struct { + ResourceType string `json:"resourceType"` + } + if err := json.Unmarshal([]byte(line), &envelope); err != nil { + issues = append(issues, PreflightIssue{ + Code: "invalid_json", + File: filepath.Base(file), + ResourceType: expectedResourceType, + Row: row, + Message: fmt.Sprintf("%s row %d is not valid JSON: %v", filepath.Base(file), row, err), + }) + } else if envelope.ResourceType == "" { + issues = append(issues, PreflightIssue{ + Code: "missing_resource_type", + File: filepath.Base(file), + ResourceType: expectedResourceType, + Row: row, + Message: fmt.Sprintf("%s row %d does not declare resourceType", filepath.Base(file), row), + }) + } else if envelope.ResourceType != expectedResourceType { + issues = append(issues, PreflightIssue{ + Code: "resource_type_mismatch", + File: filepath.Base(file), + ResourceType: expectedResourceType, + Row: row, + Message: fmt.Sprintf("%s row %d declares resourceType %q, expected %q from the staged filename", filepath.Base(file), row, envelope.ResourceType, expectedResourceType), + }) + } + if sampled >= sampleRows { + break + } + } + if err := scanner.Err(); err != nil { + return 0, nil, err + } + return sampled, issues, nil +} diff --git a/internal/ingest/preflight_test.go b/internal/ingest/preflight_test.go new file mode 100644 index 0000000..277bad9 --- /dev/null +++ b/internal/ingest/preflight_test.go @@ -0,0 +1,176 @@ +package ingest + +import ( + "context" + "errors" + "os" + "path/filepath" + "reflect" + "testing" + + "github.com/calypr/loom/internal/schemaidentity" + arangostore "github.com/calypr/loom/internal/store/arango" + + "github.com/bmeg/jsonschemagraph/graph" +) + +func TestPreflightFilesSelectsGeneratedAndGenericModesFromActiveSchema(t *testing.T) { + schema, err := graph.Load(repoPath(t, "schemas", "graph-fhir.json")) + if err != nil { + t.Fatalf("load schema: %v", err) + } + dir := t.TempDir() + patient := writePreflightFixture(t, dir, "Patient.ndjson", `{"resourceType":"Patient"}`+"\n") + diagnosticReport := writePreflightFixture(t, dir, "DiagnosticReport.ndjson", `{"resourceType":"DiagnosticReport"}`+"\n") + + report, err := PreflightFiles([]string{patient, diagnosticReport}, schema, 1) + if err != nil { + t.Fatalf("preflight: %v", err) + } + if !report.Valid() || len(report.Resources) != 2 { + t.Fatalf("unexpected report: %+v", report) + } + if got := report.Resources[0]; got.ResourceType != "DiagnosticReport" || got.Mode != IngestionModeGeneric || !got.GraphSchemaSupported || got.GeneratedLoaderSupported || got.SampledRows != 1 { + t.Fatalf("unexpected generic resource report: %+v", got) + } + if got := report.Resources[1]; got.ResourceType != "Patient" || got.Mode != IngestionModeGenerated || !got.GraphSchemaSupported || !got.GeneratedLoaderSupported || got.SampledRows != 1 { + t.Fatalf("unexpected generated resource report: %+v", got) + } +} + +func TestPreflightFilesReportsAllStagedInputProblems(t *testing.T) { + schema, err := graph.Load(repoPath(t, "schemas", "graph-fhir.json")) + if err != nil { + t.Fatalf("load schema: %v", err) + } + dir := t.TempDir() + patient := writePreflightFixture(t, dir, "Patient.ndjson", "not-json\n") + specimen := writePreflightFixture(t, dir, "Specimen.ndjson", `{"resourceType":"Patient"}`+"\n") + unknown := writePreflightFixture(t, dir, "Unknown.ndjson", `{"resourceType":"Unknown"}`+"\n") + + report, err := PreflightFiles([]string{patient, specimen, unknown}, schema, 10) + if err == nil { + t.Fatal("expected preflight error") + } + var preflightErr *PreflightError + if !errors.As(err, &preflightErr) { + t.Fatalf("expected PreflightError, got %T: %v", err, err) + } + if report.Valid() || len(report.Issues) != 3 { + t.Fatalf("unexpected report: %+v", report) + } + codes := map[string]bool{} + for _, issue := range report.Issues { + codes[issue.Code] = true + } + for _, want := range []string{"invalid_json", "resource_type_mismatch", "unsupported_graph_schema_resource"} { + if !codes[want] { + t.Fatalf("issues missing %q: %+v", want, report.Issues) + } + } + if len(preflightErr.Report.Issues) != len(report.Issues) { + t.Fatalf("error report does not preserve issues: %+v", preflightErr.Report) + } +} + +func TestPreflightFilesBoundsPayloadSamplingPerFile(t *testing.T) { + schema, err := graph.Load(repoPath(t, "schemas", "graph-fhir.json")) + if err != nil { + t.Fatalf("load schema: %v", err) + } + dir := t.TempDir() + patient := writePreflightFixture(t, dir, "Patient.ndjson", `{"resourceType":"Patient"}`+"\n"+`{"resourceType":"Specimen"}`+"\n") + + report, err := PreflightFiles([]string{patient}, schema, 1) + if err != nil { + t.Fatalf("preflight: %v", err) + } + if got := report.Resources[0].SampledRows; got != 1 { + t.Fatalf("sampled rows = %d, want 1", got) + } +} + +func TestLoadReturnsPreflightReportBeforeOpeningArango(t *testing.T) { + dir := t.TempDir() + writePreflightFixture(t, dir, "Unknown.ndjson", `{"resourceType":"Unknown"}`+"\n") + schemaPath := repoPath(t, "schemas", "graph-fhir.json") + wantIdentity, err := schemaidentity.Load(schemaPath) + if err != nil { + t.Fatalf("load expected schema identity: %v", err) + } + + var events []string + var preflightStart map[string]any + + summary, err := Load(context.Background(), LoadOptions{ + Schema: schemaPath, + MetaDir: dir, + // A connection to this endpoint would fail. Receiving a structured + // preflight error instead proves validation happens before backend open. + ConnectionOptions: arangostore.ConnectionOptions{ + URL: "http://127.0.0.1:1", + Database: "preflight_must_not_connect", + }, + EventSink: func(event string, fields map[string]any) { + events = append(events, event) + if event == "go_preflight_start" { + preflightStart = fields + } + }, + }) + if err == nil { + t.Fatal("expected preflight error") + } + var preflightErr *PreflightError + if !errors.As(err, &preflightErr) { + t.Fatalf("Load() error = %T %v, want PreflightError", err, err) + } + if summary.Preflight.Valid() || len(summary.Preflight.Issues) != 1 { + t.Fatalf("Load() preflight summary = %+v", summary.Preflight) + } + if summary.SchemaIdentity == nil { + t.Fatal("Load() schema identity is nil after schema-backed preflight") + } + if got, want := summary.SchemaIdentity.SchemaSHA256(), wantIdentity.SchemaSHA256(); got != want { + t.Errorf("Load() schema digest = %q, want %q", got, want) + } + if got, want := summary.SchemaIdentity.GeneratedResourceTypes(), wantIdentity.GeneratedResourceTypes(); !reflect.DeepEqual(got, want) { + t.Errorf("Load() generated roots = %#v, want %#v", got, want) + } + if preflightStart == nil { + t.Fatal("missing go_preflight_start event") + } + if got, want := preflightStart["schemaSha256"], wantIdentity.SchemaSHA256(); got != want { + t.Errorf("go_preflight_start schemaSha256 = %#v, want %#v", got, want) + } + if got, want := preflightStart["generatedRootCount"], len(wantIdentity.GeneratedResourceTypes()); got != want { + t.Errorf("go_preflight_start generatedRootCount = %#v, want %#v", got, want) + } + for _, event := range events { + if event == "go_backend_connect_start" || event == "go_backend_connect_complete" || event == "go_bootstrap_start" { + t.Fatalf("Load() emitted %q after an invalid staged input; events = %v", event, events) + } + } +} + +func TestLoadMissingSchemaReturnsNoSchemaIdentity(t *testing.T) { + summary, err := Load(context.Background(), LoadOptions{ + Schema: filepath.Join(t.TempDir(), "missing-graph.json"), + MetaDir: t.TempDir(), + }) + if !errors.Is(err, os.ErrNotExist) { + t.Fatalf("Load() missing schema error = %v, want os.ErrNotExist", err) + } + if summary.SchemaIdentity != nil { + t.Fatalf("Load() missing schema identity = %#v, want nil", summary.SchemaIdentity) + } +} + +func writePreflightFixture(t *testing.T, dir, name, contents string) string { + t.Helper() + path := filepath.Join(dir, name) + if err := os.WriteFile(path, []byte(contents), 0o644); err != nil { + t.Fatalf("write fixture %s: %v", path, err) + } + return path +} diff --git a/internal/ingest/row_builder.go b/internal/ingest/row_builder.go index 9e493a4..53d4d31 100644 --- a/internal/ingest/row_builder.go +++ b/internal/ingest/row_builder.go @@ -44,6 +44,9 @@ func (b *GeneratedRowBuilder) Build(resourceType string, line []byte, stageSecon } if b.authResourcePath != "" { vDoc.AuthResourcePath = b.authResourcePath + for i := range eDocs { + eDocs[i] = edgeWithAuthResourcePath(eDocs[i], b.authResourcePath) + } } marshalStart := time.Now() vBytes, err := sonic.ConfigFastest.Marshal(&vDoc) @@ -65,6 +68,22 @@ func (b *GeneratedRowBuilder) Build(resourceType string, line []byte, stageSecon }, "", nil } +func edgeWithAuthResourcePath(edge json.RawMessage, authResourcePath string) json.RawMessage { + if authResourcePath == "" { + return edge + } + var doc map[string]any + if err := sonic.ConfigFastest.Unmarshal(edge, &doc); err != nil { + return edge + } + doc["auth_resource_path"] = authResourcePath + out, err := sonic.ConfigFastest.Marshal(doc) + if err != nil { + return edge + } + return json.RawMessage(out) +} + type GenericRowBuilder struct { project string class *jsonschema.Schema @@ -119,6 +138,7 @@ func (b *GenericRowBuilder) Build(resourceType string, line []byte, stageSeconds } convertedEdges := make([]json.RawMessage, 0, len(gripEdges)) + authResourcePath, _ := b.extraArgs["auth_resource_path"].(string) for _, generatedEdge := range gripEdges { edge, err := jsgarango.EdgeFromGrip(b.project, resourceType, generatedEdge) if err != nil { @@ -130,6 +150,9 @@ func (b *GenericRowBuilder) Build(resourceType string, line []byte, stageSeconds if err != nil { return rowBuildResult{}, rowErrorEdge, err } + if authResourcePath != "" { + eBytes = edgeWithAuthResourcePath(eBytes, authResourcePath) + } convertedEdges = append(convertedEdges, json.RawMessage(eBytes)) } diff --git a/internal/ingest/row_builder_auth_test.go b/internal/ingest/row_builder_auth_test.go new file mode 100644 index 0000000..0bd445b --- /dev/null +++ b/internal/ingest/row_builder_auth_test.go @@ -0,0 +1,56 @@ +package ingest + +import ( + "bufio" + "encoding/json" + "os" + "testing" + + "github.com/bmeg/jsonschemagraph/graph" +) + +func TestGenericRowBuilderPropagatesAuthScopeToEdges(t *testing.T) { + schema, err := graph.Load(repoPath(t, "schemas", "graph-fhir.json")) + if err != nil { + t.Fatal(err) + } + class := schema.GetClass("Specimen") + if class == nil { + t.Fatal("Specimen class is missing from checked-in graph schema") + } + line := firstFixtureLine(t, repoPath(t, "META", "Specimen.ndjson")) + builder := NewGenericRowBuilder("P1", class, schema, graphExtraArgs("/programs/p1")) + result, kind, err := builder.Build("Specimen", line, map[string]float64{}) + if err != nil || kind != "" { + t.Fatalf("generic Build() kind=%q error=%v", kind, err) + } + if len(result.edges) == 0 { + t.Fatal("fixture Specimen produced no graph edges") + } + for _, raw := range result.edges { + var edge map[string]any + if err := json.Unmarshal(raw, &edge); err != nil { + t.Fatal(err) + } + if got := edge["auth_resource_path"]; got != "/programs/p1" { + t.Fatalf("generic edge scope = %#v, want /programs/p1; edge=%s", got, raw) + } + } +} + +func firstFixtureLine(t *testing.T, path string) []byte { + t.Helper() + file, err := os.Open(path) + if err != nil { + t.Fatal(err) + } + defer file.Close() + scanner := bufio.NewScanner(file) + if !scanner.Scan() { + t.Fatalf("fixture %s is empty", path) + } + if err := scanner.Err(); err != nil { + t.Fatal(err) + } + return append([]byte(nil), scanner.Bytes()...) +} diff --git a/internal/recipe/recipe_test.go b/internal/recipe/recipe_test.go new file mode 100644 index 0000000..3128a36 --- /dev/null +++ b/internal/recipe/recipe_test.go @@ -0,0 +1,91 @@ +package recipe + +import ( + "errors" + "reflect" + "testing" +) + +func TestNormalizeRecipeV1(t *testing.T) { + recipe := validRecipe() + recipe.Columns = append(recipe.Columns, ColumnSelection{ID: " patient.id "}) + recipe.Filters = []Filter{{ColumnID: "patient.id", Operator: " EQUALS ", Values: []string{" 123 "}}} + got, err := recipe.Normalize() + if err != nil { + t.Fatalf("Normalize: %v", err) + } + if len(got.Columns) != 2 || got.Columns[0].ID != "patient.id" || got.Filters[0].Operator != FilterEquals || got.Filters[0].Values[0] != "123" { + t.Fatalf("unexpected normalization: %#v", got) + } + if len(recipe.Columns) != 3 { + t.Fatal("Normalize mutated its input") + } +} + +func TestAllProductTemplatesValidate(t *testing.T) { + for _, template := range ListTemplates() { + r := validRecipe() + r.Template, r.Grain = template.ID, template.AllowedGrains[0] + if err := r.Validate(); err != nil { + t.Errorf("template %s: %v", template.ID, err) + } + } +} + +func TestRecipeValidationErrorsAreTyped(t *testing.T) { + r := validRecipe() + r.Grain = GrainFile + err := r.Validate() + var validation *ValidationError + if !errors.As(err, &validation) || validation.Code != "incompatible_grain" || validation.Field != "grain" { + t.Fatalf("unexpected error: %#v", err) + } +} + +func TestRecipeRejectsUnsafeOrAmbiguousIntent(t *testing.T) { + tests := []func(*Recipe){ + func(r *Recipe) { r.Version = "v2" }, + func(r *Recipe) { r.Project = "" }, + func(r *Recipe) { r.GenerationPolicy = GenerationPinned }, + func(r *Recipe) { r.Columns = nil }, + func(r *Recipe) { r.Columns[0].ID = "FOR x IN users" }, + func(r *Recipe) { r.Columns[1].OutputName = r.Columns[0].OutputName }, + func(r *Recipe) { + r.Filters = []Filter{{ColumnID: "not.selected", Operator: FilterEquals, Values: []string{"x"}}} + }, + func(r *Recipe) { + r.Filters = []Filter{{ColumnID: "patient.id", Operator: FilterBetween, Values: []string{"x"}}} + }, + func(r *Recipe) { r.Destination.Type = "shell" }, + } + for index, mutate := range tests { + r := validRecipe() + mutate(&r) + if err := r.Validate(); err == nil { + t.Errorf("case %d unexpectedly succeeded: %#v", index, r) + } + } +} + +func TestNormalizeDefensiveCopies(t *testing.T) { + r := validRecipe() + r.Filters = []Filter{{ColumnID: "patient.id", Operator: FilterIn, Values: []string{"a", "b"}}} + got, err := r.Normalize() + if err != nil { + t.Fatal(err) + } + got.Columns[0].ID = "changed" + got.Filters[0].Values[0] = "changed" + if reflect.DeepEqual(r, got) || r.Columns[0].ID == "changed" || r.Filters[0].Values[0] == "changed" { + t.Fatal("normalized recipe aliases input storage") + } +} + +func validRecipe() Recipe { + return Recipe{ + Version: VersionV1, Template: TemplatePatientCohort, TemplateVersion: 1, + Project: "demo", GenerationPolicy: GenerationLatest, Grain: GrainPatient, + Columns: []ColumnSelection{{ID: "patient.id", OutputName: "patient_id"}, {ID: "patient.gender", OutputName: "gender"}}, + Destination: Destination{Type: DestinationPreview}, + } +} diff --git a/internal/recipe/templates.go b/internal/recipe/templates.go new file mode 100644 index 0000000..9cf2d5f --- /dev/null +++ b/internal/recipe/templates.go @@ -0,0 +1,229 @@ +package recipe + +import ( + "fmt" + "strings" +) + +// TemplateMetadata describes a bounded product starting point. It deliberately +// contains no FHIR paths, compiler configuration, or destination credentials: +// selected columns and filters remain opaque capability IDs in Recipe. +type TemplateMetadata struct { + ID TemplateID `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + AllowedGrains []Grain `json:"allowedGrains"` + DefaultDestination DestinationType `json:"defaultDestination"` + AllowedDestinations []DestinationType `json:"allowedDestinations"` +} + +// ListTemplates returns the six supported product starting points in stable +// product-flow order. The returned metadata and every nested slice are owned by +// the caller and may be changed without affecting subsequent calls. +func ListTemplates() []TemplateMetadata { + templates := make([]TemplateMetadata, len(templateRegistry)) + for index, template := range templateRegistry { + templates[index] = cloneTemplateMetadata(template) + } + return templates +} + +// LookupTemplate returns metadata for one supported product starting point. +// The returned metadata is a defensive copy. +func LookupTemplate(id TemplateID) (TemplateMetadata, bool) { + template, ok := templateByID[id] + if !ok { + return TemplateMetadata{}, false + } + return cloneTemplateMetadata(template), true +} + +func templateAllowsGrain(template TemplateMetadata, grain Grain) bool { + for _, allowed := range template.AllowedGrains { + if grain == allowed { + return true + } + } + return false +} + +func templateAllowsDestination(template TemplateMetadata, destination DestinationType) bool { + for _, allowed := range template.AllowedDestinations { + if destination == allowed { + return true + } + } + return false +} + +func cloneTemplateMetadata(template TemplateMetadata) TemplateMetadata { + template.AllowedGrains = append([]Grain(nil), template.AllowedGrains...) + template.AllowedDestinations = append([]DestinationType(nil), template.AllowedDestinations...) + return template +} + +var templateRegistry = []TemplateMetadata{ + { + ID: TemplatePatientCohort, + Name: "Patient cohort", + Description: "Build one row per patient for a cohort.", + AllowedGrains: []Grain{GrainPatient}, + DefaultDestination: DestinationPreview, + AllowedDestinations: allDestinations(), + }, + { + ID: TemplateSpecimenInventory, + Name: "Specimen inventory", + Description: "Build one row per specimen for an inventory.", + AllowedGrains: []Grain{GrainSpecimen}, + DefaultDestination: DestinationPreview, + AllowedDestinations: allDestinations(), + }, + { + ID: TemplateFileManifest, + Name: "File manifest", + Description: "Build one row per file for a manifest.", + AllowedGrains: []Grain{GrainFile}, + DefaultDestination: DestinationPreview, + AllowedDestinations: allDestinations(), + }, + { + ID: TemplateDiagnoses, + Name: "Diagnoses", + Description: "Build one row per diagnosis.", + AllowedGrains: []Grain{GrainDiagnosis}, + DefaultDestination: DestinationPreview, + AllowedDestinations: allDestinations(), + }, + { + ID: TemplateLabsObservations, + Name: "Labs and observations", + Description: "Build one row per lab or observation.", + AllowedGrains: []Grain{GrainObservation}, + DefaultDestination: DestinationPreview, + AllowedDestinations: allDestinations(), + }, + { + ID: TemplateStudyEnrollment, + Name: "Study enrollment", + Description: "Build one row per study enrollment.", + AllowedGrains: []Grain{GrainStudyEnrollment}, + DefaultDestination: DestinationPreview, + AllowedDestinations: allDestinations(), + }, +} + +var templateByID = mustIndexTemplates(templateRegistry) + +func mustIndexTemplates(templates []TemplateMetadata) map[TemplateID]TemplateMetadata { + if err := validateTemplateRegistry(templates); err != nil { + panic(fmt.Sprintf("invalid recipe template registry: %v", err)) + } + indexed := make(map[TemplateID]TemplateMetadata, len(templates)) + for _, template := range templates { + indexed[template.ID] = cloneTemplateMetadata(template) + } + return indexed +} + +func validateTemplateRegistry(templates []TemplateMetadata) error { + expected := map[TemplateID]struct{}{ + TemplatePatientCohort: {}, TemplateSpecimenInventory: {}, + TemplateFileManifest: {}, TemplateDiagnoses: {}, + TemplateLabsObservations: {}, TemplateStudyEnrollment: {}, + } + if len(templates) != len(expected) { + return fmt.Errorf("expected metadata for %d templates, got %d", len(expected), len(templates)) + } + seenTemplates := make(map[TemplateID]struct{}, len(templates)) + for index, template := range templates { + field := fmt.Sprintf("templates[%d]", index) + if _, known := expected[template.ID]; !known { + return fmt.Errorf("%s.id %q is not a supported template", field, template.ID) + } + if _, duplicate := seenTemplates[template.ID]; duplicate { + return fmt.Errorf("%s.id %q is duplicated", field, template.ID) + } + seenTemplates[template.ID] = struct{}{} + if strings.TrimSpace(template.Name) == "" || hasControl(template.Name) { + return fmt.Errorf("%s.name must be non-empty printable text", field) + } + if strings.TrimSpace(template.Description) == "" || hasControl(template.Description) { + return fmt.Errorf("%s.description must be non-empty printable text", field) + } + if err := validateTemplateGrains(template.AllowedGrains, field); err != nil { + return err + } + if err := validateTemplateDestinations(template, field); err != nil { + return err + } + } + for id := range expected { + if _, ok := seenTemplates[id]; !ok { + return fmt.Errorf("missing metadata for template %q", id) + } + } + return nil +} + +func validateTemplateGrains(grains []Grain, field string) error { + if len(grains) == 0 { + return fmt.Errorf("%s.allowedGrains must not be empty", field) + } + known := map[Grain]struct{}{ + GrainPatient: {}, GrainSpecimen: {}, GrainFile: {}, + GrainDiagnosis: {}, GrainObservation: {}, GrainStudyEnrollment: {}, + } + seen := make(map[Grain]struct{}, len(grains)) + for _, grain := range grains { + if _, ok := known[grain]; !ok { + return fmt.Errorf("%s.allowedGrains contains unsupported grain %q", field, grain) + } + if _, duplicate := seen[grain]; duplicate { + return fmt.Errorf("%s.allowedGrains contains duplicate grain %q", field, grain) + } + seen[grain] = struct{}{} + } + return nil +} + +func validateTemplateDestinations(template TemplateMetadata, field string) error { + if len(template.AllowedDestinations) == 0 { + return fmt.Errorf("%s.allowedDestinations must not be empty", field) + } + seen := make(map[DestinationType]struct{}, len(template.AllowedDestinations)) + for _, destination := range template.AllowedDestinations { + if !validDestination(destination) { + return fmt.Errorf("%s.allowedDestinations contains unsupported destination %q", field, destination) + } + if _, duplicate := seen[destination]; duplicate { + return fmt.Errorf("%s.allowedDestinations contains duplicate destination %q", field, destination) + } + seen[destination] = struct{}{} + } + if !validDestination(template.DefaultDestination) { + return fmt.Errorf("%s.defaultDestination %q is unsupported", field, template.DefaultDestination) + } + if _, ok := seen[template.DefaultDestination]; !ok { + return fmt.Errorf("%s.defaultDestination %q is not allowed", field, template.DefaultDestination) + } + return nil +} + +func validDestination(destination DestinationType) bool { + switch destination { + case DestinationPreview, DestinationNDJSON, DestinationCSV, DestinationElasticsearch: + return true + default: + return false + } +} + +func allDestinations() []DestinationType { + return []DestinationType{ + DestinationPreview, + DestinationNDJSON, + DestinationCSV, + DestinationElasticsearch, + } +} diff --git a/internal/recipe/templates_test.go b/internal/recipe/templates_test.go new file mode 100644 index 0000000..2d4e4f4 --- /dev/null +++ b/internal/recipe/templates_test.go @@ -0,0 +1,109 @@ +package recipe + +import ( + "reflect" + "strings" + "testing" +) + +func TestListTemplatesReturnsAllProductIntentsInStableOrder(t *testing.T) { + first := ListTemplates() + second := ListTemplates() + if !reflect.DeepEqual(first, second) { + t.Fatalf("ListTemplates is not deterministic:\nfirst: %#v\nsecond: %#v", first, second) + } + gotIDs := make([]TemplateID, len(first)) + for index, template := range first { + gotIDs[index] = template.ID + if template.Name == "" || template.Description == "" { + t.Fatalf("template %q has incomplete presentation metadata: %#v", template.ID, template) + } + if len(template.AllowedGrains) == 0 || len(template.AllowedDestinations) == 0 { + t.Fatalf("template %q has incomplete capabilities: %#v", template.ID, template) + } + if !templateAllowsDestination(template, template.DefaultDestination) { + t.Fatalf("template %q default destination %q is not allowed", template.ID, template.DefaultDestination) + } + } + wantIDs := []TemplateID{ + TemplatePatientCohort, + TemplateSpecimenInventory, + TemplateFileManifest, + TemplateDiagnoses, + TemplateLabsObservations, + TemplateStudyEnrollment, + } + if !reflect.DeepEqual(gotIDs, wantIDs) { + t.Fatalf("template order = %v, want %v", gotIDs, wantIDs) + } +} + +func TestTemplateMetadataAPIsAreDefensive(t *testing.T) { + listed := ListTemplates() + listed[0].Name = "changed" + listed[0].AllowedGrains[0] = GrainFile + listed[0].AllowedDestinations[0] = DestinationCSV + + lookedUp, ok := LookupTemplate(TemplatePatientCohort) + if !ok { + t.Fatal("LookupTemplate(patient_cohort) = not found") + } + lookedUp.Description = "changed" + lookedUp.AllowedGrains[0] = GrainFile + lookedUp.AllowedDestinations[0] = DestinationCSV + + freshList := ListTemplates() + freshLookup, ok := LookupTemplate(TemplatePatientCohort) + if !ok { + t.Fatal("LookupTemplate(patient_cohort) after mutation = not found") + } + if freshList[0].Name == "changed" || freshList[0].AllowedGrains[0] != GrainPatient || freshList[0].AllowedDestinations[0] != DestinationPreview { + t.Fatalf("ListTemplates leaked mutable registry data: %#v", freshList[0]) + } + if freshLookup.Description == "changed" || freshLookup.AllowedGrains[0] != GrainPatient || freshLookup.AllowedDestinations[0] != DestinationPreview { + t.Fatalf("LookupTemplate leaked mutable registry data: %#v", freshLookup) + } + if _, ok := LookupTemplate("unknown"); ok { + t.Fatal("LookupTemplate accepted unknown template") + } +} + +func TestTemplateRegistryValidationRejectsDuplicateAndMissingMetadata(t *testing.T) { + tests := []struct { + name string + templates []TemplateMetadata + contains string + }{ + { + name: "duplicate ID", + templates: func() []TemplateMetadata { + got := ListTemplates() + got[1].ID = got[0].ID + return got + }(), + contains: "duplicated", + }, + { + name: "missing metadata", + templates: ListTemplates()[:5], + contains: "expected metadata", + }, + { + name: "missing capability", + templates: func() []TemplateMetadata { + got := ListTemplates() + got[0].AllowedGrains = nil + return got + }(), + contains: "allowedGrains", + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + err := validateTemplateRegistry(test.templates) + if err == nil || !strings.Contains(err.Error(), test.contains) { + t.Fatalf("validateTemplateRegistry() error = %v, want message containing %q", err, test.contains) + } + }) + } +} diff --git a/internal/recipe/types.go b/internal/recipe/types.go new file mode 100644 index 0000000..b5bac14 --- /dev/null +++ b/internal/recipe/types.go @@ -0,0 +1,91 @@ +// Package recipe defines product intent independently of FHIR and dataframe +// compiler implementation details. +package recipe + +const VersionV1 = "v1" + +type TemplateID string + +const ( + TemplatePatientCohort TemplateID = "patient_cohort" + TemplateSpecimenInventory TemplateID = "specimen_inventory" + TemplateFileManifest TemplateID = "file_manifest" + TemplateDiagnoses TemplateID = "diagnoses" + TemplateLabsObservations TemplateID = "labs_observations" + TemplateStudyEnrollment TemplateID = "study_enrollment" +) + +type Grain string + +const ( + GrainPatient Grain = "patient" + GrainSpecimen Grain = "specimen" + GrainFile Grain = "file" + GrainDiagnosis Grain = "diagnosis" + GrainObservation Grain = "observation" + GrainStudyEnrollment Grain = "study_enrollment" +) + +type GenerationPolicy string + +const ( + GenerationLatest GenerationPolicy = "latest" + GenerationPinned GenerationPolicy = "pinned" +) + +type ColumnSelection struct { + ID string `json:"id"` + OutputName string `json:"outputName,omitempty"` +} + +type FilterOperator string + +const ( + FilterEquals FilterOperator = "equals" + FilterNotEquals FilterOperator = "not_equals" + FilterIn FilterOperator = "in" + FilterNotIn FilterOperator = "not_in" + FilterExists FilterOperator = "exists" + FilterMissing FilterOperator = "missing" + FilterContains FilterOperator = "contains" + FilterGreaterThan FilterOperator = "greater_than" + FilterLessThan FilterOperator = "less_than" + FilterBetween FilterOperator = "between" +) + +type Filter struct { + ColumnID string `json:"columnId"` + Operator FilterOperator `json:"operator"` + Values []string `json:"values,omitempty"` +} + +type DestinationType string + +const ( + DestinationPreview DestinationType = "preview" + DestinationNDJSON DestinationType = "ndjson" + DestinationCSV DestinationType = "csv" + DestinationElasticsearch DestinationType = "elasticsearch" +) + +// Destination intentionally contains no credentials or backend-specific +// configuration. Those belong to a future authorized delivery adapter. +type Destination struct { + Type DestinationType `json:"type"` +} + +// Recipe is the V1 product-level intent contract. Column and filter IDs are +// opaque semantic IDs issued by Loom's future capability API, never FHIR paths +// or AQL expressions. +type Recipe struct { + Version string `json:"version"` + Template TemplateID `json:"template"` + TemplateVersion int `json:"templateVersion"` + Project string `json:"project"` + GenerationPolicy GenerationPolicy `json:"generationPolicy"` + Generation string `json:"generation,omitempty"` + Grain Grain `json:"grain"` + Columns []ColumnSelection `json:"columns"` + Filters []Filter `json:"filters,omitempty"` + Destination Destination `json:"destination"` +} diff --git a/internal/recipe/validation.go b/internal/recipe/validation.go new file mode 100644 index 0000000..c4c0fd0 --- /dev/null +++ b/internal/recipe/validation.go @@ -0,0 +1,179 @@ +package recipe + +import ( + "fmt" + "strings" + "unicode" +) + +const ( + maxColumns = 512 + maxFilters = 128 + maxFilterValues = 1024 +) + +type ValidationError struct { + Code string + Field string + Message string +} + +func (e *ValidationError) Error() string { + return fmt.Sprintf("%s: %s", e.Field, e.Message) +} + +func invalid(code, field, message string) error { + return &ValidationError{Code: code, Field: field, Message: message} +} + +func (r Recipe) Validate() error { + _, err := r.Normalize() + return err +} + +// Normalize trims user-owned labels, canonicalizes operator spelling, removes +// duplicate column selections, and returns a defensive copy. +func (r Recipe) Normalize() (Recipe, error) { + r.Project = strings.TrimSpace(r.Project) + r.Generation = strings.TrimSpace(r.Generation) + if r.Version != VersionV1 { + return Recipe{}, invalid("unsupported_version", "version", fmt.Sprintf("must be %q", VersionV1)) + } + template, ok := templateByID[r.Template] + if !ok { + return Recipe{}, invalid("unknown_template", "template", fmt.Sprintf("unknown template %q", r.Template)) + } + if r.TemplateVersion <= 0 { + return Recipe{}, invalid("invalid_template_version", "templateVersion", "must be positive") + } + if r.Project == "" || hasControl(r.Project) { + return Recipe{}, invalid("invalid_project", "project", "must be a non-empty printable identifier") + } + if !templateAllowsGrain(template, r.Grain) { + return Recipe{}, invalid("incompatible_grain", "grain", fmt.Sprintf("template %q does not support grain %q", r.Template, r.Grain)) + } + switch r.GenerationPolicy { + case GenerationLatest: + if r.Generation != "" { + return Recipe{}, invalid("unexpected_generation", "generation", "must be empty when policy is latest") + } + case GenerationPinned: + if r.Generation == "" || hasControl(r.Generation) { + return Recipe{}, invalid("missing_generation", "generation", "is required when policy is pinned") + } + default: + return Recipe{}, invalid("invalid_generation_policy", "generationPolicy", "must be latest or pinned") + } + if len(r.Columns) == 0 { + return Recipe{}, invalid("missing_columns", "columns", "at least one column is required") + } + if len(r.Columns) > maxColumns { + return Recipe{}, invalid("too_many_columns", "columns", fmt.Sprintf("cannot exceed %d", maxColumns)) + } + columns := make([]ColumnSelection, 0, len(r.Columns)) + knownColumns := make(map[string]struct{}, len(r.Columns)) + outputNames := make(map[string]struct{}, len(r.Columns)) + for index, column := range r.Columns { + column.ID = strings.TrimSpace(column.ID) + column.OutputName = strings.TrimSpace(column.OutputName) + field := fmt.Sprintf("columns[%d]", index) + if !validSemanticID(column.ID) { + return Recipe{}, invalid("invalid_semantic_id", field+".id", "must be a stable semantic identifier") + } + if column.OutputName != "" && hasControl(column.OutputName) { + return Recipe{}, invalid("invalid_output_name", field+".outputName", "contains control characters") + } + if _, exists := knownColumns[column.ID]; exists { + continue + } + if column.OutputName != "" { + if _, exists := outputNames[column.OutputName]; exists { + return Recipe{}, invalid("duplicate_output_name", field+".outputName", fmt.Sprintf("%q is duplicated", column.OutputName)) + } + outputNames[column.OutputName] = struct{}{} + } + knownColumns[column.ID] = struct{}{} + columns = append(columns, column) + } + r.Columns = columns + if len(r.Filters) > maxFilters { + return Recipe{}, invalid("too_many_filters", "filters", fmt.Sprintf("cannot exceed %d", maxFilters)) + } + r.Filters = append([]Filter(nil), r.Filters...) + for index := range r.Filters { + filter := &r.Filters[index] + filter.ColumnID = strings.TrimSpace(filter.ColumnID) + filter.Operator = FilterOperator(strings.ToLower(strings.TrimSpace(string(filter.Operator)))) + filter.Values = append([]string(nil), filter.Values...) + field := fmt.Sprintf("filters[%d]", index) + if !validSemanticID(filter.ColumnID) { + return Recipe{}, invalid("invalid_semantic_id", field+".columnId", "must be a stable semantic identifier") + } + if _, exists := knownColumns[filter.ColumnID]; !exists { + return Recipe{}, invalid("unknown_filter_column", field+".columnId", "must reference a selected column") + } + if err := validateFilter(filter, field); err != nil { + return Recipe{}, err + } + } + if !validDestination(r.Destination.Type) { + return Recipe{}, invalid("invalid_destination", "destination.type", fmt.Sprintf("unknown destination %q", r.Destination.Type)) + } + if !templateAllowsDestination(template, r.Destination.Type) { + return Recipe{}, invalid("unsupported_destination", "destination.type", fmt.Sprintf("template %q does not support destination %q", r.Template, r.Destination.Type)) + } + return r, nil +} + +func validateFilter(filter *Filter, field string) error { + if len(filter.Values) > maxFilterValues { + return invalid("too_many_filter_values", field+".values", fmt.Sprintf("cannot exceed %d", maxFilterValues)) + } + for index := range filter.Values { + filter.Values[index] = strings.TrimSpace(filter.Values[index]) + if hasControl(filter.Values[index]) { + return invalid("invalid_filter_value", fmt.Sprintf("%s.values[%d]", field, index), "contains control characters") + } + } + want := -1 + switch filter.Operator { + case FilterExists, FilterMissing: + want = 0 + case FilterEquals, FilterNotEquals, FilterContains, FilterGreaterThan, FilterLessThan: + want = 1 + case FilterBetween: + want = 2 + case FilterIn, FilterNotIn: + if len(filter.Values) == 0 { + return invalid("missing_filter_values", field+".values", "at least one value is required") + } + return nil + default: + return invalid("invalid_filter_operator", field+".operator", fmt.Sprintf("unknown operator %q", filter.Operator)) + } + if len(filter.Values) != want { + return invalid("invalid_filter_values", field+".values", fmt.Sprintf("operator %q requires %d values", filter.Operator, want)) + } + return nil +} + +func validSemanticID(value string) bool { + if value == "" || len(value) > 256 { + return false + } + for _, r := range value { + if !(unicode.IsLetter(r) || unicode.IsDigit(r) || strings.ContainsRune("._:-", r)) { + return false + } + } + return true +} + +func hasControl(value string) bool { + for _, r := range value { + if unicode.IsControl(r) { + return true + } + } + return false +} diff --git a/internal/recipecompiler/bridge.go b/internal/recipecompiler/bridge.go new file mode 100644 index 0000000..cfff5cc --- /dev/null +++ b/internal/recipecompiler/bridge.go @@ -0,0 +1,417 @@ +// Package recipecompiler turns the product-level recipe contract into the +// compiler's internal Builder only after resolving its opaque capabilities +// against fresh, authorized discovery facts. +// +// This first bridge is intentionally root-only. A recipe column or filter can +// refer only to the resource represented by its named row grain; relationship +// choices, repeated-value quantifiers, pivots, aggregates, and row expansion +// need explicit product contracts before they can be lowered safely. +package recipecompiler + +import ( + "errors" + "fmt" + "math" + "strconv" + "strings" + + "github.com/calypr/loom/internal/dataframe" + "github.com/calypr/loom/internal/discovery" + "github.com/calypr/loom/internal/fhirschema" + "github.com/calypr/loom/internal/recipe" +) + +// Stable errors returned by Build. Callers should use errors.Is rather than +// parsing error text; the bridge deliberately does not disclose raw catalog +// selectors or unrecognized recipe identifiers in those errors. +var ( + ErrCatalogProjectMismatch = errors.New("recipe project does not match catalog facts") + ErrColumnCapabilityUnavailable = errors.New("recipe column capability is unavailable") + ErrRelatedResource = errors.New("recipe capability belongs to a related resource") + ErrPivotChoiceUnsupported = errors.New("recipe pivot-only capability is unsupported") + ErrRepeatedColumn = errors.New("recipe repeated column requires an explicit cardinality decision") + ErrRepeatedFilter = errors.New("recipe repeated filter requires an explicit quantifier decision") + ErrUnsupportedValueConversion = errors.New("recipe filter value cannot be converted to the resolved schema kind") + ErrUnsupportedFilter = errors.New("recipe filter is unsupported for the resolved schema capability") + ErrOutputNameCollision = errors.New("recipe output names collide after compiler normalization") + ErrGenerationBindingRequired = errors.New("pinned recipe generation requires a dataset generation binding") +) + +// Plan is the compiler-ready result of resolving a Recipe against one fresh +// authorized catalog snapshot. Recipe is normalized and Builder contains only +// selectors recovered from discovery capability resolution, never selectors +// supplied by the recipe input. +type Plan struct { + Recipe recipe.Recipe + Builder dataframe.Builder +} + +// Build normalizes input, resolves every opaque column/filter capability from +// the supplied fresh CatalogFacts, and produces a root-only dataframe Builder. +// +// A recipe BETWEEN filter is intentionally lowered as two inclusive filters: +// GTE for the first value and LTE for the second. NOT_IN is lowered as one +// scalar NOT_EQUALS filter per value. Repeated values are rejected in V1 rather +// than assuming ANY, ALL, or a projection/cardinality policy on the user's +// behalf. +// +// CatalogFacts must have been collected for the caller's current authorized +// project/scope. The returned Builder intentionally leaves AuthResourcePaths +// unset: caller authorization remains the responsibility of dataframe.Service +// or the owning request layer, which has the principal and scope identity. +// Pinned recipes return ErrGenerationBindingRequired until an owning dataset +// layer supplies facts bound to the requested generation. +func Build(input recipe.Recipe, facts discovery.CatalogFacts) (Plan, error) { + normalized, err := input.Normalize() + if err != nil { + return Plan{}, err + } + if normalized.GenerationPolicy == recipe.GenerationPinned { + // CatalogFacts deliberately has no dataset-generation identity. Accepting + // a pinned recipe here would silently compile it against whichever facts + // happen to be current, violating the recipe's reproducibility contract. + return Plan{}, ErrGenerationBindingRequired + } + if strings.TrimSpace(facts.Project) != normalized.Project { + return Plan{}, ErrCatalogProjectMismatch + } + + resolver, err := discovery.NewCapabilityResolver(facts) + if err != nil { + return Plan{}, err + } + rowGrain, rootResourceType, err := rootForRecipeGrain(normalized.Grain) + if err != nil { + return Plan{}, err + } + + resolvedColumns := make(map[string]discovery.ResolvedColumn, len(normalized.Columns)) + for _, selection := range normalized.Columns { + resolved, err := resolveRootColumn(resolver, selection.ID, rootResourceType) + if err != nil { + return Plan{}, err + } + resolvedColumns[selection.ID] = resolved + } + + builder := dataframe.Builder{ + Project: normalized.Project, + RootResourceType: rootResourceType, + RowGrain: rowGrain, + Fields: make([]dataframe.FieldSelect, 0, len(normalized.Columns)), + Filters: make([]dataframe.TypedFilter, 0, len(normalized.Filters)), + } + + // Resolve filters before materializing selections so a recipe which uses a + // repeated field as a filter receives the precise missing-quantifier error; + // a repeated selected field without a filter receives ErrRepeatedColumn. + for _, filter := range normalized.Filters { + resolved, ok := resolvedColumns[filter.ColumnID] + if !ok { + // Normalize currently proves this cannot happen, but do not turn a + // future recipe-contract regression into a selector fallback. + return Plan{}, ErrColumnCapabilityUnavailable + } + lowered, err := lowerRootFilter(rootResourceType, resolved, filter) + if err != nil { + return Plan{}, err + } + builder.Filters = append(builder.Filters, lowered...) + } + + outputNames, err := outputNames(normalized.Columns) + if err != nil { + return Plan{}, err + } + for index, selection := range normalized.Columns { + field, err := lowerRootSelection(resolvedColumns[selection.ID], outputNames[index]) + if err != nil { + return Plan{}, err + } + builder.Fields = append(builder.Fields, field) + } + + // This verifies the internal builder has a valid generated-schema semantic + // shape before it reaches later service/catalog validation or lowering. + if _, err := dataframe.BuildSemanticPlan(builder); err != nil { + return Plan{}, fmt.Errorf("recipe compiler generated invalid dataframe builder: %w", err) + } + + return Plan{Recipe: normalized, Builder: builder}, nil +} + +func rootForRecipeGrain(grain recipe.Grain) (dataframe.RowGrain, string, error) { + var rowGrain dataframe.RowGrain + switch grain { + case recipe.GrainPatient: + rowGrain = dataframe.RowGrainPatient + case recipe.GrainSpecimen: + rowGrain = dataframe.RowGrainSpecimen + case recipe.GrainFile: + rowGrain = dataframe.RowGrainFile + case recipe.GrainDiagnosis: + rowGrain = dataframe.RowGrainDiagnosis + case recipe.GrainObservation: + rowGrain = dataframe.RowGrainObservation + case recipe.GrainStudyEnrollment: + rowGrain = dataframe.RowGrainStudyEnrollment + default: + return "", "", fmt.Errorf("recipe grain %q has no named dataframe row grain", grain) + } + rootResourceType, ok := dataframe.RootResourceForGrain(rowGrain) + if !ok || rootResourceType == "" { + return "", "", fmt.Errorf("dataframe row grain %q has no named root resource", rowGrain) + } + return rowGrain, rootResourceType, nil +} + +func resolveRootColumn(resolver *discovery.CapabilityResolver, id string, rootResourceType string) (discovery.ResolvedColumn, error) { + resolved, err := resolver.ResolveColumn(discovery.ColumnID(id)) + if err != nil { + if errors.Is(err, discovery.ErrColumnUnavailable) { + return discovery.ResolvedColumn{}, fmt.Errorf("%w: %w", ErrColumnCapabilityUnavailable, discovery.ErrColumnUnavailable) + } + return discovery.ResolvedColumn{}, err + } + if resolved.ResourceType != rootResourceType { + return discovery.ResolvedColumn{}, ErrRelatedResource + } + return resolved, nil +} + +func lowerRootSelection(resolved discovery.ResolvedColumn, outputName string) (dataframe.FieldSelect, error) { + if pivotOnly(resolved) { + return dataframe.FieldSelect{}, ErrPivotChoiceUnsupported + } + if resolved.Repeated { + return dataframe.FieldSelect{}, ErrRepeatedColumn + } + if !resolved.CanSelect || resolved.Selector == nil { + return dataframe.FieldSelect{}, ErrColumnCapabilityUnavailable + } + return dataframe.FieldSelect{ + Name: outputName, + FieldRef: string(resolved.ID), + Select: fhirschema.SelectorExpression(*resolved.Selector), + ValueMode: "AUTO", + }, nil +} + +func lowerRootFilter(rootResourceType string, resolved discovery.ResolvedColumn, input recipe.Filter) ([]dataframe.TypedFilter, error) { + if pivotOnly(resolved) { + return nil, ErrPivotChoiceUnsupported + } + if resolved.Repeated { + return nil, ErrRepeatedFilter + } + if !resolved.CanFilter || resolved.Selector == nil { + return nil, ErrUnsupportedFilter + } + + kind, ok := dataframeFilterKind(resolved.ValueKind) + if !ok { + return nil, ErrUnsupportedValueConversion + } + values, err := convertFilterValues(kind, input.Values) + if err != nil { + return nil, err + } + newFilter := func(operator dataframe.FilterOperator, filterValues []dataframe.FilterValue) (dataframe.TypedFilter, error) { + filter := dataframe.TypedFilter{ + FieldRef: string(resolved.ID), + Selector: fhirschema.SelectorExpression(*resolved.Selector), + FieldKind: kind, + Operator: operator, + Values: append([]dataframe.FilterValue(nil), filterValues...), + } + if err := dataframe.ValidateTypedFilterForResource(rootResourceType, filter); err != nil { + return dataframe.TypedFilter{}, ErrUnsupportedFilter + } + return filter, nil + } + + switch input.Operator { + case recipe.FilterEquals: + filter, err := newFilter(dataframe.FilterEquals, values) + return oneFilter(filter, err) + case recipe.FilterNotEquals: + filter, err := newFilter(dataframe.FilterNotEquals, values) + return oneFilter(filter, err) + case recipe.FilterIn: + filter, err := newFilter(dataframe.FilterIn, values) + return oneFilter(filter, err) + case recipe.FilterNotIn: + filters := make([]dataframe.TypedFilter, 0, len(values)) + for _, value := range values { + filter, err := newFilter(dataframe.FilterNotEquals, []dataframe.FilterValue{value}) + if err != nil { + return nil, err + } + filters = append(filters, filter) + } + return filters, nil + case recipe.FilterExists: + filter, err := newFilter(dataframe.FilterExists, nil) + return oneFilter(filter, err) + case recipe.FilterMissing: + filter, err := newFilter(dataframe.FilterMissing, nil) + return oneFilter(filter, err) + case recipe.FilterContains: + filter, err := newFilter(dataframe.FilterContains, values) + return oneFilter(filter, err) + case recipe.FilterGreaterThan: + filter, err := newFilter(dataframe.FilterGreaterThan, values) + return oneFilter(filter, err) + case recipe.FilterLessThan: + filter, err := newFilter(dataframe.FilterLessThan, values) + return oneFilter(filter, err) + case recipe.FilterBetween: + lower, err := newFilter(dataframe.FilterGreaterEq, values[:1]) + if err != nil { + return nil, err + } + upper, err := newFilter(dataframe.FilterLessEq, values[1:]) + if err != nil { + return nil, err + } + return []dataframe.TypedFilter{lower, upper}, nil + default: + // Recipe.Normalize currently keeps this closed, but never fall through + // to a textual operator or a future unsupported enum value. + return nil, ErrUnsupportedFilter + } +} + +func oneFilter(filter dataframe.TypedFilter, err error) ([]dataframe.TypedFilter, error) { + if err != nil { + return nil, err + } + return []dataframe.TypedFilter{filter}, nil +} + +func pivotOnly(resolved discovery.ResolvedColumn) bool { + return resolved.ValueKind == discovery.ValueKindComposite || (!resolved.CanSelect && resolved.CanPivot) +} + +func dataframeFilterKind(kind discovery.ValueKind) (dataframe.FilterValueKind, bool) { + switch kind { + case discovery.ValueKindString: + return dataframe.FilterString, true + case discovery.ValueKindBoolean: + return dataframe.FilterBoolean, true + case discovery.ValueKindInteger: + return dataframe.FilterInteger, true + case discovery.ValueKindDecimal: + return dataframe.FilterDecimal, true + case discovery.ValueKindDate: + return dataframe.FilterDate, true + case discovery.ValueKindDateTime: + return dataframe.FilterDateTime, true + default: + return "", false + } +} + +func convertFilterValues(kind dataframe.FilterValueKind, values []string) ([]dataframe.FilterValue, error) { + converted := make([]dataframe.FilterValue, 0, len(values)) + for _, value := range values { + convertedValue, err := convertFilterValue(kind, value) + if err != nil { + return nil, err + } + converted = append(converted, convertedValue) + } + return converted, nil +} + +func convertFilterValue(kind dataframe.FilterValueKind, raw string) (dataframe.FilterValue, error) { + var value dataframe.FilterValue + switch kind { + case dataframe.FilterString: + value = dataframe.FilterValue{Kind: kind, String: &raw} + case dataframe.FilterBoolean: + var parsed bool + switch raw { + case "true": + parsed = true + case "false": + parsed = false + default: + return dataframe.FilterValue{}, ErrUnsupportedValueConversion + } + value = dataframe.FilterValue{Kind: kind, Boolean: &parsed} + case dataframe.FilterInteger: + parsed, err := strconv.ParseInt(raw, 10, 64) + if err != nil { + return dataframe.FilterValue{}, ErrUnsupportedValueConversion + } + value = dataframe.FilterValue{Kind: kind, Integer: &parsed} + case dataframe.FilterDecimal: + parsed, err := strconv.ParseFloat(raw, 64) + if err != nil || math.IsNaN(parsed) || math.IsInf(parsed, 0) { + return dataframe.FilterValue{}, ErrUnsupportedValueConversion + } + value = dataframe.FilterValue{Kind: kind, Decimal: &parsed} + case dataframe.FilterDate: + value = dataframe.FilterValue{Kind: kind, Date: &raw} + case dataframe.FilterDateTime: + value = dataframe.FilterValue{Kind: kind, DateTime: &raw} + default: + return dataframe.FilterValue{}, ErrUnsupportedValueConversion + } + if err := value.Validate(); err != nil { + return dataframe.FilterValue{}, ErrUnsupportedValueConversion + } + return value, nil +} + +func outputNames(columns []recipe.ColumnSelection) ([]string, error) { + // Check all explicit names first, so defaults can avoid a user-provided + // column_1 instead of creating a lower-level compiler collision. + usedCompilerNames := make(map[string]struct{}, len(columns)) + for _, column := range columns { + if column.OutputName == "" { + continue + } + name := compilerOutputName(column.OutputName) + if _, exists := usedCompilerNames[name]; exists { + return nil, ErrOutputNameCollision + } + usedCompilerNames[name] = struct{}{} + } + + names := make([]string, len(columns)) + for index, column := range columns { + if column.OutputName != "" { + names[index] = column.OutputName + continue + } + for suffix := index + 1; ; suffix++ { + candidate := fmt.Sprintf("column_%d", suffix) + compilerName := compilerOutputName(candidate) + if _, exists := usedCompilerNames[compilerName]; exists { + continue + } + usedCompilerNames[compilerName] = struct{}{} + names[index] = candidate + break + } + } + return names, nil +} + +// compilerOutputName intentionally mirrors dataframe's output-key +// normalization so recipe input cannot create duplicate compiled columns by +// using different punctuation in otherwise identical display names. +func compilerOutputName(name string) string { + var builder strings.Builder + for _, r := range name { + switch { + case r >= 'a' && r <= 'z', r >= 'A' && r <= 'Z', r >= '0' && r <= '9': + builder.WriteRune(r) + default: + builder.WriteRune('_') + } + } + return builder.String() +} diff --git a/internal/recipecompiler/bridge_test.go b/internal/recipecompiler/bridge_test.go new file mode 100644 index 0000000..f08ac47 --- /dev/null +++ b/internal/recipecompiler/bridge_test.go @@ -0,0 +1,336 @@ +package recipecompiler + +import ( + "errors" + "fmt" + "reflect" + "strings" + "testing" + + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/dataframe" + "github.com/calypr/loom/internal/discovery" + "github.com/calypr/loom/internal/fhirschema" + "github.com/calypr/loom/internal/recipe" +) + +func TestBuildPatientCohortProducesCompilerReadyTypedFilters(t *testing.T) { + facts := bridgeFacts() + genderID := capabilityID(t, facts, "Patient", "gender") + birthDateID := capabilityID(t, facts, "Patient", "birthDate") + + input := patientRecipe(genderID, birthDateID) + input.Columns[0].OutputName = "Sex" + input.Columns[1].OutputName = "Birth date" + input.Filters = []recipe.Filter{ + {ColumnID: genderID, Operator: recipe.FilterEquals, Values: []string{"female"}}, + {ColumnID: birthDateID, Operator: recipe.FilterBetween, Values: []string{"1970-01-01", "2000-12-31"}}, + {ColumnID: genderID, Operator: recipe.FilterNotIn, Values: []string{"unknown", "other"}}, + } + + plan, err := Build(input, facts) + if err != nil { + t.Fatalf("Build() error = %v", err) + } + if plan.Recipe.Project != "project-a" || plan.Builder.Project != "project-a" { + t.Errorf("project normalization = recipe %q builder %q, want project-a", plan.Recipe.Project, plan.Builder.Project) + } + if plan.Builder.RootResourceType != "Patient" || plan.Builder.RowGrain != dataframe.RowGrainPatient { + t.Errorf("root builder = %+v, want Patient/patient", plan.Builder) + } + if plan.Builder.AuthResourcePaths != nil { + t.Errorf("bridge unexpectedly invented authorization paths: %#v", plan.Builder.AuthResourcePaths) + } + if got, want := len(plan.Builder.Fields), 2; got != want { + t.Fatalf("field count = %d, want %d", got, want) + } + if got := plan.Builder.Fields[0]; got.Name != "Sex" || got.FieldRef != genderID || got.Select != "gender" || got.ValueMode != "AUTO" { + t.Errorf("gender field = %+v", got) + } + if got := plan.Builder.Fields[1]; got.Name != "Birth date" || got.FieldRef != birthDateID || got.Select != "birthDate" || got.ValueMode != "AUTO" { + t.Errorf("birth date field = %+v", got) + } + + // BETWEEN is an inclusive range: the lower and upper endpoints are + // explicitly represented as GTE and LTE rather than a string expression. + wantOperators := []dataframe.FilterOperator{ + dataframe.FilterEquals, + dataframe.FilterGreaterEq, + dataframe.FilterLessEq, + dataframe.FilterNotEquals, + dataframe.FilterNotEquals, + } + if got := filterOperators(plan.Builder.Filters); !reflect.DeepEqual(got, wantOperators) { + t.Errorf("filter operators = %v, want %v", got, wantOperators) + } + if got := plan.Builder.Filters[0]; got.FieldKind != dataframe.FilterString || got.Values[0].String == nil || *got.Values[0].String != "female" { + t.Errorf("gender typed filter = %+v", got) + } + for index, want := range []string{"1970-01-01", "2000-12-31"} { + filter := plan.Builder.Filters[index+1] + if filter.FieldKind != dataframe.FilterDate || len(filter.Values) != 1 || filter.Values[0].Date == nil || *filter.Values[0].Date != want { + t.Errorf("between filter %d = %+v, want DATE %q", index, filter, want) + } + } + + compiled, err := dataframe.CompileRequest(plan.Builder, 25) + if err != nil { + t.Fatalf("CompileRequest(recipe builder) error = %v", err) + } + if compiled.RootResourceType != "Patient" || compiled.RowIdentity == nil || compiled.RowIdentity.Grain != dataframe.RowGrainPatient { + t.Errorf("compiled query metadata = %+v", compiled) + } + if !strings.Contains(compiled.Query, " >= ") || !strings.Contains(compiled.Query, " <= ") { + t.Errorf("compiled inclusive BETWEEN predicates missing from query:\n%s", compiled.Query) + } +} + +func TestBuildMapsEverySupportedRootFilterOperator(t *testing.T) { + facts := bridgeFacts() + genderID := capabilityID(t, facts, "Patient", "gender") + birthDateID := capabilityID(t, facts, "Patient", "birthDate") + + tests := []struct { + name string + columnID string + operator recipe.FilterOperator + values []string + want []dataframe.FilterOperator + wantKind dataframe.FilterValueKind + }{ + {name: "equals", columnID: genderID, operator: recipe.FilterEquals, values: []string{"female"}, want: []dataframe.FilterOperator{dataframe.FilterEquals}, wantKind: dataframe.FilterString}, + {name: "not equals", columnID: genderID, operator: recipe.FilterNotEquals, values: []string{"male"}, want: []dataframe.FilterOperator{dataframe.FilterNotEquals}, wantKind: dataframe.FilterString}, + {name: "in", columnID: genderID, operator: recipe.FilterIn, values: []string{"female", "male"}, want: []dataframe.FilterOperator{dataframe.FilterIn}, wantKind: dataframe.FilterString}, + {name: "not in", columnID: genderID, operator: recipe.FilterNotIn, values: []string{"unknown", "other"}, want: []dataframe.FilterOperator{dataframe.FilterNotEquals, dataframe.FilterNotEquals}, wantKind: dataframe.FilterString}, + {name: "exists", columnID: genderID, operator: recipe.FilterExists, want: []dataframe.FilterOperator{dataframe.FilterExists}, wantKind: dataframe.FilterString}, + {name: "missing", columnID: genderID, operator: recipe.FilterMissing, want: []dataframe.FilterOperator{dataframe.FilterMissing}, wantKind: dataframe.FilterString}, + {name: "contains", columnID: genderID, operator: recipe.FilterContains, values: []string{"em"}, want: []dataframe.FilterOperator{dataframe.FilterContains}, wantKind: dataframe.FilterString}, + {name: "greater than", columnID: birthDateID, operator: recipe.FilterGreaterThan, values: []string{"1970-01-01"}, want: []dataframe.FilterOperator{dataframe.FilterGreaterThan}, wantKind: dataframe.FilterDate}, + {name: "less than", columnID: birthDateID, operator: recipe.FilterLessThan, values: []string{"2000-12-31"}, want: []dataframe.FilterOperator{dataframe.FilterLessThan}, wantKind: dataframe.FilterDate}, + {name: "between inclusive", columnID: birthDateID, operator: recipe.FilterBetween, values: []string{"1970-01-01", "2000-12-31"}, want: []dataframe.FilterOperator{dataframe.FilterGreaterEq, dataframe.FilterLessEq}, wantKind: dataframe.FilterDate}, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + input := patientRecipe(test.columnID) + input.Filters = []recipe.Filter{{ColumnID: test.columnID, Operator: test.operator, Values: test.values}} + plan, err := Build(input, facts) + if err != nil { + t.Fatalf("Build() error = %v", err) + } + if got := filterOperators(plan.Builder.Filters); !reflect.DeepEqual(got, test.want) { + t.Errorf("operators = %v, want %v", got, test.want) + } + for _, filter := range plan.Builder.Filters { + if filter.FieldKind != test.wantKind { + t.Errorf("filter kind = %q, want %q", filter.FieldKind, test.wantKind) + } + } + }) + } +} + +func TestBuildRejectsStaleUnknownAndRawFHIRPathCapabilities(t *testing.T) { + facts := bridgeFacts() + genderID := capabilityID(t, facts, "Patient", "gender") + freshFacts := discovery.CatalogFacts{ + Project: "project-a", + Fields: []catalog.PopulatedField{{ + Project: "project-a", ResourceType: "Patient", Path: "birthDate", Kind: "scalar", DocCount: 1, + }}, + } + + tests := []struct { + name string + id string + facts discovery.CatalogFacts + }{ + {name: "stale opaque ID", id: genderID, facts: freshFacts}, + {name: "raw FHIR path", id: "gender", facts: facts}, + {name: "unknown opaque shaped ID", id: "col_" + strings.Repeat("0", 64), facts: facts}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + input := patientRecipe(test.id) + plan, err := Build(input, test.facts) + if !errors.Is(err, ErrColumnCapabilityUnavailable) { + t.Fatalf("Build() error = %v, want ErrColumnCapabilityUnavailable", err) + } + if !errors.Is(err, discovery.ErrColumnUnavailable) { + t.Errorf("Build() error = %v, want discovery.ErrColumnUnavailable cause", err) + } + if len(plan.Builder.Fields) != 0 || len(plan.Builder.Filters) != 0 { + t.Errorf("failed bridge returned a usable builder: %+v", plan.Builder) + } + if strings.Contains(fmt.Sprintf("%#v", plan), "gender") { + t.Errorf("raw recipe path leaked into failed plan: %#v", plan) + } + }) + } +} + +func TestBuildRejectsRelatedPivotAndRepeatedChoices(t *testing.T) { + facts := bridgeFacts() + genderID := capabilityID(t, facts, "Patient", "gender") + observationValueID := capabilityID(t, facts, "Observation", "valueInteger") + observationCodeID := capabilityID(t, facts, "Observation", "code") + repeatedNameID := capabilityID(t, facts, "Patient", "name[].family") + + t.Run("related root column", func(t *testing.T) { + _, err := Build(patientRecipe(genderID, observationValueID), facts) + if !errors.Is(err, ErrRelatedResource) { + t.Fatalf("Build() error = %v, want ErrRelatedResource", err) + } + }) + + t.Run("composite pivot only choice", func(t *testing.T) { + input := observationRecipe(observationCodeID) + _, err := Build(input, facts) + if !errors.Is(err, ErrPivotChoiceUnsupported) { + t.Fatalf("Build() error = %v, want ErrPivotChoiceUnsupported", err) + } + }) + + t.Run("repeated root column", func(t *testing.T) { + _, err := Build(patientRecipe(repeatedNameID), facts) + if !errors.Is(err, ErrRepeatedColumn) { + t.Fatalf("Build() error = %v, want ErrRepeatedColumn", err) + } + }) + + t.Run("repeated root filter needs quantifier", func(t *testing.T) { + input := patientRecipe(repeatedNameID) + input.Filters = []recipe.Filter{{ColumnID: repeatedNameID, Operator: recipe.FilterExists}} + _, err := Build(input, facts) + if !errors.Is(err, ErrRepeatedFilter) { + t.Fatalf("Build() error = %v, want ErrRepeatedFilter", err) + } + }) +} + +func TestBuildRejectsInvalidTypedFilterValues(t *testing.T) { + facts := bridgeFacts() + booleanID := capabilityID(t, facts, "Patient", "deceasedBoolean") + integerID := capabilityID(t, facts, "Patient", "multipleBirthInteger") + dateID := capabilityID(t, facts, "Patient", "birthDate") + + tests := []struct { + name string + id string + value string + }{ + {name: "boolean", id: booleanID, value: "yes"}, + {name: "integer", id: integerID, value: "twelve"}, + {name: "date", id: dateID, value: "2024-99-99"}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + input := patientRecipe(test.id) + input.Filters = []recipe.Filter{{ColumnID: test.id, Operator: recipe.FilterEquals, Values: []string{test.value}}} + _, err := Build(input, facts) + if !errors.Is(err, ErrUnsupportedValueConversion) { + t.Fatalf("Build() error = %v, want ErrUnsupportedValueConversion", err) + } + }) + } +} + +func TestBuildRejectsPinnedRecipeWithoutGenerationBinding(t *testing.T) { + facts := bridgeFacts() + genderID := capabilityID(t, facts, "Patient", "gender") + input := patientRecipe(genderID) + input.GenerationPolicy = recipe.GenerationPinned + input.Generation = "generation-42" + + _, err := Build(input, facts) + if !errors.Is(err, ErrGenerationBindingRequired) { + t.Fatalf("Build() error = %v, want ErrGenerationBindingRequired", err) + } +} + +func TestBuildRejectsProjectMismatchedCatalogFacts(t *testing.T) { + facts := bridgeFacts() + genderID := capabilityID(t, facts, "Patient", "gender") + input := patientRecipe(genderID) + input.Project = "another-project" + + _, err := Build(input, facts) + if !errors.Is(err, ErrCatalogProjectMismatch) { + t.Fatalf("Build() error = %v, want ErrCatalogProjectMismatch", err) + } +} + +func patientRecipe(columnIDs ...string) recipe.Recipe { + return productRecipe(recipe.TemplatePatientCohort, recipe.GrainPatient, columnIDs...) +} + +func observationRecipe(columnIDs ...string) recipe.Recipe { + return productRecipe(recipe.TemplateLabsObservations, recipe.GrainObservation, columnIDs...) +} + +func productRecipe(template recipe.TemplateID, grain recipe.Grain, columnIDs ...string) recipe.Recipe { + columns := make([]recipe.ColumnSelection, 0, len(columnIDs)) + for _, id := range columnIDs { + columns = append(columns, recipe.ColumnSelection{ID: id}) + } + return recipe.Recipe{ + Version: recipe.VersionV1, + Template: template, + TemplateVersion: 1, + Project: "project-a", + GenerationPolicy: recipe.GenerationLatest, + Grain: grain, + Columns: columns, + Destination: recipe.Destination{Type: recipe.DestinationPreview}, + } +} + +func bridgeFacts() discovery.CatalogFacts { + return discovery.CatalogFacts{ + Project: "project-a", + Fields: []catalog.PopulatedField{ + {Project: "project-a", ResourceType: "Patient", Path: "gender", Kind: "scalar", DocCount: 3, DistinctValues: []string{"female", "male"}}, + {Project: "project-a", ResourceType: "Patient", Path: "birthDate", Kind: "scalar", DocCount: 3, DistinctValues: []string{"1970-01-01", "2000-12-31"}}, + {Project: "project-a", ResourceType: "Patient", Path: "name[].family", Kind: "scalar", DocCount: 3, DistinctValues: []string{"Ng", "Smith"}}, + {Project: "project-a", ResourceType: "Patient", Path: "deceasedBoolean", Kind: "scalar", DocCount: 3, DistinctValues: []string{"false", "true"}}, + {Project: "project-a", ResourceType: "Patient", Path: "multipleBirthInteger", Kind: "scalar", DocCount: 3, DistinctValues: []string{"1", "2"}}, + { + Project: "project-a", ResourceType: "Observation", Path: "code", Kind: "codeable_concept", DocCount: 3, + PivotCandidate: true, PivotFamily: fhirschema.PivotFamilyObservationCodeValue, + PivotColumnSelect: "code.coding[].display", PivotValueSelect: "valueInteger", PivotColumns: []string{"Hemoglobin"}, + }, + {Project: "project-a", ResourceType: "Observation", Path: "valueInteger", Kind: "scalar", DocCount: 3, DistinctValues: []string{"12", "13"}}, + }, + } +} + +func capabilityID(t *testing.T, facts discovery.CatalogFacts, resourceType, canonicalPath string) string { + t.Helper() + snapshot, err := discovery.BuildSnapshot(facts) + if err != nil { + t.Fatalf("BuildSnapshot() error = %v", err) + } + resolver, err := discovery.NewCapabilityResolver(facts) + if err != nil { + t.Fatalf("NewCapabilityResolver() error = %v", err) + } + for _, column := range snapshot.Columns { + resolved, err := resolver.ResolveColumn(column.ID) + if err != nil { + t.Fatalf("ResolveColumn(%q) error = %v", column.ID, err) + } + if resolved.ResourceType == resourceType && resolved.CanonicalPath == canonicalPath { + return string(column.ID) + } + } + t.Fatalf("no capability for %s.%s", resourceType, canonicalPath) + return "" +} + +func filterOperators(filters []dataframe.TypedFilter) []dataframe.FilterOperator { + operators := make([]dataframe.FilterOperator, 0, len(filters)) + for _, filter := range filters { + operators = append(operators, filter.Operator) + } + return operators +} diff --git a/internal/schemaidentity/identity.go b/internal/schemaidentity/identity.go new file mode 100644 index 0000000..807be98 --- /dev/null +++ b/internal/schemaidentity/identity.go @@ -0,0 +1,208 @@ +// Package schemaidentity identifies the graph schema compiled into this Loom +// process. It intentionally does not decide whether a dataset is compatible +// with that schema; dataset-generation persistence and comparison belong to a +// later layer. +package schemaidentity + +import ( + "bytes" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "io" + "os" + "sort" + "strings" + + "github.com/calypr/loom/internal/fhirschema" +) + +var ( + // ErrGraphSchemaPathRequired reports a missing configured graph-schema path. + ErrGraphSchemaPathRequired = errors.New("graph schema path is required") + // ErrMalformedGraphSchema reports JSON that cannot safely provide schema + // identity metadata. + ErrMalformedGraphSchema = errors.New("malformed graph schema") +) + +// Identity is a stable description of the configured graph-schema file and +// the generated FHIR roots available to this Loom binary. Its fields are kept +// private so callers cannot mutate the identity after it has been loaded. +// +// GeneratedResourceTypes is deliberately binary metadata, not a second +// classification of the configured file. Loading a different graph-schema +// file changes its source metadata and byte digest, but later ingestion +// compatibility validation must decide whether that file matches the compiled +// fhirschema artifact. +// +// SchemaID is copied only from the graph schema's top-level "$id" value. +// FHIRVersion is copied only from an explicit top-level "fhirVersion" value; +// Loom does not infer it from a URL, definition description, or resource +// content. It is therefore normally empty for the checked-in schema. +type Identity struct { + schemaID string + fhirVersion string + schemaSHA256 string + generatedResourceTypes []string +} + +// Load reads the configured graph-schema JSON file and returns its immutable +// identity. The SHA-256 is computed over the exact bytes read from disk, before +// JSON decoding, so whitespace and any other file change changes the digest. +// The configured file supplies only source metadata; root-resource metadata is +// always read from the generated fhirschema artifact compiled into this binary. +func Load(path string) (Identity, error) { + if strings.TrimSpace(path) == "" { + return Identity{}, ErrGraphSchemaPathRequired + } + + contents, err := os.ReadFile(path) + if err != nil { + return Identity{}, fmt.Errorf("read graph schema %q: %w", path, err) + } + + metadata, err := parseMetadata(contents) + if err != nil { + return Identity{}, err + } + + digest := sha256.Sum256(contents) + resourceTypes := fhirschema.ResourceTypes() + sort.Strings(resourceTypes) + + return Identity{ + schemaID: metadata.schemaID, + fhirVersion: metadata.fhirVersion, + schemaSHA256: hex.EncodeToString(digest[:]), + generatedResourceTypes: append([]string(nil), resourceTypes...), + }, nil +} + +// SchemaID returns the exact top-level "$id" value, or an empty string when +// the configured graph schema does not declare one. +func (i Identity) SchemaID() string { return i.schemaID } + +// FHIRVersion returns the exact top-level "fhirVersion" value, or an empty +// string when the configured graph schema does not explicitly declare it. +func (i Identity) FHIRVersion() string { return i.fhirVersion } + +// SchemaSHA256 returns the lower-case hexadecimal SHA-256 of the exact graph +// schema bytes read by Load. +func (i Identity) SchemaSHA256() string { return i.schemaSHA256 } + +// GeneratedResourceTypes returns a sorted defensive copy of the concrete FHIR +// resource roots in generated fhirschema metadata. It deliberately does not +// classify JSON definitions in the configured file a second time. +func (i Identity) GeneratedResourceTypes() []string { + return append([]string(nil), i.generatedResourceTypes...) +} + +// MarshalJSON serializes the immutable identity without exposing its backing +// slice. There is intentionally no UnmarshalJSON method: an Identity must be +// created by Load so its digest and generated-resource metadata stay coupled. +func (i Identity) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + SchemaID string `json:"schemaId,omitempty"` + FHIRVersion string `json:"fhirVersion,omitempty"` + SchemaSHA256 string `json:"schemaSha256"` + GeneratedResourceTypes []string `json:"generatedResourceTypes"` + }{ + SchemaID: i.schemaID, + FHIRVersion: i.fhirVersion, + SchemaSHA256: i.schemaSHA256, + GeneratedResourceTypes: i.GeneratedResourceTypes(), + }) +} + +type metadata struct { + schemaID string + fhirVersion string +} + +func parseMetadata(contents []byte) (metadata, error) { + decoder := json.NewDecoder(bytes.NewReader(contents)) + start, err := decoder.Token() + if err != nil { + return metadata{}, malformedGraphSchemaError("decode JSON", err) + } + if start != json.Delim('{') { + return metadata{}, malformedGraphSchemaError("top-level JSON value must be an object", nil) + } + + var result metadata + seen := make(map[string]struct{}, 2) + for decoder.More() { + keyToken, err := decoder.Token() + if err != nil { + return metadata{}, malformedGraphSchemaError("read object key", err) + } + key, ok := keyToken.(string) + if !ok { + return metadata{}, malformedGraphSchemaError("top-level object key is not a string", nil) + } + + var value json.RawMessage + if err := decoder.Decode(&value); err != nil { + return metadata{}, malformedGraphSchemaError(fmt.Sprintf("read top-level field %q", key), err) + } + + switch key { + case "$id": + if _, duplicate := seen[key]; duplicate { + return metadata{}, malformedGraphSchemaError("duplicate top-level \"$id\"", nil) + } + seen[key] = struct{}{} + value, err := requiredJSONString(value) + if err != nil { + return metadata{}, malformedGraphSchemaError("top-level \"$id\" must be a string", err) + } + result.schemaID = value + case "fhirVersion": + if _, duplicate := seen[key]; duplicate { + return metadata{}, malformedGraphSchemaError("duplicate top-level \"fhirVersion\"", nil) + } + seen[key] = struct{}{} + value, err := requiredJSONString(value) + if err != nil { + return metadata{}, malformedGraphSchemaError("top-level \"fhirVersion\" must be a string", err) + } + result.fhirVersion = value + } + } + + end, err := decoder.Token() + if err != nil { + return metadata{}, malformedGraphSchemaError("finish top-level object", err) + } + if end != json.Delim('}') { + return metadata{}, malformedGraphSchemaError("top-level JSON value must be an object", nil) + } + if _, err := decoder.Token(); !errors.Is(err, io.EOF) { + if err == nil { + return metadata{}, malformedGraphSchemaError("multiple top-level JSON values", nil) + } + return metadata{}, malformedGraphSchemaError("finish JSON document", err) + } + + return result, nil +} + +func requiredJSONString(raw json.RawMessage) (string, error) { + if bytes.Equal(bytes.TrimSpace(raw), []byte("null")) { + return "", errors.New("null is not a string") + } + var value string + if err := json.Unmarshal(raw, &value); err != nil { + return "", err + } + return value, nil +} + +func malformedGraphSchemaError(problem string, err error) error { + if err == nil { + return fmt.Errorf("%w: %s", ErrMalformedGraphSchema, problem) + } + return fmt.Errorf("%w: %s: %v", ErrMalformedGraphSchema, problem, err) +} diff --git a/internal/schemaidentity/identity_test.go b/internal/schemaidentity/identity_test.go new file mode 100644 index 0000000..e2d389f --- /dev/null +++ b/internal/schemaidentity/identity_test.go @@ -0,0 +1,191 @@ +package schemaidentity + +import ( + "crypto/sha256" + "encoding/hex" + "encoding/json" + "errors" + "os" + "path/filepath" + "reflect" + "sort" + "testing" + + "github.com/calypr/loom/internal/fhirschema" +) + +func TestLoadCheckedInGraphFHIRSchema(t *testing.T) { + path := filepath.Join("..", "..", "schemas", "graph-fhir.json") + contents, err := os.ReadFile(path) + if err != nil { + t.Fatalf("read checked-in graph schema: %v", err) + } + + identity, err := Load(path) + if err != nil { + t.Fatalf("Load(%q): %v", path, err) + } + + wantDigest := sha256.Sum256(contents) + if got, want := identity.SchemaSHA256(), hex.EncodeToString(wantDigest[:]); got != want { + t.Fatalf("SchemaSHA256() = %q, want %q", got, want) + } + if got, want := identity.SchemaID(), "http://graph-fhir.io/schema/0.0.2"; got != want { + t.Fatalf("SchemaID() = %q, want %q", got, want) + } + if got := identity.FHIRVersion(); got != "" { + t.Fatalf("FHIRVersion() = %q, want empty because graph-fhir.json has no explicit top-level fhirVersion", got) + } + + if got, want := identity.GeneratedResourceTypes(), fhirschema.ResourceTypes(); !reflect.DeepEqual(got, want) { + t.Fatalf("GeneratedResourceTypes() = %#v, want generated fhirschema roots %#v", got, want) + } + if !sort.StringsAreSorted(identity.GeneratedResourceTypes()) { + t.Fatal("GeneratedResourceTypes() is not sorted") + } +} + +func TestLoadUsesExactBytesAndOnlyExplicitMetadata(t *testing.T) { + dir := t.TempDir() + first := filepath.Join(dir, "first.json") + second := filepath.Join(dir, "second.json") + contents := []byte("{\n \"$id\": \"urn:example:graph\",\n \"fhirVersion\": \"R5\",\n \"$defs\": {}\n}\n") + if err := os.WriteFile(first, contents, 0o600); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(second, append([]byte(" "), contents...), 0o600); err != nil { + t.Fatal(err) + } + + identity, err := Load(first) + if err != nil { + t.Fatalf("Load(first): %v", err) + } + if got, want := identity.SchemaID(), "urn:example:graph"; got != want { + t.Fatalf("SchemaID() = %q, want %q", got, want) + } + if got, want := identity.FHIRVersion(), "R5"; got != want { + t.Fatalf("FHIRVersion() = %q, want %q", got, want) + } + + secondIdentity, err := Load(second) + if err != nil { + t.Fatalf("Load(second): %v", err) + } + if identity.SchemaSHA256() == secondIdentity.SchemaSHA256() { + t.Fatal("SchemaSHA256() did not change after an exact-byte change") + } +} + +func TestLoadRootsComeFromCompiledFHIRSchemaNotAlternateInput(t *testing.T) { + path := writeTempSchema(t, `{ + "$id": "urn:example:alternate-graph", + "$defs": { + "NotACompiledFHIRRoot": { + "type": "object" + } + } +}`) + + identity, err := Load(path) + if err != nil { + t.Fatalf("Load(%q): %v", path, err) + } + if got, want := identity.GeneratedResourceTypes(), fhirschema.ResourceTypes(); !reflect.DeepEqual(got, want) { + t.Fatalf("GeneratedResourceTypes() = %#v, want compiled fhirschema roots %#v", got, want) + } + for _, resourceType := range identity.GeneratedResourceTypes() { + if resourceType == "NotACompiledFHIRRoot" { + t.Fatal("Load classified an alternate input definition instead of using compiled fhirschema metadata") + } + } +} + +func TestLoadDoesNotInferFHIRVersion(t *testing.T) { + path := writeTempSchema(t, `{ + "$id": "https://example.test/fhir/R5/schema", + "version": "definitely-not-a-fhir-version" +}`) + + identity, err := Load(path) + if err != nil { + t.Fatalf("Load(%q): %v", path, err) + } + if got := identity.FHIRVersion(); got != "" { + t.Fatalf("FHIRVersion() = %q, want empty without explicit top-level fhirVersion", got) + } +} + +func TestIdentityDefensivelyCopiesAndSerializes(t *testing.T) { + identity, err := Load(writeTempSchema(t, `{"$id":"urn:example:immutable"}`)) + if err != nil { + t.Fatal(err) + } + + roots := identity.GeneratedResourceTypes() + if len(roots) == 0 { + t.Fatal("GeneratedResourceTypes() returned no roots") + } + roots[0] = "mutated" + if identity.GeneratedResourceTypes()[0] == "mutated" { + t.Fatal("GeneratedResourceTypes() exposed mutable backing storage") + } + + encoded, err := json.Marshal(identity) + if err != nil { + t.Fatalf("json.Marshal(Identity): %v", err) + } + var serialized struct { + SchemaID string `json:"schemaId"` + SchemaSHA256 string `json:"schemaSha256"` + GeneratedResourceTypes []string `json:"generatedResourceTypes"` + } + if err := json.Unmarshal(encoded, &serialized); err != nil { + t.Fatalf("json.Unmarshal serialized identity: %v", err) + } + if got, want := serialized.SchemaID, identity.SchemaID(); got != want { + t.Fatalf("serialized schemaId = %q, want %q", got, want) + } + if got, want := serialized.SchemaSHA256, identity.SchemaSHA256(); got != want { + t.Fatalf("serialized schemaSha256 = %q, want %q", got, want) + } + if got, want := serialized.GeneratedResourceTypes, identity.GeneratedResourceTypes(); !reflect.DeepEqual(got, want) { + t.Fatalf("serialized roots = %#v, want %#v", got, want) + } +} + +func TestLoadRejectsMissingAndMalformedInputs(t *testing.T) { + if _, err := Load(" "); !errors.Is(err, ErrGraphSchemaPathRequired) { + t.Fatalf("Load(blank) error = %v, want ErrGraphSchemaPathRequired", err) + } + + missing := filepath.Join(t.TempDir(), "missing.json") + if _, err := Load(missing); !errors.Is(err, os.ErrNotExist) { + t.Fatalf("Load(missing) error = %v, want os.ErrNotExist", err) + } + + for _, contents := range []string{ + `{`, + `[]`, + `null`, + `{"$id": 7}`, + `{"$id": null}`, + `{"fhirVersion": false}`, + `{"$id": "one", "$id": "two"}`, + `{} {}`, + } { + path := writeTempSchema(t, contents) + if _, err := Load(path); !errors.Is(err, ErrMalformedGraphSchema) { + t.Errorf("Load(%q) error = %v, want ErrMalformedGraphSchema", contents, err) + } + } +} + +func writeTempSchema(t *testing.T, contents string) string { + t.Helper() + path := filepath.Join(t.TempDir(), "graph.json") + if err := os.WriteFile(path, []byte(contents), 0o600); err != nil { + t.Fatal(err) + } + return path +} diff --git a/internal/store/arango/explain.go b/internal/store/arango/explain.go new file mode 100644 index 0000000..8b22b65 --- /dev/null +++ b/internal/store/arango/explain.go @@ -0,0 +1,271 @@ +package arango + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "sort" +) + +// ExplainRequest is the portable JSON body accepted by ArangoDB's AQL +// explain endpoint. It intentionally has no dependency on the Arango driver. +type ExplainRequest struct { + Query string `json:"query"` + BindVars map[string]any `json:"bindVars,omitempty"` + Options ExplainOptions `json:"options,omitempty"` +} + +type ExplainOptions struct { + AllPlans bool `json:"allPlans,omitempty"` + MaxNumberOfPlans int `json:"maxNumberOfPlans,omitempty"` + Optimizer OptimizerOptions `json:"optimizer,omitempty"` +} + +type OptimizerOptions struct { + Rules []string `json:"rules,omitempty"` +} + +// ExplainResult models both single-plan and all-plans responses. +type ExplainResult struct { + Plan *ExplainPlan `json:"plan,omitempty"` + Plans []ExplainPlan `json:"plans,omitempty"` + Warnings []ExplainWarning `json:"warnings,omitempty"` + Stats ExplainStats `json:"stats,omitempty"` + Cacheable bool `json:"cacheable,omitempty"` +} + +type ExplainPlan struct { + Nodes []ExplainNode `json:"nodes,omitempty"` + Rules []string `json:"rules,omitempty"` + Collections []ExplainCollection `json:"collections,omitempty"` + EstimatedCost float64 `json:"estimatedCost,omitempty"` + EstimatedNrItems float64 `json:"estimatedNrItems,omitempty"` +} + +type ExplainNode struct { + Type string `json:"type,omitempty"` + ID int64 `json:"id,omitempty"` + Dependencies []int64 `json:"dependencies,omitempty"` + Collection string `json:"collection,omitempty"` + EdgeCollections []string `json:"edgeCollections,omitempty"` + Indexes ExplainIndexes `json:"indexes,omitempty"` + EstimatedCost float64 `json:"estimatedCost,omitempty"` + EstimatedNrItems float64 `json:"estimatedNrItems,omitempty"` +} + +// ExplainIndexes accepts the shapes emitted by different ArangoDB plan nodes. +// Index nodes use an array, while traversal and optimizer nodes can emit a +// single object or an object keyed by an internal index role. +type ExplainIndexes []ExplainIndex + +func (indexes *ExplainIndexes) UnmarshalJSON(data []byte) error { + data = bytes.TrimSpace(data) + if len(data) == 0 || bytes.Equal(data, []byte("null")) { + *indexes = nil + return nil + } + values, err := decodeExplainIndexes(data, true) + if err != nil { + return err + } + *indexes = values + return nil +} + +// decodeExplainIndexes accepts every index shape emitted by the explain API: +// a direct index object, an array, or nested traversal-index containers such +// as {"base": [...], "levels": {...}}. Nested non-index metadata is ignored; +// a malformed top-level indexes value still returns an error. +func decodeExplainIndexes(data []byte, strict bool) ([]ExplainIndex, error) { + data = bytes.TrimSpace(data) + if len(data) == 0 || bytes.Equal(data, []byte("null")) { + return nil, nil + } + switch data[0] { + case '[': + var items []json.RawMessage + if err := json.Unmarshal(data, &items); err != nil { + return nil, err + } + out := make([]ExplainIndex, 0, len(items)) + for _, item := range items { + values, err := decodeExplainIndexes(item, false) + if err != nil { + return nil, err + } + out = append(out, values...) + } + return out, nil + case '{': + var one ExplainIndex + if err := json.Unmarshal(data, &one); err != nil { + return nil, err + } + if isExplainIndex(one) { + return []ExplainIndex{one}, nil + } + + var keyed map[string]json.RawMessage + if err := json.Unmarshal(data, &keyed); err != nil { + return nil, err + } + keys := make([]string, 0, len(keyed)) + for key := range keyed { + keys = append(keys, key) + } + sort.Strings(keys) + out := make([]ExplainIndex, 0, len(keyed)) + for _, key := range keys { + values, err := decodeExplainIndexes(keyed[key], false) + if err != nil { + return nil, err + } + out = append(out, values...) + } + return out, nil + default: + if strict { + return nil, fmt.Errorf("unexpected indexes JSON value %q", string(data)) + } + return nil, nil + } +} + +func isExplainIndex(index ExplainIndex) bool { + return index.ID != "" || index.Name != "" || index.Type != "" || len(index.Fields) > 0 +} + +type ExplainIndex struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` + Collection string `json:"collection,omitempty"` + Fields []string `json:"fields,omitempty"` + Unique bool `json:"unique,omitempty"` + Sparse bool `json:"sparse,omitempty"` + SelectivityEstimate *float64 `json:"selectivityEstimate,omitempty"` +} + +type ExplainCollection struct { + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` +} + +type ExplainWarning struct { + Code int `json:"code,omitempty"` + Message string `json:"message,omitempty"` +} + +type ExplainStats struct { + PlansCreated int `json:"plansCreated,omitempty"` + RulesExecuted int `json:"rulesExecuted,omitempty"` + RulesSkipped int `json:"rulesSkipped,omitempty"` + PeakMemoryUsage uint64 `json:"peakMemoryUsage,omitempty"` +} + +// ExplainIndexUse associates an index with the plan node and collection that +// use it. Collection falls back to the node collection when omitted by Arango. +type ExplainIndexUse struct { + Plan int + NodeID int64 + NodeType string + Collection string + Index ExplainIndex +} + +type explainEnvelope struct { + ExplainResult + Error bool `json:"error,omitempty"` + ErrorNum int `json:"errorNum,omitempty"` + ErrorMessage string `json:"errorMessage,omitempty"` + Code int `json:"code,omitempty"` +} + +// ParseExplainResult decodes an Arango explain response, rejects trailing JSON, +// and promotes Arango error envelopes to Go errors. +func ParseExplainResult(data []byte) (ExplainResult, error) { + decoder := json.NewDecoder(bytes.NewReader(data)) + var envelope explainEnvelope + if err := decoder.Decode(&envelope); err != nil { + return ExplainResult{}, fmt.Errorf("decode Arango explain response: %w", err) + } + if err := rejectTrailingJSON(decoder); err != nil { + return ExplainResult{}, err + } + if envelope.Error { + return ExplainResult{}, fmt.Errorf("Arango explain error %d (HTTP %d): %s", envelope.ErrorNum, envelope.Code, envelope.ErrorMessage) + } + if envelope.Plan == nil && len(envelope.Plans) == 0 { + return ExplainResult{}, fmt.Errorf("Arango explain response contains no plan") + } + return envelope.ExplainResult, nil +} + +// ExtractPlanIndexes returns deterministic, deduplicated index uses from the +// single plan followed by any alternative plans. +func ExtractPlanIndexes(result ExplainResult) []ExplainIndexUse { + plans := make([]ExplainPlan, 0, 1+len(result.Plans)) + if result.Plan != nil { + plans = append(plans, *result.Plan) + } + plans = append(plans, result.Plans...) + + uses := make([]ExplainIndexUse, 0) + seen := map[string]bool{} + for planIndex, plan := range plans { + for _, node := range plan.Nodes { + for _, index := range node.Indexes { + collection := explainIndexCollection(node, index) + key := fmt.Sprintf("%d\x00%d\x00%s\x00%s\x00%s", planIndex, node.ID, collection, index.ID, index.Name) + if seen[key] { + continue + } + seen[key] = true + uses = append(uses, ExplainIndexUse{Plan: planIndex, NodeID: node.ID, NodeType: node.Type, Collection: collection, Index: index}) + } + } + } + sort.SliceStable(uses, func(i, j int) bool { + if uses[i].Plan != uses[j].Plan { + return uses[i].Plan < uses[j].Plan + } + if uses[i].NodeID != uses[j].NodeID { + return uses[i].NodeID < uses[j].NodeID + } + if uses[i].Collection != uses[j].Collection { + return uses[i].Collection < uses[j].Collection + } + return uses[i].Index.Name < uses[j].Index.Name + }) + return uses +} + +// explainIndexCollection resolves the collection that owns an index across +// Arango's node shapes. Traversal nodes typically omit `collection` and put +// the edge collection in `edgeCollections`, while ordinary IndexNodes use +// `collection` directly. +func explainIndexCollection(node ExplainNode, index ExplainIndex) string { + if index.Collection != "" { + return index.Collection + } + if node.Collection != "" { + return node.Collection + } + if len(node.EdgeCollections) == 1 { + return node.EdgeCollections[0] + } + return "" +} + +func rejectTrailingJSON(decoder *json.Decoder) error { + var extra any + err := decoder.Decode(&extra) + if err == io.EOF { + return nil + } + if err != nil { + return fmt.Errorf("decode trailing Arango explain data: %w", err) + } + return fmt.Errorf("Arango explain response contains trailing JSON") +} diff --git a/internal/store/arango/explain_assessment.go b/internal/store/arango/explain_assessment.go new file mode 100644 index 0000000..c051f9f --- /dev/null +++ b/internal/store/arango/explain_assessment.go @@ -0,0 +1,147 @@ +package arango + +import ( + "sort" + "strings" +) + +// ExplainAssessment is a deterministic compiler-facing summary of one Arango +// explain response. Plan 0 is the primary plan when Result.Plan is present; +// alternative plans follow in response order. +type ExplainAssessment struct { + Plans []ExplainPlanEstimate + FullCollectionScans []ExplainCollectionScan + Indexes []ExplainIndexSummary + Warnings []ExplainWarning + AppliedOptimizerRules []string +} + +type ExplainPlanEstimate struct { + Plan int + EstimatedCost float64 + EstimatedNrItems float64 +} + +// ExplainCollectionScan records an EnumerateCollectionNode. Such a node is a +// full collection enumeration indicator even when a different node elsewhere +// in the plan uses an index. +type ExplainCollectionScan struct { + Plan int + NodeID int64 + Collection string +} + +// ExplainIndexSummary groups equivalent indexes across plan nodes while +// retaining every plan/node use. +type ExplainIndexSummary struct { + Collection string + ID string + Name string + Type string + Fields []string + Uses []ExplainIndexLocation +} + +type ExplainIndexLocation struct { + Plan int + NodeID int64 +} + +// AssessExplainResult converts parsed explain data into stable findings without +// issuing queries or depending on an Arango client. +func AssessExplainResult(result ExplainResult) ExplainAssessment { + plans := explainPlans(result) + assessment := ExplainAssessment{ + Plans: make([]ExplainPlanEstimate, 0, len(plans)), + FullCollectionScans: []ExplainCollectionScan{}, + Indexes: []ExplainIndexSummary{}, + Warnings: append([]ExplainWarning{}, result.Warnings...), + AppliedOptimizerRules: []string{}, + } + + rules := map[string]bool{} + indexByKey := map[string]int{} + for planNumber, plan := range plans { + assessment.Plans = append(assessment.Plans, ExplainPlanEstimate{ + Plan: planNumber, EstimatedCost: plan.EstimatedCost, EstimatedNrItems: plan.EstimatedNrItems, + }) + for _, rule := range plan.Rules { + if rule = strings.TrimSpace(rule); rule != "" { + rules[rule] = true + } + } + for _, node := range plan.Nodes { + if node.Type == "EnumerateCollectionNode" { + assessment.FullCollectionScans = append(assessment.FullCollectionScans, ExplainCollectionScan{ + Plan: planNumber, NodeID: node.ID, Collection: node.Collection, + }) + } + for _, index := range node.Indexes { + collection := explainIndexCollection(node, index) + fields := append([]string(nil), index.Fields...) + key := strings.Join([]string{collection, index.ID, index.Name, index.Type, strings.Join(fields, "\x1f")}, "\x00") + position, ok := indexByKey[key] + if !ok { + position = len(assessment.Indexes) + indexByKey[key] = position + assessment.Indexes = append(assessment.Indexes, ExplainIndexSummary{ + Collection: collection, ID: index.ID, Name: index.Name, Type: index.Type, Fields: fields, + }) + } + assessment.Indexes[position].Uses = append(assessment.Indexes[position].Uses, ExplainIndexLocation{Plan: planNumber, NodeID: node.ID}) + } + } + } + + for rule := range rules { + assessment.AppliedOptimizerRules = append(assessment.AppliedOptimizerRules, rule) + } + sort.Strings(assessment.AppliedOptimizerRules) + sort.Slice(assessment.FullCollectionScans, func(i, j int) bool { + a, b := assessment.FullCollectionScans[i], assessment.FullCollectionScans[j] + if a.Collection != b.Collection { + return a.Collection < b.Collection + } + if a.Plan != b.Plan { + return a.Plan < b.Plan + } + return a.NodeID < b.NodeID + }) + sort.Slice(assessment.Indexes, func(i, j int) bool { + a, b := assessment.Indexes[i], assessment.Indexes[j] + if a.Collection != b.Collection { + return a.Collection < b.Collection + } + if a.Name != b.Name { + return a.Name < b.Name + } + if a.ID != b.ID { + return a.ID < b.ID + } + return a.Type < b.Type + }) + for i := range assessment.Indexes { + sort.Slice(assessment.Indexes[i].Uses, func(a, b int) bool { + left, right := assessment.Indexes[i].Uses[a], assessment.Indexes[i].Uses[b] + if left.Plan != right.Plan { + return left.Plan < right.Plan + } + return left.NodeID < right.NodeID + }) + } + sort.Slice(assessment.Warnings, func(i, j int) bool { + if assessment.Warnings[i].Code != assessment.Warnings[j].Code { + return assessment.Warnings[i].Code < assessment.Warnings[j].Code + } + return assessment.Warnings[i].Message < assessment.Warnings[j].Message + }) + return assessment +} + +func explainPlans(result ExplainResult) []ExplainPlan { + plans := make([]ExplainPlan, 0, 1+len(result.Plans)) + if result.Plan != nil { + plans = append(plans, *result.Plan) + } + return append(plans, result.Plans...) +} diff --git a/internal/store/arango/explain_assessment_test.go b/internal/store/arango/explain_assessment_test.go new file mode 100644 index 0000000..c7af015 --- /dev/null +++ b/internal/store/arango/explain_assessment_test.go @@ -0,0 +1,71 @@ +package arango + +import ( + "reflect" + "testing" +) + +func TestAssessExplainResultRealisticPlan(t *testing.T) { + result, err := ParseExplainResult([]byte(`{ + "plan": { + "nodes": [ + {"type":"EnumerateCollectionNode","id":8,"collection":"Observation","estimatedCost":900,"estimatedNrItems":800}, + {"type":"IndexNode","id":5,"collection":"Patient","indexes":[{"id":"Patient/42","name":"idx_project_auth","type":"persistent","fields":["project","auth_resource_path"]}]}, + {"type":"IndexNode","id":3,"collection":"fhir_edge","indexes":[{"id":"fhir_edge/9","name":"idx_edge_project","type":"persistent","collection":"fhir_edge","fields":["project","label"]}]} + ], + "rules":["use-indexes","move-filters-up","use-indexes"], + "estimatedCost":123.5, + "estimatedNrItems":27 + }, + "warnings":[{"code":1578,"message":"late"},{"code":1577,"message":"early"}] +}`)) + if err != nil { + t.Fatal(err) + } + assessment := AssessExplainResult(result) + if !reflect.DeepEqual(assessment.Plans, []ExplainPlanEstimate{{Plan: 0, EstimatedCost: 123.5, EstimatedNrItems: 27}}) { + t.Fatalf("estimates = %#v", assessment.Plans) + } + if !reflect.DeepEqual(assessment.FullCollectionScans, []ExplainCollectionScan{{Plan: 0, NodeID: 8, Collection: "Observation"}}) { + t.Fatalf("full scans = %#v", assessment.FullCollectionScans) + } + if got := []string{assessment.Indexes[0].Collection + "/" + assessment.Indexes[0].Name, assessment.Indexes[1].Collection + "/" + assessment.Indexes[1].Name}; !reflect.DeepEqual(got, []string{"Patient/idx_project_auth", "fhir_edge/idx_edge_project"}) { + t.Fatalf("index ordering = %#v", got) + } + if !reflect.DeepEqual(assessment.AppliedOptimizerRules, []string{"move-filters-up", "use-indexes"}) { + t.Fatalf("rules = %#v", assessment.AppliedOptimizerRules) + } + if assessment.Warnings[0].Code != 1577 { + t.Fatalf("warnings are unstable: %#v", assessment.Warnings) + } +} + +func TestAssessExplainResultAlternativePlansStableAndGrouped(t *testing.T) { + result := ExplainResult{Plans: []ExplainPlan{ + {EstimatedCost: 20, EstimatedNrItems: 5, Rules: []string{"z-rule"}, Nodes: []ExplainNode{ + {Type: "IndexNode", ID: 9, Collection: "Patient", Indexes: []ExplainIndex{{ID: "Patient/1", Name: "primary", Type: "primary", Fields: []string{"_key"}}}}, + {Type: "EnumerateCollectionNode", ID: 10, Collection: "Specimen"}, + }}, + {EstimatedCost: 10, EstimatedNrItems: 2, Rules: []string{"a-rule"}, Nodes: []ExplainNode{ + {Type: "IndexNode", ID: 2, Collection: "Patient", Indexes: []ExplainIndex{{ID: "Patient/1", Name: "primary", Type: "primary", Fields: []string{"_key"}}}}, + {Type: "EnumerateCollectionNode", ID: 1, Collection: "Observation"}, + }}, + }} + assessment := AssessExplainResult(result) + if len(assessment.Indexes) != 1 || !reflect.DeepEqual(assessment.Indexes[0].Uses, []ExplainIndexLocation{{Plan: 0, NodeID: 9}, {Plan: 1, NodeID: 2}}) { + t.Fatalf("grouped index uses = %#v", assessment.Indexes) + } + if got := assessment.FullCollectionScans; len(got) != 2 || got[0].Collection != "Observation" || got[1].Collection != "Specimen" { + t.Fatalf("scan ordering = %#v", got) + } + if !reflect.DeepEqual(assessment.AppliedOptimizerRules, []string{"a-rule", "z-rule"}) { + t.Fatalf("rule ordering = %#v", assessment.AppliedOptimizerRules) + } +} + +func TestAssessExplainResultReturnsNonNilEmptyFindings(t *testing.T) { + assessment := AssessExplainResult(ExplainResult{}) + if assessment.Plans == nil || assessment.FullCollectionScans == nil || assessment.Indexes == nil || assessment.Warnings == nil || assessment.AppliedOptimizerRules == nil { + t.Fatalf("empty assessment contains nil slices: %#v", assessment) + } +} diff --git a/internal/store/arango/explain_client.go b/internal/store/arango/explain_client.go new file mode 100644 index 0000000..1fc9a5a --- /dev/null +++ b/internal/store/arango/explain_client.go @@ -0,0 +1,53 @@ +package arango + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "strings" +) + +// Explain submits a typed AQL explain request to this client's database. It is +// intentionally separate from QueryRows so compiler tooling can inspect a plan +// without executing a dataframe query. +func (c *Client) Explain(ctx context.Context, request ExplainRequest) (ExplainResult, error) { + if strings.TrimSpace(request.Query) == "" { + return ExplainResult{}, fmt.Errorf("AQL explain query is required") + } + body, err := json.Marshal(request) + if err != nil { + return ExplainResult{}, fmt.Errorf("encode AQL explain request: %w", err) + } + endpoint := fmt.Sprintf("%s/_db/%s/_api/explain", strings.TrimRight(c.rawURL, "/"), url.PathEscape(c.dbName)) + httpRequest, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint, bytes.NewReader(body)) + if err != nil { + return ExplainResult{}, fmt.Errorf("create AQL explain request: %w", err) + } + httpRequest.Header.Set("Content-Type", "application/json") + + response, err := c.client.Do(httpRequest) + if err != nil { + return ExplainResult{}, fmt.Errorf("send AQL explain request: %w", err) + } + defer func() { + _, _ = io.Copy(io.Discard, response.Body) + _ = response.Body.Close() + }() + + responseBody, err := io.ReadAll(response.Body) + if err != nil { + return ExplainResult{}, fmt.Errorf("read AQL explain response: %w", err) + } + if response.StatusCode >= http.StatusBadRequest { + return ExplainResult{}, fmt.Errorf("AQL explain HTTP %d: %s", response.StatusCode, strings.TrimSpace(string(responseBody))) + } + result, err := ParseExplainResult(responseBody) + if err != nil { + return ExplainResult{}, err + } + return result, nil +} diff --git a/internal/store/arango/explain_client_test.go b/internal/store/arango/explain_client_test.go new file mode 100644 index 0000000..de9993d --- /dev/null +++ b/internal/store/arango/explain_client_test.go @@ -0,0 +1,70 @@ +package arango + +import ( + "bytes" + "context" + "io" + "net/http" + "strings" + "testing" +) + +func TestClientExplainPostsTypedRequest(t *testing.T) { + client := &Client{ + rawURL: "http://arango.test", + dbName: "fhir_proto", + client: &http.Client{Transport: roundTripFunc(func(r *http.Request) (*http.Response, error) { + if r.Method != http.MethodPost { + t.Fatalf("method = %s", r.Method) + } + if r.URL.Path != "/_db/fhir_proto/_api/explain" { + t.Fatalf("path = %s", r.URL.Path) + } + body, err := io.ReadAll(r.Body) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(string(body), `"query":"FOR p IN Patient RETURN p"`) { + t.Fatalf("unexpected request body: %s", body) + } + return &http.Response{ + StatusCode: http.StatusOK, + Header: make(http.Header), + Body: io.NopCloser(bytes.NewBufferString(`{"plan":{"nodes":[{"id":1,"type":"SingletonNode"}]}}`)), + Request: r, + }, nil + })}, + } + result, err := client.Explain(context.Background(), ExplainRequest{Query: "FOR p IN Patient RETURN p"}) + if err != nil { + t.Fatal(err) + } + if result.Plan == nil || len(result.Plan.Nodes) != 1 { + t.Fatalf("unexpected result: %#v", result) + } +} + +func TestClientExplainRejectsHTTPError(t *testing.T) { + client := &Client{ + rawURL: "http://arango.test", + dbName: "fhir_proto", + client: &http.Client{Transport: roundTripFunc(func(r *http.Request) (*http.Response, error) { + return &http.Response{ + StatusCode: http.StatusBadRequest, + Header: make(http.Header), + Body: io.NopCloser(strings.NewReader("bad query")), + Request: r, + }, nil + })}, + } + _, err := client.Explain(context.Background(), ExplainRequest{Query: "FOR p IN Patient RETURN p"}) + if err == nil || !strings.Contains(err.Error(), "HTTP 400") { + t.Fatalf("expected HTTP error, got %v", err) + } +} + +type roundTripFunc func(*http.Request) (*http.Response, error) + +func (fn roundTripFunc) RoundTrip(request *http.Request) (*http.Response, error) { + return fn(request) +} diff --git a/internal/store/arango/explain_test.go b/internal/store/arango/explain_test.go new file mode 100644 index 0000000..a117fd9 --- /dev/null +++ b/internal/store/arango/explain_test.go @@ -0,0 +1,129 @@ +package arango + +import ( + "encoding/json" + "strings" + "testing" +) + +func TestExplainRequestJSON(t *testing.T) { + request := ExplainRequest{ + Query: "FOR d IN @@collection RETURN d", + BindVars: map[string]any{"@collection": "Patient"}, + Options: ExplainOptions{AllPlans: true, MaxNumberOfPlans: 4, Optimizer: OptimizerOptions{Rules: []string{"+use-indexes"}}}, + } + data, err := json.Marshal(request) + if err != nil { + t.Fatal(err) + } + for _, fragment := range []string{`"query"`, `"bindVars"`, `"allPlans":true`, `"maxNumberOfPlans":4`, `"rules":["+use-indexes"]`} { + if !strings.Contains(string(data), fragment) { + t.Errorf("request JSON %s does not contain %s", data, fragment) + } + } +} + +func TestParseExplainResultAndExtractIndexes(t *testing.T) { + payload := []byte(`{ + "plan": { + "nodes": [ + {"type":"IndexNode","id":7,"collection":"Patient","estimatedCost":2.5,"estimatedNrItems":1,"indexes":[ + {"id":"Patient/123","name":"idx_project","type":"persistent","fields":["project"],"unique":false,"sparse":false,"selectivityEstimate":0.2}, + {"id":"Patient/123","name":"idx_project","type":"persistent","fields":["project"]} + ]} + ], + "rules":["use-indexes"], + "collections":[{"name":"Patient","type":"read"}], + "estimatedCost":3.5, + "estimatedNrItems":1 + }, + "warnings":[{"code":1577,"message":"example"}], + "stats":{"plansCreated":1,"rulesExecuted":8,"rulesSkipped":2,"peakMemoryUsage":4096}, + "cacheable":true +}`) + result, err := ParseExplainResult(payload) + if err != nil { + t.Fatal(err) + } + if result.Plan == nil || result.Plan.EstimatedCost != 3.5 || len(result.Warnings) != 1 || result.Stats.PeakMemoryUsage != 4096 { + t.Fatalf("unexpected parsed explain result: %#v", result) + } + uses := ExtractPlanIndexes(result) + if len(uses) != 1 { + t.Fatalf("index uses = %#v", uses) + } + if uses[0].Plan != 0 || uses[0].NodeID != 7 || uses[0].Collection != "Patient" || uses[0].Index.Name != "idx_project" { + t.Fatalf("unexpected index use: %#v", uses[0]) + } + if uses[0].Index.SelectivityEstimate == nil || *uses[0].Index.SelectivityEstimate != 0.2 { + t.Fatalf("missing selectivity estimate: %#v", uses[0].Index) + } +} + +func TestExtractIndexesFromAlternativePlans(t *testing.T) { + result := ExplainResult{Plans: []ExplainPlan{ + {Nodes: []ExplainNode{{ID: 9, Type: "IndexNode", Collection: "Observation", Indexes: ExplainIndexes{{Name: "z"}}}}}, + {Nodes: []ExplainNode{{ID: 2, Type: "IndexNode", Indexes: ExplainIndexes{{Name: "a", Collection: "Specimen"}}}}}, + }} + uses := ExtractPlanIndexes(result) + if len(uses) != 2 || uses[0].Plan != 0 || uses[1].Plan != 1 || uses[1].Collection != "Specimen" { + t.Fatalf("unexpected alternative-plan indexes: %#v", uses) + } +} + +func TestParseExplainResultRejectsErrorsAndInvalidBodies(t *testing.T) { + tests := []struct { + name string + body string + want string + }{ + {"Arango error", `{"error":true,"errorNum":1501,"errorMessage":"parse error","code":400}`, "1501"}, + {"missing plan", `{"warnings":[]}`, "no plan"}, + {"trailing JSON", `{"plan":{"nodes":[]}} {}`, "trailing JSON"}, + {"invalid JSON", `{`, "decode Arango"}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + _, err := ParseExplainResult([]byte(test.body)) + if err == nil || !strings.Contains(err.Error(), test.want) { + t.Fatalf("error = %v; want substring %q", err, test.want) + } + }) + } +} + +func TestParseExplainResultAcceptsObjectIndexes(t *testing.T) { + result, err := ParseExplainResult([]byte(`{ + "plan": {"nodes": [ + {"type":"TraversalNode","id":9,"collection":"fhir_edge","indexes":{"edge":{"id":"edge/1","name":"edge_index","type":"edge","fields":["_from"]}}} + ]} +}`)) + if err != nil { + t.Fatal(err) + } + uses := ExtractPlanIndexes(result) + if len(uses) != 1 || uses[0].Index.Name != "edge_index" { + t.Fatalf("unexpected object indexes: %#v", uses) + } +} + +func TestParseExplainResultAcceptsNestedTraversalIndexes(t *testing.T) { + result, err := ParseExplainResult([]byte(`{ + "plan": {"nodes": [ + {"type":"TraversalNode","id":9,"edgeCollections":["fhir_edge"],"indexes":{ + "base":[{"id":"fhir_edge/2","name":"edge","type":"edge","fields":["_to"]}], + "levels":{"1":[{"id":"fhir_edge/12","name":"project_label","type":"persistent","fields":["project","label"]}]} + }} + ]} +}`)) + if err != nil { + t.Fatal(err) + } + uses := ExtractPlanIndexes(result) + if len(uses) != 2 { + t.Fatalf("nested traversal index uses = %#v", uses) + } + if uses[0].Index.Name != "edge" || uses[1].Index.Name != "project_label" || uses[0].Collection != "fhir_edge" || uses[1].Collection != "fhir_edge" { + t.Fatalf("nested traversal indexes = %#v", uses) + } +} diff --git a/queries/build_focus_ref.aql b/queries/build_focus_ref.aql deleted file mode 100644 index c7b9c1e..0000000 --- a/queries/build_focus_ref.aql +++ /dev/null @@ -1,30 +0,0 @@ -LET page = ( - FOR d IN @@collection - FILTER @lower_key == null OR d._key >= @lower_key - FILTER @upper_key == null OR d._key < @upper_key - FILTER @after_key == null OR d._key > @after_key - SORT d._key - LIMIT @page_size - RETURN d -) -LET inserted = ( - FOR d IN page - FOR focus IN d.payload.focus ? d.payload.focus : [] - LET ref = focus.reference - FILTER ref != null - LET parts = SPLIT(ref, "/") - FILTER LENGTH(parts) == 2 - INSERT { - _key: CONCAT(@collection, "-", d._key, "-focus-", parts[0], "-", parts[1]), - _from: d._id, - _to: CONCAT(parts[0], "/", d.project, "::", parts[1]), - project: d.project, - reference_path: "focus" - } INTO focus_ref OPTIONS { overwriteMode: "replace" } - RETURN 1 -) -RETURN { - docs: LENGTH(page), - edges: LENGTH(inserted), - last_key: LENGTH(page) > 0 ? LAST(page)._key : null -} diff --git a/queries/build_member_ref.aql b/queries/build_member_ref.aql deleted file mode 100644 index a746b8c..0000000 --- a/queries/build_member_ref.aql +++ /dev/null @@ -1,30 +0,0 @@ -LET page = ( - FOR d IN @@collection - FILTER @lower_key == null OR d._key >= @lower_key - FILTER @upper_key == null OR d._key < @upper_key - FILTER @after_key == null OR d._key > @after_key - SORT d._key - LIMIT @page_size - RETURN d -) -LET inserted = ( - FOR d IN page - FOR member IN d.payload.member ? d.payload.member : [] - LET ref = member.entity ? member.entity.reference : null - FILTER ref != null - LET parts = SPLIT(ref, "/") - FILTER LENGTH(parts) == 2 - INSERT { - _key: CONCAT(@collection, "-", d._key, "-member-", parts[0], "-", parts[1]), - _from: d._id, - _to: CONCAT(parts[0], "/", d.project, "::", parts[1]), - project: d.project, - reference_path: "member" - } INTO member_ref OPTIONS { overwriteMode: "replace" } - RETURN 1 -) -RETURN { - docs: LENGTH(page), - edges: LENGTH(inserted), - last_key: LENGTH(page) > 0 ? LAST(page)._key : null -} diff --git a/queries/build_subject_ref.aql b/queries/build_subject_ref.aql deleted file mode 100644 index 1e3a77a..0000000 --- a/queries/build_subject_ref.aql +++ /dev/null @@ -1,29 +0,0 @@ -LET page = ( - FOR d IN @@collection - FILTER @lower_key == null OR d._key >= @lower_key - FILTER @upper_key == null OR d._key < @upper_key - FILTER @after_key == null OR d._key > @after_key - SORT d._key - LIMIT @page_size - RETURN d -) -LET inserted = ( - FOR d IN page - LET ref = d.payload.subject.reference - FILTER ref != null - LET parts = SPLIT(ref, "/") - FILTER LENGTH(parts) == 2 - INSERT { - _key: CONCAT(@collection, "-", d._key, "-subject-", parts[0], "-", parts[1]), - _from: d._id, - _to: CONCAT(parts[0], "/", d.project, "::", parts[1]), - project: d.project, - reference_path: "subject" - } INTO subject_ref OPTIONS { overwriteMode: "replace" } - RETURN 1 -) -RETURN { - docs: LENGTH(page), - edges: LENGTH(inserted), - last_key: LENGTH(page) > 0 ? LAST(page)._key : null -} diff --git a/queries/document_reference_rows.aql b/queries/document_reference_rows.aql deleted file mode 100644 index 2ae97c2..0000000 --- a/queries/document_reference_rows.aql +++ /dev/null @@ -1,200 +0,0 @@ -FOR d IN DocumentReference - FILTER @project == null OR d.project == @project - FILTER @auth_resource_path == null OR d.auth_resource_path == @auth_resource_path - FILTER @lower_key == null OR d._key >= @lower_key - FILTER @upper_key == null OR d._key < @upper_key - FILTER @after_key == null OR d._key > @after_key - SORT d._key - LIMIT @page_size - LET doc = d.payload - - LET raw_subject = FIRST( - FOR v, e IN 1..1 OUTBOUND d subject_ref - FILTER e.reference_path == "subject" - RETURN v - ) - - LET raw_subject_of_subject = raw_subject ? FIRST( - FOR v, e IN 1..1 OUTBOUND raw_subject subject_ref - FILTER e.reference_path == "subject" - RETURN v - ) : null - - LET direct_subject_payload = raw_subject ? raw_subject.payload : null - LET subject_of_subject_payload = raw_subject_of_subject ? raw_subject_of_subject.payload : null - - LET doc_identifier = LENGTH(doc.identifier ? doc.identifier : []) > 0 - ? doc.identifier[0].value - : null - - LET doc_attachment = LENGTH(doc.content ? doc.content : []) > 0 && doc.content[0].attachment - ? doc.content[0].attachment - : {} - - LET based_on_entries = doc.basedOn ? doc.basedOn : [] - LET based_on_values = LENGTH(based_on_entries) == 0 - ? {} - : MERGE( - FOR i IN 0..(LENGTH(based_on_entries) - 1) - LET entry = based_on_entries[i] - FILTER entry.reference != null - RETURN { [CONCAT("basedOn_", TO_STRING(i))]: entry.reference } - ) - - LET direct_subject_flat = direct_subject_payload ? MERGE( - { - [CONCAT(LOWER(direct_subject_payload.resourceType), "_id")]: direct_subject_payload.id, - [CONCAT(LOWER(direct_subject_payload.resourceType), "_resourceType")]: direct_subject_payload.resourceType, - [CONCAT(LOWER(direct_subject_payload.resourceType), "_identifier")]: - LENGTH(direct_subject_payload.identifier ? direct_subject_payload.identifier : []) > 0 - ? direct_subject_payload.identifier[0].value - : null - }, - direct_subject_payload.resourceType == "Patient" - ? { - patient_gender: direct_subject_payload.gender, - patient_birthDate: direct_subject_payload.birthDate, - patient_family_name: direct_subject_payload.name[0].family, - patient_given_name: direct_subject_payload.name[0].given[0] - } - : {}, - direct_subject_payload.resourceType == "Specimen" - ? { - specimen_status: direct_subject_payload.status, - specimen_type: direct_subject_payload.type.coding[0].display, - specimen_parent: LENGTH(direct_subject_payload.parent ? direct_subject_payload.parent : []) > 0 - ? CONCAT_SEPARATOR(",", FOR parent_ref IN direct_subject_payload.parent RETURN LAST(SPLIT(parent_ref.reference, "/"))) - : null - } - : {} - ) : {} - - LET subject_of_subject_flat = subject_of_subject_payload ? MERGE( - { - [CONCAT(LOWER(subject_of_subject_payload.resourceType), "_id")]: subject_of_subject_payload.id, - [CONCAT(LOWER(subject_of_subject_payload.resourceType), "_resourceType")]: subject_of_subject_payload.resourceType, - [CONCAT(LOWER(subject_of_subject_payload.resourceType), "_identifier")]: - LENGTH(subject_of_subject_payload.identifier ? subject_of_subject_payload.identifier : []) > 0 - ? subject_of_subject_payload.identifier[0].value - : null - }, - subject_of_subject_payload.resourceType == "Patient" - ? { - patient_gender: subject_of_subject_payload.gender, - patient_birthDate: subject_of_subject_payload.birthDate, - patient_family_name: subject_of_subject_payload.name[0].family, - patient_given_name: subject_of_subject_payload.name[0].given[0] - } - : {} - ) : {} - - LET observation_value_docs = ( - FOR obs, e IN 1..1 INBOUND d focus_ref - LET payload = obs.payload - LET raw_top_level_key = payload.code && payload.code.text ? payload.code.text : "value" - LET top_level_key_clean = REGEX_REPLACE(raw_top_level_key, "[^A-Za-z0-9_]+", "_") - LET top_level_key = top_level_key_clean == "" - ? "_" - : (REGEX_TEST(top_level_key_clean, "^[0-9]") ? CONCAT("_", top_level_key_clean) : top_level_key_clean) - LET top_level_value = ( - payload.valueQuantity ? CONCAT(TO_STRING(payload.valueQuantity.value), payload.valueQuantity.unit ? CONCAT(" ", payload.valueQuantity.unit) : "") : - payload.valueCodeableConcept ? CONCAT_SEPARATOR(" ", FOR coding IN payload.valueCodeableConcept.coding ? payload.valueCodeableConcept.coding : [] RETURN coding.display ? coding.display : coding.code) : - payload.valueCoding ? payload.valueCoding.display : - payload.valueString ? payload.valueString : - payload.valueCode ? payload.valueCode : - payload.valueBoolean != null ? TO_STRING(payload.valueBoolean) : - payload.valueInteger != null ? TO_STRING(payload.valueInteger) : - payload.valueRange ? CONCAT( - TO_STRING(payload.valueRange.low.value), - " - ", - TO_STRING(payload.valueRange.high.value), - payload.valueRange.low.unit ? CONCAT(" ", payload.valueRange.low.unit) : "" - ) : - payload.valueRatio ? CONCAT( - TO_STRING(payload.valueRatio.numerator.value), - payload.valueRatio.numerator.unit ? CONCAT(" ", payload.valueRatio.numerator.unit) : "", - "/", - TO_STRING(payload.valueRatio.denominator.value), - payload.valueRatio.denominator.unit ? CONCAT(" ", payload.valueRatio.denominator.unit) : "" - ) : - payload.valueSampledData ? payload.valueSampledData.data : - payload.valueTime ? payload.valueTime : - payload.valueDateTime ? payload.valueDateTime : - payload.valuePeriod ? CONCAT(payload.valuePeriod.start, " to ", payload.valuePeriod.end) : - payload.valueUrl ? payload.valueUrl : - payload.valueDate ? payload.valueDate : - payload.valueCount ? payload.valueCount.value : - null - ) - LET component_values = MERGE( - FOR component IN payload.component ? payload.component : [] - LET raw_component_key = component.code && component.code.text ? component.code.text : "component" - LET component_key_clean = REGEX_REPLACE(raw_component_key, "[^A-Za-z0-9_]+", "_") - LET component_key = component_key_clean == "" - ? "_" - : (REGEX_TEST(component_key_clean, "^[0-9]") ? CONCAT("_", component_key_clean) : component_key_clean) - LET component_value = ( - component.valueQuantity ? CONCAT(TO_STRING(component.valueQuantity.value), component.valueQuantity.unit ? CONCAT(" ", component.valueQuantity.unit) : "") : - component.valueCodeableConcept ? CONCAT_SEPARATOR(" ", FOR coding IN component.valueCodeableConcept.coding ? component.valueCodeableConcept.coding : [] RETURN coding.display ? coding.display : coding.code) : - component.valueCoding ? component.valueCoding.display : - component.valueString ? component.valueString : - component.valueCode ? component.valueCode : - component.valueBoolean != null ? TO_STRING(component.valueBoolean) : - component.valueInteger != null ? TO_STRING(component.valueInteger) : - component.valueRange ? CONCAT( - TO_STRING(component.valueRange.low.value), - " - ", - TO_STRING(component.valueRange.high.value), - component.valueRange.low.unit ? CONCAT(" ", component.valueRange.low.unit) : "" - ) : - component.valueRatio ? CONCAT( - TO_STRING(component.valueRatio.numerator.value), - component.valueRatio.numerator.unit ? CONCAT(" ", component.valueRatio.numerator.unit) : "", - "/", - TO_STRING(component.valueRatio.denominator.value), - component.valueRatio.denominator.unit ? CONCAT(" ", component.valueRatio.denominator.unit) : "" - ) : - component.valueSampledData ? component.valueSampledData.data : - component.valueTime ? component.valueTime : - component.valueDateTime ? component.valueDateTime : - component.valuePeriod ? CONCAT(component.valuePeriod.start, " to ", component.valuePeriod.end) : - component.valueUrl ? component.valueUrl : - component.valueDate ? component.valueDate : - component.valueCount ? component.valueCount.value : - null - ) - FILTER component_value != null - RETURN { [component_key]: component_value } - ) - RETURN MERGE( - top_level_value != null ? { [top_level_key]: top_level_value } : {}, - payload.code && payload.code.text ? { observation_code: payload.code.text } : {}, - component_values - ) - ) - - LET row = MERGE( - { - page_key: d._key, - _key: d._key, - project: d.project, - recipe: "flattened_document_reference", - id: doc.id, - resourceType: doc.resourceType, - identifier: doc_identifier, - status: doc.status, - docStatus: doc.docStatus, - description: doc.description, - date: doc.date, - url: doc_attachment.url, - title: doc_attachment.title, - size: doc_attachment.size, - hash: doc_attachment.hash - }, - based_on_values, - direct_subject_flat, - subject_of_subject_flat, - LENGTH(observation_value_docs) > 0 ? MERGE(observation_value_docs) : {} - ) - - RETURN row diff --git a/queries/gdc_case_assay_matrix_arango_rows.aql b/queries/gdc_case_assay_matrix_arango_rows.aql deleted file mode 100644 index 1f14845..0000000 --- a/queries/gdc_case_assay_matrix_arango_rows.aql +++ /dev/null @@ -1,285 +0,0 @@ -FOR p IN Patient - FILTER p.project == @project - FILTER @auth_resource_paths_unrestricted == true OR p.auth_resource_path IN @auth_resource_paths - SORT p._key - - LET patient = p.payload - LET patient_ids = patient.identifier ? patient.identifier : [] - LET patient_exts = patient.extension ? patient.extension : [] - LET case_id = FIRST(FOR id IN patient_ids FILTER CONTAINS(id.system ? id.system : "", "case_id") RETURN id.value) - LET case_submitter_id = FIRST(FOR id IN patient_ids FILTER CONTAINS(id.system ? id.system : "", "case_submitter_id") RETURN id.value) - LET race = FIRST(FOR ext IN patient_exts FILTER CONTAINS(ext.url ? ext.url : "", "us-core-race") RETURN ext.valueString ? ext.valueString : ext.valueCode) - LET ethnicity = FIRST(FOR ext IN patient_exts FILTER CONTAINS(ext.url ? ext.url : "", "us-core-ethnicity") RETURN ext.valueString ? ext.valueString : ext.valueCode) - LET birth_sex = FIRST(FOR ext IN patient_exts FILTER CONTAINS(ext.url ? ext.url : "", "us-core-birthsex") RETURN ext.valueCode ? ext.valueCode : ext.valueString) - LET patient_age = FIRST(FOR ext IN patient_exts FILTER CONTAINS(ext.url ? ext.url : "", "Patient-age") RETURN ext.valueQuantity ? ext.valueQuantity.value : null) - LET patient_study_ref = FIRST(FOR ext IN patient_exts FILTER CONTAINS(ext.url ? ext.url : "", "part-of-study") && ext.valueReference RETURN ext.valueReference.reference) - - LET patient_neighbors = ( - FOR neighbor, edge IN 1..1 INBOUND p fhir_edge - FILTER edge.project == @project - FILTER edge.label == "subject_Patient" - RETURN neighbor - ) - LET specimens = ( - FOR neighbor IN patient_neighbors - FILTER neighbor.resourceType == "Specimen" - SORT neighbor._key - RETURN neighbor - ) - LET specimen_types = UNIQUE( - FOR specimen IN specimens - LET payload = specimen.payload - LET coding = payload.type && payload.type.coding && LENGTH(payload.type.coding) > 0 ? payload.type.coding[0] : null - FILTER coding != null - RETURN coding.display ? coding.display : coding.code - ) - LET preservation_methods = UNIQUE(FLATTEN( - FOR specimen IN specimens - LET payload = specimen.payload - RETURN ( - FOR processing IN payload.processing ? payload.processing : [] - FOR coding IN processing.method && processing.method.coding ? processing.method.coding : [] - FILTER CONTAINS(coding.system ? coding.system : "", "preservation_method") - RETURN coding.display ? coding.display : coding.code - ) - )) - - LET groups = UNIQUE( - FOR specimen IN specimens - FOR group, edge IN 1..1 INBOUND specimen fhir_edge - FILTER edge.project == @project - FILTER edge.label == "member_entity_Specimen" - FILTER group.resourceType == "Group" - RETURN group - ) - LET direct_files = ( - FOR specimen IN specimens - FOR doc, edge IN 1..1 INBOUND specimen fhir_edge - FILTER edge.project == @project - FILTER edge.label == "subject_Specimen" - FILTER doc.resourceType == "DocumentReference" - RETURN doc - ) - LET grouped_files = ( - FOR group IN groups - FOR doc, edge IN 1..1 INBOUND group fhir_edge - FILTER edge.project == @project - FILTER edge.label == "subject_Group" - FILTER doc.resourceType == "DocumentReference" - RETURN doc - ) - LET patient_files = ( - FOR neighbor IN patient_neighbors - FILTER neighbor.resourceType == "DocumentReference" - RETURN neighbor - ) - LET files = UNIQUE(APPEND(APPEND(direct_files, grouped_files), patient_files)) - - LET file_summaries = ( - FOR doc_ref IN files - LET doc = doc_ref.payload - LET doc_ids = doc.identifier ? doc.identifier : [] - LET content = LENGTH(doc.content ? doc.content : []) > 0 ? doc.content[0] : {} - LET attachment = content.attachment ? content.attachment : {} - LET type_codings = doc.type && doc.type.coding ? doc.type.coding : [] - LET category_codings = FLATTEN( - FOR category IN doc.category ? doc.category : [] - RETURN category.coding ? category.coding : [] - ) - LET file_id = FIRST(FOR id IN doc_ids FILTER CONTAINS(id.system ? id.system : "", "file_id") RETURN id.value) - LET data_format = FIRST(FOR coding IN type_codings RETURN coding.display ? coding.display : coding.code) - LET data_category = FIRST(FOR coding IN category_codings FILTER CONTAINS(coding.system ? coding.system : "", "data_category") RETURN coding.display ? coding.display : coding.code) - LET data_type = FIRST(FOR coding IN category_codings FILTER CONTAINS(coding.system ? coding.system : "", "data_type") RETURN coding.display ? coding.display : coding.code) - LET experimental_strategy = FIRST(FOR coding IN category_codings FILTER CONTAINS(coding.system ? coding.system : "", "experimental_strategy") RETURN coding.display ? coding.display : coding.code) - LET workflow_type = FIRST(FOR coding IN category_codings FILTER CONTAINS(coding.system ? coding.system : "", "workflow_type") RETURN coding.display ? coding.display : coding.code) - LET platform = FIRST(FOR coding IN category_codings FILTER CONTAINS(coding.system ? coding.system : "", "platform") RETURN coding.display ? coding.display : coding.code) - LET access = FIRST(FOR coding IN category_codings FILTER CONTAINS(coding.system ? coding.system : "", "access") RETURN coding.display ? coding.display : coding.code) - RETURN { - file_did: doc.id, - file_id: file_id, - file_name: attachment.title, - file_url: attachment.url, - file_size: attachment.size, - data_category: data_category, - data_type: data_type, - data_format: data_format, - experimental_strategy: experimental_strategy, - workflow_type: workflow_type, - platform: platform, - access: access, - is_snv: data_category == "Simple Nucleotide Variation", - is_annotated_somatic: data_category == "Simple Nucleotide Variation" && data_type == "Annotated Somatic Mutation", - is_raw_somatic: data_category == "Simple Nucleotide Variation" && data_type == "Raw Simple Somatic Mutation", - is_expression: data_category == "Transcriptome Profiling" && data_type == "Gene Expression Quantification", - is_fusion: data_type == "Transcript Fusion", - is_cnv: data_category == "Copy Number Variation", - is_methylation: data_category == "DNA Methylation", - is_slide: data_type == "Slide Image", - is_aligned_reads: data_type == "Aligned Reads", - is_clinical: data_category == "Clinical", - is_wxs: experimental_strategy == "WXS", - is_wgs: experimental_strategy == "WGS", - is_rnaseq: experimental_strategy == "RNA-Seq" - } - ) - - LET file_rollup = MERGE( - FOR file IN file_summaries - COLLECT AGGREGATE - file_count = SUM(1), - snv_file_count = SUM(file.is_snv ? 1 : 0), - annotated_somatic_file_count = SUM(file.is_annotated_somatic ? 1 : 0), - raw_somatic_file_count = SUM(file.is_raw_somatic ? 1 : 0), - expression_file_count = SUM(file.is_expression ? 1 : 0), - fusion_file_count = SUM(file.is_fusion ? 1 : 0), - cnv_file_count = SUM(file.is_cnv ? 1 : 0), - methylation_file_count = SUM(file.is_methylation ? 1 : 0), - slide_file_count = SUM(file.is_slide ? 1 : 0), - aligned_read_file_count = SUM(file.is_aligned_reads ? 1 : 0), - clinical_file_count = SUM(file.is_clinical ? 1 : 0), - has_wxs_count = SUM(file.is_wxs ? 1 : 0), - has_wgs_count = SUM(file.is_wgs ? 1 : 0), - has_rnaseq_count = SUM(file.is_rnaseq ? 1 : 0) - RETURN { - file_count: file_count, - snv_file_count: snv_file_count, - annotated_somatic_file_count: annotated_somatic_file_count, - raw_somatic_file_count: raw_somatic_file_count, - expression_file_count: expression_file_count, - fusion_file_count: fusion_file_count, - cnv_file_count: cnv_file_count, - methylation_file_count: methylation_file_count, - slide_file_count: slide_file_count, - aligned_read_file_count: aligned_read_file_count, - clinical_file_count: clinical_file_count, - has_snv: snv_file_count > 0, - has_expression: expression_file_count > 0, - has_fusion: fusion_file_count > 0, - has_cnv: cnv_file_count > 0, - has_methylation: methylation_file_count > 0, - has_slide: slide_file_count > 0, - has_wxs: has_wxs_count > 0, - has_wgs: has_wgs_count > 0, - has_rnaseq: has_rnaseq_count > 0 - } - ) - LET data_categories = UNIQUE(FOR f IN file_summaries FILTER f.data_category != null RETURN f.data_category) - LET data_types = UNIQUE(FOR f IN file_summaries FILTER f.data_type != null RETURN f.data_type) - LET experimental_strategies = UNIQUE(FOR f IN file_summaries FILTER f.experimental_strategy != null RETURN f.experimental_strategy) - LET workflow_types = UNIQUE(FOR f IN file_summaries FILTER f.workflow_type != null RETURN f.workflow_type) - LET representative_snv_files = SLICE(FOR f IN file_summaries FILTER f.is_snv RETURN f, 0, 5) - LET representative_expression_files = SLICE(FOR f IN file_summaries FILTER f.is_expression RETURN f, 0, 5) - LET representative_cnv_files = SLICE(FOR f IN file_summaries FILTER f.is_cnv RETURN f, 0, 5) - LET representative_methylation_files = SLICE(FOR f IN file_summaries FILTER f.is_methylation RETURN f, 0, 5) - LET representative_slide_files = SLICE(FOR f IN file_summaries FILTER f.is_slide RETURN f, 0, 5) - - LET conditions = ( - FOR neighbor IN patient_neighbors - FILTER neighbor.resourceType == "Condition" - SORT neighbor._key - RETURN neighbor.payload - ) - LET primary_condition = FIRST(conditions) - LET primary_condition_ids = primary_condition ? primary_condition.identifier ? primary_condition.identifier : [] : [] - LET primary_condition_codings = primary_condition && primary_condition.code && primary_condition.code.coding ? primary_condition.code.coding : [] - LET primary_diagnosis_preferred = FIRST( - FOR coding IN primary_condition_codings - FILTER CONTAINS(coding.system ? coding.system : "", "primary_diagnosis") - RETURN coding.display ? coding.display : coding.code - ) - LET primary_diagnosis = primary_diagnosis_preferred ? primary_diagnosis_preferred : FIRST( - FOR coding IN primary_condition_codings - RETURN coding.display ? coding.display : coding.code - ) - LET diagnosis_id = FIRST(FOR id IN primary_condition_ids FILTER CONTAINS(id.system ? id.system : "", "diagnosis_id") RETURN id.value) - LET diagnosis_body_site = FIRST( - FOR body_site IN primary_condition ? primary_condition.bodySite ? primary_condition.bodySite : [] : [] - FOR coding IN body_site.coding ? body_site.coding : [] - RETURN coding.display ? coding.display : coding.code - ) - - LET research_subject_payload = FIRST( - FOR neighbor IN patient_neighbors - FILTER neighbor.resourceType == "ResearchSubject" - SORT neighbor._key - RETURN neighbor.payload - ) - LET study_ref = research_subject_payload && research_subject_payload.study ? research_subject_payload.study.reference : patient_study_ref - LET study_parts = study_ref ? SPLIT(study_ref, "/") : [] - LET study_id = LENGTH(study_parts) == 2 ? study_parts[1] : null - LET study = study_id ? DOCUMENT(CONCAT("ResearchStudy/", study_id)) : null - LET study_payload = study ? study.payload : null - LET study_ids = study_payload ? study_payload.identifier ? study_payload.identifier : [] : [] - - LET treatments = ( - FOR neighbor IN patient_neighbors - FILTER neighbor.resourceType == "MedicationAdministration" - RETURN neighbor.payload - ) - LET treatment_categories = UNIQUE(FLATTEN( - FOR treatment IN treatments - RETURN ( - FOR category IN treatment.category ? treatment.category : [] - FOR coding IN category.coding ? category.coding : [] - RETURN coding.display ? coding.display : coding.code - ) - )) - - RETURN { - _key: p._key, - project: p.project, - recipe: "gdc_case_assay_matrix", - case_fhir_id: patient.id, - case_id: case_id, - case_submitter_id: case_submitter_id, - gender: patient.gender, - deceased: patient.deceasedBoolean, - birth_sex: birth_sex, - race: race, - ethnicity: ethnicity, - patient_age: patient_age, - diagnosis_count: LENGTH(conditions), - diagnosis_id: diagnosis_id, - primary_diagnosis: primary_diagnosis, - diagnosis_body_site: diagnosis_body_site, - research_subject_id: research_subject_payload ? research_subject_payload.id : null, - research_subject_status: research_subject_payload ? research_subject_payload.status : null, - study_id: study_payload ? study_payload.id : null, - study_identifier: FIRST(FOR id IN study_ids RETURN id.value), - study_name: study_payload ? study_payload.name : null, - study_title: study_payload ? study_payload.title : null, - specimen_count: LENGTH(specimens), - specimen_types: specimen_types, - preservation_methods: preservation_methods, - file_count: file_rollup.file_count ? file_rollup.file_count : 0, - data_categories: data_categories, - data_types: data_types, - experimental_strategies: experimental_strategies, - workflow_types: workflow_types, - has_snv: file_rollup.has_snv ? file_rollup.has_snv : false, - snv_file_count: file_rollup.snv_file_count ? file_rollup.snv_file_count : 0, - annotated_somatic_file_count: file_rollup.annotated_somatic_file_count ? file_rollup.annotated_somatic_file_count : 0, - raw_somatic_file_count: file_rollup.raw_somatic_file_count ? file_rollup.raw_somatic_file_count : 0, - has_wxs: file_rollup.has_wxs ? file_rollup.has_wxs : false, - has_wgs: file_rollup.has_wgs ? file_rollup.has_wgs : false, - has_rnaseq: file_rollup.has_rnaseq ? file_rollup.has_rnaseq : false, - has_expression: file_rollup.has_expression ? file_rollup.has_expression : false, - expression_file_count: file_rollup.expression_file_count ? file_rollup.expression_file_count : 0, - has_fusion: file_rollup.has_fusion ? file_rollup.has_fusion : false, - fusion_file_count: file_rollup.fusion_file_count ? file_rollup.fusion_file_count : 0, - has_cnv: file_rollup.has_cnv ? file_rollup.has_cnv : false, - cnv_file_count: file_rollup.cnv_file_count ? file_rollup.cnv_file_count : 0, - has_methylation: file_rollup.has_methylation ? file_rollup.has_methylation : false, - methylation_file_count: file_rollup.methylation_file_count ? file_rollup.methylation_file_count : 0, - has_slide: file_rollup.has_slide ? file_rollup.has_slide : false, - slide_file_count: file_rollup.slide_file_count ? file_rollup.slide_file_count : 0, - aligned_read_file_count: file_rollup.aligned_read_file_count ? file_rollup.aligned_read_file_count : 0, - clinical_file_count: file_rollup.clinical_file_count ? file_rollup.clinical_file_count : 0, - treatment_count: LENGTH(treatments), - treatment_categories: treatment_categories, - representative_snv_files: representative_snv_files, - representative_expression_files: representative_expression_files, - representative_cnv_files: representative_cnv_files, - representative_methylation_files: representative_methylation_files, - representative_slide_files: representative_slide_files - } diff --git a/queries/gdc_case_assay_matrix_rows.aql b/queries/gdc_case_assay_matrix_rows.aql deleted file mode 100644 index 1a97a62..0000000 --- a/queries/gdc_case_assay_matrix_rows.aql +++ /dev/null @@ -1,270 +0,0 @@ -FOR p IN Patient - FILTER @lower_key == null OR p._key >= @lower_key - FILTER @upper_key == null OR p._key < @upper_key - FILTER @after_key == null OR p._key > @after_key - SORT p._key - LIMIT @page_size - - LET patient = p.payload - LET patient_ref = CONCAT("Patient/", patient.id) - LET patient_ids = patient.identifier ? patient.identifier : [] - LET patient_exts = patient.extension ? patient.extension : [] - LET case_id = FIRST(FOR id IN patient_ids FILTER CONTAINS(id.system ? id.system : "", "case_id") RETURN id.value) - LET case_submitter_id = FIRST(FOR id IN patient_ids FILTER CONTAINS(id.system ? id.system : "", "case_submitter_id") RETURN id.value) - LET race = FIRST(FOR ext IN patient_exts FILTER CONTAINS(ext.url ? ext.url : "", "us-core-race") RETURN ext.valueString ? ext.valueString : ext.valueCode) - LET ethnicity = FIRST(FOR ext IN patient_exts FILTER CONTAINS(ext.url ? ext.url : "", "us-core-ethnicity") RETURN ext.valueString ? ext.valueString : ext.valueCode) - LET birth_sex = FIRST(FOR ext IN patient_exts FILTER CONTAINS(ext.url ? ext.url : "", "us-core-birthsex") RETURN ext.valueCode ? ext.valueCode : ext.valueString) - LET patient_age = FIRST(FOR ext IN patient_exts FILTER CONTAINS(ext.url ? ext.url : "", "Patient-age") RETURN ext.valueQuantity ? ext.valueQuantity.value : null) - LET patient_study_ref = FIRST(FOR ext IN patient_exts FILTER CONTAINS(ext.url ? ext.url : "", "part-of-study") && ext.valueReference RETURN ext.valueReference.reference) - - LET specimens = ( - FOR specimen IN 1..1 INBOUND p subject_ref - FILTER specimen.resourceType == "Specimen" - SORT specimen._key - RETURN specimen - ) - LET specimen_refs = ( - FOR specimen IN specimens - RETURN CONCAT("Specimen/", specimen.payload.id) - ) - LET specimen_types = UNIQUE( - FOR specimen IN specimens - LET payload = specimen.payload - LET coding = payload.type && payload.type.coding && LENGTH(payload.type.coding) > 0 ? payload.type.coding[0] : null - FILTER coding != null - RETURN coding.display ? coding.display : coding.code - ) - LET preservation_methods = UNIQUE(FLATTEN( - FOR specimen IN specimens - LET payload = specimen.payload - RETURN ( - FOR processing IN payload.processing ? payload.processing : [] - FOR coding IN processing.method && processing.method.coding ? processing.method.coding : [] - FILTER CONTAINS(coding.system ? coding.system : "", "preservation_method") - RETURN coding.display ? coding.display : coding.code - ) - )) - - LET groups = UNIQUE( - FOR specimen IN specimens - FOR group IN 1..1 INBOUND specimen member_ref - FILTER group.resourceType == "Group" - RETURN group - ) - LET direct_files = ( - FOR specimen IN specimens - FOR doc IN 1..1 INBOUND specimen subject_ref - FILTER doc.resourceType == "DocumentReference" - RETURN doc - ) - LET grouped_files = ( - FOR group IN groups - FOR doc IN 1..1 INBOUND group subject_ref - FILTER doc.resourceType == "DocumentReference" - RETURN doc - ) - LET patient_files = ( - FOR doc IN 1..1 INBOUND p subject_ref - FILTER doc.resourceType == "DocumentReference" - RETURN doc - ) - LET files = UNIQUE(APPEND(APPEND(direct_files, grouped_files), patient_files)) - - LET file_summaries = ( - FOR doc_ref IN files - LET doc = doc_ref.payload - LET doc_ids = doc.identifier ? doc.identifier : [] - LET content = LENGTH(doc.content ? doc.content : []) > 0 ? doc.content[0] : {} - LET attachment = content.attachment ? content.attachment : {} - LET type_codings = doc.type && doc.type.coding ? doc.type.coding : [] - LET category_codings = FLATTEN( - FOR category IN doc.category ? doc.category : [] - RETURN category.coding ? category.coding : [] - ) - LET file_id = FIRST(FOR id IN doc_ids FILTER CONTAINS(id.system ? id.system : "", "file_id") RETURN id.value) - LET data_format = FIRST(FOR coding IN type_codings RETURN coding.display ? coding.display : coding.code) - LET data_category = FIRST(FOR coding IN category_codings FILTER CONTAINS(coding.system ? coding.system : "", "data_category") RETURN coding.display ? coding.display : coding.code) - LET data_type = FIRST(FOR coding IN category_codings FILTER CONTAINS(coding.system ? coding.system : "", "data_type") RETURN coding.display ? coding.display : coding.code) - LET experimental_strategy = FIRST(FOR coding IN category_codings FILTER CONTAINS(coding.system ? coding.system : "", "experimental_strategy") RETURN coding.display ? coding.display : coding.code) - LET workflow_type = FIRST(FOR coding IN category_codings FILTER CONTAINS(coding.system ? coding.system : "", "workflow_type") RETURN coding.display ? coding.display : coding.code) - LET platform = FIRST(FOR coding IN category_codings FILTER CONTAINS(coding.system ? coding.system : "", "platform") RETURN coding.display ? coding.display : coding.code) - LET access = FIRST(FOR coding IN category_codings FILTER CONTAINS(coding.system ? coding.system : "", "access") RETURN coding.display ? coding.display : coding.code) - RETURN { - file_did: doc.id, - file_id: file_id, - file_name: attachment.title, - file_url: attachment.url, - file_size: attachment.size, - data_category: data_category, - data_type: data_type, - data_format: data_format, - experimental_strategy: experimental_strategy, - workflow_type: workflow_type, - platform: platform, - access: access - } - ) - - LET snv_files = ( - FOR f IN file_summaries - FILTER f.data_category == "Simple Nucleotide Variation" - RETURN f - ) - LET annotated_somatic_files = ( - FOR f IN snv_files - FILTER f.data_type == "Annotated Somatic Mutation" - RETURN f - ) - LET raw_somatic_files = ( - FOR f IN snv_files - FILTER f.data_type == "Raw Simple Somatic Mutation" - RETURN f - ) - LET expression_files = ( - FOR f IN file_summaries - FILTER f.data_category == "Transcriptome Profiling" - FILTER f.data_type == "Gene Expression Quantification" - RETURN f - ) - LET fusion_files = ( - FOR f IN file_summaries - FILTER f.data_type == "Transcript Fusion" - RETURN f - ) - LET cnv_files = ( - FOR f IN file_summaries - FILTER f.data_category == "Copy Number Variation" - RETURN f - ) - LET methylation_files = ( - FOR f IN file_summaries - FILTER f.data_category == "DNA Methylation" - RETURN f - ) - LET slide_files = ( - FOR f IN file_summaries - FILTER f.data_type == "Slide Image" - RETURN f - ) - LET aligned_read_files = ( - FOR f IN file_summaries - FILTER f.data_type == "Aligned Reads" - RETURN f - ) - LET clinical_files = ( - FOR f IN file_summaries - FILTER f.data_category == "Clinical" - RETURN f - ) - - LET conditions = ( - FOR c IN 1..1 INBOUND p subject_ref - FILTER c.resourceType == "Condition" - SORT c._key - RETURN c.payload - ) - LET primary_condition = FIRST(conditions) - LET primary_condition_ids = primary_condition ? primary_condition.identifier ? primary_condition.identifier : [] : [] - LET primary_condition_codings = primary_condition && primary_condition.code && primary_condition.code.coding ? primary_condition.code.coding : [] - LET primary_diagnosis_preferred = FIRST( - FOR coding IN primary_condition_codings - FILTER CONTAINS(coding.system ? coding.system : "", "primary_diagnosis") - RETURN coding.display ? coding.display : coding.code - ) - LET primary_diagnosis = primary_diagnosis_preferred ? primary_diagnosis_preferred : FIRST( - FOR coding IN primary_condition_codings - RETURN coding.display ? coding.display : coding.code - ) - LET diagnosis_id = FIRST(FOR id IN primary_condition_ids FILTER CONTAINS(id.system ? id.system : "", "diagnosis_id") RETURN id.value) - LET diagnosis_body_site = FIRST( - FOR body_site IN primary_condition ? primary_condition.bodySite ? primary_condition.bodySite : [] : [] - FOR coding IN body_site.coding ? body_site.coding : [] - RETURN coding.display ? coding.display : coding.code - ) - - LET research_subject = FIRST( - FOR rs IN 1..1 INBOUND p subject_ref - FILTER rs.resourceType == "ResearchSubject" - SORT rs._key - RETURN rs.payload - ) - LET study_ref = research_subject && research_subject.study ? research_subject.study.reference : patient_study_ref - LET study_parts = study_ref ? SPLIT(study_ref, "/") : [] - LET study_id = LENGTH(study_parts) == 2 ? study_parts[1] : null - LET study = study_id ? DOCUMENT(CONCAT("ResearchStudy/", p.project, "::", study_id)) : null - LET study_payload = study ? study.payload : null - LET study_ids = study_payload ? study_payload.identifier ? study_payload.identifier : [] : [] - - LET treatments = ( - FOR ma IN 1..1 INBOUND p subject_ref - FILTER ma.resourceType == "MedicationAdministration" - RETURN ma.payload - ) - LET treatment_categories = UNIQUE(FLATTEN( - FOR treatment IN treatments - RETURN ( - FOR category IN treatment.category ? treatment.category : [] - FOR coding IN category.coding ? category.coding : [] - RETURN coding.display ? coding.display : coding.code - ) - )) - - RETURN { - page_key: p._key, - _key: p._key, - project: p.project, - recipe: "gdc_case_assay_matrix", - case_fhir_id: patient.id, - case_id: case_id, - case_submitter_id: case_submitter_id, - gender: patient.gender, - deceased: patient.deceasedBoolean, - birth_sex: birth_sex, - race: race, - ethnicity: ethnicity, - patient_age: patient_age, - diagnosis_count: LENGTH(conditions), - diagnosis_id: diagnosis_id, - primary_diagnosis: primary_diagnosis, - diagnosis_body_site: diagnosis_body_site, - research_subject_id: research_subject ? research_subject.id : null, - research_subject_status: research_subject ? research_subject.status : null, - study_id: study_payload ? study_payload.id : null, - study_identifier: FIRST(FOR id IN study_ids RETURN id.value), - study_name: study_payload ? study_payload.name : null, - study_title: study_payload ? study_payload.title : null, - specimen_count: LENGTH(specimens), - specimen_types: specimen_types, - preservation_methods: preservation_methods, - file_count: LENGTH(file_summaries), - data_categories: UNIQUE(FOR f IN file_summaries FILTER f.data_category != null RETURN f.data_category), - data_types: UNIQUE(FOR f IN file_summaries FILTER f.data_type != null RETURN f.data_type), - experimental_strategies: UNIQUE(FOR f IN file_summaries FILTER f.experimental_strategy != null RETURN f.experimental_strategy), - workflow_types: UNIQUE(FOR f IN file_summaries FILTER f.workflow_type != null RETURN f.workflow_type), - has_snv: LENGTH(snv_files) > 0, - snv_file_count: LENGTH(snv_files), - annotated_somatic_file_count: LENGTH(annotated_somatic_files), - raw_somatic_file_count: LENGTH(raw_somatic_files), - has_wxs: LENGTH(FOR f IN file_summaries FILTER f.experimental_strategy == "WXS" RETURN 1) > 0, - has_wgs: LENGTH(FOR f IN file_summaries FILTER f.experimental_strategy == "WGS" RETURN 1) > 0, - has_rnaseq: LENGTH(FOR f IN file_summaries FILTER f.experimental_strategy == "RNA-Seq" RETURN 1) > 0, - has_expression: LENGTH(expression_files) > 0, - expression_file_count: LENGTH(expression_files), - has_fusion: LENGTH(fusion_files) > 0, - fusion_file_count: LENGTH(fusion_files), - has_cnv: LENGTH(cnv_files) > 0, - cnv_file_count: LENGTH(cnv_files), - has_methylation: LENGTH(methylation_files) > 0, - methylation_file_count: LENGTH(methylation_files), - has_slide: LENGTH(slide_files) > 0, - slide_file_count: LENGTH(slide_files), - aligned_read_file_count: LENGTH(aligned_read_files), - clinical_file_count: LENGTH(clinical_files), - treatment_count: LENGTH(treatments), - treatment_categories: treatment_categories, - representative_snv_files: SLICE(snv_files, 0, 5), - representative_expression_files: SLICE(expression_files, 0, 5), - representative_cnv_files: SLICE(cnv_files, 0, 5), - representative_methylation_files: SLICE(methylation_files, 0, 5), - representative_slide_files: SLICE(slide_files, 0, 5) - } diff --git a/queries/gdc_file_sample_matrix_rows.aql b/queries/gdc_file_sample_matrix_rows.aql deleted file mode 100644 index 8f2fe35..0000000 --- a/queries/gdc_file_sample_matrix_rows.aql +++ /dev/null @@ -1,193 +0,0 @@ -FOR d IN DocumentReference - FILTER @project == null OR d.project == @project - FILTER @auth_resource_path == null OR d.auth_resource_path == @auth_resource_path - FILTER @lower_key == null OR d._key >= @lower_key - FILTER @upper_key == null OR d._key < @upper_key - FILTER @after_key == null OR d._key > @after_key - SORT d._key - LIMIT @page_size - - LET doc = d.payload - LET doc_ids = doc.identifier ? doc.identifier : [] - LET doc_content = LENGTH(doc.content ? doc.content : []) > 0 ? doc.content[0] : {} - LET attachment = doc_content.attachment ? doc_content.attachment : {} - LET doc_category_codings = FLATTEN( - FOR category IN doc.category ? doc.category : [] - RETURN category.coding ? category.coding : [] - ) - LET doc_type_codings = doc.type && doc.type.coding ? doc.type.coding : [] - LET file_id = FIRST(FOR id IN doc_ids FILTER CONTAINS(id.system ? id.system : "", "file_id") RETURN id.value) - LET file_submitter_id = FIRST(FOR id IN doc_ids FILTER CONTAINS(id.system ? id.system : "", "submitter_id") RETURN id.value) - LET data_format = FIRST(FOR coding IN doc_type_codings RETURN coding.display ? coding.display : coding.code) - LET data_category = FIRST(FOR coding IN doc_category_codings FILTER CONTAINS(coding.system ? coding.system : "", "data_category") RETURN coding.display ? coding.display : coding.code) - LET data_type = FIRST(FOR coding IN doc_category_codings FILTER CONTAINS(coding.system ? coding.system : "", "data_type") RETURN coding.display ? coding.display : coding.code) - LET experimental_strategy = FIRST(FOR coding IN doc_category_codings FILTER CONTAINS(coding.system ? coding.system : "", "experimental_strategy") RETURN coding.display ? coding.display : coding.code) - LET platform = FIRST(FOR coding IN doc_category_codings FILTER CONTAINS(coding.system ? coding.system : "", "platform") RETURN coding.display ? coding.display : coding.code) - LET workflow_type = FIRST(FOR coding IN doc_category_codings FILTER CONTAINS(coding.system ? coding.system : "", "workflow_type") RETURN coding.display ? coding.display : coding.code) - LET access = FIRST(FOR coding IN doc_category_codings FILTER CONTAINS(coding.system ? coding.system : "", "access") RETURN coding.display ? coding.display : coding.code) - - LET subject_ref = doc.subject ? doc.subject.reference : null - LET subject_parts = subject_ref ? SPLIT(subject_ref, "/") : [] - LET subject_type = LENGTH(subject_parts) == 2 ? subject_parts[0] : null - LET subject_id = LENGTH(subject_parts) == 2 ? subject_parts[1] : null - LET subject_doc = subject_type && subject_id ? DOCUMENT(CONCAT(subject_type, "/", d.project, "::", subject_id)) : null - - LET group_payload = subject_doc && subject_doc.payload.resourceType == "Group" ? subject_doc.payload : null - LET group_ids = group_payload ? group_payload.identifier ? group_payload.identifier : [] : [] - LET group_members = group_payload ? group_payload.member ? group_payload.member : [] : [] - LET group_member_refs = ( - FOR member IN group_members - FILTER member.entity && member.entity.reference - RETURN member.entity.reference - ) - LET direct_specimen_refs = subject_type == "Specimen" ? [subject_ref] : [] - LET specimen_refs = LENGTH(group_member_refs) > 0 ? group_member_refs : direct_specimen_refs - LET specimen_member_indexes = LENGTH(specimen_refs) == 0 ? [-1] : 0..(LENGTH(specimen_refs) - 1) - - FOR specimen_member_index IN specimen_member_indexes - LET specimen_ref = specimen_member_index < 0 ? null : specimen_refs[specimen_member_index] - LET specimen_parts = specimen_ref ? SPLIT(specimen_ref, "/") : [] - LET specimen_id = LENGTH(specimen_parts) == 2 ? specimen_parts[1] : null - LET specimen = specimen_id ? DOCUMENT(CONCAT("Specimen/", d.project, "::", specimen_id)) : null - LET specimen_payload = specimen ? specimen.payload : null - LET specimen_ids = specimen_payload ? specimen_payload.identifier ? specimen_payload.identifier : [] : [] - LET specimen_type = specimen_payload && specimen_payload.type && specimen_payload.type.coding && LENGTH(specimen_payload.type.coding) > 0 - ? (specimen_payload.type.coding[0].display ? specimen_payload.type.coding[0].display : specimen_payload.type.coding[0].code) - : null - LET specimen_processing_codings = specimen_payload ? FLATTEN( - FOR processing IN specimen_payload.processing ? specimen_payload.processing : [] - RETURN processing.method && processing.method.coding ? processing.method.coding : [] - ) : [] - LET preservation_method = FIRST( - FOR coding IN specimen_processing_codings - FILTER CONTAINS(coding.system ? coding.system : "", "preservation_method") - RETURN coding.display ? coding.display : coding.code - ) - LET specimen_parent_refs = specimen_payload ? ( - FOR parent IN specimen_payload.parent ? specimen_payload.parent : [] - FILTER parent.reference != null - RETURN parent.reference - ) : [] - LET patient_ref = specimen_payload && specimen_payload.subject ? specimen_payload.subject.reference : (subject_type == "Patient" ? subject_ref : null) - LET patient_parts = patient_ref ? SPLIT(patient_ref, "/") : [] - LET patient_id = LENGTH(patient_parts) == 2 ? patient_parts[1] : null - LET patient = patient_id ? DOCUMENT(CONCAT("Patient/", d.project, "::", patient_id)) : null - LET patient_payload = patient ? patient.payload : null - LET patient_ids = patient_payload ? patient_payload.identifier ? patient_payload.identifier : [] : [] - LET patient_exts = patient_payload ? patient_payload.extension ? patient_payload.extension : [] : [] - LET case_id = FIRST(FOR id IN patient_ids FILTER CONTAINS(id.system ? id.system : "", "case_id") RETURN id.value) - LET case_submitter_id = FIRST(FOR id IN patient_ids FILTER CONTAINS(id.system ? id.system : "", "case_submitter_id") RETURN id.value) - LET race = FIRST(FOR ext IN patient_exts FILTER CONTAINS(ext.url ? ext.url : "", "us-core-race") RETURN ext.valueString ? ext.valueString : ext.valueCode) - LET ethnicity = FIRST(FOR ext IN patient_exts FILTER CONTAINS(ext.url ? ext.url : "", "us-core-ethnicity") RETURN ext.valueString ? ext.valueString : ext.valueCode) - LET birth_sex = FIRST(FOR ext IN patient_exts FILTER CONTAINS(ext.url ? ext.url : "", "us-core-birthsex") RETURN ext.valueCode ? ext.valueCode : ext.valueString) - LET patient_study_ref = FIRST(FOR ext IN patient_exts FILTER CONTAINS(ext.url ? ext.url : "", "part-of-study") && ext.valueReference RETURN ext.valueReference.reference) - - LET condition = patient_ref ? FIRST( - FOR c IN Condition - FILTER c.project == d.project - FILTER c.payload.subject.reference == patient_ref - SORT c._key - LIMIT 1 - RETURN c.payload - ) : null - LET condition_ids = condition ? condition.identifier ? condition.identifier : [] : [] - LET condition_code_codings = condition && condition.code && condition.code.coding ? condition.code.coding : [] - LET primary_diagnosis_preferred = FIRST( - FOR coding IN condition_code_codings - FILTER CONTAINS(coding.system ? coding.system : "", "primary_diagnosis") - RETURN coding.display ? coding.display : coding.code - ) - LET primary_diagnosis = primary_diagnosis_preferred ? primary_diagnosis_preferred : FIRST( - FOR coding IN condition_code_codings - RETURN coding.display ? coding.display : coding.code - ) - LET diagnosis_id = FIRST(FOR id IN condition_ids FILTER CONTAINS(id.system ? id.system : "", "diagnosis_id") RETURN id.value) - LET diagnosis_body_site = FIRST( - FOR body_site IN condition ? condition.bodySite ? condition.bodySite : [] : [] - FOR coding IN body_site.coding ? body_site.coding : [] - RETURN coding.display ? coding.display : coding.code - ) - LET onset_age = condition && condition.onsetAge ? condition.onsetAge.value : null - - LET research_subject = patient_ref ? FIRST( - FOR rs IN ResearchSubject - FILTER rs.project == d.project - FILTER rs.payload.subject.reference == patient_ref - SORT rs._key - LIMIT 1 - RETURN rs.payload - ) : null - LET study_ref = research_subject && research_subject.study ? research_subject.study.reference : patient_study_ref - LET study_parts = study_ref ? SPLIT(study_ref, "/") : [] - LET study_id = LENGTH(study_parts) == 2 ? study_parts[1] : null - LET study = study_id ? DOCUMENT(CONCAT("ResearchStudy/", d.project, "::", study_id)) : null - LET study_payload = study ? study.payload : null - LET study_ids = study_payload ? study_payload.identifier ? study_payload.identifier : [] : [] - LET study_identifier = FIRST(FOR id IN study_ids RETURN id.value) - - LET treatments = patient_ref ? ( - FOR ma IN MedicationAdministration - FILTER ma.project == d.project - FILTER ma.payload.subject.reference == patient_ref - RETURN ma.payload - ) : [] - LET treatment_categories = UNIQUE(FLATTEN( - FOR treatment IN treatments - RETURN ( - FOR category IN treatment.category ? treatment.category : [] - FOR coding IN category.coding ? category.coding : [] - RETURN coding.display ? coding.display : coding.code - ) - )) - - RETURN { - page_key: d._key, - _key: CONCAT(d._key, "::", specimen_id ? specimen_id : "no_specimen"), - project: d.project, - recipe: "gdc_file_sample_matrix", - file_did: doc.id, - file_id: file_id, - file_submitter_id: file_submitter_id, - file_name: attachment.title, - file_url: attachment.url, - file_size: attachment.size, - file_hash: attachment.hash, - file_status: doc.status, - file_date: doc.date, - data_category: data_category, - data_type: data_type, - data_format: data_format, - experimental_strategy: experimental_strategy, - platform: platform, - workflow_type: workflow_type, - access: access, - group_id: group_payload ? group_payload.id : null, - group_identifier: FIRST(FOR id IN group_ids RETURN id.value), - group_member_count: LENGTH(specimen_refs), - group_member_index: specimen_member_index < 0 ? null : specimen_member_index, - specimen_id: specimen_payload ? specimen_payload.id : null, - specimen_submitter_id: FIRST(FOR id IN specimen_ids RETURN id.value), - specimen_type: specimen_type, - preservation_method: preservation_method, - specimen_parent_refs: specimen_parent_refs, - case_fhir_id: patient_payload ? patient_payload.id : null, - case_id: case_id, - case_submitter_id: case_submitter_id, - gender: patient_payload ? patient_payload.gender : null, - deceased: patient_payload ? patient_payload.deceasedBoolean : null, - birth_sex: birth_sex, - race: race, - ethnicity: ethnicity, - diagnosis_id: diagnosis_id, - primary_diagnosis: primary_diagnosis, - diagnosis_body_site: diagnosis_body_site, - onset_age: onset_age, - research_subject_id: research_subject ? research_subject.id : null, - research_subject_status: research_subject ? research_subject.status : null, - study_id: study_payload ? study_payload.id : null, - study_identifier: study_identifier, - study_name: study_payload ? study_payload.name : null, - study_title: study_payload ? study_payload.title : null, - treatment_count: LENGTH(treatments), - treatment_categories: treatment_categories - } From 0f4c30acc41c74a395a7157b198b2a91b532c5c4 Mon Sep 17 00:00:00 2001 From: matthewpeterkort Date: Sun, 12 Jul 2026 14:12:04 -0700 Subject: [PATCH 03/15] ogranize, continue building out compiler --- Makefile | 41 +- README.md | 39 +- cmd/arango-fhir-server/main.go | 23 +- cmd/dataframe-query/main.go | 241 + cmd/dataframe-query/main_test.go | 81 + cmd/generate/main.go | 24 +- cmd/generate/main_test.go | 38 +- cmd/gqlgenfix/main.go | 66 + docs/AQL_OPTIMIZATION_WORKLIST.md | 577 + docs/COMPILER_CLEANUP_AUDIT.md | 133 - docs/COMPILER_FIRST_PLAN.md | 14 +- docs/COMPILER_IMPLEMENTATION_STATUS.md | 198 - docs/DEVELOPER_ARCHITECTURE.md | 45 +- docs/FORMAL_GAP_ANALYSIS.md | 12 +- docs/LUNA_COMPILER_FINALIZATION_PLAN.md | 646 + docs/LUNA_RICH_PHYSICAL_RENDERER_EXECUTION.md | 519 + docs/PHYSICAL_RENDERER_REPLACEMENT_PLAN.md | 251 + docs/PRODUCT_RECIPE_DISCOVERY.md | 589 - docs/QUICKSTART.md | 41 + docs/RICH_PHYSICAL_RENDERER_PLAN.md | 257 + docs/TERRA_ULTRA_EXECUTION_PLAN.md | 30 +- docs/benchmarks/AQL_PROFILE_CORPUS.md | 37 + .../compiler_semantics.go | 0 .../compiler_semantics_test.go | 0 .../fhirschema => fhirschema}/generated.go | 0 .../root_resources_test.go | 0 {internal/fhirschema => fhirschema}/schema.go | 0 .../fhirschema => fhirschema}/schema_test.go | 0 .../terminal_metadata.go | 0 .../terminal_metadata_test.go | 0 go.mod | 1 + go.sum | 14 + gqlgen.yml | 8 +- .../dataframe}/active_generation.go | 2 +- .../dataframe}/active_generation_test.go | 87 +- .../dataframe}/auth_scope_test.go | 32 +- .../dataframe}/fieldrefs.go | 4 +- .../dataframe}/fieldrefs_test.go | 2 +- .../dataframe}/helpers.go | 2 +- .../dataframe}/input_mapping.go | 4 +- .../dataframe}/input_mapping_test.go | 4 +- .../dataframe}/input_resolution.go | 4 +- .../dataframe}/introspection.go | 2 +- .../dataframe}/introspection_test.go | 2 +- .../dataframe}/service.go | 17 +- .../dataframe}/types.go | 2 +- graphqlapi/dataframe_diagnostics.go | 55 + .../graphqlapi => graphqlapi}/generated.go | 2998 +- .../graphqlapi => graphqlapi}/handler.go | 0 .../http_integration_test.go | 27 +- .../graphqlapi => graphqlapi}/model/models.go | 55 +- .../output_mapping.go | 12 +- graphqlapi/resolver.go | 13 + .../graphqlapi => graphqlapi}/scalars.go | 0 .../graphqlapi => graphqlapi}/schema.graphqls | 54 + .../schema.resolvers.go | 14 +- internal/api/doc.go | 2 - internal/catalog/{cache => }/cache.go | 48 +- internal/catalog/{cache => }/cache_test.go | 46 +- internal/catalog/write_profiler.go | 2 +- internal/catalog/write_profiler_test.go | 2 +- internal/dataframe/aggregate_compile_test.go | 8 +- internal/dataframe/builder_types.go | 60 +- internal/dataframe/compile.go | 129 +- internal/dataframe/compile_fields.go | 227 - internal/dataframe/compile_validation_test.go | 75 - .../compiler_arango_integration_test.go | 136 +- internal/dataframe/compiler_explanation.go | 478 - .../dataframe/compiler_explanation_test.go | 218 - internal/dataframe/dataframe_test.go | 456 - internal/dataframe/dataset_generation_test.go | 6 +- internal/dataframe/execution.go | 37 +- internal/dataframe/filter.go | 2 +- internal/dataframe/filter_compile.go | 134 - internal/dataframe/filter_compile_test.go | 102 - internal/dataframe/filter_literal.go | 31 + internal/dataframe/filter_semantics.go | 2 +- internal/dataframe/generic_lowering.go | 316 - internal/dataframe/generic_lowering_test.go | 111 - internal/dataframe/generic_physical_plan.go | 618 +- .../dataframe/generic_physical_plan_test.go | 331 +- internal/dataframe/grain.go | 2 +- internal/dataframe/lowered_compile.go | 839 - internal/dataframe/lowered_types.go | 335 - .../optimizer_traversal_sharing_test.go | 280 - internal/dataframe/physical_cost.go | 129 + internal/dataframe/physical_diagnostics.go | 163 + internal/dataframe/physical_execution.go | 84 +- internal/dataframe/physical_execution_test.go | 45 +- internal/dataframe/physical_helpers.go | 179 + internal/dataframe/physical_lowering.go | 17 + internal/dataframe/physical_lowering_test.go | 52 + internal/dataframe/physical_optimize.go | 337 + internal/dataframe/physical_optimize_test.go | 254 + internal/dataframe/physical_plan.go | 863 +- internal/dataframe/physical_plan_test.go | 102 + internal/dataframe/physical_prefix.go | 231 + internal/dataframe/physical_render.go | 851 +- internal/dataframe/physical_render_test.go | 133 + internal/dataframe/physical_required_match.go | 164 + ..._required_match_arango_integration_test.go | 48 + .../dataframe/physical_required_match_test.go | 86 + internal/dataframe/physical_scope.go | 2 +- internal/dataframe/pivots.go | 2 +- internal/dataframe/planner.go | 256 - internal/dataframe/profile.go | 23 + internal/dataframe/relationship_match.go | 100 - .../dataframe/relationship_match_compile.go | 67 - internal/dataframe/relationship_match_test.go | 214 - internal/dataframe/selection_semantics.go | 2 +- internal/dataframe/selector_render.go | 40 + internal/dataframe/selectors.go | 2 +- internal/dataframe/semantic_plan.go | 15 +- internal/dataframe/semantic_validation.go | 2 +- internal/dataframe/service.go | 32 +- internal/dataframe/shaping.go | 200 - internal/dataframe/shaping_plan.go | 202 - internal/dataframe/shaping_plan_test.go | 74 - internal/dataframe/shaping_test.go | 98 - internal/dataframe/storage_route.go | 66 +- internal/dataframe/storage_route_test.go | 274 - internal/dataframe/validation.go | 2 +- internal/dataframe/value_mode_test.go | 82 - internal/dataframebuilder/guided_discovery.go | 79 - .../dataframebuilder/guided_discovery_test.go | 76 - internal/dataframebuilder/recipe.go | 146 - internal/dataframebuilder/recipe_test.go | 308 - internal/dataframeexport/doc.go | 16 - internal/dataframeexport/stream.go | 65 - internal/dataframeexport/stream_test.go | 176 - internal/dataset/active.go | 33 +- internal/dataset/active_test.go | 81 +- .../arango}/collections.go | 2 +- .../{datasetstore => dataset/arango}/doc.go | 10 +- .../{datasetstore => dataset/arango}/store.go | 2 +- .../arango}/store_test.go | 2 +- internal/dataset/binding.go | 112 - internal/dataset/schema.go | 12 +- internal/dataset/schema_test.go | 6 +- internal/dataset/scope.go | 164 - internal/dataset/scope_test.go | 78 - internal/dataset/validation.go | 3 - internal/discovery/build.go | 640 - internal/discovery/discovery_test.go | 253 - internal/discovery/resolution.go | 169 - internal/discovery/resolution_test.go | 201 - internal/discovery/types.go | 186 - internal/discovery/validation.go | 326 - internal/export/encode.go | 369 - internal/export/encode_test.go | 215 - internal/fhir/extract.go | 80173 ---------------- internal/fhir/helpers.go | 140 - internal/fhir/model.go | 3044 - internal/fhir/validate.go | 14864 --- internal/graphqlapi/resolver.go | 13 - .../identity.go | 6 +- .../identity_test.go | 4 +- internal/httpapi/doc.go | 2 + internal/{api => httpapi}/http_test.go | 2 +- internal/{api => httpapi}/import_route.go | 2 +- internal/{api => httpapi}/middleware.go | 2 +- internal/{api => httpapi}/routes.go | 2 +- internal/{api => httpapi}/server.go | 2 +- internal/{api => httpapi}/service.go | 2 +- internal/{api => httpapi}/service_test.go | 2 +- internal/ingest/backend.go | 4 +- internal/ingest/bench_test.go | 2 +- internal/ingest/files_test.go | 12 + internal/ingest/generated_load.go | 2 +- internal/ingest/generated_load_test.go | 2 +- internal/ingest/generation_load.go | 21 +- internal/ingest/generation_load_test.go | 42 +- internal/ingest/load.go | 41 +- internal/ingest/parity_test.go | 2 +- internal/ingest/preflight_test.go | 4 +- internal/recipe/recipe_test.go | 91 - internal/recipe/templates.go | 229 - internal/recipe/templates_test.go | 109 - internal/recipe/types.go | 91 - internal/recipe/validation.go | 179 - internal/recipecompiler/bridge.go | 417 - internal/recipecompiler/bridge_test.go | 336 - internal/store/arango/profile.go | 188 + internal/store/arango/profile_client.go | 56 + internal/store/arango/profile_client_test.go | 59 + .../store/arango/profile_integration_test.go | 189 + internal/store/arango/profile_test.go | 70 + 187 files changed, 11360 insertions(+), 110619 deletions(-) create mode 100644 cmd/dataframe-query/main.go create mode 100644 cmd/dataframe-query/main_test.go create mode 100644 cmd/gqlgenfix/main.go create mode 100644 docs/AQL_OPTIMIZATION_WORKLIST.md delete mode 100644 docs/COMPILER_CLEANUP_AUDIT.md delete mode 100644 docs/COMPILER_IMPLEMENTATION_STATUS.md create mode 100644 docs/LUNA_COMPILER_FINALIZATION_PLAN.md create mode 100644 docs/LUNA_RICH_PHYSICAL_RENDERER_EXECUTION.md create mode 100644 docs/PHYSICAL_RENDERER_REPLACEMENT_PLAN.md delete mode 100644 docs/PRODUCT_RECIPE_DISCOVERY.md create mode 100644 docs/RICH_PHYSICAL_RENDERER_PLAN.md create mode 100644 docs/benchmarks/AQL_PROFILE_CORPUS.md rename {internal/fhirschema => fhirschema}/compiler_semantics.go (100%) rename {internal/fhirschema => fhirschema}/compiler_semantics_test.go (100%) rename {internal/fhirschema => fhirschema}/generated.go (100%) rename {internal/fhirschema => fhirschema}/root_resources_test.go (100%) rename {internal/fhirschema => fhirschema}/schema.go (100%) rename {internal/fhirschema => fhirschema}/schema_test.go (100%) rename {internal/fhirschema => fhirschema}/terminal_metadata.go (100%) rename {internal/fhirschema => fhirschema}/terminal_metadata_test.go (100%) rename {internal/dataframebuilder => graphqlapi/dataframe}/active_generation.go (96%) rename {internal/dataframebuilder => graphqlapi/dataframe}/active_generation_test.go (54%) rename {internal/dataframebuilder => graphqlapi/dataframe}/auth_scope_test.go (79%) rename {internal/dataframebuilder => graphqlapi/dataframe}/fieldrefs.go (98%) rename {internal/dataframebuilder => graphqlapi/dataframe}/fieldrefs_test.go (98%) rename {internal/dataframebuilder => graphqlapi/dataframe}/helpers.go (93%) rename {internal/dataframebuilder => graphqlapi/dataframe}/input_mapping.go (98%) rename {internal/dataframebuilder => graphqlapi/dataframe}/input_mapping_test.go (96%) rename {internal/dataframebuilder => graphqlapi/dataframe}/input_resolution.go (99%) rename {internal/dataframebuilder => graphqlapi/dataframe}/introspection.go (99%) rename {internal/dataframebuilder => graphqlapi/dataframe}/introspection_test.go (99%) rename {internal/dataframebuilder => graphqlapi/dataframe}/service.go (87%) rename {internal/dataframebuilder => graphqlapi/dataframe}/types.go (96%) create mode 100644 graphqlapi/dataframe_diagnostics.go rename {internal/graphqlapi => graphqlapi}/generated.go (71%) rename {internal/graphqlapi => graphqlapi}/handler.go (100%) rename {internal/graphqlapi => graphqlapi}/http_integration_test.go (90%) rename {internal/graphqlapi => graphqlapi}/model/models.go (79%) rename {internal/graphqlapi => graphqlapi}/output_mapping.go (90%) create mode 100644 graphqlapi/resolver.go rename {internal/graphqlapi => graphqlapi}/scalars.go (100%) rename {internal/graphqlapi => graphqlapi}/schema.graphqls (71%) rename {internal/graphqlapi => graphqlapi}/schema.resolvers.go (85%) delete mode 100644 internal/api/doc.go rename internal/catalog/{cache => }/cache.go (61%) rename internal/catalog/{cache => }/cache_test.go (63%) delete mode 100644 internal/dataframe/compile_fields.go delete mode 100644 internal/dataframe/compile_validation_test.go delete mode 100644 internal/dataframe/compiler_explanation.go delete mode 100644 internal/dataframe/compiler_explanation_test.go delete mode 100644 internal/dataframe/dataframe_test.go delete mode 100644 internal/dataframe/filter_compile.go delete mode 100644 internal/dataframe/filter_compile_test.go create mode 100644 internal/dataframe/filter_literal.go delete mode 100644 internal/dataframe/generic_lowering.go delete mode 100644 internal/dataframe/generic_lowering_test.go delete mode 100644 internal/dataframe/lowered_compile.go delete mode 100644 internal/dataframe/lowered_types.go delete mode 100644 internal/dataframe/optimizer_traversal_sharing_test.go create mode 100644 internal/dataframe/physical_cost.go create mode 100644 internal/dataframe/physical_diagnostics.go create mode 100644 internal/dataframe/physical_helpers.go create mode 100644 internal/dataframe/physical_lowering.go create mode 100644 internal/dataframe/physical_lowering_test.go create mode 100644 internal/dataframe/physical_optimize.go create mode 100644 internal/dataframe/physical_optimize_test.go create mode 100644 internal/dataframe/physical_prefix.go create mode 100644 internal/dataframe/physical_required_match.go create mode 100644 internal/dataframe/physical_required_match_arango_integration_test.go create mode 100644 internal/dataframe/physical_required_match_test.go delete mode 100644 internal/dataframe/planner.go create mode 100644 internal/dataframe/profile.go delete mode 100644 internal/dataframe/relationship_match_compile.go delete mode 100644 internal/dataframe/relationship_match_test.go create mode 100644 internal/dataframe/selector_render.go delete mode 100644 internal/dataframe/shaping.go delete mode 100644 internal/dataframe/shaping_plan.go delete mode 100644 internal/dataframe/shaping_plan_test.go delete mode 100644 internal/dataframe/shaping_test.go delete mode 100644 internal/dataframe/storage_route_test.go delete mode 100644 internal/dataframe/value_mode_test.go delete mode 100644 internal/dataframebuilder/guided_discovery.go delete mode 100644 internal/dataframebuilder/guided_discovery_test.go delete mode 100644 internal/dataframebuilder/recipe.go delete mode 100644 internal/dataframebuilder/recipe_test.go delete mode 100644 internal/dataframeexport/doc.go delete mode 100644 internal/dataframeexport/stream.go delete mode 100644 internal/dataframeexport/stream_test.go rename internal/{datasetstore => dataset/arango}/collections.go (98%) rename internal/{datasetstore => dataset/arango}/doc.go (69%) rename internal/{datasetstore => dataset/arango}/store.go (99%) rename internal/{datasetstore => dataset/arango}/store_test.go (99%) delete mode 100644 internal/dataset/binding.go delete mode 100644 internal/dataset/scope.go delete mode 100644 internal/dataset/scope_test.go delete mode 100644 internal/discovery/build.go delete mode 100644 internal/discovery/discovery_test.go delete mode 100644 internal/discovery/resolution.go delete mode 100644 internal/discovery/resolution_test.go delete mode 100644 internal/discovery/types.go delete mode 100644 internal/discovery/validation.go delete mode 100644 internal/export/encode.go delete mode 100644 internal/export/encode_test.go delete mode 100644 internal/fhir/extract.go delete mode 100644 internal/fhir/helpers.go delete mode 100644 internal/fhir/model.go delete mode 100644 internal/fhir/validate.go delete mode 100644 internal/graphqlapi/resolver.go rename internal/{schemaidentity => graphschema}/identity.go (97%) rename internal/{schemaidentity => graphschema}/identity_test.go (98%) create mode 100644 internal/httpapi/doc.go rename internal/{api => httpapi}/http_test.go (99%) rename internal/{api => httpapi}/import_route.go (99%) rename internal/{api => httpapi}/middleware.go (99%) rename internal/{api => httpapi}/routes.go (98%) rename internal/{api => httpapi}/server.go (99%) rename internal/{api => httpapi}/service.go (99%) rename internal/{api => httpapi}/service_test.go (99%) delete mode 100644 internal/recipe/recipe_test.go delete mode 100644 internal/recipe/templates.go delete mode 100644 internal/recipe/templates_test.go delete mode 100644 internal/recipe/types.go delete mode 100644 internal/recipe/validation.go delete mode 100644 internal/recipecompiler/bridge.go delete mode 100644 internal/recipecompiler/bridge_test.go create mode 100644 internal/store/arango/profile.go create mode 100644 internal/store/arango/profile_client.go create mode 100644 internal/store/arango/profile_client_test.go create mode 100644 internal/store/arango/profile_integration_test.go create mode 100644 internal/store/arango/profile_test.go diff --git a/Makefile b/Makefile index 3354be8..11019e1 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,19 @@ -.PHONY: build build-cli build-server clean compiler-bench conformance generate-fhir generate-graphql graphql-check gqlgen-check test docker-build docker-run +.PHONY: build build-cli build-server clean compiler-bench compiler-arango-bench dataframe-demo conformance generate-fhir generate-graphql graphql-check gqlgen-check test docker-build docker-run GO ?= go GOCACHE_DIR ?= $(CURDIR)/.gocache GOFLAGS ?= SCHEMA_PATH ?= schemas/graph-fhir.json IMAGE ?= arango-fhir-proto:local +BENCH_TIME ?= 10x +BENCH_COUNT ?= 5 +GRAPHQL_URL ?= http://127.0.0.1:8080/graphql +DATAFRAME_REPEAT ?= 1 +DATAFRAME_LIMIT ?= 0 +DATAFRAME_TIMEOUT ?= 5m +DATAFRAME_PRINT_RESPONSE ?= false +DATAFRAME_QUERY ?= examples/meta_gdc_case_matrix.graphql +DATAFRAME_VARIABLES ?= examples/meta_gdc_case_matrix.variables.json build: build-cli build-server @@ -17,23 +26,23 @@ build-server: GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) build $(GOFLAGS) -o bin/arango-fhir-server ./cmd/arango-fhir-server generate-graphql: - rm -f internal/graphqlapi/generated.go internal/graphqlapi/model/models.go internal/graphqlapi/schema.resolvers.go mkdir -p $(GOCACHE_DIR) - @status=0; \ - GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) run github.com/99designs/gqlgen generate || status=$$?; \ - if [ -f internal/graphqlapi/generated.go ]; then \ - perl -0pi -e 's/return &res, graphql::ErrorOnPath\\(ctx, err\\)/return res, graphql::ErrorOnPath(ctx, err)/g; s/return &res, graphql\\.ErrorOnPath\\(ctx, err\\)/return res, graphql.ErrorOnPath(ctx, err)/g' internal/graphqlapi/generated.go; \ + @status=0; fix_status=0; \ + GOFLAGS="$(GOFLAGS) -mod=mod" GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) run -mod=mod github.com/99designs/gqlgen generate || status=$$?; \ + if [ -f graphqlapi/generated.go ]; then \ + GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) run ./cmd/gqlgenfix graphqlapi/generated.go || fix_status=$$?; \ fi; \ - test $$status -eq 0 -o -f internal/graphqlapi/generated.go + test $$fix_status -eq 0; \ + test $$status -eq 0 -o -f graphqlapi/generated.go generate-fhir: mkdir -p $(GOCACHE_DIR) - GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) run ./cmd/generate -schema $(SCHEMA_PATH) -out-dir internal/fhir - gofmt -w internal/fhir/model.go internal/fhir/validate.go internal/fhir/extract.go internal/fhirschema/generated.go + GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) run ./cmd/generate -schema $(SCHEMA_PATH) -structs-out fhirstructs -metadata-out fhirschema/generated.go + gofmt -w fhirstructs/model.go fhirstructs/validate.go fhirstructs/extract.go fhirstructs/helpers.go fhirschema/generated.go graphql-check: mkdir -p $(GOCACHE_DIR) - GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) test $(GOFLAGS) ./internal/graphqlapi ./internal/dataframe -count=1 + GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) test $(GOFLAGS) ./graphqlapi ./internal/dataframe -count=1 gqlgen-check: graphql-check @@ -45,6 +54,18 @@ compiler-bench: mkdir -p $(GOCACHE_DIR) GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) test $(GOFLAGS) ./conformance/compiler -run '^$$' -bench '^BenchmarkCompilerOracle$$' -benchmem +# Requires a locally loaded META fixture. Override BENCH_TIME/BENCH_COUNT for +# a longer run, for example: make compiler-arango-bench BENCH_TIME=3s BENCH_COUNT=10. +compiler-arango-bench: + mkdir -p $(GOCACHE_DIR) + LOOM_COMPILER_ARANGO_INTEGRATION=1 GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) test $(GOFLAGS) ./internal/dataframe -run '^$$' -bench '^BenchmarkGenericCompilerAgainstArango$$' -benchmem -benchtime=$(BENCH_TIME) -count=$(BENCH_COUNT) + +# Requires `arango-fhir-server --no-auth` and a loaded META project. Prints the +# actual GraphQL dataframe response and per-request wall-clock timings. +dataframe-demo: + mkdir -p $(GOCACHE_DIR) + GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) run ./cmd/dataframe-query -url $(GRAPHQL_URL) -query $(DATAFRAME_QUERY) -variables $(DATAFRAME_VARIABLES) -repeat $(DATAFRAME_REPEAT) -limit $(DATAFRAME_LIMIT) -timeout $(DATAFRAME_TIMEOUT) -print-response=$(DATAFRAME_PRINT_RESPONSE) + conformance: mkdir -p $(GOCACHE_DIR) GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) test $(GOFLAGS) ./conformance/... -count=1 diff --git a/README.md b/README.md index fcb3288..4aee411 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,7 @@ The current product direction is: - store graph edges in `fhir_edge` - profile populated fields into `fhir_field_catalog` - lower typed dataframe requests through the FHIR-aware compiler into scoped AQL -- expose the current expert/compatibility GraphQL transport while the guided - recipe transport is being added +- expose the current compiler-backed GraphQL transport ArangoDB is the only runtime backend. The tracked [`experimental/`](experimental/) directory contains the local Arango compose setup. @@ -26,12 +25,13 @@ directory contains the local Arango compose setup. - [Quickstart](docs/QUICKSTART.md) - [Developer Architecture](docs/DEVELOPER_ARCHITECTURE.md) -- [Product Recipes and Dataset Discovery](docs/PRODUCT_RECIPE_DISCOVERY.md) - [Formal Product Gap Analysis](docs/FORMAL_GAP_ANALYSIS.md) - [Compiler-First FHIR/AQL Plan](docs/COMPILER_FIRST_PLAN.md) -- [Compiler-First Implementation Status](docs/COMPILER_IMPLEMENTATION_STATUS.md) +- [Physical Renderer Replacement Plan](docs/PHYSICAL_RENDERER_REPLACEMENT_PLAN.md) +- [Rich Physical Renderer Plan](docs/RICH_PHYSICAL_RENDERER_PLAN.md) +- [Luna Rich Physical Renderer Execution Plan](docs/LUNA_RICH_PHYSICAL_RENDERER_EXECUTION.md) +- [Luna Compiler Finalization Plan](docs/LUNA_COMPILER_FINALIZATION_PLAN.md) - [Terra Ultra Parallel Execution Plan](docs/TERRA_ULTRA_EXECUTION_PLAN.md) -- [Compiler Cleanup Audit](docs/COMPILER_CLEANUP_AUDIT.md) ## Current Layout @@ -39,19 +39,15 @@ directory contains the local Arango compose setup. - [`cmd/arango-fhir-server/main.go`](cmd/arango-fhir-server/main.go): HTTP server entrypoint - [`internal/ingest`](internal/ingest): load pipeline and Arango ingest bootstrap/runtime - [`internal/catalog`](internal/catalog): populated-field and populated-reference discovery -- [`internal/catalog/cache`](internal/catalog/cache): per-project discovery cache -- [`internal/discovery`](internal/discovery): safe guided capability snapshots built from scoped catalog facts - [`internal/dataset`](internal/dataset): dataset generation, schema, and scope lifecycle contract -- [`internal/datasetstore`](internal/datasetstore): Arango-backed immutable manifest and active-generation pointer store -- [`internal/graphqlapi`](internal/graphqlapi): GraphQL schema, request mapping, introspection service +- [`internal/dataset/arango`](internal/dataset/arango): Arango-backed immutable manifest and active-generation pointer store +- [`graphqlapi`](graphqlapi): GraphQL schema, request mapping, introspection service, and gqlgen output +- [`graphqlapi/dataframe`](graphqlapi/dataframe): GraphQL dataframe input translation and builder introspection - [`internal/dataframe`](internal/dataframe): dataframe validation, lowering, and AQL compilation -- [`internal/export`](internal/export): strict flat-row NDJSON and CSV encoding primitives -- [`internal/dataframeexport`](internal/dataframeexport): streaming bridge from dataframe execution to flat encoders -- [`internal/fhirschema`](internal/fhirschema): generated schema metadata used by planner/validation -- [`internal/dataframebuilder`](internal/dataframebuilder): builder introspection, friendly `fieldRef`s, and GraphQL input translation -- [`internal/recipe`](internal/recipe): versioned product recipe intent and guided template metadata -- [`internal/schemaidentity`](internal/schemaidentity): exact graph-schema identity captured by dataset generations -- [`internal/api`](internal/api): HTTP host, authenticated GraphQL mounting, and legacy import compatibility wiring +- [`fhirstructs`](fhirstructs): generated FHIR structs, validators, and graph-edge extraction +- [`fhirschema`](fhirschema): generated compiler schema metadata and selector/traversal resolution +- [`internal/graphschema`](internal/graphschema): exact graph-schema identity captured by dataset generations +- [`internal/httpapi`](internal/httpapi): HTTP host, authenticated GraphQL mounting, and legacy import compatibility wiring - [`internal/authscope`](internal/authscope): shared request principal context and auth-resource-path scope resolution - [`experimental/`](experimental/): local Arango development compose setup @@ -154,7 +150,7 @@ The server mounts: - `POST /graphql` - `POST /api/v1/imports` (legacy one-file import; disabled with `--dataset-generations`) -HTTP wiring lives in [`internal/api/routes.go`](internal/api/routes.go) and [`internal/api/server.go`](internal/api/server.go). +HTTP wiring lives in [`internal/httpapi/routes.go`](internal/httpapi/routes.go) and [`internal/httpapi/server.go`](internal/httpapi/server.go). ## Primary Collections @@ -173,10 +169,5 @@ What is current and real: - GraphQL introspection for populated traversals/fields/pivots - GraphQL dataframe execution on Arango -- generated schema metadata in `internal/fhirschema` -- derived field aliases in `internal/dataframebuilder` and explicit lowering rules in `internal/dataframe` - -What is explicitly experimental: - -- the guided discovery, recipe, and streaming-export foundations until their - public delivery API exists +- generated schema metadata in `fhirschema` +- derived field aliases in `graphqlapi/dataframe` and explicit lowering rules in `internal/dataframe` diff --git a/cmd/arango-fhir-server/main.go b/cmd/arango-fhir-server/main.go index 39bac8d..9b48eec 100644 --- a/cmd/arango-fhir-server/main.go +++ b/cmd/arango-fhir-server/main.go @@ -9,14 +9,14 @@ import ( "os/signal" "syscall" - "github.com/calypr/loom/internal/api" + "github.com/calypr/loom/graphqlapi" + dataframeapi "github.com/calypr/loom/graphqlapi/dataframe" "github.com/calypr/loom/internal/authscope" "github.com/calypr/loom/internal/catalog" - catalogcache "github.com/calypr/loom/internal/catalog/cache" "github.com/calypr/loom/internal/dataframe" - "github.com/calypr/loom/internal/dataframebuilder" - "github.com/calypr/loom/internal/datasetstore" - "github.com/calypr/loom/internal/graphqlapi" + "github.com/calypr/loom/internal/dataset" + datasetarango "github.com/calypr/loom/internal/dataset/arango" + api "github.com/calypr/loom/internal/httpapi" "github.com/calypr/loom/internal/ingest" arangostore "github.com/calypr/loom/internal/store/arango" ) @@ -47,23 +47,26 @@ func main() { Database: *database, } - var activeManifestResolver *datasetstore.Store + // Keep this as an interface, not a typed *datasetarango.Store nil. Passing a + // typed nil into dataframeapi.Config makes the interface non-nil and + // incorrectly activates immutable-generation lookup for legacy META loads. + var activeManifestResolver dataset.ActiveManifestResolver if *datasetGenerations { lifecycleClient, err := arangostore.Open(context.Background(), connOpts.URL, connOpts.Database) if err != nil { exitf("open dataset lifecycle store: %v", err) } defer lifecycleClient.Close(context.Background()) - if err := lifecycleClient.Bootstrap(context.Background(), datasetstore.BootstrapSpec()); err != nil { + if err := lifecycleClient.Bootstrap(context.Background(), datasetarango.BootstrapSpec()); err != nil { exitf("bootstrap dataset lifecycle store: %v", err) } - activeManifestResolver, err = datasetstore.New(lifecycleClient) + activeManifestResolver, err = datasetarango.New(lifecycleClient) if err != nil { exitf("create dataset lifecycle store: %v", err) } } - discoveryCache := catalogcache.New() + discoveryCache := catalog.NewCache() discoverFields := discoveryCache.DiscoverFields(catalog.DiscoverPopulatedFields) discoverReferences := discoveryCache.DiscoverReferences(catalog.DiscoverPopulatedReferences) @@ -85,7 +88,7 @@ func main() { ScopeResolver: scopeResolver, ActiveManifestResolver: activeManifestResolver, }) - resolver := graphqlapi.NewResolver(dataframebuilder.Config{ + resolver := graphqlapi.NewResolver(dataframeapi.Config{ ConnectionOptions: connOpts, DiscoverReferences: discoverReferences, DiscoverFields: discoverFields, diff --git a/cmd/dataframe-query/main.go b/cmd/dataframe-query/main.go new file mode 100644 index 0000000..8348db8 --- /dev/null +++ b/cmd/dataframe-query/main.go @@ -0,0 +1,241 @@ +// dataframe-query executes a checked-in GraphQL dataframe request and prints +// the response with wall-clock timing. It is deliberately a small developer +// tool: benchmark loops belong in Go benchmarks, while this command makes one +// human-readable dataframe request easy to inspect end to end. +package main + +import ( + "bytes" + "context" + "encoding/json" + "flag" + "fmt" + "io" + "net/http" + "os" + "strings" + "time" +) + +type graphqlRequest struct { + Query string `json:"query"` + Variables json.RawMessage `json:"variables"` +} + +func main() { + var ( + url string + queryPath string + variablesPath string + repeat int + limit int + timeout time.Duration + printResponse bool + ) + flag.StringVar(&url, "url", "http://127.0.0.1:8080/graphql", "GraphQL endpoint") + flag.StringVar(&queryPath, "query", "examples/meta_patient_dataframe.graphql", "GraphQL operation file") + flag.StringVar(&variablesPath, "variables", "examples/meta_patient_dataframe.variables.json", "GraphQL variables JSON file") + flag.IntVar(&repeat, "repeat", 1, "number of sequential requests; only the final response is printed") + flag.IntVar(&limit, "limit", 0, "override GraphQL row limit; 0 preserves the variables file") + flag.DurationVar(&timeout, "timeout", 60*time.Second, "per-request HTTP timeout") + flag.BoolVar(&printResponse, "print-response", true, "pretty-print the final GraphQL response") + flag.Parse() + + if repeat < 1 { + fatalf("repeat must be positive") + } + variables, err := os.ReadFile(variablesPath) + if err != nil { + fatalf("read variables %q: %v", variablesPath, err) + } + if !json.Valid(variables) { + fatalf("variables file %q is not valid JSON", variablesPath) + } + if limit > 0 { + variables, err = withLimit(variables, limit) + if err != nil { + fatalf("override row limit: %v", err) + } + } + query, err := os.ReadFile(queryPath) + if err != nil { + fatalf("read query %q: %v", queryPath, err) + } + payload, err := json.Marshal(graphqlRequest{Query: string(query), Variables: variables}) + if err != nil { + fatalf("encode GraphQL request: %v", err) + } + + client := &http.Client{Timeout: timeout} + + durations := make([]time.Duration, 0, repeat) + var responseBody []byte + var responseMetrics dataframeResponseMetrics + for run := 0; run < repeat; run++ { + started := time.Now() + responseBody, err = execute(client, url, payload) + duration := time.Since(started) + durations = append(durations, duration) + if err != nil { + fatalf("request %d/%d: %v", run+1, repeat, err) + } + responseMetrics = inspectDataframeResponse(responseBody, duration) + } + + min, average, max := summarizeDurations(durations) + fmt.Printf("GraphQL dataframe request: %s\n", url) + fmt.Printf("HTTP/server total: runs=%d cold=%s warm=%s min=%s avg=%s max=%s\n", repeat, durations[0].Round(time.Microsecond), durations[len(durations)-1].Round(time.Microsecond), min.Round(time.Microsecond), average.Round(time.Microsecond), max.Round(time.Microsecond)) + fmt.Printf("Response: rows=%d bytes=%d rows/sec=%.1f\n\n", responseMetrics.Rows, responseMetrics.Bytes, responseMetrics.RowsPerSecond) + if responseMetrics.Diagnostics != nil { + d := responseMetrics.Diagnostics + fmt.Printf("Server stages (ms): input_resolution=%.3f request_preparation=%.3f compilation=%.3f arango_query=%.3f row_materialization=%.3f result_assembly=%.3f dataframe_service_total=%.3f\n", d.InputResolutionMs, d.RequestPreparationMs, d.CompilationMs, d.ArangoQueryMs, d.RowMaterializationMs, d.ResultAssemblyMs, d.TotalMs) + fmt.Printf("Outside dataframe service (GraphQL serialization + HTTP): %.3f ms\n\n", durationMinusMillis(durations[len(durations)-1], d.TotalMs)) + fmt.Printf("Compiler plan: traversal_sets=%d shared_traversals=%d required_match_reuse=%d scope_safe_sharing_groups=%d scope_safe_sharing_sets=%d potential_sharing_groups=%d potential_sharing_sets=%d\n", d.Plan.TraversalSets, d.Plan.SharedTraversalCount, d.Plan.RequiredMatchReuseCount, d.Plan.ScopedSharingCandidateGroups, d.Plan.ScopedSharingCandidateSets, d.Plan.PotentialSharingOpportunityGroups, d.Plan.PotentialSharingOpportunitySets) + for _, reuse := range d.Plan.RichSourceReuse { + fmt.Printf(" rich source reuse: set=%s total=%d aggregates=%d pivots=%d slices=%d\n", reuse.SourceSet, reuse.TotalConsumers, reuse.AggregateConsumers, reuse.PivotConsumers, reuse.SliceConsumers) + } + fmt.Println() + } + if printResponse { + fmt.Println("Response:") + if err := prettyPrint(os.Stdout, responseBody); err != nil { + fatalf("format GraphQL response: %v", err) + } + } +} + +// dataframeResponseMetrics is intentionally derived from the GraphQL response +// rather than server internals. Servers that select the diagnostics field also +// return service-stage timings; older Loom servers remain compatible but omit +// that optional measurement block. +type dataframeResponseMetrics struct { + Rows int + Bytes int + RowsPerSecond float64 + Diagnostics *dataframeDiagnostics +} + +type dataframeDiagnostics struct { + InputResolutionMs float64 `json:"inputResolutionMs"` + RequestPreparationMs float64 `json:"requestPreparationMs"` + CompilationMs float64 `json:"compilationMs"` + ArangoQueryMs float64 `json:"arangoQueryMs"` + RowMaterializationMs float64 `json:"rowMaterializationMs"` + ResultAssemblyMs float64 `json:"resultAssemblyMs"` + TotalMs float64 `json:"totalMs"` + Plan dataframeCompilerPlanDiagnostics `json:"plan"` +} + +type dataframeCompilerPlanDiagnostics struct { + TraversalSets int `json:"traversalSets"` + SharedTraversalCount int `json:"sharedTraversalCount"` + RequiredMatchReuseCount int `json:"requiredMatchReuseCount"` + ScopedSharingCandidateGroups int `json:"scopedSharingCandidateGroups"` + ScopedSharingCandidateSets int `json:"scopedSharingCandidateSets"` + PotentialSharingOpportunityGroups int `json:"potentialSharingOpportunityGroups"` + PotentialSharingOpportunitySets int `json:"potentialSharingOpportunitySets"` + RichSourceReuse []dataframeRichSourceReuse `json:"richSourceReuse"` +} + +type dataframeRichSourceReuse struct { + SourceSet string `json:"sourceSet"` + AggregateConsumers int `json:"aggregateConsumers"` + PivotConsumers int `json:"pivotConsumers"` + SliceConsumers int `json:"sliceConsumers"` + TotalConsumers int `json:"totalConsumers"` +} + +func inspectDataframeResponse(body []byte, duration time.Duration) dataframeResponseMetrics { + metrics := dataframeResponseMetrics{Bytes: len(body)} + var envelope struct { + Data struct { + Run struct { + RowCount int `json:"rowCount"` + Rows []json.RawMessage `json:"rows"` + Diagnostics *dataframeDiagnostics `json:"diagnostics"` + } `json:"runFhirDataframe"` + } `json:"data"` + } + if err := json.Unmarshal(body, &envelope); err != nil { + return metrics + } + metrics.Rows = envelope.Data.Run.RowCount + metrics.Diagnostics = envelope.Data.Run.Diagnostics + if metrics.Rows == 0 { + metrics.Rows = len(envelope.Data.Run.Rows) + } + if duration > 0 { + metrics.RowsPerSecond = float64(metrics.Rows) / duration.Seconds() + } + return metrics +} + +func durationMinusMillis(duration time.Duration, milliseconds float64) float64 { + remaining := float64(duration)/float64(time.Millisecond) - milliseconds + if remaining < 0 { + return 0 + } + return remaining +} + +func withLimit(variables []byte, limit int) ([]byte, error) { + if limit <= 0 { + return variables, nil + } + var decoded map[string]any + if err := json.Unmarshal(variables, &decoded); err != nil { + return nil, err + } + decoded["limit"] = limit + return json.Marshal(decoded) +} + +func execute(client *http.Client, url string, payload []byte) ([]byte, error) { + request, err := http.NewRequestWithContext(context.Background(), http.MethodPost, url, bytes.NewReader(payload)) + if err != nil { + return nil, err + } + request.Header.Set("Content-Type", "application/json") + response, err := client.Do(request) + if err != nil { + return nil, err + } + defer response.Body.Close() + body, err := io.ReadAll(response.Body) + if err != nil { + return nil, err + } + if response.StatusCode < http.StatusOK || response.StatusCode >= http.StatusMultipleChoices { + return nil, fmt.Errorf("HTTP %s: %s", response.Status, strings.TrimSpace(string(body))) + } + return body, nil +} + +func summarizeDurations(durations []time.Duration) (time.Duration, time.Duration, time.Duration) { + minimum, maximum := durations[0], durations[0] + var total time.Duration + for _, duration := range durations { + if duration < minimum { + minimum = duration + } + if duration > maximum { + maximum = duration + } + total += duration + } + return minimum, total / time.Duration(len(durations)), maximum +} + +func prettyPrint(writer io.Writer, body []byte) error { + var formatted bytes.Buffer + if err := json.Indent(&formatted, body, "", " "); err != nil { + return err + } + _, err := fmt.Fprintln(writer, formatted.String()) + return err +} + +func fatalf(format string, args ...any) { + fmt.Fprintf(os.Stderr, "dataframe-query: "+format+"\n", args...) + os.Exit(1) +} diff --git a/cmd/dataframe-query/main_test.go b/cmd/dataframe-query/main_test.go new file mode 100644 index 0000000..23d08ae --- /dev/null +++ b/cmd/dataframe-query/main_test.go @@ -0,0 +1,81 @@ +package main + +import ( + "io" + "net/http" + "strings" + "testing" + "time" +) + +func TestExecutePostsGraphQLJSON(t *testing.T) { + client := &http.Client{Transport: roundTripper(func(request *http.Request) (*http.Response, error) { + if request.Method != http.MethodPost { + t.Fatalf("method = %s", request.Method) + } + if got := request.Header.Get("Content-Type"); got != "application/json" { + t.Fatalf("content type = %q", got) + } + body, err := io.ReadAll(request.Body) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(string(body), `"query":"query { ping }"`) { + t.Fatalf("unexpected request body: %s", body) + } + return &http.Response{ + StatusCode: http.StatusOK, + Status: "200 OK", + Body: io.NopCloser(strings.NewReader(`{"data":{"ping":"pong"}}`)), + Header: make(http.Header), + }, nil + })} + + body, err := execute(client, "http://example.test/graphql", []byte(`{"query":"query { ping }","variables":{}}`)) + if err != nil { + t.Fatal(err) + } + if string(body) != `{"data":{"ping":"pong"}}` { + t.Fatalf("body = %s", body) + } +} + +type roundTripper func(*http.Request) (*http.Response, error) + +func (fn roundTripper) RoundTrip(request *http.Request) (*http.Response, error) { + return fn(request) +} + +func TestSummarizeDurations(t *testing.T) { + minimum, average, maximum := summarizeDurations([]time.Duration{10 * time.Millisecond, 20 * time.Millisecond, 30 * time.Millisecond}) + if minimum != 10*time.Millisecond || average != 20*time.Millisecond || maximum != 30*time.Millisecond { + t.Fatalf("summary = %s, %s, %s", minimum, average, maximum) + } +} + +func TestWithLimit(t *testing.T) { + variables, err := withLimit([]byte(`{"limit":25,"input":{"project":"P1"}}`), 1000) + if err != nil { + t.Fatal(err) + } + if string(variables) != `{"input":{"project":"P1"},"limit":1000}` { + t.Fatalf("variables = %s", variables) + } +} + +func TestInspectDataframeResponse(t *testing.T) { + metrics := inspectDataframeResponse([]byte(`{"data":{"runFhirDataframe":{"rowCount":25,"rows":[{"id":"1"}]}}}`), time.Second) + if metrics.Rows != 25 { + t.Fatalf("rows = %d, want 25", metrics.Rows) + } + if metrics.Bytes == 0 || metrics.RowsPerSecond != 25 { + t.Fatalf("metrics = %+v", metrics) + } +} + +func TestInspectDataframeResponseFallsBackToRowsLength(t *testing.T) { + metrics := inspectDataframeResponse([]byte(`{"data":{"runFhirDataframe":{"rows":[{"id":"1"},{"id":"2"}]}}}`), 2*time.Second) + if metrics.Rows != 2 || metrics.RowsPerSecond != 1 { + t.Fatalf("metrics = %+v", metrics) + } +} diff --git a/cmd/generate/main.go b/cmd/generate/main.go index f9999c9..726b335 100644 --- a/cmd/generate/main.go +++ b/cmd/generate/main.go @@ -65,7 +65,8 @@ type TemplatePointers struct { func main() { fs := flag.NewFlagSet("generate", flag.ExitOnError) schemaPath := fs.String("schema", "schemas/graph-fhir.json", "Path to graph-fhir JSON schema") - outputDir := fs.String("out-dir", "internal/fhir", "Directory for generated FHIR Go code") + structsDir := fs.String("structs-out", "fhirstructs", "Directory for generated FHIR Go structs, validation, and edge extraction") + metadataOut := fs.String("metadata-out", "fhirschema/generated.go", "Path for generated compiler FHIR schema metadata") if err := fs.Parse(os.Args[1:]); err != nil { fmt.Fprintf(os.Stderr, "Error parsing flags: %v\n", err) os.Exit(2) @@ -84,36 +85,35 @@ func main() { os.Exit(1) } - if err := os.MkdirAll(*outputDir, 0755); err != nil { + if err := os.MkdirAll(*structsDir, 0755); err != nil { fmt.Fprintf(os.Stderr, "Error creating output directory: %v\n", err) os.Exit(1) } - fhirSchemaDir := filepath.Join(filepath.Dir(*outputDir), "fhirschema") - if err := os.MkdirAll(fhirSchemaDir, 0755); err != nil { - fmt.Fprintf(os.Stderr, "Error creating schema metadata directory: %v\n", err) + if err := os.MkdirAll(filepath.Dir(*metadataOut), 0755); err != nil { + fmt.Fprintf(os.Stderr, "Error creating compiler metadata directory: %v\n", err) os.Exit(1) } // 1. Generate model.go - if err := generateModel(&schema, filepath.Join(*outputDir, "model.go")); err != nil { + if err := generateModel(&schema, filepath.Join(*structsDir, "model.go")); err != nil { fmt.Fprintf(os.Stderr, "Error generating model.go: %v\n", err) os.Exit(1) } // 2. Generate validate.go - if err := generateValidate(&schema, filepath.Join(*outputDir, "validate.go")); err != nil { + if err := generateValidate(&schema, filepath.Join(*structsDir, "validate.go")); err != nil { fmt.Fprintf(os.Stderr, "Error generating validate.go: %v\n", err) os.Exit(1) } // 3. Generate extract.go - if err := generateExtract(&schema, filepath.Join(*outputDir, "extract.go")); err != nil { + if err := generateExtract(&schema, filepath.Join(*structsDir, "extract.go")); err != nil { fmt.Fprintf(os.Stderr, "Error generating extract.go: %v\n", err) os.Exit(1) } // 4. Generate fhirschema metadata - if err := generateFHIRSchema(&schema, filepath.Join(fhirSchemaDir, "generated.go")); err != nil { + if err := generateFHIRSchema(&schema, *metadataOut); err != nil { fmt.Fprintf(os.Stderr, "Error generating fhirschema/generated.go: %v\n", err) os.Exit(1) } @@ -252,7 +252,7 @@ func getGoType(prop *Property, isField bool) string { func generateModel(schema *Schema, path string) error { var sb strings.Builder sb.WriteString("// Code generated by cmd/generate/main.go. DO NOT EDIT.\n") - sb.WriteString("package fhir\n\n") + sb.WriteString("package fhirstructs\n\n") var keys []string for k := range schema.Defs { @@ -293,7 +293,7 @@ func generateModel(schema *Schema, path string) error { func generateValidate(schema *Schema, path string) error { var sb strings.Builder sb.WriteString("// Code generated by cmd/generate/main.go. DO NOT EDIT.\n") - sb.WriteString("package fhir\n\n") + sb.WriteString("package fhirstructs\n\n") sb.WriteString("import (\n") sb.WriteString("\t\"fmt\"\n") sb.WriteString("\t\"regexp\"\n") @@ -575,7 +575,7 @@ func escapePattern(pat string) string { func generateExtract(schema *Schema, path string) error { var sb strings.Builder sb.WriteString("// Code generated by cmd/generate/main.go. DO NOT EDIT.\n") - sb.WriteString("package fhir\n\n") + sb.WriteString("package fhirstructs\n\n") sb.WriteString("import (\n") sb.WriteString("\t\"bytes\"\n") sb.WriteString("\t\"crypto/sha1\"\n") diff --git a/cmd/generate/main_test.go b/cmd/generate/main_test.go index 1d5ce48..01dcddc 100644 --- a/cmd/generate/main_test.go +++ b/cmd/generate/main_test.go @@ -50,12 +50,46 @@ func TestFHIRSchemaMetadataGenerationMatchesCheckedInArtifact(t *testing.T) { if err != nil { t.Fatalf("format generated metadata: %v", err) } - want, err := os.ReadFile(filepath.Join("..", "..", "internal", "fhirschema", "generated.go")) + want, err := os.ReadFile(filepath.Join("..", "..", "fhirschema", "generated.go")) if err != nil { t.Fatalf("read checked-in metadata: %v", err) } if !bytes.Equal(got, want) { - t.Fatal("checked-in internal/fhirschema/generated.go is stale; run make generate-fhir") + t.Fatal("checked-in fhirschema/generated.go is stale; run make generate-fhir") + } +} + +func TestFHIRStructGenerationMatchesCheckedInArtifacts(t *testing.T) { + schema := loadCheckedInGraphFHIRSchema(t) + for _, artifact := range []struct { + name string + generate func(*Schema, string) error + }{ + {name: "model.go", generate: generateModel}, + {name: "validate.go", generate: generateValidate}, + {name: "extract.go", generate: generateExtract}, + } { + t.Run(artifact.name, func(t *testing.T) { + generatedPath := filepath.Join(t.TempDir(), artifact.name) + if err := artifact.generate(schema, generatedPath); err != nil { + t.Fatalf("generate %s: %v", artifact.name, err) + } + got, err := os.ReadFile(generatedPath) + if err != nil { + t.Fatalf("read generated %s: %v", artifact.name, err) + } + got, err = format.Source(got) + if err != nil { + t.Fatalf("format generated %s: %v", artifact.name, err) + } + want, err := os.ReadFile(filepath.Join("..", "..", "fhirstructs", artifact.name)) + if err != nil { + t.Fatalf("read checked-in %s: %v", artifact.name, err) + } + if !bytes.Equal(got, want) { + t.Fatalf("checked-in fhirstructs/%s is stale; run make generate-fhir", artifact.name) + } + }) } } diff --git a/cmd/gqlgenfix/main.go b/cmd/gqlgenfix/main.go new file mode 100644 index 0000000..f54be25 --- /dev/null +++ b/cmd/gqlgenfix/main.go @@ -0,0 +1,66 @@ +// Command gqlgenfix corrects two invalid pointer returns emitted by the pinned +// gqlgen version for Loom's generated GraphQL types. +package main + +import ( + "fmt" + "os" + "strings" +) + +func main() { + if len(os.Args) != 2 { + fail("usage: gqlgenfix GENERATED_GO_FILE") + } + path := os.Args[1] + contents, err := os.ReadFile(path) + if err != nil { + fail("read %s: %v", path, err) + } + + source := string(contents) + source, err = replaceInFunction(source, + "func (ec *executionContext) unmarshalNJSON2", + "return &res, graphql.ErrorOnPath(ctx, err)", + "return res, graphql.ErrorOnPath(ctx, err)", + ) + if err != nil { + fail("fix JSON unmarshal return: %v", err) + } + source, err = replaceInFunction(source, + "func (ec *executionContext) unmarshalNFhirAggregateInput", + "return res, graphql.ErrorOnPath(ctx, err)", + "return &res, graphql.ErrorOnPath(ctx, err)", + ) + if err != nil { + fail("fix aggregate input unmarshal return: %v", err) + } + if err := os.WriteFile(path, []byte(source), 0o644); err != nil { + fail("write %s: %v", path, err) + } +} + +func replaceInFunction(contents, signature, old, replacement string) (string, error) { + start := strings.Index(contents, signature) + if start < 0 { + return "", fmt.Errorf("function %q not found", signature) + } + rest := contents[start:] + end := strings.Index(rest, "\n}\n") + if end < 0 { + return "", fmt.Errorf("function %q has no closing brace", signature) + } + function := rest[:end+3] + if strings.Contains(function, old) { + return contents[:start] + strings.Replace(function, old, replacement, 1) + rest[end+3:], nil + } + if strings.Contains(function, replacement) { + return contents, nil + } + return "", fmt.Errorf("function %q has neither expected return", signature) +} + +func fail(format string, args ...any) { + fmt.Fprintf(os.Stderr, format+"\n", args...) + os.Exit(1) +} diff --git a/docs/AQL_OPTIMIZATION_WORKLIST.md b/docs/AQL_OPTIMIZATION_WORKLIST.md new file mode 100644 index 0000000..dd465e8 --- /dev/null +++ b/docs/AQL_OPTIMIZATION_WORKLIST.md @@ -0,0 +1,577 @@ +# AQL optimization work list + +This is the post-measurement work list for Loom's physical dataframe +compiler. It is deliberately compiler-first: frontend work must not hide an +unbounded or repeatedly correlated AQL plan. + +It applies to every schema-defined FHIR relationship. Nothing below may +special-case Patient, GDC, `subject_Patient`, or a fixture resource type. +`fhirschema` remains the source of valid routes and selectors; the physical +optimizer decides whether a particular request can share work. The GDC case +matrix is an integration specimen that exercises fields, filters, aggregates, +pivots, slices, and nested traversal together; it is not the shape the +optimizer is allowed to recognize or optimize specially. + +## Measured starting point + +The checked-in GDC case-matrix request, run against the loaded `META` data, +has these measured characteristics: + +| Measure | Observation | +|---|---:| +| 1,000 rich Patient rows | about 8.15 seconds/request | +| Arango cursor time | about 8.10 seconds/request | +| compilation | about 1 millisecond/request | +| Loom row shaping | about 2 milliseconds/request | +| GraphQL serialization + HTTP | about 54 milliseconds/request | +| physical traversal sets | 6 | +| traversals shared today | 0 | +| broad sharing opportunities | 1 group / 3 sibling sets | +| repeated rich-set consumers | 4 sets | + +The broad sharing opportunity is the generic pattern “one parent variable, +one directed edge label, several target resource types.” In the current GDC +request it appears as Patient's `subject_Patient` traversals to Condition, +Specimen, and Observation. The current optimizer must not share it because +the full scoped subplans are not yet proven alpha-equivalent after variable +rebinding. + +Repeated rich consumers are also real, but distinct from repeated traversals: +Condition and Specimen each have two aggregates plus a slice; DocumentReference +has three aggregates plus a slice; Observation has two aggregates plus a +pivot. The relationship set is materialized once, then the current renderer +loops over it independently for each rich expression. + +## Non-negotiable contracts + +Every work package must preserve: + +1. result parity: row count, root order, columns, null/empty behavior, array + ordering, pivot collision behavior, and representative slice selection; +2. authorization and dataset-generation isolation on both traversed edge and + target node; +3. optional versus required traversal semantics; +4. bind-only user values and schema-validated selector paths; +5. generic operation over every valid schema route. + +Do not claim an optimization from rendered-AQL string similarity. Prove it +with physical-plan tests, old-versus-new result parity on Arango, and a live +`PROFILE` comparison of the same request. + +## Required benchmark and parity corpus + +Every optimization must run against a corpus of semantic shapes, not one +dataframe. Maintain these generic cases using routes discovered from +`fhirschema` and data loaded from `META` where available: + +| Case | What it protects | +|---|---| +| scalar root preview | root scope, sort, limit, and projection cost | +| one optional child | ordinary field selection and empty-child behavior | +| sibling targets on one edge label | generic traversal-prefix sharing | +| proven outbound route | direction-specific edge discriminator behavior | +| required relationship match | semi-join/root filtering semantics | +| child and nested filters | predicate placement and auth/generation scope | +| deep traversal (3+ hops) | captures, variable rebinding, and nested scope | +| aggregate-only child | count/distinct/exists value semantics | +| aggregate + slice over one set | prepared-set reuse without ordering drift | +| Observation-style pivot | grouped/keyed values and sparse columns | +| mixed rich dataframe | cross-feature composition; the GDC case matrix lives here | +| generated root sweep | every root resource type advertised by `fhirschema` compiles or rejects deterministically | + +Fixture names may describe their contents, but optimizer implementation and +tests must assert only physical properties: route equality, scope equality, +typed selector semantics, and output parity. A new route with the same +physical properties must receive the same rewrite without code changes. + +## WP0 — Make live Arango PROFILE the source of truth + +**Goal:** attribute the 8-second request to actual Arango executor nodes +before changing the renderer. + +### Implement + +1. Extend `internal/store/arango` with a profile operation for a parameterized + query. It must accept the generated AQL and bind variables without + interpolation. +2. Capture plan nodes, calls, items, filtered items, runtime, and estimated + cost wherever the installed Arango version provides them. Preserve warnings, + indexes, and applied optimizer rules already collected by `EXPLAIN`. +3. Add an opt-in dataframe diagnostic path; never run `PROFILE` on normal + frontend requests. A local-only GraphQL flag or a dedicated developer CLI + mode is acceptable. +4. Emit a stable, compact report grouped by node type and by AQL source + fragment: root scan, each traversal set, aggregate, pivot, slice, sort, + and return. +5. Save sanitized JSON profile artifacts for a small/medium/large sample of + the required corpus—not only GDC—under `docs/benchmarks/` or a gitignored + local artifact path. + +### Tests and gate + +- Unit-test profile JSON decoding against checked-in fixtures. +- Live tests: profile representative root, sibling, deep, required-match, and + pivot cases; assert the root scoped index and `fhir_edge` edge index are + selected with no full collection scan. +- Record the top five runtime nodes. Do not start WP1 until the profile output + identifies whether root sibling traversals dominate as expected. + +## WP1 — Canonicalize generic traversal prefixes + +**Goal:** represent the shareable prefix of any physical traversal without +depending on incidental variable names or semantic provenance. + +### Implement + +1. Add a typed `PhysicalTraversalPrefix` (or equivalent canonical helper) + containing source variable, direction, edge collection, edge label, edge + target-type discriminator, project/generation/auth constraints, and the + canonical node/edge variables used inside that prefix. +2. Split each child `PhysicalSet` into: + - a shareable traversal-and-scope prefix; + - a target-type subset; + - consumer-specific filters and nested work. +3. Implement alpha-renaming for target and edge variables across typed filters, + auth checks, selector extractions, required-match predicates, nested sets, + aggregate predicates, pivots, and slices. +4. Make the share key derive only from semantic physical behavior. It must not + include alias names, projection names, or `PhysicalSource` provenance. +5. Keep an explicit `not shareable` reason for each rejected set: different + direction, label, parent variable, scope, required/optional mode, or a + not-yet-supported operation. + +### Tests and gate + +- Table tests for alpha-equivalent prefixes with different generated variable + names. +- Negative tests for every rejection reason. +- Validate the rewritten plan before rendering; no renderer-only rewrite. +- At least one corpus sibling-route fixture must move from zero scope-safe + candidates to a proven candidate group, and a structurally equivalent route + with different FHIR resource types must share without a code change. + +## WP2 — Render shared neighbor traversals and typed subsets + +**Depends on:** WP1. + +**Goal:** execute one generic neighbor traversal for compatible siblings, then +derive each resource-type-specific child set from it. + +### Implement + +1. Add a physical operation for a shared neighbor set with a bind-backed list + of target types. +2. Render one correlated AQL subquery per parent row: + + ```aql + LET shared_neighbors = ( + FOR node, edge IN 1..1 INBOUND parent fhir_edge + FILTER scoped_edge_and_node_predicates + FILTER edge.label == @label + FILTER node.resourceType IN @target_types + RETURN node + ) + ``` + +3. Render each child as a typed subset of `shared_neighbors`; retain its own + target-type check and its consumer-specific predicates. +4. Preserve child ordering (`_key` or the existing explicit semantic order), + uniqueness, and empty-set behavior. +5. Support both INBOUND and proven OUTBOUND routes. Do not enable `ANY` until + a separate parity proof exists. +6. Keep required relationship matching as a semi-join. It may consume a shared + prefix only after proving that it does not accidentally materialize optional + output or change root filtering order. + +### Tests and gate + +- Result parity between unshared and shared plans for optional siblings, + filtered siblings, auth-restricted paths, empty sets, and nested children. +- Live parity for the sibling-route fixture, a deep traversal fixture, and the + mixed GDC matrix at 25 and 1,000 rows where the dataset contains that many + roots. +- `PROFILE` must show fewer traversal executor calls/items for the shared + sibling group and lower or equal total Arango runtime. If it does not, keep + the rewrite behind a cost gate rather than forcing it globally. + +## WP3 — Fuse rich consumers over one child set + +**Depends on:** WP0; can begin design in parallel with WP1. + +**Goal:** avoid re-scanning and re-extracting FHIR selectors independently for +every aggregate, pivot, and slice over the same child set. + +### Implement + +1. Add a typed `PhysicalPreparedSet` or `PhysicalSetProjection` operation, + owned by a child relationship set. +2. Collect the union of selector inputs required by that set's aggregates, + pivot key/value expressions, slice predicates/sort keys, and slice fields. +3. Render one bounded pass over the child set that produces a small prepared + object per child. It may contain the original node only when nested work + still requires it; otherwise project just the selected values. +4. Lower aggregate, pivot, and slice expressions to consume prepared values. + Preserve each feature's own null, distinct, predicate, collision, and sort + semantics. +5. Do not prepare selectors that are used once; require at least two consumers + or a profile-backed benefit. +6. Do not force unbounded arrays into memory. Keep representative slices + bounded, and retain aggregate streaming/grouping where Arango can do it. + +### Tests and gate + +- Unit parity for `COUNT`, `COUNT_DISTINCT`, `EXISTS`, `DISTINCT_VALUES`, + pivot collisions, null selectors, and sorted slices. +- Fixture assertions for aggregate/slice, aggregate/pivot, and nested-child + reuse sites across more than one resource family. +- `PROFILE` must show fewer selector/subquery executions and no increase in + returned intermediate items that erases the gain. + +## WP4 — Fuse compatible aggregates and pivots before prepared-set lowering + +**Depends on:** WP3 design; implementation may be folded into WP3 if simpler. + +**Goal:** exploit operations that can share more than selector extraction. + +### Implement + +1. Group aggregates with the same source and predicate into one AQL pass. +2. Group pivots with the same source/key/value/predicate and differing allowed + columns into one grouped map, then project requested column subsets. +3. Share predicate evaluation between aggregates and slices only when the + predicate is identical and preserving it does not affect slice ordering. +4. Maintain a deterministic operation ordering and stable bind-variable names + so Explain fixtures remain readable. + +### Tests and gate + +- Same-source / different-predicate operations remain separate. +- Same-source / same-predicate groups have byte-for-byte output parity. +- Observation pivot receives a dedicated live `PROFILE` gate because `COLLECT` + can be slower than separate bounded loops on sparse data. + +## WP5 — Predicate and required-match reuse + +**Depends on:** WP1 and WP2. + +**Goal:** eliminate duplicate graph work when the same relationship appears in +both a required root filter and an optional projected child set. + +### Implement + +1. Teach the physical plan to identify an `EXISTS`/required-match predicate + whose route and scope prefix match a materialized child set. +2. Retain root filtering before root `SORT`/`LIMIT`; do not turn a required + predicate into post-limit filtering. +3. Permit a shared root-scoped existence result only when it cannot leak child + data across authorization scopes. +4. Record reuse versus rejection in compiler-plan diagnostics. + +### Tests and gate + +- Required match plus optional projection parity for no match, one match, many + matches, restricted auth, and nested match routes. +- Live explain/profile demonstrates fewer duplicate edge traversals. + +## WP6 — Index and query-shape audit driven by PROFILE + +**Depends on:** WP0; repeat after WP2 and WP3. + +**Goal:** ensure the optimized AQL can use Arango's physical indexes rather +than merely containing the right filters. + +### Implement + +1. Inventory the actual root indexes used for project, generation, auth path, + `_key` sort, and root resource collection selection. +2. Inventory `fhir_edge` indexes used by direction. Confirm whether label and + type discriminators are post-filtered after the edge index and whether a + persistent composite index would materially reduce traversal fan-out. +3. Test candidate indexes against the loaded META data and a larger synthetic + fan-out fixture. Do not add every possible composite index by default; + index write cost matters for bulk ingest. +4. Compare root-first `LIMIT` placement, filter movement, and traversal + options only with result-parity proof. + +### Tests and gate + +- Explain assertions cover index name, fields, absence of collection scans, + and estimated item/cost regressions. +- Profile evidence justifies each new index and documents its ingest tradeoff. + +## WP7 — Cost model, diagnostics, and regression gates + +**Depends on:** WP0 through WP6 incrementally. + +**Goal:** make optimizer decisions observable and prevent a future renderer +change from silently restoring correlated work. + +### Implement + +1. Keep GraphQL diagnostics opt-in or development-only; production dataframe + responses should not expose compiler internals by default. +2. Report: traversal-set count, shared set count, scope-safe candidate count, + broader opportunity count, rejected reasons, and rich-source consumer + counts. +3. Add a compiler cost heuristic that only enables sharing/fusion when its + estimated savings exceeds extra materialization cost. Start conservative; + correctness and profile evidence outrank cleverness. +4. Add benchmark commands for 25, 100, and 1,000 rows with one cold run and + at least three warm runs. Print per-request—not cumulative—timings. +5. Track response bytes, returned rows, compile time, Arango execution, + serialization, profile node totals, and plan diagnostics together. + +### Acceptance gate + +The entire corpus must have committed baseline and post-change evidence. GDC +is one required mixed-feature case, not a privileged one. A performance claim +requires all of: + +- unchanged output result hash/canonical comparison; +- no authorization or generation-scope regression; +- no full collection scan or lost required index; +- lower profile work for the targeted node(s); +- lower or statistically neutral warm 1,000-row runtime. + +## Execution order and parallelism + +| Order | Package | Parallelism | Why | +|---:|---|---|---| +| 1 | WP0 profiling | alone | establishes the real target before rewrites | +| 2 | WP1 canonical prefix | alone | changes the physical IR contract | +| 3 | WP2 shared traversal | after WP1 | first high-value generic rewrite | +| 3 | WP3 prepared sets | design only alongside WP2 | implementation waits for stable IR | +| 4 | WP3 implementation | after WP2 profile | avoids optimizing the wrong cost | +| 5 | WP4 and WP5 | separate workers | distinct physical expression versus predicate ownership | +| 6 | WP6 | after each major rewrite | index choices require final query shapes | +| 7 | WP7 | continuous | gates every merge rather than a final cleanup | + +The first implementation target is therefore not “make the GDC query fast.” +It is “make every schema-defined sibling traversal safely shareable when the +typed physical plan proves it is equivalent,” then use `PROFILE` to verify the +benefit across the corpus, including—but never limited to—GDC. + +## Luna multi-agent execution map + +This work can use several Luna agents, but only one agent at a time may own a +physical IR or renderer contract. The safe unit of parallelism is a package +with a narrow output contract, not a broad instruction such as “optimize AQL.” + +### Coordinator responsibilities + +The coordinator owns these files and resolves all interface changes before +implementation workers begin: + +- `internal/dataframe/physical_plan.go` +- `internal/dataframe/physical_optimize.go` +- `internal/dataframe/physical_render.go` +- `internal/dataframe/physical_execution.go` +- `internal/dataframe/physical_diagnostics.go` + +The coordinator must publish one short interface note before the first merge: + +1. operation/type names and fields for traversal prefixes, shared sets, typed + subsets, and prepared sets; +2. ownership and lifetime of physical variables/captures; +3. which phase lowers, rewrites, validates, and renders each operation; +4. whether a new operation is enabled immediately or rendered behind an + explicit optimizer rule; +5. the canonical result-parity comparator and profile artifact format. + +No worker may rename or reshape those types independently. If a worker needs a +new field, it proposes the exact change and waits for the coordinator to add +it or approve it. + +### Wave A — independent foundations + +These packages may begin together because they do not change the physical plan +contract. + +| Worker | Scope and owned files | Deliverable | Merge gate | +|---|---|---|---| +| A1: Profile adapter | `internal/store/arango/`, new profile fixtures/tests | Parameterized `PROFILE` request/decoder, stable node summaries, warnings/index/rule capture | Unit fixtures plus a live opt-in profile test; no dataframe renderer edits | +| A2: Benchmark corpus | `conformance/compiler/fixtures/`, `examples/`, benchmark docs/tests | Route-neutral corpus described above, fixture loader helpers, canonical output comparator | Existing GDC remains; each fixture compiles or has deterministic rejection | +| A3: Diagnostics/CLI | `cmd/dataframe-query/`, GraphQL diagnostic mapping, docs | Opt-in display of plan facts, timing, profile artifact path; 25/100/1K benchmark commands | No optimizer behavior changes; works against server without diagnostics where practical | +| A4: Index audit | `internal/store/arango/` Explain helpers, integration tests, docs | Inventory of root/edge indexes and Explain/profile assertions for corpus shapes | No new persistent index without recorded profile evidence and ingest-cost note | + +**A-wave handoff:** A1 publishes `ProfileReport`; A2 publishes fixture IDs and +expected shape metadata; A3 consumes both as read-only contracts; A4 consumes +A1 reports. These workers should avoid editing the same generated GraphQL files +by having A3 own schema/model regeneration. + +### Wave B — traversal-sharing vertical slice + +These are sequential at the IR boundary but can overlap in test preparation. + +| Worker | Scope | Depends on | Deliverable | +|---|---|---|---| +| B1: Prefix IR | typed traversal-prefix decomposition and validator | coordinator interface note | canonical prefix and rejection-reason API; no changed runtime behavior yet | +| B2: Prefix tests | physical-plan fixture builders and alpha-renaming tests | B1 type signature | positive/negative equivalence corpus, auth/generation/required-match cases | +| B3: Shared renderer | optimizer rewrite plus renderer support | B1 merged; B2 tests available | one shared neighbor traversal plus typed subsets, initially behind a rule | +| B4: Sharing parity/profile | live Arango parity and profile comparisons | B3 | proof that the generic rewrite reduces traversal work for at least two distinct route families | + +Only B1 edits the initial prefix type. Only B3 edits sharing rewrite/rendering. +B2 and B4 may prepare code in parallel but must rebase on B1/B3 respectively. + +### Wave C — rich-expression reuse vertical slice + +This wave may begin its semantic/test work while Wave B is in progress, but it +must not merge physical-plan type changes until B1's prefix contract is fixed. + +| Worker | Scope | Depends on | Deliverable | +|---|---|---|---| +| C1: Prepared-set design | proposal plus tests for selector union and value lifetime | coordinator interface note | approved prepared-set IR contract and decision table for one versus many consumers | +| C2: Aggregate fusion | aggregate grouping tests and lowering helpers | C1 contract | same-source/same-predicate aggregate grouping with parity proof | +| C3: Pivot/slice reuse | pivot/slice test corpus and selector-extraction helpers | C1 contract | prepared-value consumers preserving collision, null, sort, and limit behavior | +| C4: Rich profile gate | profile comparison harness | A1 and C2/C3 | before/after node-level evidence for aggregate, pivot, and slice shapes | + +C2 and C3 have separate feature ownership. Neither may modify the other's +renderer branch; the coordinator integrates their operations after the +prepared-set contract is merged. + +### Wave D — cross-cutting reuse and hardening + +| Worker | Scope | Depends on | Deliverable | +|---|---|---|---| +| D1: Required-match reuse | physical required-match lowering and parity tests | B3 | shared-prefix reuse without changing pre-limit semi-join semantics | +| D2: Cost policy | optimizer decision heuristic and explainable rejection reasons | B3, C4 | conservative enablement rule, diagnostics, and disable switch | +| D3: Index changes | candidate index migrations/bootstrap plus measurement | A4, B4, C4 | only profile-justified index additions and documented ingest tradeoff | +| D4: Regression suite | corpus benchmark automation and result/profile artifact checks | A1–A4, B4, C4 | merge-blocking performance/parity gate | + +### Required worker prompt template + +Give each Luna worker a bounded prompt in this form: + +```text +You own . Do not edit . + +Objective: + + +Read first: +- docs/AQL_OPTIMIZATION_WORKLIST.md +- + +Contract: +- Inputs: +- Outputs: +- Must not: special-case FHIR resource names or change public dataframe results. + +Acceptance: +1. +2. +3. go test +4. report changed files, interface assumptions, and any coordinator decision needed. +``` + +### Merge discipline + +1. Merge Wave A first, but permit A1/A2/A3/A4 independent commits. +2. Merge B1 before any shared traversal renderer code. +3. Merge B2 test coverage before B3, then require B4 evidence before enabling + sharing by default. +4. Merge C1 contract before C2/C3 renderer work; merge C4 evidence before + enabling fusion by default. +5. Run the complete corpus after every coordinator merge, not only a worker's + narrow package tests. +6. If a physical IR conflict appears, stop the conflicting workers and have + the coordinator choose one contract; do not resolve it by retaining two + transitional representations. + +### Recommended initial allocation + +With four Luna workers plus a coordinator: + +- Worker 1: A1 profile adapter +- Worker 2: A2 generic fixture/benchmark corpus +- Worker 3: A3 diagnostics/CLI and GraphQL regeneration +- Worker 4: B2 traversal-sharing parity and alpha-renaming test design +- Coordinator: freeze B1 prefix IR after reviewing A2/B2 requirements, then + assign B1 and B3 sequentially. + +With eight workers, add A4, C1, C2 test preparation, and C3 test preparation. +Do not assign two workers to `physical_optimize.go` or `physical_render.go` at +the same time. + +## Execution status + +As of the current execution pass: + +- **Complete:** WP0 profile adapter and corpus profile fixtures. +- **Complete:** generic FHIR benchmark/parity corpus beyond GDC. +- **Complete:** compiler timing and plan diagnostics CLI path. +- **Complete:** B1 canonical traversal-prefix decomposition and rejection + reasons. +- **Complete:** B3 generic scope-safe sibling traversal sharing, including + recursive variable rebinding and typed subsets. It remains constrained to + decomposition-proven plans. +- **Complete:** WP3b recursive nested object rendering and recursive object + cycle validation. +- **Complete:** WP3/WP4 prepared-set reuse and aggregate/pivot/slice + consumer fusion for eligible child sets. +- **Complete:** WP6 profile-driven Explain/index corpus harness (live execution + remains opt-in with `LOOM_COMPILER_ARANGO_INTEGRATION=1`). +- **Complete:** WP5 required-match reuse: duplicate required EXISTS routes are + deduplicated only when their typed route/filter key is identical, with reuse + counted separately from optional traversal sharing. Required routes can also + materialize selected child fields after the pre-window semi-join. +- **Complete:** WP7 structural corpus regression gates, opt-in compiled-query + profiling API, generic Explain/profile artifacts, and the conservative + structural cost policy (`LOOM_PHYSICAL_COST_POLICY` / minimum-savings switch). +- **Complete:** WP8 compatibility renderer deletion and legacy test migration. + The production physical compiler is now the only dataframe compiler path; + the old lowered renderer, planner, named-set types, and compatibility-only + tests have been removed. + +The complete repository test suite is green after the completed packages. +Production and conformance code now use the physical compiler exclusively. + +## Explicit renderer completion packages + +The work packages above also require these two explicitly named renderer +packages. They were previously implicit and should be assigned as separate +Luna tasks. + +### WP3b — Nested object expression rendering + +**Depends on:** WP1 and the frozen physical expression contract. + +`PhysicalObjectExpression` exists in the IR and validator, but it must have a +real renderer before the compatibility renderer can be removed. + +Implementation: + +1. Add recursive `renderObject` support to `physical_render.go`. +2. Render every object field through `renderExpression`, including nested + objects, extracts, aggregates, pivots, slices, and optional child values. +3. Use bind-backed output names; never concatenate user-provided field names + into AQL source. +4. Preserve null/empty behavior and deterministic field ordering. +5. Support objects inside representative slices and nested traversal + projections. +6. Reject recursive physical object cycles during plan validation. + +Acceptance requires scalar-object, nested-object, object-with-pivot, and +object-with-slice fixtures plus live result parity. No object expression may +pass validation without a renderer test. + +### WP8 — Compatibility renderer deletion + +**Depends on:** WP2, WP3, WP3b, WP4, WP5, and the complete parity corpus. + +This is a gated package, not incidental cleanup: + +1. Prove repository-wide that `CompileRequest` is the only production + dataframe execution entrypoint. +2. Replace parity tests that depend only on compatibility AQL text with + semantic-result and live Arango parity tests. +3. Delete `compileLowered`, `Lower`, `lowerSemanticBuilder`, `NamedSet`, and + compatibility-only helpers/tests in dependency order. +4. Remove stale compatibility metadata while preserving any still-public API + fields. +5. Run the full corpus, GraphQL suite, Explain/profile suite, and generated-root + sweep after deletion. + +The deletion gate fails if any physical expression validates without rendering, +any production call site bypasses `CompileRequest`, or any parity fixture still +depends on compatibility-only output text. diff --git a/docs/COMPILER_CLEANUP_AUDIT.md b/docs/COMPILER_CLEANUP_AUDIT.md deleted file mode 100644 index a444255..0000000 --- a/docs/COMPILER_CLEANUP_AUDIT.md +++ /dev/null @@ -1,133 +0,0 @@ -# Compiler-Era Cleanup Audit - -This audit asks a narrower question than `go tool deadcode`: which package -tracks no longer belong in Loom now that dataframe requests have a real, -generation-aware FHIR compiler? It traces production call sites and storage -contracts as of this checkout. It does not treat a new compiler foundation as -dead merely because it has not yet reached the final product transport. - -## Runtime authority - -The executing dataframe path is: - -```text -POST /graphql - -> graphqlapi resolver - -> dataframebuilder.Service.Run - -> dataframe.Service - -> semantic validation / Lower - -> compileLowered - -> Arango QueryRows or Stream -``` - -The current compiler, catalog, generated FHIR metadata, loader, and Arango -client all remain live core. Generic lowering is real execution code; the -physical-plan renderer is currently an Explain/diagnostic foundation, not its -replacement. - -## Removed in this cleanup - -| Track | Why it was removed | Evidence | -| --- | --- | --- | -| Hard-coded GDC AQL CLI/exporter | It bypassed compiler validation and generation scope. Its default query performed unqualified document lookup and had no `dataset_generation` predicate. It was not an Elasticsearch delivery implementation. | The only command entries were `query-gdc-case-assay-matrix` and `export-gdc-case-assay-matrix`; the only integration dependency was its own raw-AQL assertion. | -| `queries/*.aql` | The files encoded GDC-specific rows, old `project::id` keys, or alternate edge collections which current ingest neither creates nor reads. | No generic compiler or catalog call site used them. | -| `/builder` browser page | The 1,062-line page hard-coded a GDC project, fields, pivots, and an eight-item edge-label map, then submitted raw graph-editor inputs. It did not build requests from compiler-safe catalog capabilities. | Its only production entry was `GET /builder`. | -| `patient_file_rollup` bootstrap collection | No loader wrote it and no compiler, query, or reader consumed it. Creating its indexes at every bootstrap advertised a materialization that did not exist. | References were limited to bootstrap, its bootstrap test, and docs. Existing operator-created collections are deliberately not dropped by this code cleanup. | -| `fhir_scalar_index` constant | It had no bootstrap, writer, reader, or test. | The declaration was its only reference. | - -The Docker image no longer copies manual AQL files. The legacy integration test -now verifies load/catalog behavior rather than an obsolete query recipe. - -## Package decisions - -| Area | Decision | Reason | -| --- | --- | --- | -| `cmd/arango-fhir-proto` | Keep as an operator surface, simplify | It now owns loading and catalog diagnostics only; the hard-coded GDC query/export commands were removed. | -| `cmd/arango-fhir-server` | Keep | It wires the compiler, catalog cache, authorization, GraphQL, and optional active-generation resolver. | -| `internal/api` | Keep, remove only the demo page | It is the HTTP host and principal-propagation boundary. The one-file import route is a separate compatibility decision. | -| `internal/graphqlapi` and generated model | Keep temporarily; stop extending | This is the live compiler transport. It should be replaced by the guided product contract in one deliberate schema/codegen cutover, not deleted piecemeal. | -| `internal/authscope` | Keep | It is the runtime authorization-scope contract used by catalog discovery and compiler execution. | -| `internal/store/arango` | Keep | It is the only executing backend and owns native query, lifecycle, and Explain operations. | -| `internal/fhir`, `internal/fhirschema`, `cmd/generate` | Keep | They are generator-owned FHIR/schema authority and support every active root. | -| `internal/ingest`, `fhir_edge`, `fhir_field_catalog` | Keep | They are the actual write path and compiler evidence layer. Do not prune traversal/index strategy without new Explain coverage. | -| `internal/catalog` and cache | Keep | They supply scoped observed fields, values, pivots, and relationship facts to both current GraphQL and guided discovery. | -| `internal/datasetstore` and `schemaidentity` | Keep | Immutable manifest/pointer lifecycle and exact schema identity are on the generation-aware read/write path. | -| `internal/dataset` read-binding helpers | Defer a focused decision | Some value types are only unit-tested while runtime reads use `authscope.ReadScope`; they are new lifecycle work, not an old compiler track. | -| `internal/dataframe` generic lowering | Keep and extend | It is the live compiler execution path for general requests. | -| Specialized Patient/case-assay lowering | Retain behind explicit deletion gates | It still changes semantics and shares sibling traversals more aggressively than generic lowering. | -| `internal/dataframe` physical plan/renderer | Retain as incomplete new compiler work | It is navigation-only Explain/diagnostic IR, not a stale pre-compiler implementation. Do not describe it as an execution replacement until it renders all semantic operations. | -| `internal/dataframebuilder` and current GraphQL AST | Keep temporarily; stop extending | They are the only public execution transport, but expose raw graph-editor concepts that conflict with the guided product contract. | -| `internal/discovery`, `recipe`, `recipecompiler`, `export`, `dataframeexport` | Keep as product foundations | They are intentionally not yet publicly wired; they are not duplicate AQL implementations. | -| Mutable CLI load and one-file HTTP import | Keep temporarily; do not extend | They remain reachable compatibility paths. Generation-mode server already rejects the HTTP route. Delete only with a complete bundle/job replacement. | -| `experimental/docker-compose.yml` | Keep | It is the tracked local Arango development runtime. | - -## Compiler correctness found during audit - -Generic lowering had one semantic inconsistency: an `AUTO` selection of a -repeated related field was documented as `FIRST` but rendered as a sorted unique -array. The generic lowering path now lowers it as deterministic `FIRST` and -sorts the related set by `_key`; the pre-existing specialized Patient behavior -is left unchanged pending its dedicated migration. Focused value-mode tests -cover both `AUTO` and `FIRST` traversal selection. - -## Do not delete the specialized Patient lowerer yet - -Deleting `planner.go`'s Patient/case-assay branch, `traversal_rules.go`, or -`document_reference_semantics.go` today would remove real behavior, not dead -code. The deletion requires all of the following: - -1. A generic sibling-prefix sharing pass that traverses the common Patient - neighbor prefix once, then applies resource-type subsets. The specialized - plan currently shares this work across Condition, Specimen, Observation, - and related children; generic sharing only recognizes identical target - types. -2. Explicit, authorization-scoped outbound lowering for - `ResearchSubject -> study -> ResearchStudy`. Current generic storage-route - validation correctly rejects the forward stored edge; the legacy lookup is - an implicit workaround, not an equivalent generic route. -3. Result-shape and Arango Explain/cost parity for representative patient, - specimen/file, DocumentReference, and study-enrollment fixtures. -4. An explicit product decision about GDC-style DocumentReference summaries. - That special logic chooses `content[0]`, applies code/display fallbacks, - and emits GDC classifications. If it is needed, it belongs in a named - manifest/recipe capability rather than generic FHIR lowering. - -Only then should the old set kinds, special traversal registry, lookup logic, -and legacy conformance fixtures be removed together. - -## Next cleanup boundaries - -These items are deliberately deferred rather than silently removed: - -- Current GraphQL exposes `cursor` and `selectionHint` that the input mapper - does not use, while the compiler has typed filters and required traversal - matching that GraphQL cannot express. Fix this in one transport cutover: - publish guided capabilities/recipe preview, then remove the raw GraphQL - graph-editor contract and regenerate gqlgen. -- The direct pre-lowered `Builder` surface contains legacy set/derived - operation variants and nested traversal fields with no runtime producer. - Encapsulate it after conformance fixtures compile request-level plans rather - than construct lowered internals directly; this avoids deleting a test-only - escape hatch while it is still a de facto API. -- `shaping.go` and `shaping_plan.go` are currently test-only normalization - helpers whose policies are not consumed by the executing renderer. Either - connect them to semantic lowering or remove/quarantine them in the same - lowered-IR encapsulation pass. -- `internal/dataset` has a few read-binding/fingerprint helpers used only by - their own tests, while live reads use `authscope.ReadScope` and - `datasetstore.ResolveActiveManifest`. They are newly added lifecycle - foundations, so decide whether to integrate or prune them in a dedicated - lifecycle pass rather than mixing that decision into removal of old code. - -## Verification expectation - -After any cleanup touching compiler behavior, run: - -```bash -GOCACHE=$(pwd)/.gocache GOTOOLCHAIN=auto go test ./... -make conformance -make compiler-bench -``` - -For traversal/index changes, also run the opt-in local Arango Explain gate from -[`COMPILER_IMPLEMENTATION_STATUS.md`](COMPILER_IMPLEMENTATION_STATUS.md). diff --git a/docs/COMPILER_FIRST_PLAN.md b/docs/COMPILER_FIRST_PLAN.md index 36812dc..bad1e84 100644 --- a/docs/COMPILER_FIRST_PLAN.md +++ b/docs/COMPILER_FIRST_PLAN.md @@ -36,14 +36,14 @@ This is not a greenfield compiler. ### Existing request and validation path -- `internal/graphqlapi/schema.graphqls` defines fields, traversals, pivots, +- `graphqlapi/schema.graphqls` defines fields, traversals, pivots, aggregates, slices, and value modes. -- `internal/dataframebuilder` maps and resolves GraphQL input. +- `graphqlapi/dataframe` maps and resolves GraphQL input. - `internal/dataframe/validation.go` validates fields and traversals against populated catalog records and generated schema metadata. -- `internal/fhirschema/generated.go` contains generated FHIR definitions and +- `fhirschema/generated.go` contains generated FHIR definitions and traversals. -- `internal/fhirschema/schema.go` resolves fields, selectors, traversals, and +- `fhirschema/schema.go` resolves fields, selectors, traversals, and pivot families. ### Existing lowering path @@ -266,7 +266,7 @@ a typed, backend-independent semantic request. ## Ownership - new `internal/dataframe/planner/semantic/` or equivalent -- adapters from `internal/dataframebuilder` +- adapters from `graphqlapi/dataframe` ## Tests and gates @@ -291,7 +291,7 @@ compiler knowledge base instead of maintaining a hardcoded Patient tuple list. ## Implementation -1. Inventory what `internal/fhirschema/generated.go` already records: +1. Inventory what `fhirschema/generated.go` already records: - definitions - properties/kinds - traversals @@ -321,7 +321,7 @@ compiler knowledge base instead of maintaining a hardcoded Patient tuple list. ## Ownership -- `internal/fhirschema/` +- `fhirschema/` - `cmd/generate/` only when necessary - no copied FHIR structs or handwritten replacement schema diff --git a/docs/COMPILER_IMPLEMENTATION_STATUS.md b/docs/COMPILER_IMPLEMENTATION_STATUS.md deleted file mode 100644 index b7e52de..0000000 --- a/docs/COMPILER_IMPLEMENTATION_STATUS.md +++ /dev/null @@ -1,198 +0,0 @@ -# Compiler-First Implementation Status - -This is a factual handoff/status document for the compiler-first program in -[`COMPILER_FIRST_PLAN.md`](COMPILER_FIRST_PLAN.md). It records what Loom can -actually do in this checkout, what evidence exists, and what still must not be -advertised as a finished product feature. - -## Current Contract - -Loom now accepts a typed dataframe request, resolves it against the checked-in -FHIR graph schema and populated catalog, and lowers supported requests into -authorization-scoped AQL. The generic path supports every concrete root type -currently generated from `schemas/graph-fhir.json`; it is not a claim of -universal support for every FHIR release or a resource not represented by that -schema. - -The checked-in schema currently produces 23 concrete dataframe roots: - -```text -BodyStructure, Condition, DiagnosticReport, DocumentReference, -FamilyMemberHistory, Group, ImagingStudy, Medication, -MedicationAdministration, MedicationRequest, MedicationStatement, -Observation, Organization, Patient, Practitioner, PractitionerRole, -Procedure, ResearchStudy, ResearchSubject, Specimen, Substance, -SubstanceDefinition, Task -``` - -The 14 cases in the optimized generated-loader dispatcher remain the fast -ingest path. The other active-schema roots use the existing generic, -schema-backed row builder. A resource type absent from the active graph schema -is deliberately rejected rather than guessed. - -## Implemented Compiler Work - -| Area | State in this checkout | Evidence / boundary | -| --- | --- | --- | -| Corpus and regression checks | Implemented | `conformance/compiler/` covers compiler fixtures, generated-root coverage, and benchmark entrypoints; `conformance/recipes/` freezes guided conversation examples. `make conformance` runs the suite and `make compiler-bench` runs the compiler oracle. | -| Semantic request and grain | Implemented | `SemanticPlan`, explicit root/row identity, typed selection, cardinality validation, and stable plan explanation live in `internal/dataframe/`. | -| Schema-derived roots and fields | Implemented | `cmd/generate` derives roots from the checked-in graph schema and verifies generated metadata stays fresh. No handwritten parallel FHIR model was introduced. | -| Generic FHIR graph lowering | Implemented, storage-route constrained | Generic root and traversal lowering work across the active generated root surface, while the older Patient path remains an optional specialized optimization. A related-resource route must have a compiler-owned stored-edge proof: generated reverse/builder routes map to `INBOUND`, and the explicitly proven `ResearchSubject --study--> ResearchStudy` route maps to `OUTBOUND`. Other schema-valid forward FHIR references remain rejected rather than compiled in the wrong direction. | -| Typed filters | Implemented | Root and child filters, date/date-time metadata, filter pushdown, scoped binds, and validation are represented before AQL generation. | -| Relationship existence | Implemented | `REQUIRED` traversal matches lower to bounded root-correlated semi-joins before root sorting and limiting; optional traversal behavior is retained. | -| Pivots and aggregates | Implemented | Bounded pivot shaping, stable values, and aggregate behavior have compiler tests. | -| Physical-plan contract | Partial | Typed generic physical plans, scope verification, and a navigation-only renderer exist. The renderer is not yet the execution compiler for selections, filters, pivots, aggregates, or required matches. | -| Optimizer rules | Implemented baseline | Filter pushdown, traversal sharing, and required relationship semi-join rules are explicit. Cost-based join choice and rollup selection are still future work. | -| Explain and Arango plan checks | Implemented baseline | Safe compiler explanation plus Arango `EXPLAIN` parsing/assessment are covered by unit tests and opt-in local integration tests. | - -## Observed Performance Evidence - -The opt-in local Arango gate runs generic lowering, required relationship -matching, specialized/generic result parity, root-preview index selection, and -the physical navigation renderer: - -```bash -LOOM_COMPILER_ARANGO_INTEGRATION=1 \ - GOCACHE=$(pwd)/.gocache GOTOOLCHAIN=auto \ - go test ./internal/dataframe -run 'Test(GenericSpecimenPlanExplainsAndRunsAgainstArango|GenericRootPreviewUsesScopedSortIndexAgainstArango|RenderedGenericPhysicalNavigationExplainsAgainstArango|GenericAndSpecializedPatientPlansHaveResultParityAgainstArango|RequiredTraversalMatchExplainsAndRunsAgainstArango)' -count=1 -v -``` - -The observed generic traversal plan uses the native `fhir_edge` edge index on -`_to` and has no full collection scan. Root preview compilation now needs the -project-plus-stable-key access path, so bootstrap creates `project,_key` and -`project,auth_resource_path,_key` indexes for every staged resource -collection—not just Patient or DocumentReference. - -That index is created at bootstrap for fresh loads. An already-loaded local -collection does not gain it until Loom bootstraps that collection again or an -operator adds the equivalent index. Do not read current local `EXPLAIN` cost -for an old collection as evidence that the new fresh-load index policy ran. - -## Ingest Safety Added Alongside the Compiler - -Before opening an Arango connection, `Load` now: - -1. loads the configured graph schema; -2. groups staged NDJSON files by their filename resource type; -3. samples a bounded number of payloads in each file to verify - `resourceType` and JSON shape; -4. reports generated, generic, or unsupported loader mode per resource; and -5. rejects the complete staged request before database bootstrap if any issue - exists. - -`PreflightError` preserves every structured issue for a future HTTP/CLI -presentation. Full validation still occurs while streaming the complete input, -so the bounded preflight does not pretend to validate an entire large import. - -Generic ingestion now also copies the auth-resource-path scope to its generated -edges. This keeps the generic fallback subject to the same edge authorization -predicates used by lowering and catalog discovery. - -`internal/schemaidentity` fingerprints the exact configured schema bytes and -exposes only source-explicit schema metadata plus this binary's generated FHIR -roots. `LoadSummary` and preflight telemetry carry that identity before Arango -is opened, and immutable generation manifests persist a defensive schema -snapshot rather than inventing a second identity representation. - -`internal/datasetstore` persists the C1 lifecycle in the non-truncating -`loom_dataset_lifecycle` collection: immutable project/generation manifests, -PREFLIGHT/LOADING/ANALYZING/READY/terminal transitions, and one active pointer -per project. Activation is one guarded AQL operation that selects a READY -candidate and supersedes the prior active generation atomically. - -`ingest.Load` keeps the old mutable behavior when `LoadOptions.Dataset` is nil. -With a validated dataset reference, it requires a complete nonempty directory, -runs schema and payload preflight before opening Arango, prohibits truncation, -namespaces vertex/edge physical keys by project and generation, writes -immutable graph and field-catalog documents, then activates only after all -files and catalog finalization succeed. Any row, edge, generation, -cancellation, or catalog failure leaves the manifest FAILED; a READY activation -transport failure is reported as an unknown outcome rather than falsely marking -it failed. The one-file loader intentionally rejects generation mode. - -The CLI command `arango-fhir-proto load-generation --generation OPAQUE_ID` -owns that complete-directory load path. `arango-fhir-server ---dataset-generations` resolves the active READY manifest before dataframe -discovery/execution and disables the legacy one-file `/api/v1/imports` route. -There is not yet an HTTP bundle-upload or background-load endpoint. - -## Thin Product Foundation Added - -The product layer deliberately stays independent from FHIR paths and AQL: - -- `internal/recipe` defines versioned recipe intent, opaque selected-column and - filter IDs, destination intent, and six stable starting templates. -- `ListTemplates` and `LookupTemplate` provide the user-facing options: - patient cohort, specimen inventory, file manifest, diagnoses, - labs/observations, and study enrollment. -- Existing `internal/dataframebuilder.Introspect` already queries the populated - field catalog, bounded distinct values, pivot candidates, and observed - one-hop relationships under caller project and authorization scope. This is - the live source for the proposed “include” and “only include” controls. -- `dataframebuilder.Service.DiscoverGuided` now composes those existing scoped - catalog readers into `internal/discovery.Snapshot`: generated-schema roots, - compiler-safe observed relationships, opaque candidate-column IDs, and - bounded guided filter suggestions. It intentionally has no GraphQL/HTTP - exposure yet. When an active-manifest resolver is configured, the snapshot, - authorization scope, catalog facts, compiler, and execution are all pinned - to the same immutable generation. -- `internal/recipecompiler.Build` and - `dataframebuilder.Service.PrepareRecipe`/`RunRecipe`/`StreamRecipe` resolve - those opaque IDs only against fresh, authorization-scoped catalog facts into - typed **root-only scalar** dataframe plans. They can preview or stream the - result through the existing compiler without accepting a browser-supplied - FHIR selector, graph label, or AQL fragment. A stale, related-resource, - repeated, pivot-only, raw-path, or pinned-generation choice is rejected - rather than guessed. -- `internal/export` now has strict flat-row NDJSON and CSV encoders, and - `internal/dataframeexport` connects them to `dataframe.Service.Stream` - without collecting result rows. They remain foundations only: no artifact - storage, jobs, public endpoint, stable generation snapshot, or Elasticsearch - transport exists yet. Inferred CSV deliberately replays the query; explicit - CSV columns are a single streaming execution. -- `dataframe.Service.Stream` now executes the same validated request path as a - preview while handing flattened rows to a caller one at a time. When the - service is configured with the active-generation resolver, it uses the same - immutable-generation binding as preview execution. It has not yet been - exposed as a delivery endpoint. - -The root-only bridge is deliberately not a claim that every recipe template is -currently executable. Relationship columns/filters, pivots, repeated-value -quantifiers, aggregates, and recipes pinned to an immutable dataset generation -still need explicit contracts and generation-bound capability facts. The next -bridge extension must preserve the same rule: it may resolve only capabilities -emitted for the current project/generation/scope, never an arbitrary FHIR path -or AQL snippet from a browser recipe. - -## Still Deliberately Incomplete - -The following are planned work, not present-product claims: - -- a public guided-capability API that joins template, observed catalog data, - and compiler support reasons; -- GraphQL/REST exposure for typed filters, required relationship match modes, - recipe creation, and safe compiler explanation; -- a full physical-plan renderer wired into execution; -- cost-based traversal/index/rollup choice and enforced scan/memory budgets; -- cursor-stable row streaming from the Arango driver; -- durable NDJSON/CSV export files, background jobs, cancellation, and retry; -- Elasticsearch transport, mapping policy, idempotency, and failure recovery; -- readiness/dependency diagnostics and production deployment controls. - -## Correct Integration Order - -1. Persist the next analysis/capability snapshot beside the now-bound immutable - dataset generation, then expose it through one public guided-capability - response. -2. Extend the existing capability-to-typed-request resolver only after its - relationship, cardinality, and generation-binding contracts are explicit; - make recipe validation call it before preview/export. -3. Wire the existing row result path to bounded streaming output and then add - durable delivery jobs around that same stream. -4. Bind reusable recipes and asynchronous delivery to an active generation and - its future analysis version; do not infer either from a mutable project. -5. Extend physical execution only when every new physical operator has result - parity and `EXPLAIN` evidence against the generic reference path. - -This order keeps a small guided UI possible without turning the browser into a -FHIR/AQL compiler or claiming support that the backend cannot prove. diff --git a/docs/DEVELOPER_ARCHITECTURE.md b/docs/DEVELOPER_ARCHITECTURE.md index 3f18ac2..f83e12f 100644 --- a/docs/DEVELOPER_ARCHITECTURE.md +++ b/docs/DEVELOPER_ARCHITECTURE.md @@ -19,11 +19,8 @@ FHIR model or a parallel AQL implementation. developer GraphQL tools. In `--dataset-generations` mode it resolves one active READY generation and rejects the legacy one-file HTTP import endpoint. -The GraphQL dataframe mutation is a live compatibility/expert transport to the -compiler, not the intended non-technical product UI. Do not add graph-editor -features to it. Guided discovery and recipe preparation live below transport -in `internal/dataframebuilder`, `internal/discovery`, and -`internal/recipecompiler` until the dedicated product endpoint is added. +The GraphQL dataframe mutation is the live compiler transport. Do not add a +second query compiler or hand-maintained AQL path behind another endpoint. ## Load and storage model @@ -47,8 +44,8 @@ as a compiler-selected physical optimization with write/read ownership, generation scope, freshness policy, and Explain coverage; it must not be added as an unused bootstrap collection. -Immutable loads use `internal/dataset`, `internal/datasetstore`, and -`internal/schemaidentity`. Their manifest records project, generation, and +Immutable loads use `internal/dataset`, `internal/dataset/arango`, and +`internal/graphschema`. Their manifest records project, generation, and schema identity; the active pointer selects one READY generation per project. The generation-qualified physical keys and mandatory generation predicates are part of the query correctness contract, not an optional filter. @@ -69,7 +66,7 @@ GraphQL request `internal/dataframe` owns semantics, authorization-aware query compilation, and execution. `internal/catalog` owns scoped observed-field and relationship -facts. `internal/fhirschema` owns generated structural metadata. These +facts. `fhirschema` owns generated structural metadata. These boundaries matter: catalog observations constrain what is populated, while schema metadata constrains what a request means. @@ -80,46 +77,20 @@ layout, plus the explicitly proven `ResearchSubject --study--> ResearchStudy` sufficient proof; every other forward route remains rejected until it has a verified storage contract. -The older specialized Patient/case-assay lowerer is still production-reachable -for selected request shapes. It cannot be deleted merely because generic -lowering exists: it currently supplies shared sibling traversal behavior, -DocumentReference normalization, and ResearchSubject-to-ResearchStudy lookup -semantics. See [`COMPILER_CLEANUP_AUDIT.md`](COMPILER_CLEANUP_AUDIT.md) for its -explicit removal gates. - `internal/dataframe/physical_plan.go` and its renderer are a typed diagnostic and optimization foundation. They are not yet the execution renderer for all selections, filters, aggregates, pivots, and required relationships. Keep them as new compiler work rather than treating their current limited runtime reachability as dead code. -## Product foundations - -The product-facing contract should exchange opaque catalog capability IDs and -recipe intent, never browser-provided FHIR selectors, graph labels, auth paths, -or AQL. Relevant ownership is: - -- `internal/discovery`: scoped guided capability snapshots; -- `internal/recipe`: versioned user intent and templates; -- `internal/recipecompiler`: capability-to-typed-dataframe translation; -- `internal/export` and `internal/dataframeexport`: flat NDJSON/CSV streaming - primitives. - -These are foundations, not a claim that the product API, job system, saved -recipes, Elasticsearch delivery, or all relationship/pivot recipes are done. -Keep the boundary clean so those features can be added without reviving a -hand-maintained AQL track. - ## Compatibility tracks and removal order The following compatibility tracks remain deliberately, but should not grow: - mutable CLI `load` and `POST /api/v1/imports`, until a complete generation-aware upload/job flow replaces them; -- raw-structure GraphQL dataframe input, until guided capability/recipe - transport is public; -- specialized Patient lowering, until generic lowering has equivalent result - and Explain/cost coverage. +- raw-structure GraphQL dataframe input, until a deliberately designed guided + transport exists. The former hard-coded GDC AQL files, GDC export command, browser `/builder` demo, and unowned bootstrap materializations were removed. They bypassed the @@ -129,7 +100,7 @@ compiler and did not work with immutable generation keys. Run `make generate-fhir` after changing the graph schema and `make generate-graphql` after changing the GraphQL schema. Do not hand-edit -generated FHIR or gqlgen output. +generated `fhirstructs`, compiler metadata, or gqlgen output. The normal verification targets are: diff --git a/docs/FORMAL_GAP_ANALYSIS.md b/docs/FORMAL_GAP_ANALYSIS.md index c19e2da..0522853 100644 --- a/docs/FORMAL_GAP_ANALYSIS.md +++ b/docs/FORMAL_GAP_ANALYSIS.md @@ -77,8 +77,8 @@ The repository already contains valuable production-shaped components: - the 14-resource development dataset under `META/` and smaller `META_SMALL/` - the active graph schema at `schemas/graph-fhir.json` -- generated Go FHIR structs, validators, and edge extractors in `internal/fhir` -- generated FHIR field/traversal metadata in `internal/fhirschema/generated.go` +- generated Go FHIR structs, validators, and edge extractors in `fhirstructs` +- generated FHIR field/traversal metadata in `fhirschema/generated.go` - existing generation commands in `cmd/generate`, `Makefile`, and `gqlgen.yml` - NDJSON and gzip discovery and scanning in `internal/ingest` - generated and generic FHIR row builders @@ -238,7 +238,7 @@ fail during preflight with a complete report rather than partway through load. ## Implementation plan -1. Add `internal/schemaidentity` with: +1. Maintain `internal/graphschema` with: - `FHIRVersion` - `SchemaName` - `SchemaVersion` @@ -269,7 +269,7 @@ fail during preflight with a complete report rather than partway through load. ## Files and packages -- add `internal/schemaidentity/` +- maintain `internal/graphschema/` - modify `internal/ingest/load.go` - modify `internal/ingest/row_builder.go` - modify `internal/ingest/generated_load.go` or generation output contract @@ -605,7 +605,7 @@ semantics and declare capability requirements without embedding canned AQL. - sensitivity classification 4. Define `SemanticRelationship` separately from physical edge labels. 5. Consolidate the mechanically derived field references in - `internal/dataframebuilder/fieldrefs.go` and the optimized traversal roles in + `graphqlapi/dataframe/fieldrefs.go` and the optimized traversal roles in `internal/dataframe/traversal_rules.go` behind these stable concepts. Avoid leaving product semantics split across unrelated packages. 6. Implement initial template definitions for all six product families. @@ -651,7 +651,7 @@ options, value suggestions, validation, and explanation. ## Implementation plan -1. Add `internal/productapi` or extend `internal/dataframebuilder` only if the +1. Add `internal/productapi` or extend `graphqlapi/dataframe` only if the latter remains semantically accurate. 2. Implement service methods: - `DatasetSummary` diff --git a/docs/LUNA_COMPILER_FINALIZATION_PLAN.md b/docs/LUNA_COMPILER_FINALIZATION_PLAN.md new file mode 100644 index 0000000..25a85f1 --- /dev/null +++ b/docs/LUNA_COMPILER_FINALIZATION_PLAN.md @@ -0,0 +1,646 @@ +# Luna Execution Plan: Finish the Physical Compiler and Delete Compatibility Lowering + +## Outcome + +Complete the remaining physical compiler features and remove the compatibility +compiler. The final production request path must be: + +```text +GraphQL input + -> graphqlapi/dataframe input mapping + -> dataframe.Builder + -> BuildSemanticPlan + -> BuildPhysicalPlan + -> physical optimization + -> RenderPhysicalPlan + -> Arango execution +``` + +The following symbols must have no production definition or call site when the +plan is finished: + +- `Compile` +- `Lower` +- `lowerSemanticBuilder` +- `compileLowered` +- `NamedSet` +- `DerivedField` +- lowered-only `RepresentativeSlice` +- `compiler` and its string-oriented helper methods + +Do not copy old AQL string helpers into the physical renderer. Migrate their +semantic meaning into typed physical operations, prove execution parity, then +delete the old implementation. + +## Repository facts Luna must use + +This repository already contains the FHIR backbone. Do not infer FHIR paths or +relationships from fixture names. + +- `fhirstructs/`: generated FHIR Go structs, validation, and edge extraction. +- `fhirschema/`: generated resource, selector, traversal, and pivot metadata. +- `META/`: real sample FHIR NDJSON. +- `internal/dataframe/storage_route.go`: authoritative physical edge-direction + evidence. Unknown outbound/ANY routes remain compiler errors. +- `internal/dataframe/semantic_plan.go`: backend-independent request meaning. +- `internal/dataframe/physical_plan.go`: typed renderer-independent execution + IR. +- `internal/dataframe/generic_physical_plan.go`: current semantic-to-physical + lowering. +- `internal/dataframe/physical_render.go`: current physical AQL renderer. +- `graphqlapi/schema.graphqls`: public input/output contract. +- `conformance/compiler/fixtures/`: compiler fixtures. + +Use `fhirschema` validation for selector/pivot decisions and the populated +catalog for bounded pivot columns. Never add Patient-, GDC-, or fixture-specific +compiler branches. + +## Current physical coverage + +The physical route currently handles: + +- root fields and typed filters; +- optional child fields and typed child filters; +- required traversal matches; +- inbound and proven outbound storage routes; +- root and child aggregates: `COUNT`, `COUNT_DISTINCT`, `EXISTS`, + `DISTINCT_VALUES`, `MIN`, `MAX`, plus predicate-qualified reductions; +- root execution window and generation/auth/project scope. + +The remaining production fallback reasons should be limited to: + +- pivots; +- representative slices; +- nested optional shapes that exceed current physical-set nesting; +- any legacy-only `Builder.DerivedFields`/`Builder.Sets` request assembled + directly by Go callers; +- compatibility traversal-sharing representation. + +Before changing code, run and record: + +```bash +GOCACHE="$(pwd)/.gocache" GOTOOLCHAIN=auto go test ./... -count=1 +GOCACHE="$(pwd)/.gocache" GOTOOLCHAIN=auto go test ./conformance/compiler -bench BenchmarkCompilerOracle -benchmem -run '^$' +``` + +Preserve unrelated dirty-worktree changes. + +## Compiler invariants + +Every work package must retain these properties: + +1. One outer root loop, one returned object per root resource. +2. Required semi-joins execute before root `SORT`/`LIMIT`; optional child work + executes after the root preview window. +3. Every scanned root, child node, and edge is constrained by project, + dataset generation, and authorization scope. +4. Request values, resource types, edge labels, selectors, pivot keys, limits, + and output names never become unvalidated AQL source. +5. Empty-set, null, scalar, array, distinct-array, and fallback behavior is + explicit in physical IR and covered by result tests. +6. Nested optional traversal never becomes a top-level `FOR` and never + multiplies root rows. +7. Stable ordering is explicit. Do not rely on Arango traversal, `UNIQUE`, or + hash-map iteration order. +8. Unsupported routes and expressions fail before rendering. + +## Work package F0 — Inventory legacy meaning before migration + +**Goal:** prove which legacy concepts represent public semantics and which are +only compatibility IR. + +**Read-only inputs** + +- `internal/dataframe/lowered_types.go` +- `internal/dataframe/planner.go` +- `internal/dataframe/generic_lowering.go` +- `internal/dataframe/lowered_compile.go` +- `graphqlapi/dataframe/input_mapping.go` + +**Deliverable:** add a table-driven test or checked-in Markdown table mapping +every legacy operation: + +| Legacy operation | Physical owner | +| --- | --- | +| `ROOT_FIELD` | `PhysicalExtract` scalar | +| `FIRST_NON_NULL` | `PhysicalExtract` with fallbacks, scalar | +| `ALL` | `PhysicalExtract` array | +| `UNIQUE` | `PhysicalExtract` distinct array | +| `COUNT` | `PhysicalAggregate(COUNT)` | +| `COUNT_DISTINCT` | `PhysicalAggregate(COUNT_DISTINCT)` | +| `COUNT_WHERE` | predicate-qualified `PhysicalAggregate(COUNT)` | +| `ANY` | predicate-qualified `PhysicalAggregate(EXISTS)` | +| `MIN`/`MAX` | typed physical aggregates | +| `PIVOT` | `PhysicalPivotMap` | +| representative slice | `PhysicalSlice` | +| `CONST` | classify as public requirement or legacy-only artifact | + +`CONST` must not be added to the physical compiler unless a current GraphQL +input or production caller requires it. If it exists only in tests/manual +lowered builders, delete that support at final cutover. + +**Acceptance:** every `DerivedOp*` constant has an explicit migration or +deletion decision. No worker may create `PhysicalDerivedField` as a generic +replacement for the old union. + +## Work package F1 — Eliminate “derived fields” as a runtime concept + +**Goal:** ensure every public output currently represented as `DerivedField` +is produced directly from `SemanticNode` by typed physical expressions. + +**Files** + +- `internal/dataframe/semantic_plan.go` +- `internal/dataframe/selection_semantics.go` +- `internal/dataframe/generic_physical_plan.go` +- `internal/dataframe/physical_plan.go` +- new `internal/dataframe/physical_derived_parity_test.go` + +**Implementation** + +1. Enumerate all places where `planner.go` creates `DerivedField`. +2. For field value modes: + - `FIRST`/`AUTO` -> scalar `PhysicalExtract` with ordered fallbacks; + - `ALL` -> array `PhysicalExtract`; + - `DISTINCT` -> distinct-array `PhysicalExtract`. +3. For aggregate-derived outputs, use `SemanticAggregate` and + `PhysicalAggregate`; do not lower them through `DerivedField`. +4. For pivot-derived outputs, wait for F2 and lower from `SemanticPivot`. +5. For representative outputs, wait for F3 and lower from `SemanticSlice`. +6. Ensure `CompiledQuery.Columns` and `PivotFields` come from final physical + return metadata, not compatibility builder arrays. +7. Add a test that builds representative public GraphQL shapes, runs + `BuildSemanticPlan`, and proves the physical plan contains no dependency on + `NamedSet` or `DerivedField`. + +**Parity matrix** + +- root scalar/array/distinct/fallback field; +- child scalar/array/distinct/fallback field; +- count/count-where/any/min/max; +- empty child set and all-null selector values. + +**Deletion gate:** after parity, remove production reads of +`Builder.DerivedFields` from `CompileRequest` routing. Directly constructed +legacy builders may remain test-only until F7. + +## Work package F2 — Physical pivots + +**Goal:** lower root and child `SemanticPivot` directly to `PhysicalPivotMap` +and render a bounded object without request-derived AQL keys. + +**Files** + +- `internal/dataframe/physical_plan.go` +- `internal/dataframe/generic_physical_plan.go` +- `internal/dataframe/physical_render.go` +- `internal/dataframe/physical_execution.go` +- `internal/dataframe/pivots.go` +- new `internal/dataframe/physical_pivot_test.go` +- optional `internal/dataframe/physical_pivot_arango_integration_test.go` + +**Preconditions** + +- `Service.expandPivotColumns` has populated a non-empty bounded column list. +- `BuildSemanticPlan` has validated both selectors through + `fhirschema.ValidatePivotSelectors`. + +**IR changes** + +Review the existing `PhysicalPivotMap`. Extend it only if needed to encode: + +- source cardinality: root singleton vs physical child set; +- collision behavior; +- empty/absent column behavior; +- output column order; +- optional value distinctness if required by current behavior. + +Do not add a raw map/AQL expression field. + +**Lowering** + +1. Root pivot source is the root document payload. +2. Child pivot source is the owning `PhysicalSet` variable. +3. Copy parsed key/value selectors and bounded columns into typed IR. +4. Store the column list in a bind variable with a deterministic compiler key. +5. Add the pivot expression to the final return using the semantic name and + mark the projection as a pivot for `CompiledQuery.PivotFields`. + +**Rendering** + +Render a fixed subquery equivalent to: + +```aql +MERGE( + FOR item IN source + FOR key IN key_values + FILTER key IN @allowed_columns + LET values = value_values + COLLECT pivot_key = key INTO grouped + RETURN { [pivot_key]: stable_collision_value(grouped) } +) +``` + +Use the existing legacy tests to determine the exact collision value. Do not +choose `FIRST`, `LAST`, or array aggregation without parity evidence. + +**Tests** + +- root and child pivots; +- sparse column set; +- duplicate key with multiple values; +- array key selector and array value selector; +- empty result object; +- requested keys absent from data; +- bind-safety test proving column strings do not appear in AQL source; +- deterministic output/pivot-field ordering. + +**Live gate:** run a real Observation pivot over `META`, compare legacy and +physical JSON rows, and require no full collection scan plus traversal-edge +index use. + +**Deletion gate:** remove production calls to `compileRootPivot`, +`compilePivotField`, `compileDerivedPivotMapLets`, +`compilePivotMapExpr`, and `compilePivotMapProjection`. + +## Work package F3 — Physical representative slices + +**Goal:** lower `SemanticSlice` to a stable, bounded `PhysicalSlice` for root +and child sources. + +**Files** + +- `internal/dataframe/physical_plan.go` +- `internal/dataframe/generic_physical_plan.go` +- `internal/dataframe/physical_render.go` +- new `internal/dataframe/physical_slice_test.go` +- optional `internal/dataframe/physical_slice_arango_integration_test.go` + +**IR contract** + +`PhysicalSlice` must encode: + +- typed source; +- optional typed predicate; +- deterministic primary sort and `_key` tie breaker; +- positive bind-backed limit; +- ordered nested object projections; +- empty-set behavior (`[]`). + +If the current `Sort` field cannot express primary plus tie-break ordering, +replace it with an ordered `[]PhysicalSortKey`; do not rely on implicit order. + +**Lowering** + +1. Root slice source is the singleton root document. +2. Child slice source is the physical set for its semantic node. +3. Reuse the typed selector/filter lowering used by child filters and aggregate + predicates. +4. Lower each `SemanticSlice.Fields` entry via `ResolveSemanticField`. +5. Bind the limit. Reject zero/negative limits in semantic or physical + validation. + +**Rendering order** + +```aql +FOR item IN source + FILTER typed_predicate + SORT typed_primary, item._key + LIMIT @slice_limit + RETURN { bound_name: typed_projection, ... } +``` + +This subquery belongs inside the returned root object and must not affect the +outer root limit. + +**Tests** + +- zero/one/many source items; +- deterministic tie behavior; +- predicate with and without equality literal; +- scalar/fallback/array nested fields; +- root and child slice; +- auth/generation-scoped source; +- limit is a bind, not an AQL literal. + +**Deletion gate:** remove production calls to `compileRepresentativeSlice`, +`compileRootSlice`, `compileSetSlice`, `compileSliceProjection`, and their +predicate-string helpers after all slice fixtures use physical execution. + +## Work package F4 — Fully general nested optional shaping + +**Goal:** allow any supported field/filter/aggregate/pivot/slice at any proven +optional traversal depth without reopening traversal paths or multiplying root +rows. + +**Files** + +- `internal/dataframe/generic_physical_plan.go` +- `internal/dataframe/physical_plan.go` +- `internal/dataframe/physical_render.go` +- `internal/dataframe/physical_scope.go` +- new `internal/dataframe/physical_nested_shape_test.go` + +**Current limitation to remove** + +Delete every `genericPhysicalNodeUnavailableReason` or lowering rejection for a +child that simultaneously has nested children and selections/shaping. + +**Lowering model** + +1. Each optional semantic child owns exactly one `PhysicalSet`. +2. A nested set captures the parent set-element variable within the parent + subplan. It must not capture the entire parent set and re-flatten unrelated + rows. +3. The owning child output is a typed `PhysicalObject` containing fields, + aggregates, pivots, slices, and nested child objects/arrays. +4. Parent output cardinality is explicit: + - child array projection remains an array; + - scalar representative uses the semantic value mode; + - nested child results remain correlated to their parent item. +5. Route resolution happens once per semantic edge through + `resolveStorageRoute`. + +**Scope proof** + +Extend `PhysicalPlan.Validate` and `ValidateGenericPhysicalPlanScope` to walk +nested subplans recursively. Every traversal inside a subplan must prove edge +and node project/generation/auth predicates before its return or nested set. + +**Required tests** + +- Patient -> Specimen -> DocumentReference fields and aggregates; +- Patient -> Specimen -> Group -> DocumentReference; +- mixed optional and required branches; +- same alias at different depths does not collide; +- zero/many children preserve root count; +- nested outbound ResearchSubject -> ResearchStudy; +- invalid capture and out-of-scope variable rejection. + +**Acceptance:** the checked-in GDC-style dataframe runs physically with no +unsupported nested-shaping reason. + +## Work package F5 — Traversal-prefix sharing optimization + +**Goal:** optimize equivalent physical traversal prefixes after unoptimized +plans have full parity. + +**Files** + +- new `internal/dataframe/physical_optimize.go` +- new `internal/dataframe/physical_optimize_test.go` +- `internal/dataframe/physical_execution.go` +- physical explain/benchmark files + +**Placement** + +```text +SemanticPlan -> BuildPhysicalPlan -> OptimizePhysicalPlan -> RenderPhysicalPlan +``` + +The semantic lowerer must always be capable of producing a correct unshared +plan. Sharing is never performed while walking `SemanticNode`. + +**Equivalence key** + +Two set/traversal prefixes can share only when all match: + +- parent capture identity; +- depth; +- direction; +- edge collection; +- edge label; +- project bind; +- dataset-generation bind; +- authorization scope inputs; +- filter prefix before target-type specialization; +- target edge-type discriminator field. + +Do not include target resource type in the broad-prefix key. Instead, only +after sharing, create typed subsets with both edge discriminator and node +`resourceType` filters. + +**Rewrite** + +1. Hash eligible prefixes by the equivalence key. +2. Keep groups with at least two consumers and at least two target types. +3. Introduce one broad set with a compiler-generated variable. +4. Rewrite each consumer to a typed filtered subset. +5. Preserve consumer request order and source provenance. +6. Re-run physical validation after rewriting. + +**Tests** + +- sibling sharing at root and nested depth; +- differing labels/directions/scopes/filters never share; +- same label but one target type does not create useless broad set; +- optimized/unoptimized execution parity; +- stable deterministic plan across runs; +- no target-type leakage. + +**Performance gate:** live Explain estimated cost and measured warm execution +must be neutral or better on the GDC fixture. Disable the rewrite if it +regresses the representative query. + +**Deletion gate:** remove compatibility `NamedSet` traversal/filter/union and +generic sibling-sharing lowering only after physical sharing owns equivalent +cases. + +## Work package F6 — Result parity and cost benchmark matrix + +**Goal:** make compiler correctness and performance measurable before deleting +the oracle. + +**Files** + +- `internal/dataframe/physical_renderer_parity_test.go` +- new `internal/dataframe/physical_rich_arango_integration_test.go` +- `conformance/compiler/fixtures/` +- `conformance/compiler/benchmark_test.go` +- `cmd/dataframe-query/` +- `examples/` + +**Fixture families** + +1. root fields/filters; +2. child fields/filters; +3. required inbound and outbound match; +4. aggregates with empty/non-empty/predicate cases; +5. root and child pivots; +6. root and child slices; +7. three- and four-hop nested shaping; +8. shared sibling prefixes; +9. restricted, unrestricted, and restricted-empty auth scopes; +10. legacy-null and explicit dataset generations. + +**Result parity harness** + +For each fixture: + +1. compile through physical path; +2. compile through compatibility oracle while it still exists; +3. execute both against the same database and generation; +4. canonicalize only JSON object-key ordering; +5. compare row count, row order, columns, pivot fields, scalar/null/array/object + values, and duplicate behavior; +6. print the first semantic difference with fixture ID and physical operator + provenance. + +Do not sort returned rows unless the public contract declares order irrelevant. + +**Explain gates** + +- no full collection scan; +- scoped root persistent index selected; +- `fhir_edge` edge index selected for every traversal; +- no warning; +- estimated item count does not explode between optional nested stages; +- shared plan estimated cost is neutral or better than unshared. + +**Human-readable benchmark output** + +`cmd/dataframe-query` must report separately: + +- HTTP/server total; +- compile time if exposed by response/diagnostics; +- Arango execution time if exposed; +- rows; +- response bytes; +- rows/second; +- cold first request and warm subsequent request timings. + +Check in a proper GDC-style request under `examples/` that includes fields, +child files, aggregates, observation pivot, representative slices, and nested +groups. + +## Work package F7 — Remove production fallback + +**Preconditions** + +- all supported GraphQL shapes compile physically; +- `genericPhysicalPlanUnavailableReason` has no supported-shape branch; +- F6 parity and Explain matrix is green; +- the GDC-style request executes physically. + +**Implementation** + +1. Replace `CompileRequest` with a single path: + + ```go + semantic, err := BuildSemanticPlan(builder) + if err != nil { return CompiledQuery{}, err } + physical, err := BuildPhysicalPlan(semantic) + if err != nil { return CompiledQuery{}, err } + physical, err = OptimizePhysicalPlan(physical) + if err != nil { return CompiledQuery{}, err } + return compilePhysicalExecution(physical, semantic, limit) + ``` + +2. Remove `compileRequestPlans` and every runtime fallback call. +3. Change unsupported semantics to explicit errors from semantic or physical + validation, not compatibility execution. +4. Retain the compatibility compiler only long enough for F6 tests; do not + expose it through runtime/service code. + +**Acceptance:** `rg` finds no production path from service/GraphQL to +`compileLowered`, `Lower`, or lowered builder types. + +## Work package F8 — Delete compatibility implementation + +Perform this as one focused deletion after F7 is green. + +**Delete or empty by deadcode evidence** + +- `internal/dataframe/lowered_compile.go` +- `internal/dataframe/lowered_types.go` +- compatibility sections of `planner.go`, `generic_lowering.go`, + `compile_fields.go`, relationship-match compilation, and storage-route + adapters; +- old `compiler` struct and AQL string helpers; +- legacy named-set optimization tests; +- compatibility-only fixtures. + +**Remove fields from `Builder` and `TraversalStep`** + +- `Sets` +- `DerivedFields` +- `RepresentativeSlices` +- compatibility plan hints that no longer describe public diagnostics. + +Do not remove public GraphQL fields, aggregates, pivots, or slices. Remove only +the lowered duplicates. + +**Test migration** + +- rewrite tests that assert legacy variable names or AQL substrings to assert + physical operators, bind safety, result parity, or Explain behavior; +- keep precise AQL tests only at renderer boundaries; +- remove direct `Lower -> Compile` conformance calls and use + `CompileRequest`/physical plan fixtures. + +**Final commands** + +```bash +GOCACHE="$(pwd)/.gocache" GOTOOLCHAIN=auto go test ./... -count=1 +GOCACHE="$(pwd)/.gocache" deadcode -test ./... +git diff --check +``` + +With local Arango: + +```bash +LOOM_COMPILER_ARANGO_INTEGRATION=1 \ +GOCACHE="$(pwd)/.gocache" GOTOOLCHAIN=auto \ +go test ./internal/dataframe -run 'Test.*Arango' -count=1 -v + +make dataframe-demo +``` + +**Final source audit** + +```bash +rg -n 'compileLowered|lowerSemanticBuilder|type NamedSet|type DerivedField|Builder\.Sets|Builder\.DerivedFields' . +``` + +Expected result: no production definitions or call sites. Test migration notes +may mention removed symbol names only in historical documentation. + +## Luna merge order and worker ownership + +The compiler hotspots are: + +- `physical_plan.go` +- `generic_physical_plan.go` +- `physical_render.go` +- `physical_execution.go` +- `compile.go` + +Only one integration owner edits those files per wave. + +| Wave | Primary implementation | Parallel safe work | Integration owner | +| --- | --- | --- | --- | +| 0 | F0 inventory | fixture enumeration | compiler core | +| 1 | F1 semantic derived migration | parity cases | physical lowerer | +| 2 | F2 pivots | pivot fixtures/live data inspection | pivot worker | +| 3 | F3 slices | slice fixtures | slice worker | +| 4 | F4 nested shaping | nested parity fixtures | physical lowerer | +| 5 | F5 sharing optimizer | Explain/cost harness | optimizer worker | +| 6 | F6 matrix | benchmark CLI/example | test owner | +| 7 | F7 cutover | deletion inventory | compiler core | +| 8 | F8 deletion | docs cleanup | deletion owner | + +Workers contributing fixtures must not edit compiler hotspot files. F7 and F8 +are serialized: do not delete the oracle while a parity worker still uses it. + +## Definition of done + +- Pivots and slices execute through typed physical expressions. +- Any supported shape can nest at any proven traversal depth without changing + root grain. +- Physical traversal sharing is validated and benchmark-backed. +- Rich-shape parity and Explain gates pass against `META`. +- A human-readable GDC dataframe request runs physically and reports useful + timing/row statistics. +- Production contains one compiler path. +- Compatibility lowering, named sets, derived-field IR, and string compiler + helpers are deleted. diff --git a/docs/LUNA_RICH_PHYSICAL_RENDERER_EXECUTION.md b/docs/LUNA_RICH_PHYSICAL_RENDERER_EXECUTION.md new file mode 100644 index 0000000..1d58773 --- /dev/null +++ b/docs/LUNA_RICH_PHYSICAL_RENDERER_EXECUTION.md @@ -0,0 +1,519 @@ +# Luna Execution Plan: Remove the Lowered AQL Compiler + +## Mission + +Make the physical compiler the only runtime execution path for supported +dataframe requests. The final runtime pipeline is: + +```text +GraphQL input + -> graphqlapi/dataframe + -> dataframe.Builder + -> dataframe.BuildSemanticPlan + -> dataframe.BuildPhysicalPlan + -> dataframe.RenderPhysicalPlan + -> Arango AQL +``` + +Delete the runtime compatibility path (`lowerSemanticBuilder`, `Compile`, and +`compileLowered`) only after the physical renderer covers the same supported +semantic operations and has result parity. Do not preserve old AQL helpers for +backward compatibility once their physical replacement is enabled. + +This is an implementation plan, not a request to invent FHIR behavior. The +repository already contains the FHIR facts and generated backbone: + +- `fhirstructs/`: generated FHIR structs, validators, and edge extraction; +- `fhirschema/`: generated resource metadata, selectors, and traversals; +- `META/`: loaded sample FHIR NDJSON data; +- `graphqlapi/schema.graphqls`: current public GraphQL contract; +- `internal/dataframe/storage_route.go`: the only authority for physically + proven FHIR edge directions; +- `internal/dataframe/semantic_plan.go`: semantic request meaning; +- `internal/dataframe/physical_plan.go`: renderer-independent physical IR. + +Never add a hard-coded resource-specific FHIR route or field just to make a +fixture pass. Resolve fields through `fhirschema` and routes through +`resolveStorageRoute`. + +## Current baseline (verify before editing) + +The physical runtime currently owns: + +- root scan plus project, dataset-generation, and authorization scope; +- root sort and preview limit; +- root field extraction, selector fallbacks, scalar/array/distinct-array + values, and root typed filters; +- optional navigation-only traversal sets; +- optional child traversal sets with child field projections and typed child + filters, including nested child sets; +- root and child aggregates (COUNT, COUNT_DISTINCT, EXISTS, DISTINCT_VALUES, + MIN, MAX, and predicate-qualified reductions); +- required traversal matches as scoped correlated `EXISTS` subplans; +- proven inbound routes and the explicit outbound + `ResearchSubject -> ResearchStudy` route. + +The compatibility compiler still owns: + +- derived fields; +- pivots; +- representative slices; +- legacy named-set traversal sharing. + +Before work, run: + +```bash +GOCACHE="$(pwd)/.gocache" GOTOOLCHAIN=auto go test ./... -count=1 +``` + +If the checkout has unrelated dirty changes, preserve them. Do not reset or +reformat unrelated code. + +## Non-negotiable compiler invariants + +Every work package must maintain these invariants: + +1. One outer `FOR root` produces at most one row per root resource. +2. `SORT root._key` and optional `LIMIT @limit` occur before optional child + traversal work. Required semi-joins occur before that window. +3. Every participating root, child node, and `fhir_edge` document has project, + dataset-generation, and authorization predicates. +4. AQL contains only compiler-owned syntax. Request values, field names, + resource types, labels, projection names, and pivot keys are bind values or + generated metadata; never concatenate request data into AQL source. +5. Physical plan validation rejects unsafe bind keys, selector paths, variable + capture/scope violations, untyped collection binds, and missing return + values before rendering. +6. Fallback/value-mode behavior is part of the output contract. Preserve + scalar `null`, empty arrays, array order, and distinct semantics as proven + by existing compatibility tests. +7. Unknown outbound or `ANY` routes fail through `resolveStorageRoute`; do not + make them work by guessing edge direction. + +## Physical IR rules + +Use the existing typed IR. Add fields only when a semantic concept cannot be +expressed safely with the current structures: + +- `PhysicalSet` / `PhysicalSubplan`: correlated array-valued child set; +- `PhysicalExpression`: value, extract, aggregate, pivot map, slice, object; +- `PhysicalPredicateExpression`: comparison, all, any, not, exists; +- `PhysicalExtract`: parsed selector plus fallbacks and explicit cardinality; +- `PhysicalAggregate`, `PhysicalPivotMap`, `PhysicalSlice`. + +Do not reintroduce `NamedSet`, string expressions, or an AQL snippet field to +the physical plan. If an operation cannot be rendered without a raw string, +the IR is incomplete and must be extended first. + +## Work package 1 — Make physical subplans fully executable + +**Files owned** + +- `internal/dataframe/physical_plan.go` +- `internal/dataframe/physical_render.go` +- `internal/dataframe/physical_helpers.go` +- `internal/dataframe/physical_plan_test.go` + +**Goal** + +Finish the generic support for `PhysicalSet` and nested `PhysicalSubplan` +before semantic lowering starts producing them for real child fields. + +**Implementation steps** + +1. Make `clonePhysicalPlan` deeply clone every rich IR payload: expressions, + predicate trees, sets, subplans, selectors, projections, and bind values. + `withGenericPhysicalExecutionWindow` must not mutate its input plan. +2. In `PhysicalPlan.Validate`, validate set captures against the parent lexical + scope. A subplan may reference only captures and variables it defines. +3. Reject root scans, outer returns, sort, and preview limits inside a child + subplan. A child subplan can contain traversal, scoped filters, derived lets, + nested sets, and a typed return expression. +4. Extend collection-bind discovery and render validation recursively through + sets, exists predicates, aggregate/slice/pivot expressions, and nested + object projections. +5. Implement deterministic AQL rendering for `PhysicalSet`: + + ```aql + LET child_set = ( + FOR child, edge IN 1..1 INBOUND parent @@edge_collection + ... mandatory scope filters ... + RETURN child + ) + ``` + + Apply `UNIQUE` only when `PhysicalSet.Unique` is true. Do not emit a top + level child loop. + +**Tests** + +- deep-clone mutation test for every rich payload; +- capture rejection, future-variable rejection, and nested-scope rejection; +- collection bind inside nested set/existence validation; +- renderer golden proving nested sets remain under root `LET` expressions. + +**Done when**: a hand-built nested child-set physical plan validates and renders +without raw AQL payloads, and `go test ./internal/dataframe -run TestPhysical` +passes. + +## Work package 2 — Lower optional child nodes to physical sets + +**Files owned** + +- `internal/dataframe/generic_physical_plan.go` +- `internal/dataframe/physical_lowering.go` +- `internal/dataframe/physical_helpers.go` +- new `internal/dataframe/physical_child_set_test.go` + +**Goal** + +Replace navigation-only child traversals with a physical set hierarchy that is +usable by fields, filters, aggregates, pivots, and slices. + +**Implementation steps** + +1. Add an internal lowering context with deterministic counters for set/node/ + edge variable names and bind keys. Do not derive names from user aliases. +2. For each optional `SemanticNode`, call: + + ```go + resolveStorageRoute(parent.ResourceType, child.EdgeLabel, child.ResourceType) + ``` + + Populate a `PhysicalSet` with a subplan that captures the parent variable + (or parent set-element variable for nesting). +3. Inside each set subplan, emit in this order: + - one-hop typed `PhysicalTraversal`; + - edge and child project filters; + - edge and child dataset-generation filters; + - edge and child authorization filters; + - child resource type and edge target-type discriminator filters; + - child typed filters (work package 4); + - nested child sets (recursive call); + - typed return object/value for the owning projection. +4. Preserve semantic request ordering. Grouping or traversal sharing is not + allowed in this package. +5. Update `genericPhysicalNodeUnavailableReason` only for the exact feature + implemented. Do not mark pivots, aggregates, slices, or derived fields as + physical merely because a child set exists. + +**Tests** + +- Patient -> Specimen field; +- Patient -> Specimen -> DocumentReference nested field; +- root row count remains one with zero/many children; +- inbound and ResearchSubject -> ResearchStudy outbound route rendering; +- unknown forward route remains rejected. + +**Done when**: optional child field-only requests select `BuildPhysicalPlan` +and no longer invoke `lowerSemanticBuilder` at runtime. + +## Work package 3 — Project fields from child sets + +**Files owned** + +- `internal/dataframe/generic_physical_plan.go` +- `internal/dataframe/physical_render.go` +- `internal/dataframe/selection_semantics.go` only if an existing semantic + contract is missing +- `internal/dataframe/physical_child_projection_test.go` + +**Goal** + +Emit exactly the current output shapes for traversed selections. + +**Implementation steps** + +1. Reuse `ResolveSemanticField(resourceType, nodeAlias, index, field)` for + every child `SemanticField`. Do not duplicate its selection semantics. +2. Lower a child field to `PhysicalExtract` with source equal to the child set + element payload and use explicit cardinality/null behavior. +3. For a child field output, render one typed subquery over the set: + - scalar/first: `FIRST(...)` according to semantic projection; + - array: ordered values; + - distinct array: physical distinct operation followed by required stable + ordering, matching existing tests. +4. Nested child fields are evaluated inside their parent child-set subplan, not + by reopening an uncorrelated root traversal. +5. Add projection names to `CompiledQuery.Columns` from the final physical + return operation. Do not reconstruct columns from `Builder` after lowering. + +**Parity fixtures** + +Use existing `META` resource types and add a physical fixture that selects: + +- specimen type from a patient-linked specimen; +- DocumentReference attachment title from a specimen-linked file; +- an array-valued field and a fallback field. + +Compare legacy and physical rows after canonical JSON key ordering. Compare +columns and row values, not raw AQL text. + +**Done when**: child field outputs have live Arango result parity and all +field-only traversal requests run physically. + +## Work package 4 — Child filters and required-match filters + +**Files owned** + +- `internal/dataframe/generic_physical_plan.go` +- `internal/dataframe/physical_required_match.go` +- `internal/dataframe/physical_render.go` +- `internal/dataframe/physical_child_filter_test.go` +- `internal/dataframe/physical_required_match_test.go` + +**Goal** + +Use one typed predicate lowering path for root filters, child set filters, and +required-match subplan filters. + +**Implementation steps** + +1. Extract root predicate construction from `appendRootPhysicalFilters` into + `lowerPhysicalFilters(resourceType, sourcePayload, filters, bindVars, + bindPrefix)`. It returns typed `PhysicalPredicateExpression`s and owns all + bind keys. +2. Invoke the helper in child set subplans immediately after mandatory scope + filters and before subplan return. +3. Invoke the same helper in `buildRequiredTraversalExists`; remove its current + rejection of `node.Filters`. +4. Retain exact existing `TypedFilter` behavior: `EQUALS`, `NOT_EQUALS`, `IN`, + `CONTAINS_TEXT`, `GT`, `GTE`, `LT`, `LTE`, `EXISTS`, `MISSING`, and + ALL/ANY/NONE. Use parsed selectors and bind literals only. +5. For date/datetime comparison, preserve existing `DATE_TIMESTAMP` behavior + from the compatibility compiler. + +**Tests** + +- every filter operation at child depth one; +- nested child filter; +- required traversal filter in both inbound and proven outbound directions; +- scope test where a matching document is out of auth scope or wrong dataset + generation; +- live `EXPLAIN` test checks a traversal edge index and no full collection scan. + +**Done when**: `compileTypedFilters` has no production call site outside the +compatibility oracle and all field/filter traversal requests run physically. + +## Work package 5 — Aggregates and derived fields + +**Files owned** + +- `internal/dataframe/physical_plan.go` +- `internal/dataframe/generic_physical_plan.go` +- `internal/dataframe/physical_render.go` +- new `internal/dataframe/physical_aggregate_test.go` + +**Goal** + +Lower `SemanticAggregate` and supported derived fields over typed physical +sets, with no use of `Builder.Sets` or `DerivedField` in runtime execution. + +**Implementation steps** + +1. Map every `SemanticAggregate.Operation` currently accepted by validation to + a `PhysicalAggregateOperation`. Before coding, enumerate the accepted + operations from `semantic_validation.go` and write a table-driven test that + rejects an unmapped operation. +2. Lower aggregate selectors and optional predicates with the shared helpers + from work packages 3 and 4. +3. Specify output behavior from existing compatibility tests before rendering: + - count/distinct count: `0` on empty set; + - values/distinct values: `[]` on empty set; + - first/min/max: `null` on empty set unless current test behavior differs. +4. Render fixed aggregate AQL templates only. Do not store function names in + request data. Ensure distinct arrays retain required ordering. +5. Lower derived count/values/first operations as typed expressions referencing + a physical set variable or prior physical expression. Do not permit an AQL + variable name from `Builder` to cross the boundary. + +**Tests** + +- zero/one/many child documents; +- repeated values and distinct values; +- predicate-qualified count; +- `META` GDC case -> specimen -> file counts/values; +- physical-vs-compat execution parity. + +**Deletion gate** + +Delete the corresponding production branches in `compileRootAggregateExpr` and +`compileDerivedField` after all aggregate fixtures select physical execution. + +## Work package 6 — Pivots + +**Files owned** + +- `internal/dataframe/physical_plan.go` +- `internal/dataframe/generic_physical_plan.go` +- `internal/dataframe/physical_render.go` +- new `internal/dataframe/physical_pivot_test.go` + +**Goal** + +Make root and child `SemanticPivot` physical without string-generated object +keys. + +**Implementation steps** + +1. Lower each pivot to `PhysicalPivotMap` with typed source, resource type, + parsed key/value selectors, and a bind-backed permitted column list. +2. Establish collision behavior by executing the existing compatibility pivot + tests; encode it as IR/renderer behavior and test duplicates explicitly. +3. Render a fixed AQL pivot subquery that filters values to permitted columns. + Requested output column names are bind values. +4. Set `CompiledQuery.PivotFields` from physical return projection metadata, + not from the old builder. + +**Tests** + +- root and child pivot; +- sparse values, duplicate key, absent permitted key, nested array selector; +- real observation pivot fixture from `META`; +- bind-safety test: no requested key appears interpolated in AQL source. + +**Deletion gate** + +Remove `compileRootPivot`, `compileDerivedPivotMapLets`, and their production +call sites after parity is green. + +## Work package 7 — Representative slices + +**Files owned** + +- `internal/dataframe/generic_physical_plan.go` +- `internal/dataframe/physical_render.go` +- `internal/dataframe/physical_plan.go` only if required +- new `internal/dataframe/physical_slice_test.go` + +**Goal** + +Lower `SemanticSlice` to a bounded typed local subquery. + +**Implementation steps** + +1. Lower the source child set, optional typed predicate, sort expression, + positive bind-backed limit, and nested projection to `PhysicalSlice`. +2. Require an explicit deterministic sort with a tie breaker. Do not inherit + incidental collection or `UNIQUE` order. +3. Render `FILTER`, `SORT`, `LIMIT`, and object projection inside the slice + subquery. Never alter the outer root preview window. +4. Validate limit type/positivity in physical plan validation. + +**Tests** + +- zero/one/many children; +- equal primary sort values prove tie stability; +- predicate + slice interaction; +- nested field object projection; +- output parity with existing representative slice fixture. + +**Deletion gate** + +Delete `compileRepresentativeSlice`, `compileRootSlice`, and slice-only legacy +tests once all slice fixtures are physical. + +## Work package 8 — Traversal sharing optimization + +**Dependencies**: work packages 2–7 must already have unshared physical parity. + +**Files owned** + +- new `internal/dataframe/physical_optimize.go` +- `internal/dataframe/physical_plan.go` +- `internal/dataframe/physical_render.go` only if an existing set form cannot + render the optimized plan +- new `internal/dataframe/physical_optimize_test.go` + +**Goal** + +Recreate generic sibling-prefix sharing as a physical-plan optimization, +without changing semantic results. + +**Implementation steps** + +1. Match only sets with identical parent capture, direction, edge collection, + label, project/generation/auth scopes, and traversal depth. +2. Materialize one broad shared set only when children differ solely by target + resource type. Create typed filtered subsets for each target type. +3. Run this optimizer after semantic lowering and before rendering. Keep an + unoptimized plan available for deterministic test comparison. +4. Record sharing count and set count in physical explain metadata; do not + expose raw AQL variable names to GraphQL clients. + +**Tests and performance gate** + +- optimized/unoptimized result parity; +- no target type broadening; +- `EXPLAIN` confirms edge traversal index use; +- benchmark must be cost-neutral or better before enabling optimization. + +## Work package 9 — Production cutover and deletion + +**Preconditions** + +- all supported semantic features have physical parity; +- full `META` fixture matrix executes through `CompileRequest` without + `lowerSemanticBuilder`; +- live Arango explain/cost coverage is green; +- one real GDC-style GraphQL request produces a useful dataframe (fields, + child fields, counts, pivots, slices) through the physical path. + +**Implementation steps** + +1. Change `CompileRequest` to exactly: + + ```go + semantic, err := BuildSemanticPlan(builder) + if err != nil { return CompiledQuery{}, err } + physical, err := BuildPhysicalPlan(semantic) + if err != nil { return CompiledQuery{}, err } + return compilePhysicalExecution(physical, semantic, limit) + ``` + +2. Move compatibility execution comparison into test-only helpers. It may be + retained temporarily in a test package as an oracle, but it must have no + production caller. +3. Delete production `Compile`, `Lower`, `lowerSemanticBuilder`, + `compileLowered`, `NamedSet`, and lowered-only helpers/types when deadcode + proves no production consumers remain. +4. Delete obsolete compatibility-only fixtures and replace them with physical + plan plus execution-parity fixtures. +5. Run: + + ```bash + GOCACHE="$(pwd)/.gocache" GOTOOLCHAIN=auto go test ./... -count=1 + GOCACHE="$(pwd)/.gocache" deadcode -test ./... + git diff --check + ``` + +6. With local Arango available, run the named Explain tests plus the + human-readable dataframe command: + + ```bash + LOOM_COMPILER_ARANGO_INTEGRATION=1 \ + GOCACHE="$(pwd)/.gocache" GOTOOLCHAIN=auto \ + go test ./internal/dataframe -run 'Test.*Explain.*Arango' -count=1 -v + + make dataframe-demo + ``` + +## Parallelization rules for Luna + +Use one integration owner per wave. `physical_plan.go`, +`physical_render.go`, `generic_physical_plan.go`, and `compile.go` are shared +hotspots and must not be edited concurrently by multiple workers. + +| Wave | Worker A | Worker B | Integration owner | +| --- | --- | --- | --- | +| 1 | WP1 IR/subplan validation | fixtures and parity harness | WP1 owner | +| 2 | WP2 child set lowering | WP3 child projection tests | WP2 owner | +| 3 | WP4 predicates/required filters | live Explain tests | WP4 owner | +| 4 | WP5 aggregates/derived fields | aggregate parity fixtures | WP5 owner | +| 5 | WP6 pivots | pivot fixtures/benchmark reporting | WP6 owner | +| 6 | WP7 slices | slice fixtures | WP7 owner | +| 7 | WP8 sharing/perf | WP9 deletion audit | compiler core owner | + +Workers must not write `compile.go` until work package 9. Each feature worker +reports the exact supported semantic shapes and leaves unsupported shapes +explicitly rejected by `BuildPhysicalPlan`; do not add a new fallback. diff --git a/docs/PHYSICAL_RENDERER_REPLACEMENT_PLAN.md b/docs/PHYSICAL_RENDERER_REPLACEMENT_PLAN.md new file mode 100644 index 0000000..736d813 --- /dev/null +++ b/docs/PHYSICAL_RENDERER_REPLACEMENT_PLAN.md @@ -0,0 +1,251 @@ +# Physical Renderer Replacement Plan + +## Objective + +Replace the compatibility `compileLowered(Builder, limit)` AQL string compiler +with one executable pipeline: + +```text +GraphQL Builder + -> SemanticPlan + -> PhysicalPlan + -> RenderPhysicalPlan + -> parameterized AQL +``` + +The physical plan is the only place where AQL execution strategy is chosen. +It must preserve the semantic plan exactly, including root row grain, selected +columns, filters, required relationship matches, pivots, aggregates, +representative slices, authorization scope, and dataset generation scope. + +`compileLowered` remains only as a test oracle during the migration. Do not +move its string-building helpers into the new renderer. + +## Non-negotiable invariants + +- No raw user-controlled AQL fragments enter the physical plan or renderer. +- Every root, traversed node, and edge is constrained by project, dataset + generation, and authorization scope. +- A physical plan validates lexical variable scope and bind-variable ownership + before rendering. +- The root execution window (`SORT root._key`, then optional `LIMIT`) occurs + before optional traversal work, unless a semantic ordering contract says + otherwise. +- Output column names and array/scalar/null semantics match the current + compiler exactly. +- A new route is enabled only after deterministic result parity and live + Arango `EXPLAIN` coverage prove it is correct and index-backed. + +## Target physical IR + +Keep the existing root scan, traversal, filter, derived-let, sort, limit, and +return operations, but replace the current navigation-only subset with typed +operations that can describe every semantic feature. + +| Capability | Required physical operation/value | +| --- | --- | +| FHIR selector extraction | `Extract` value: root value, selector path, fallback paths, value mode | +| Typed filters | `Predicate` tree: all/any/not, comparison, exists, membership, string match; typed bind values only | +| Relationship existence | `Exists` expression with a bounded typed traversal subplan and `LIMIT 1` | +| Optional child traversal | `Set`/subquery operation with traversal, resource-type filter, predicate, uniqueness, and stable sort | +| Shared traversal prefixes | `Set` operation can feed typed filtered subsets; lowering records shared-source provenance | +| Aggregates | `Aggregate` expression: count, distinct count, values, first/representative, and predicate guard | +| Pivots | `PivotMap` expression: key selector, value selector, permitted columns, collision/value mode | +| Representative slices | `Slice` expression: typed source set, predicate, stable sort, limit, nested projection | +| Derived fields | `Derived` expression: count, values, first, pivot map, and references to prior typed sets only | +| Projection | projection values can be scalar, array, object, aggregate, pivot, slice, or derived expression | + +Do not add one physical operation per historical AQL helper. Prefer a compact, +validated expression tree plus explicit set-producing operations. The renderer +owns only serialization of that tree; semantic interpretation belongs in the +lowerer. + +## Work packages + +### P1 — Freeze the executable IR contract + +**Owner:** compiler core. **Blocks:** all renderer work. + +1. Introduce `PhysicalExpression`, `PhysicalSet`, and typed predicate nodes in + `internal/dataframe/physical_plan.go`; make operation payloads a closed, + validated union. +2. Add explicit value cardinality and null behavior to expressions. Do not + infer scalar-versus-array behavior from renderer context. +3. Add `PhysicalSubplan`/set scope rules so a subquery cannot reference a + variable introduced later or outside its parent scope. +4. Version the physical plan and provide deterministic JSON fixtures for it. +5. Extend `PhysicalPlan.Validate` with bind type, selector-path, collection + bind, provenance, and mandatory-scope checks. + +**Acceptance:** invalid plans fail before AQL rendering; a fixture can express +every current semantic selection without a raw AQL string. + +### P2 — Direct semantic-to-physical lowering + +**Owner:** compiler core. **Blocks:** P3–P7. + +1. Add `BuildPhysicalPlan(SemanticPlan, ExecutionOptions) (PhysicalPlan, + error)`. +2. Stop using `lowerSemanticBuilder` in this new route. It may remain only for + compatibility-oracle tests until P9. +3. Lower root scan, root project/generation/auth scope, deterministic root + window, and `_key` projection directly from the semantic plan. +4. Lower each semantic node using the proven `storage_route` contract; + unsupported outbound/ANY routes must remain explicit compiler errors. +5. Carry semantic aliases and source fields into `PhysicalSource` for errors, + explain output, and goldens. + +**Acceptance:** navigation-only `CompileRequest` uses this route with no +`Builder.Sets` dependency and remains byte-stable where practical. + +### P3 — Typed selector extraction and root filters + +**Can run after P1/P2.** + +1. Lower `SemanticField` selectors, fallbacks, and value modes to `Extract`. +2. Lower `TypedFilter` to physical predicate trees; encode literals in bind + vars and retain existing FHIR payload traversal semantics. +3. Render extraction/predicate trees as fixed AQL templates, including nested + array iteration and null behavior. +4. Add parity fixtures for each filter operator and every supported value mode. + +**Acceptance:** root-only field/filter requests use the physical renderer and +match the compatibility query’s rows, JSON values, columns, and bind safety. + +### P4 — Required traversal matches and scoped relationship filters + +**Can run in parallel with P3 after P1/P2.** + +1. Lower `TraversalMatchMode` and required relationship filters into typed + `Exists` subplans instead of generated `LENGTH(FOR ...)` strings. +2. Render a bounded `LIMIT 1` correlated traversal with edge/node project, + generation, auth, label, target edge-type, and resource-type predicates. +3. Reuse the existing proven `storage_route` direction evidence; add explicit + tests for ResearchSubject -> ResearchStudy outbound traversal. + +**Acceptance:** required-match parity, no unscoped edge/node in rendered AQL, +and live Explain coverage for inbound and proven outbound routes. + +### P5 — Optional traversal sets and traversal-sharing + +**Can start once P1/P2 are stable; completes after P3/P4.** + +1. Lower child `SemanticNode`s into typed set subplans, preserving optional + traversal semantics and root row grain. +2. Materialize sibling-prefix sharing only when route, source, label, scope, + and traversal direction are equivalent; create typed filtered subsets for + distinct target resource types. +3. Implement dedupe and deterministic ordering as physical semantics, not + renderer-side textual rewrites. +4. Add plan goldens proving shared prefixes do not broaden target types or + alter result order. + +**Acceptance:** nested optional traversal fields execute through physical +plans; no regression in root row count; shared-prefix Explain/cost coverage. + +### P6 — Aggregates, derived fields, and representative slices + +**Depends on P3/P5.** + +1. Lower `SemanticAggregate`, `SemanticSlice`, and derived field operations + directly from semantic nodes/typed sets. +2. Specify empty-set behavior for every aggregate and derive it from current + result fixtures before implementation. +3. Render only fixed aggregate functions; reject unknown operations during + physical validation. +4. Ensure every representative slice has stable sort, bounded limit, and + nested typed projection. + +**Acceptance:** GDC-style counts, value lists, representative samples/files, +and derived fields have exact result parity on META fixtures. + +### P7 — Pivots and shaped object projections + +**Depends on P3/P5; can overlap P6.** + +1. Lower semantic pivots to `PivotMap` expressions with validated permitted + columns, key/value selectors, and collision semantics. +2. Render pivot maps with bind-backed column names; never synthesize AQL keys + from data or request strings. +3. Compose fields, aggregates, pivots, slices, and child-derived values into a + typed return object in requested column order. + +**Acceptance:** complex GDC dataframe fixtures with samples/files/groups/ +observations and pivots execute only through the physical renderer and retain +column shape exactly. + +### P8 — Performance, Explain, and observability gates + +**Runs continuously after P3; owns final performance sign-off.** + +1. Add a named real-world GDC dataframe fixture under `examples/` or + `conformance/compiler/`, with human-readable GraphQL input and expected + NDJSON/column contract. +2. Add cold/warm benchmark commands that report compile time, Arango query + execution time, rows, bytes, and rows/second separately. +3. For each physical feature, require live Arango `EXPLAIN` assertions: + no full collection scans, scoped root index use, traversal edge index use, + and bounded estimated cost relative to fixture cardinality. +4. Add a physical-plan explanation that reports operator counts, traversals, + shared prefixes, and selected indexes without exposing raw AQL internals. + +**Acceptance:** documented benchmark baseline and regression threshold for the +representative GDC dataframe; failures identify compiler phase versus Arango +execution phase. + +### P9 — Shadow parity and cutover + +**Depends on P3–P8.** + +1. Build a test-only harness that compiles each fixture through both the + physical path and `compileLowered`, executes both against the same Arango + generation, canonicalizes row-object key order, and compares rows/columns. +2. Cover root fields, nested fields, all filters, required matches, inbound and + outbound routes, aggregates, slices, pivots, auth scopes, empty results, + generation scope, and preview limits. +3. Make `CompileRequest` select the physical route for one capability family at + a time only after that family has parity and Explain gates. +4. Remove the fallback condition only when the full conformance matrix uses + physical plans. + +**Acceptance:** zero compatibility fallbacks in conformance; physical path is +the default for every supported GraphQL dataframe request. + +### P10 — Delete the compatibility compiler + +**Depends on P9. Must be one focused deletion PR.** + +1. Delete `compileLowered`, `compiler`, `NamedSet`, `DerivedField`, and other + lowered-only types/helpers that have no non-test consumer. +2. Delete `lowerSemanticBuilder` and old lowered-query goldens. +3. Simplify `CompileRequest` to semantic validation -> physical lowering -> + rendering. Preserve the public GraphQL input/output contract. +4. Run deadcode with tests, full Go tests, compiler conformance, integration + Explain tests, and benchmark gate. + +**Acceptance:** no production reference to `Builder.Sets`, `compileLowered`, +or lowered AQL string helpers; one compiler execution path remains. + +## Parallelization and merge order + +| Wave | Work packages | Shared files / merge owner | +| --- | --- | --- | +| 0 | P1, fixture/benchmark design from P8 | `physical_plan.go`: P1 owner | +| 1 | P2, P3, P4 | `physical_lowering.go`: P2 owner; P3/P4 add isolated feature files | +| 2 | P5, P6, P7, P8 | `physical_render.go`: renderer owner serializes reviewed IR additions | +| 3 | P9 | `compile.go`: cutover owner | +| 4 | P10 | deletion owner, after green matrix only | + +No worker edits `compile.go` while P1–P8 are in flight. Feature workers add +IR/lowering tests and renderer tests; the renderer owner integrates accepted +operation kinds. This prevents one feature from silently reintroducing +string-oriented lowering. + +## Explicit non-goals + +- Do not add unproven FHIR traversal directions merely to increase coverage. +- Do not optimize by materializing new collections before physical plans can +select and explain them. +- Do not alter GraphQL input/output names during this migration. +- Do not delete the compatibility compiler before live result parity, not just + query-string similarity, is proven. diff --git a/docs/PRODUCT_RECIPE_DISCOVERY.md b/docs/PRODUCT_RECIPE_DISCOVERY.md deleted file mode 100644 index 56a71b6..0000000 --- a/docs/PRODUCT_RECIPE_DISCOVERY.md +++ /dev/null @@ -1,589 +0,0 @@ -# Product Recipes and Dataset Discovery - -This document describes a product direction for turning freshly loaded FHIR -data into useful flat dataframes without asking users to understand FHIRPath, -GraphQL, AQL, or graph traversal mechanics. - -The central product idea is: - -> The user describes a familiar dataset, Loom turns that intent into a validated -> recipe, and the backend compiles the recipe into performant AQL. - -The frontend should not be an unrestricted visual query builder. It should be a -small, guided interface backed by dataset-aware analysis queries and a stable -recipe contract. - -## 1. Target User Experience - -The primary flow should read like a short conversation. - -### What are you making? - -Start from a curated use case: - -- Patient cohort -- Specimen inventory -- File manifest -- Diagnoses -- Labs or observations -- Study enrollment - -This choice establishes a recipe family. A recipe family supplies sensible -defaults, supported row grains, known FHIR relationships, common columns, and -backend planning hints. It is not a saved AQL string. - -### One row per... - -Choose the meaning of one output row: - -- Patient -- Specimen -- File -- Observation - -The row grain is the most important semantic choice in the workflow. It -determines which resource anchors the output, which relationships are safe to -traverse, and whether related values should be selected, aggregated, pivoted, -or emitted as additional rows. - -The frontend should use the phrase "one row per" rather than "root resource" -or "traversal root." - -### Include... - -Present a searchable, plain-language column checklist: - -- show common, populated columns first -- group columns by familiar concepts rather than raw resource names -- display a short example value when safe and useful -- show approximate coverage, such as "present for 92% of patients" -- hide advanced FHIR paths and internal graph identifiers by default -- explain when a selection changes the row grain or creates multiple values - -The column picker should be populated from Loom's analysis API. It should not -be a hardcoded copy of the theoretical FHIR schema. - -### Only include... - -Build filters as guided sentences, for example: - -- diagnosis is melanoma -- specimen type is Primary Tumor -- file type is BAM -- observation name is Hemoglobin -- study is TCGA-LUAD - -The available operators and values should come from field metadata and bounded -value-frequency queries. Free text should be used only when the field cannot -provide a useful enumerated value list. - -### Preview, then deliver - -After validation, the user can: - -- preview a small sample -- download flat NDJSON -- download CSV -- send the rows to Elasticsearch -- save the configuration as a reusable recipe - -Preview and export are different workloads. Preview should be synchronous, -small, and optimized for rapid correction. Export should eventually be a -streaming or asynchronous job with durable status and bounded memory. - -## 2. The Product Contract Is a Recipe - -The frontend, a future natural-language assistant, the CLI, and API clients -should all produce the same versioned recipe object. - -A conceptual recipe looks like this: - -```json -{ - "version": 1, - "template": "file_manifest", - "project": "example-project", - "grain": "file", - "columns": [ - "cap_patient_submitter_id", - "cap_specimen_type", - "cap_file_name", - "cap_file_type", - "cap_file_size" - ], - "filters": [ - { - "field": "cap_file_type", - "operator": "equals", - "value": "BAM" - } - ], - "destination": { - "type": "preview" - } -} -``` - -This is intentionally not the current GraphQL dataframe input and not AQL. -The `cap_*` values are illustrative opaque capability identifiers issued by -Loom; a browser never constructs a FHIR path from them. It is a product-level -intermediate representation. - -The recipe compiler is responsible for translating friendly concepts into: - -1. concrete FHIR resource types and fields -2. a supported relationship path -3. field selections, filters, aggregates, pivots, and representative slices -4. the existing dataframe builder request -5. the lowered internal plan -6. AQL and bind variables - -Keeping these layers separate has several benefits: - -- the frontend remains small -- recipes can be saved and migrated -- a future LLM only needs to emit a constrained object -- validation can return user-facing errors before compiling AQL -- planner improvements do not invalidate saved user intent -- the same recipe can target preview, file export, or Elasticsearch - -## 3. Why Dataset Analysis Comes First - -FHIR defines what may exist. A newly loaded dataset determines what actually -exists, how it is connected, and whether it is useful. - -Loom already profiles populated fields in `fhir_field_catalog` and discovers -populated references from `fhir_edge`. These are necessary primitives, but the -product needs higher-level answers. - -The analysis layer must build on the repository's existing generated FHIR -backbone: `schemas/graph-fhir.json`, generated Go structs/validators/edge -extractors under `internal/fhir`, generated metadata under `internal/fhirschema`, -and the sample data in `META/`. It should not introduce a second FHIR model or -infer schema structure independently from those owners. - -The frontend should not call a collection of unrelated low-level queries and -attempt to infer the product model itself. Loom should expose analysis results -that already use the same semantics and authorization rules as recipe -validation and compilation. - -### Implemented foundation - -`dataframebuilder.Service.DiscoverGuided` now composes the existing scoped -catalog readers into an internal `discovery.Snapshot`. The snapshot contains -only generated-schema roots, compiler-safe observed relationships, opaque -candidate-column IDs, and bounded guided filter suggestions. It deliberately -does not yet have a public GraphQL/HTTP endpoint. When configured with an -active-manifest resolver, it is bound to that active dataset generation before -catalog discovery so cached/persisted capabilities cannot be used outside the -scope or load they describe. - -The lifecycle vocabulary is persisted by `internal/datasetstore` (schema -snapshot, immutable generation reference, lifecycle state, and active pointer), -and generation-aware discovery/compiler requests propagate that selection. It -is still not a public discovery response or a finalized analysis-capability -snapshot. - -The first internal capability bridge is also implemented: -`internal/recipecompiler.Build` and -`dataframebuilder.Service.PrepareRecipe`/`RunRecipe`/`StreamRecipe` resolve -opaque IDs from fresh, authorization-scoped catalog facts into typed root-only -scalar dataframe selections and filters. That makes an internal preview/row -stream possible today while rejecting raw paths, stale IDs, cross-resource -choices, repeated fields without a quantifier, pivots, and pinned generations. -It does not yet make a saved recipe, relationship-aware template, download, or -Elasticsearch delivery product-supported. - -## 4. Required Analysis Query Families - -Analysis queries should be project-scoped and auth-resource-path-scoped. Their -results should be cacheable and invalidated when a load changes the project. - -### 4.1 Dataset summary - -Purpose: determine what kind of dataset was loaded. - -Return: - -- populated resource types and document counts -- available auth resource paths -- total edge counts -- field-catalog freshness/version -- load or analysis timestamp -- high-level warnings, such as resources with no usable references - -This powers the initial landing state and prevents the frontend from offering -recipe families that have no backing data. - -### 4.2 Relationship inventory - -Purpose: understand which FHIR resource types are actually linked. - -Return for each observed relationship: - -- source resource type -- relationship label -- target resource type -- edge count -- distinct source count -- distinct target count -- source coverage -- average and percentile fanout -- whether the relationship is recognized by Loom's semantic planner - -The current populated-reference discovery returns the relationship and edge -count. Product discovery additionally needs coverage and fanout. An edge count -alone cannot tell the UI whether a relationship is nearly universal or a rare -outlier, nor whether it will multiply output rows unexpectedly. - -### 4.3 Reachable recipe paths - -Purpose: expose useful, supported paths rather than arbitrary graph walks. - -Given a row grain or recipe family, return paths such as: - -- Patient to Specimen -- Patient to DocumentReference -- Patient to Specimen to DocumentReference -- Patient to Condition -- Patient to Observation -- Patient to ResearchSubject to ResearchStudy - -Each path should include: - -- friendly label -- concrete edge labels and resource types -- observed coverage -- estimated fanout -- supported planner operations -- support state: supported, preview-only, experimental, or unavailable -- reason when unavailable - -This endpoint must reflect the planner's real capabilities. A path is not -product-supported merely because matching edges exist. - -### 4.4 Candidate columns - -Purpose: populate the plain-language column checklist. - -Given a recipe family, grain, and optional path, return: - -- stable friendly field identifier -- display label and description -- owning concept/resource -- underlying canonical selector -- data kind -- document count and coverage percentage -- bounded example values -- cardinality estimate -- whether values are scalar, repeated, or complex -- allowed value modes -- whether aggregation or pivoting is required at the selected grain -- common, suggested, or advanced classification -- sensitivity or display restrictions when applicable - -The existing field catalog supplies much of the raw evidence. The analysis -layer adds grain-aware presentation and planner compatibility. - -### 4.5 Filter suggestions and value frequencies - -Purpose: power guided filter sentences. - -Given a candidate field, return: - -- supported operators -- common distinct values and counts -- approximate or exact frequency indicator -- truncation state -- null/missing count -- search over high-cardinality values - -The existing catalog's bounded distinct values are useful for initial hints. -They are not sufficient for every filter UI because they do not necessarily -represent value frequency or support searching a high-cardinality domain. - -Expensive value analysis should be requested on demand, bounded, cached, and -subject to the same authorization scope as dataframe execution. - -### 4.6 Grain and cardinality analysis - -Purpose: explain what one output row means before execution. - -Given a proposed recipe, estimate: - -- number of base entities at the selected grain -- expected output rows -- which selections can multiply rows -- which selections produce arrays -- which selections will be aggregated or pivoted -- expected null coverage -- whether a stable document identifier can be produced - -This is both a correctness feature and a user-experience feature. Many failed -dataframe requests are really misunderstandings about cardinality. - -### 4.7 Recipe validation and explain - -Purpose: provide one authoritative preflight operation. - -Given a recipe, return: - -- normalized recipe -- validation status -- user-facing warnings and errors -- selected relationship path -- output column names and types -- estimated cardinality -- planner support state -- a safe logical-plan explanation -- whether preview, export, and Elasticsearch delivery are available - -The explain response should not expose raw AQL by default. Raw GraphQL, AQL, -and bind variables can remain available in a developer-only diagnostics view. - -### 4.8 Preview - -Purpose: let the user validate meaning with real rows. - -Preview should: - -- use the normalized recipe returned by validation -- enforce a small maximum row count -- return stable columns and representative rows -- report elapsed time and relevant warnings -- avoid retaining an unbounded result in memory -- make missing values and repeated values visually understandable - -### 4.9 Export and destination readiness - -Purpose: determine whether a validated recipe can be delivered safely. - -For file export, check: - -- output format -- expected size -- stable column schema -- whether the query can stream - -For Elasticsearch, additionally check: - -- destination/index permissions -- index or index-template compatibility -- field-name and type conflicts -- deterministic document ID strategy -- bulk batch limits -- behavior for partial failures and retries - -Elasticsearch delivery should consume the same row stream as NDJSON/CSV export; -it should not introduce a second dataframe compiler. - -## 5. Query Templates vs. Capabilities - -It is useful to create reusable backend query templates, but they should be -organized as capabilities rather than frontend pages or conversational turns. - -For example: - -| Capability | Likely backing data | Product consumer | -| --- | --- | --- | -| Dataset summary | resource collections, catalog, edges | recipe gallery | -| Relationship inventory | `fhir_edge` | grain/path selection | -| Candidate columns | `fhir_field_catalog`, schema metadata | column picker | -| Filter values | catalog plus bounded live aggregation | filter sentence | -| Recipe explain | catalog, semantics, planner | preflight panel | -| Preview | compiled dataframe AQL | result table | -| Export | compiled dataframe AQL row stream | files/Elasticsearch | - -The conversation is then a client of these capabilities. This prevents UI -wording from becoming part of the database API and makes it possible to add a -CLI, alternate frontend, or LLM later. - -## 6. Recommended API Shape - -The exact GraphQL names can be decided during implementation, but the public -surface should conceptually support: - -```graphql -datasetSummary(project: ID!): DatasetSummary! -recipeTemplates(project: ID!): [RecipeTemplate!]! -recipeOptions(input: RecipeContextInput!): RecipeOptions! -fieldValueSuggestions(input: FieldValueSuggestionInput!): FieldValuePage! -validateRecipe(input: DataframeRecipeInput!): RecipeValidation! -previewRecipe(input: DataframeRecipeInput!, limit: Int!): DataframePreview! -startRecipeExport(input: DataframeRecipeInput!, destination: ExportDestinationInput!): ExportJob! -``` - -This does not require seven unrelated implementations. Several operations can -compose the current catalog readers, generated FHIR schema, derived field -references, traversal rules, and dataframe planner. The formal gap analysis -proposes consolidating those current semantics behind one registry. - -Avoid making the frontend assemble raw `FhirTraversalStepInput` trees. That -contract remains useful as a lower-level developer API, but it is too close to -the compiler for the primary product experience. - -## 7. Recipe Template Definition - -A recipe template should declare intent and constraints, not contain canned -AQL. - -Each template should define: - -- stable template ID and version -- user-facing name and description -- supported row grains -- required and optional semantic relationships -- suggested columns -- optional default filters -- supported aggregates and pivots -- planner capability requirements -- expected identifier strategy -- supported destinations - -Initial templates should be deliberately small: - -### Patient cohort - -- default grain: Patient -- common columns: submitter ID, sex/gender, vital status, study -- common filters: diagnosis, study, demographics - -### Specimen inventory - -- default grain: Specimen -- common columns: patient ID, specimen ID/type, collection metadata -- common filters: specimen type, study, diagnosis - -### File manifest - -- default grain: File/DocumentReference -- common columns: patient ID, specimen ID/type, file name/type/size/access -- common filters: file type, specimen type, study - -### Diagnoses - -- default grain: diagnosis/Condition -- common columns: patient ID, diagnosis, stage, age/date fields -- common filters: diagnosis, stage, study - -### Labs or observations - -- default grain: Observation -- common columns: patient ID, observation code/name, value, unit, date -- common filters: observation code, status, date range - -### Study enrollment - -- default grain: ResearchSubject or patient-study membership -- common columns: patient ID, study ID/name, enrollment status, arm -- common filters: study and status - -These definitions are hypotheses until exercised against representative loaded -datasets and the actual planner. - -## 8. Implementation Sequence - -### Phase 1: capture conversations as fixtures - -Write 10 to 20 realistic user requests and expected recipe objects. Include -ambiguous and impossible requests. - -Examples: - -- "Give me a file manifest for BAM files with patient and specimen type." -- "One row per patient with melanoma diagnosis and all studies." -- "Show hemoglobin observations with value, unit, and collection date." - -These fixtures become the acceptance contract for the frontend and any future -language interface. - -### Phase 2: inventory current evidence - -For each fixture, record whether the current catalog can answer: - -- is the recipe family present? -- is the requested grain available? -- is the required path populated? -- are requested columns populated? -- are requested filter values discoverable? -- will the planner lower the request? - -This identifies missing analysis queries using evidence rather than guesswork. - -### Phase 3: add analysis services - -Start with: - -1. dataset summary -2. relationship coverage/fanout -3. grain-aware candidate columns -4. filter values/frequencies -5. recipe validation/explain - -Prefer extending the existing catalog and dataframebuilder services over adding -raw AQL strings directly to HTTP handlers. - -### Phase 4: add versioned recipes and templates - -Implement recipe types, normalization, semantic identifiers, template -definitions, and translation into the existing dataframe builder. - -### Phase 5: build the thin guided frontend - -The frontend should call the analysis and recipe APIs. It should contain little -FHIR-specific logic beyond display grouping and state management. - -### Phase 6: add streaming export - -Build NDJSON and CSV from one row-stream abstraction, then add Elasticsearch as -another destination over the same stream. - -## 9. Acceptance Criteria for the First Product Slice - -The first slice is complete when a non-technical user can: - -1. open a freshly loaded project -2. see only recipe families supported by its data and planner -3. select a row grain using plain language -4. choose suggested populated columns -5. create a filter from observed values -6. understand warnings about missing data or row multiplication -7. preview meaningful rows -8. save and reload the recipe -9. download flat NDJSON or CSV - -Direct Elasticsearch delivery can follow once the export stream and schema -validation are reliable. - -## 10. Design Guardrails - -- Do not expose arbitrary graph traversal as the default experience. -- Do not equate "edge exists" with "planner supports this recipe." -- Do not equate "FHIR field is legal" with "field is populated." -- Do not make the frontend calculate coverage, fanout, or planner support. -- Do not store AQL as the durable user artifact. -- Do not let an LLM emit or execute raw AQL. -- Do not return unbounded exports inline through GraphQL. -- Do keep project and authorization scope identical across analysis, preview, - and export. -- Do preserve a developer diagnostics view for recipe, logical plan, GraphQL, - AQL, and bind-variable inspection. - -## 11. First Concrete Work Package - -The recommended first implementation work package is a gap-analysis harness, -not a new frontend. - -It should contain: - -- representative conversation fixtures -- expected normalized recipes -- expected row grain and columns -- catalog/discovery evidence captured for each fixture -- planner validation result -- preview correctness result -- missing-capability classification - -That harness will show whether the next investment belongs in catalog analysis, -FHIR semantics, planner coverage, AQL performance, or user experience. It also -becomes the regression suite that keeps the frontend honest as Loom expands. diff --git a/docs/QUICKSTART.md b/docs/QUICKSTART.md index d0c99bb..ab781fc 100644 --- a/docs/QUICKSTART.md +++ b/docs/QUICKSTART.md @@ -348,6 +348,47 @@ Notes: - the server validates selectors/traversals against populated-field and populated-reference discovery - `fieldRef` is the preferred frontend-friendly path when available +### Run it and see the timing + +The checked-in operation and variables above are also runnable without copying +JSON from this document. With the local server running in `--no-auth` mode: + +```bash +make dataframe-demo +``` + +This prints the actual GraphQL response plus wall-clock time. To issue the +same request repeatedly and see min/average/max timing: + +```bash +make dataframe-demo DATAFRAME_REPEAT=10 +``` + +The command labels the first request as `cold` and the final request as +`warm`, then reports total HTTP/server time, returned rows, response bytes, and +rows/second. It also reports server-side field-reference resolution, request +preparation, physical compilation, Arango cursor time, per-row materialization, +and result assembly. The remaining wall-clock time is GraphQL serialization and +HTTP overhead. + +The compact example files are +[`examples/meta_patient_dataframe.graphql`](../examples/meta_patient_dataframe.graphql) +and +[`examples/meta_patient_dataframe.variables.json`](../examples/meta_patient_dataframe.variables.json). +`make dataframe-demo` runs the richer GDC-style case matrix in +[`examples/meta_gdc_case_matrix.graphql`](../examples/meta_gdc_case_matrix.graphql) +with [`examples/meta_gdc_case_matrix.variables.json`](../examples/meta_gdc_case_matrix.variables.json): +diagnoses, specimens, nested files and sample groups, Observation code/value +pivots, and representative related records. +For an explicit named GDC operation, run: + +```bash +rtk go run ./cmd/dataframe-query \ + -query examples/meta_gdc_case_matrix.graphql \ + -variables examples/meta_gdc_case_matrix.variables.json \ + -repeat 1 +``` + ## 7. Shut down local Arango ```bash diff --git a/docs/RICH_PHYSICAL_RENDERER_PLAN.md b/docs/RICH_PHYSICAL_RENDERER_PLAN.md new file mode 100644 index 0000000..a58a19c --- /dev/null +++ b/docs/RICH_PHYSICAL_RENDERER_PLAN.md @@ -0,0 +1,257 @@ +# Rich Physical Renderer Plan + +## Goal + +Finish the physical renderer for the dataframe features that still execute +through `compileLowered` today: + +1. optional child traversal projections and filters; +2. aggregates and derived values over those child sets; +3. pivots; +4. representative slices; +5. deletion of the corresponding compatibility compiler code. + +The runtime rule at completion is simple: + +```text +Builder -> SemanticPlan -> PhysicalPlan -> RenderPhysicalPlan -> AQL +``` + +`compileLowered` is an oracle during implementation only. It must not receive +new product features or remain a production fallback after its physical +equivalent is available. + +## Already physical + +- root scan, project/generation/auth scope, root sort/limit; +- root fields, selector fallback/value modes, and root typed filters; +- optional navigation-only traversal sets; +- required traversal matches as correlated, scoped `EXISTS` subplans; +- proven inbound routes and ResearchSubject -> ResearchStudy outbound route. + +## Semantic contract to preserve + +For every work package, preserve all of the following before cutover: + +- one output row per root resource; +- root sort and preview limit happen before optional traversal work; +- child traversals never multiply root rows; +- every node and edge has project, dataset-generation, and auth predicates; +- selector fallback, scalar/array/distinct-array, null, and empty-array + behavior match the existing output contract; +- output column names and request order are stable; +- no request-derived text is serialized as AQL source. + +## W1 — Child traversal sets and child field projections + +### Physical IR + +Use the existing `PhysicalSet` plus `PhysicalSubplan` for every optional child +node. A child set captures its parent variable, contains its typed traversal +and scope operations, and returns the child node. Add a typed set projection +expression that accepts: + +- source set variable; +- child resource type; +- `PhysicalExtract` expression(s); +- scalar/array/distinct-array value mode; +- explicit null/empty behavior. + +Nested traversal sets capture their parent set element rather than the root. +They must be defined inside the parent set subplan, not as a top-level AQL +`FOR`, so root row grain cannot change. + +### Lowering + +1. Lower each optional `SemanticNode` to a `PhysicalSet` in request order. +2. Resolve the route exclusively with `storage_route.go`; reject unknown + outbound/ANY routes. +3. Lower each child `SemanticField` through `ResolveSemanticField`, exactly as + root fields are lowered today. +4. Add child output expressions to the owning root/parent projection. +5. Lower sibling-prefix sharing only after unshared child projections have + exact parity. Sharing is a physical optimization, not a semantic shortcut. + +### Renderer + +Render a child set as `LET set = (FOR node, edge IN ... RETURN node)` with all +scope filters in the subquery. Render child projections by iterating only over +the set variable. Never expand a child `FOR` in the outer root query. + +### Tests and deletion + +- unit goldens: one child field, nested child field, array and fallback field; +- result parity on META for patient -> specimen -> file; +- Explain: root scoped index + `fhir_edge` traversal index; +- cut over child-field requests; +- delete the matching `compileTraversal` field-projection branch once all + child-field fixtures use physical plans. + +## W2 — Typed child filters + +### Physical IR and lowering + +Reuse `PhysicalPredicateExpression` and `PhysicalExtract`; do not add a +second filter language. Lower `SemanticNode.Filters` into the child set +subplan immediately after traversal scope filters and before its return. + +Required-match filters use the same predicate lowering inside their `EXISTS` +subplan. This removes the last special-case relationship filter renderer. + +### Renderer + +Render selector predicates through the existing fixed templates for equality, +membership, text matching, date comparisons, EXISTS/MISSING, and ALL/ANY/NONE +quantifiers. Literal values remain bind variables. + +### Tests and deletion + +- parity matrix for every filter operator on root, child, nested child, and + required-match routes; +- auth and dataset-generation tests with a matching row outside scope; +- live inbound and proven-outbound Explain tests; +- remove `compileTypedFilters` use from traversal and required-match helpers. + +## W3 — Aggregates and derived values + +### Physical IR + +Use `PhysicalAggregate` and typed expressions over a set source. Support the +currently exposed semantic operations in this order: + +1. count and distinct count; +2. value arrays and distinct value arrays; +3. first/representative value; +4. min/max; +5. predicate-qualified aggregates. + +Define empty-set output explicitly from current GraphQL behavior before each +operation: count is `0`; value arrays are `[]`; scalar representative/min/max +are `null` unless existing tests prove otherwise. + +Derived fields are expressions over previously defined typed sets or typed +aggregate values. They may not reference a textual AQL variable name. + +### Renderer + +Render aggregate expressions as bounded AQL subqueries over a set variable. +Use `UNIQUE`, `SORTED_UNIQUE`, `FIRST`, `MIN`, `MAX`, and `LENGTH` only for +their validated typed operations. Preserve deterministic representative sort. + +### Tests and deletion + +- META GDC case/file counts, values, and null/empty behavior; +- aggregation parity for no child, one child, repeated values, and scoped-out + child documents; +- delete `compileRootAggregateExpr`, aggregate portions of + `compileDerivedField`, and aggregate-only named-set helpers after cutover. + +## W4 — Pivots + +### Physical IR + +Lower each `SemanticPivot` to `PhysicalPivotMap` with: + +- a typed source set or root payload source; +- resource type and parsed key/value selectors; +- requested columns stored as a bound list; +- explicit collision rule and absent-column null behavior. + +The pivot’s output object is a typed projection expression. Dynamic data values +must never become AQL object-key source. + +### Renderer + +Build the map through a fixed subquery that filters permitted columns and uses +bound column keys. Maintain the existing output naming and key order contract. + +### Tests and deletion + +- root and child pivots; +- sparse values, repeated keys, unknown requested column, and nested selector; +- real GDC observation pivot fixture with output-shape parity; +- delete `compileRootPivot`, `compileDerivedPivotMapLets`, and pivot-specific + string compiler helpers once every pivot route is physical. + +## W5 — Representative slices + +### Physical IR + +Lower `SemanticSlice` to `PhysicalSlice` over a typed child set with: + +- optional typed predicate; +- explicit stable sort expression; +- bind-backed positive limit; +- nested typed object projection. + +### Renderer + +Render a local set subquery: filter, stable sort, limit, then return the typed +object. It must not alter the outer root window or expose an unbounded child +collection. + +### Tests and deletion + +- zero, one, and many child records; +- tie-breaking stability; +- filter + slice interaction and nested projected field behavior; +- delete `compileRepresentativeSlice`, `compileRootSlice`, and slice-only + lowered helpers after physical cutover. + +## W6 — Traversal sharing optimization + +Do this only after W1–W5 have result parity without sharing. + +1. Identify sibling child sets with identical parent set, route direction, + edge label, scope, and traversal depth. +2. Materialize one typed broad traversal set, then typed resource-filtered + subsets. Never share across differing target-type semantics. +3. Add a physical-plan optimization pass that rewrites only equivalent set + subplans and records provenance/count in explain output. +4. Require parity and Explain cost improvement or neutrality; otherwise retain + the unshared physical plan. + +Delete generic compatibility named-set sharing only after this pass owns every +currently supported sharing case. + +## W7 — Cutover and deletion + +### Per-feature gate + +A feature family may leave compatibility only when all are true: + +1. semantic-to-physical lowering has deterministic plan goldens; +2. physical and compatibility execution have row/column/value parity on META; +3. physical AQL has scoped root and traversal index Explain coverage; +4. no runtime request for that family calls `compileLowered`. + +### Final deletion PR + +After W1–W6 pass, delete in one focused change: + +- `Compile`, `Lower`, `lowerSemanticBuilder`, and `compileLowered`; +- `Builder.Sets`, `NamedSet`, lowered derived-field types, and old AQL helper + methods that no longer have physical consumers; +- compatibility-only conformance fixtures, replacing them with physical-plan + and execution-parity fixtures. + +At that point `CompileRequest` is reduced to: + +```go +semantic := BuildSemanticPlan(builder) +physical := BuildPhysicalPlan(semantic) +return RenderPhysicalPlan(physical) +``` + +## Work ownership and order + +| Wave | Work | Shared-file owner | +| --- | --- | --- | +| 1 | W1 child sets and W2 predicates | physical lowerer owner | +| 2 | W3 aggregates and W4 pivots | physical renderer owner | +| 3 | W5 slices | physical renderer owner | +| 4 | W6 sharing + benchmark/Explain | optimizer owner | +| 5 | W7 deletion | compiler core owner | + +Only the owner for a wave edits `physical_plan.go`, `physical_render.go`, and +`compile.go`. Other workers contribute isolated feature tests and fixtures. diff --git a/docs/TERRA_ULTRA_EXECUTION_PLAN.md b/docs/TERRA_ULTRA_EXECUTION_PLAN.md index 399e20e..3db0b6e 100644 --- a/docs/TERRA_ULTRA_EXECUTION_PLAN.md +++ b/docs/TERRA_ULTRA_EXECUTION_PLAN.md @@ -41,18 +41,18 @@ The baseline includes: - `schemas/graph-fhir.json`: the active graph/FHIR schema used by generation, generic validation, and edge extraction - `cmd/generate/main.go`: the existing FHIR generator -- `internal/fhir/model.go`: generated Go FHIR structs -- `internal/fhir/validate.go`: generated validation methods -- `internal/fhir/extract.go`: generated graph-edge extraction -- `internal/fhirschema/generated.go`: generated field and traversal metadata -- `internal/fhirschema/schema.go`: the handwritten lookup, selector, and pivot +- `fhirstructs/model.go`: generated Go FHIR structs +- `fhirstructs/validate.go`: generated validation methods +- `fhirstructs/extract.go`: generated graph-edge extraction +- `fhirschema/generated.go`: generated field and traversal metadata +- `fhirschema/schema.go`: the handwritten lookup, selector, and pivot logic over generated metadata - `internal/ingest/generated_load.go`: generated fast-path resource dispatch - `internal/ingest/row_builder.go`: generated/generic row-builder boundary - `internal/catalog/`: existing populated-field, distinct-value, pivot, and populated-reference profiling/discovery -- `internal/graphqlapi/schema.graphqls`: the handwritten GraphQL contract -- `gqlgen.yml` and generated gqlgen artifacts under `internal/graphqlapi/` +- `graphqlapi/schema.graphqls`: the handwritten GraphQL contract +- `gqlgen.yml` and generated gqlgen artifacts under `graphqlapi/` - `Makefile` targets `generate-fhir`, `generate-graphql`, `graphql-check`, and `test` @@ -346,7 +346,7 @@ Owns: Primary files: -- new `internal/schemaidentity/` +- `internal/graphschema/` - new `internal/dataset/` - `internal/ingest/` - generation-aware ingestion storage @@ -409,7 +409,7 @@ Primary files: During C2, consume current field and traversal behavior through adapters. Do not immediately move: -- `internal/dataframebuilder/fieldrefs.go` +- `graphqlapi/dataframe/fieldrefs.go` - `internal/dataframe/traversal_rules.go` Consolidation occurs after recipe and planner contracts agree. @@ -543,12 +543,12 @@ It must not add production shortcuts merely to pass fixtures. These files have one integration owner per wave: -- `internal/graphqlapi/schema.graphqls` -- `internal/graphqlapi/schema.resolvers.go` -- `internal/graphqlapi/generated.go` -- `internal/graphqlapi/model/models.go` -- `internal/api/routes.go` -- `internal/api/service.go` +- `graphqlapi/schema.graphqls` +- `graphqlapi/schema.resolvers.go` +- `graphqlapi/generated.go` +- `graphqlapi/model/models.go` +- `internal/httpapi/routes.go` +- `internal/httpapi/service.go` - `internal/dataframe/service.go` - current `internal/dataframe/planner.go` - `internal/dataframe/lowered_types.go` diff --git a/docs/benchmarks/AQL_PROFILE_CORPUS.md b/docs/benchmarks/AQL_PROFILE_CORPUS.md new file mode 100644 index 0000000..216550a --- /dev/null +++ b/docs/benchmarks/AQL_PROFILE_CORPUS.md @@ -0,0 +1,37 @@ +# Generic AQL profile corpus + +`TestProfileCorpusAgainstArango` exercises the Arango adapter against five +schema-independent physical query shapes: + +| Shape | Physical work covered | +| --- | --- | +| `root` | scoped root scan, sort, limit, projection | +| `sibling` | three same-parent inbound traversals with typed targets | +| `deep` | two-hop nested traversal | +| `required` | traversal-backed root semi-join | +| `pivot` | repeated value extraction and `COLLECT` grouping | + +The test is read-only and opt-in. It uses the same local defaults as the +compiler integration suite and accepts these overrides: + +```bash +LOOM_COMPILER_ARANGO_INTEGRATION=1 \ +LOOM_ARANGO_URL=http://127.0.0.1:8529 \ +LOOM_ARANGO_DATABASE=fhir_proto \ +LOOM_ARANGO_PROJECT=ARANGODB_PROTO \ +GOCACHE="$(pwd)/.gocache" GOTOOLCHAIN=auto \ +go test ./internal/store/arango -run TestProfileCorpusAgainstArango -count=1 -v +``` + +For every shape the test performs both `EXPLAIN` and cursor `PROFILE` level 2 +using bind variables. The test requires a project index on the root shape and +an edge index on every traversal shape. It also requires per-node profile +statistics, then logs a stable summary containing result count, execution +runtime, full/index scan counts, and the slowest execution node. + +The profile adapter reports Arango's execution plan node IDs and joins them to +node types from `extra.plan`. This makes repeated traversal nodes and nested +subqueries comparable across compiler rewrites without matching generated AQL +variable names. Keep the corpus queries deliberately generic: new FHIR routes +with the same physical shape should be covered without changing this test. + diff --git a/internal/fhirschema/compiler_semantics.go b/fhirschema/compiler_semantics.go similarity index 100% rename from internal/fhirschema/compiler_semantics.go rename to fhirschema/compiler_semantics.go diff --git a/internal/fhirschema/compiler_semantics_test.go b/fhirschema/compiler_semantics_test.go similarity index 100% rename from internal/fhirschema/compiler_semantics_test.go rename to fhirschema/compiler_semantics_test.go diff --git a/internal/fhirschema/generated.go b/fhirschema/generated.go similarity index 100% rename from internal/fhirschema/generated.go rename to fhirschema/generated.go diff --git a/internal/fhirschema/root_resources_test.go b/fhirschema/root_resources_test.go similarity index 100% rename from internal/fhirschema/root_resources_test.go rename to fhirschema/root_resources_test.go diff --git a/internal/fhirschema/schema.go b/fhirschema/schema.go similarity index 100% rename from internal/fhirschema/schema.go rename to fhirschema/schema.go diff --git a/internal/fhirschema/schema_test.go b/fhirschema/schema_test.go similarity index 100% rename from internal/fhirschema/schema_test.go rename to fhirschema/schema_test.go diff --git a/internal/fhirschema/terminal_metadata.go b/fhirschema/terminal_metadata.go similarity index 100% rename from internal/fhirschema/terminal_metadata.go rename to fhirschema/terminal_metadata.go diff --git a/internal/fhirschema/terminal_metadata_test.go b/fhirschema/terminal_metadata_test.go similarity index 100% rename from internal/fhirschema/terminal_metadata_test.go rename to fhirschema/terminal_metadata_test.go diff --git a/go.mod b/go.mod index 40d8f97..7988e58 100644 --- a/go.mod +++ b/go.mod @@ -52,6 +52,7 @@ require ( golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect golang.org/x/crypto v0.51.0 // indirect golang.org/x/net v0.54.0 // indirect + golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.44.0 // indirect golang.org/x/term v0.43.0 // indirect golang.org/x/text v0.37.0 // indirect diff --git a/go.sum b/go.sum index 87a35d7..c288e08 100644 --- a/go.sum +++ b/go.sum @@ -33,6 +33,8 @@ github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= +github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -133,6 +135,8 @@ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99 github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/shamaton/msgpack/v3 v3.1.2 h1:d5gWAIyMU4M0WgDjz6IFSCuXJUA2dFwRHBpDclE8CLw= @@ -162,6 +166,8 @@ github.com/tinylib/msgp v1.6.4 h1:mOwYbyYDLPj35mkA2BjjYejgJk9BuHxDdvRnb6v2ZcQ= github.com/tinylib/msgp v1.6.4/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= +github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.71.0 h1:tepR7H+Guh9VUqxxcPggYi8R3lGUu2Rsdh+z7/FCY3k= @@ -170,6 +176,8 @@ github.com/vektah/gqlparser/v2 v2.5.22 h1:yaaeJ0fu+nv1vUMW0Hl+aS1eiv1vMfapBNjpff github.com/vektah/gqlparser/v2 v2.5.22/go.mod h1:xMl+ta8a5M1Yo1A1Iwt/k7gSpscwSnHZdw7tfhEGfTM= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -204,6 +212,8 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= +golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -220,6 +230,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -247,6 +259,8 @@ golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= +golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/gqlgen.yml b/gqlgen.yml index 105e72c..5e09e35 100644 --- a/gqlgen.yml +++ b/gqlgen.yml @@ -1,17 +1,17 @@ schema: - - internal/graphqlapi/schema.graphqls + - graphqlapi/schema.graphqls exec: - filename: internal/graphqlapi/generated.go + filename: graphqlapi/generated.go package: graphqlapi model: - filename: internal/graphqlapi/model/models.go + filename: graphqlapi/model/models.go package: model resolver: layout: follow-schema - dir: internal/graphqlapi + dir: graphqlapi package: graphqlapi skip_mod_tidy: true diff --git a/internal/dataframebuilder/active_generation.go b/graphqlapi/dataframe/active_generation.go similarity index 96% rename from internal/dataframebuilder/active_generation.go rename to graphqlapi/dataframe/active_generation.go index a07ff65..b4c89a1 100644 --- a/internal/dataframebuilder/active_generation.go +++ b/graphqlapi/dataframe/active_generation.go @@ -1,4 +1,4 @@ -package dataframebuilder +package dataframeapi import ( "context" diff --git a/internal/dataframebuilder/active_generation_test.go b/graphqlapi/dataframe/active_generation_test.go similarity index 54% rename from internal/dataframebuilder/active_generation_test.go rename to graphqlapi/dataframe/active_generation_test.go index 7a6c32f..86f4a63 100644 --- a/internal/dataframebuilder/active_generation_test.go +++ b/graphqlapi/dataframe/active_generation_test.go @@ -1,17 +1,14 @@ -package dataframebuilder +package dataframeapi import ( "context" "strings" "testing" - "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/graphqlapi/model" "github.com/calypr/loom/internal/catalog" "github.com/calypr/loom/internal/dataframe" "github.com/calypr/loom/internal/dataset" - "github.com/calypr/loom/internal/discovery" - "github.com/calypr/loom/internal/graphqlapi/model" - "github.com/calypr/loom/internal/recipe" ) type builderActiveManifestResolver struct { @@ -19,12 +16,6 @@ type builderActiveManifestResolver struct { projects []string } -type builderActiveResourceAccess struct{} - -func (builderActiveResourceAccess) GetAllowedResources(context.Context, string, string, string) ([]string, error) { - return []string{"/programs/example/projects/allowed"}, nil -} - func (r *builderActiveManifestResolver) ResolveActiveManifest(_ context.Context, project string) (dataset.Manifest, error) { r.projects = append(r.projects, project) return r.manifest.Clone(), nil @@ -123,43 +114,8 @@ func TestActiveGenerationPropagatesThroughBuilderCatalogEntrypoints(t *testing.T }); err != nil { t.Fatalf("Introspect() error = %v", err) } - if _, err := service.DiscoverGuided(context.Background(), GuidedDiscoveryRequest{Project: project}); err != nil { - t.Fatalf("DiscoverGuided() error = %v", err) - } - - facts := discovery.CatalogFacts{ - Project: project, - Fields: []catalog.PopulatedField{{ - Project: project, ResourceType: "Patient", Path: "gender", Kind: "scalar", DocCount: 2, - DistinctValues: []string{"female", "male"}, - }}, - } - snapshot, err := discovery.BuildSnapshot(facts) - if err != nil { - t.Fatalf("BuildSnapshot() error = %v", err) - } - if len(snapshot.Columns) != 1 { - t.Fatalf("snapshot columns = %#v, want one gender capability", snapshot.Columns) - } - plan, err := service.PrepareRecipe(context.Background(), RecipeRequest{Recipe: recipe.Recipe{ - Version: recipe.VersionV1, - Template: recipe.TemplatePatientCohort, - TemplateVersion: 1, - Project: project, - GenerationPolicy: recipe.GenerationLatest, - Grain: recipe.GrainPatient, - Columns: []recipe.ColumnSelection{{ID: string(snapshot.Columns[0].ID)}}, - Destination: recipe.Destination{Type: recipe.DestinationPreview}, - }}) - if err != nil { - t.Fatalf("PrepareRecipe() error = %v", err) - } - if plan.Builder.DatasetGeneration != generation { - t.Fatalf("prepared recipe generation = %q, want %q", plan.Builder.DatasetGeneration, generation) - } - - if len(active.projects) < 6 { - t.Fatalf("active resolver calls = %#v, want one selection for each builder/dataframe entrypoint", active.projects) + if len(active.projects) < 4 { + t.Fatalf("active resolver calls = %#v, want one selection for each live builder/dataframe entrypoint", active.projects) } if len(fieldCalls) == 0 || len(referenceCalls) == 0 { t.Fatalf("catalog calls fields=%d references=%d, want both", len(fieldCalls), len(referenceCalls)) @@ -175,38 +131,3 @@ func TestActiveGenerationPropagatesThroughBuilderCatalogEntrypoints(t *testing.T } } } - -func TestBuilderActiveGenerationKeepsRestrictedEmptyScopeForGuidedCatalog(t *testing.T) { - const project = "project-a" - const generation = "generation-a" - scopeResolver := authscope.NewScopeResolver(authscope.ScopeResolverConfig{ - ResourceAccess: builderActiveResourceAccess{}, - ListExistingAuthResourcePaths: func(_ context.Context, options catalog.AuthResourcePathOptions) ([]string, error) { - if options.Project != project || options.DatasetGeneration != generation { - t.Fatalf("generation-aware scope options = %+v, want %s/%s", options, project, generation) - } - return []string{"example-unrelated"}, nil - }, - }) - assertRestricted := func(unrestricted *bool, paths []string, gotGeneration string) { - if gotGeneration != generation || unrestricted == nil || *unrestricted || len(paths) != 0 { - t.Fatalf("restricted empty catalog scope generation=%q unrestricted=%#v paths=%#v", gotGeneration, unrestricted, paths) - } - } - service := NewService(Config{ - ActiveManifestResolver: &builderActiveManifestResolver{manifest: builderReadyManifest(t, project, generation)}, - ScopeResolver: scopeResolver, - DiscoverFields: func(_ context.Context, options catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { - assertRestricted(options.AuthResourcePathsUnrestricted, options.AuthResourcePaths, options.DatasetGeneration) - return []catalog.PopulatedField{}, nil - }, - DiscoverReferences: func(_ context.Context, options catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { - assertRestricted(options.AuthResourcePathsUnrestricted, options.AuthResourcePaths, options.DatasetGeneration) - return []catalog.PopulatedReference{}, nil - }, - }) - ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{AuthorizationHeader: "Bearer header.payload.signature"}) - if _, err := service.DiscoverGuided(ctx, GuidedDiscoveryRequest{Project: project}); err != nil { - t.Fatalf("DiscoverGuided() error = %v", err) - } -} diff --git a/internal/dataframebuilder/auth_scope_test.go b/graphqlapi/dataframe/auth_scope_test.go similarity index 79% rename from internal/dataframebuilder/auth_scope_test.go rename to graphqlapi/dataframe/auth_scope_test.go index 5ed67c4..218b401 100644 --- a/internal/dataframebuilder/auth_scope_test.go +++ b/graphqlapi/dataframe/auth_scope_test.go @@ -1,13 +1,13 @@ -package dataframebuilder +package dataframeapi import ( "context" "testing" + "github.com/calypr/loom/graphqlapi/model" "github.com/calypr/loom/internal/authscope" "github.com/calypr/loom/internal/catalog" "github.com/calypr/loom/internal/dataframe" - "github.com/calypr/loom/internal/graphqlapi/model" ) type dataframeBuilderRestrictedEmptyResourceAccess struct{} @@ -81,7 +81,7 @@ func TestRunPreservesRestrictedEmptyScopeIntoDataframeService(t *testing.T) { } } -func TestIntrospectAndGuidedDiscoveryKeepRestrictedEmptyCatalogMode(t *testing.T) { +func TestIntrospectKeepsRestrictedEmptyCatalogMode(t *testing.T) { resolver := dataframeBuilderRestrictedEmptyScopeResolver() fieldCalls := 0 referenceCalls := 0 @@ -103,37 +103,11 @@ func TestIntrospectAndGuidedDiscoveryKeepRestrictedEmptyCatalogMode(t *testing.T if _, err := service.Introspect(ctx, IntrospectionRequest{Project: "P1", RootResourceType: "Patient"}); err != nil { t.Fatalf("Introspect() error = %v", err) } - if _, err := service.DiscoverGuided(ctx, GuidedDiscoveryRequest{Project: "P1"}); err != nil { - t.Fatalf("DiscoverGuided() error = %v", err) - } if fieldCalls == 0 || referenceCalls == 0 { t.Fatalf("catalog calls = fields %d references %d, want both", fieldCalls, referenceCalls) } } -func TestPrepareRecipeKeepsRestrictedEmptyCatalogMode(t *testing.T) { - facts := recipeServiceFacts() - genderID := recipeServiceCapabilityID(t, facts, "Patient", "gender") - service := NewService(Config{ - ScopeResolver: dataframeBuilderRestrictedEmptyScopeResolver(), - DiscoverFields: func(_ context.Context, options catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { - assertRestrictedEmptyFieldScope(t, options) - return append([]catalog.PopulatedField(nil), facts.Fields...), nil - }, - }) - - plan, err := service.PrepareRecipe(dataframeBuilderRestrictedEmptyContext(), RecipeRequest{Recipe: recipePreview(genderID)}) - if err != nil { - t.Fatalf("PrepareRecipe() error = %v", err) - } - if plan.Builder.AuthScopeMode != authscope.ReadScopeRestricted { - t.Fatalf("prepared recipe scope mode = %q, want restricted", plan.Builder.AuthScopeMode) - } - if len(plan.Builder.AuthResourcePaths) != 0 { - t.Fatalf("prepared recipe paths = %#v, want empty", plan.Builder.AuthResourcePaths) - } -} - func assertRestrictedEmptyFieldScope(t *testing.T, options catalog.PopulatedFieldOptions) { t.Helper() if options.AuthResourcePathsUnrestricted == nil || *options.AuthResourcePathsUnrestricted { diff --git a/internal/dataframebuilder/fieldrefs.go b/graphqlapi/dataframe/fieldrefs.go similarity index 98% rename from internal/dataframebuilder/fieldrefs.go rename to graphqlapi/dataframe/fieldrefs.go index 457c58b..fad3c75 100644 --- a/internal/dataframebuilder/fieldrefs.go +++ b/graphqlapi/dataframe/fieldrefs.go @@ -1,12 +1,12 @@ -package dataframebuilder +package dataframeapi import ( "fmt" "regexp" "strings" + "github.com/calypr/loom/fhirschema" "github.com/calypr/loom/internal/catalog" - "github.com/calypr/loom/internal/fhirschema" ) type FieldHint struct { diff --git a/internal/dataframebuilder/fieldrefs_test.go b/graphqlapi/dataframe/fieldrefs_test.go similarity index 98% rename from internal/dataframebuilder/fieldrefs_test.go rename to graphqlapi/dataframe/fieldrefs_test.go index 85a4691..710e75d 100644 --- a/internal/dataframebuilder/fieldrefs_test.go +++ b/graphqlapi/dataframe/fieldrefs_test.go @@ -1,4 +1,4 @@ -package dataframebuilder +package dataframeapi import ( "strings" diff --git a/internal/dataframebuilder/helpers.go b/graphqlapi/dataframe/helpers.go similarity index 93% rename from internal/dataframebuilder/helpers.go rename to graphqlapi/dataframe/helpers.go index 2411086..414ab2c 100644 --- a/internal/dataframebuilder/helpers.go +++ b/graphqlapi/dataframe/helpers.go @@ -1,4 +1,4 @@ -package dataframebuilder +package dataframeapi import "github.com/calypr/loom/internal/catalog" diff --git a/internal/dataframebuilder/input_mapping.go b/graphqlapi/dataframe/input_mapping.go similarity index 98% rename from internal/dataframebuilder/input_mapping.go rename to graphqlapi/dataframe/input_mapping.go index d0a3fea..8131dd8 100644 --- a/internal/dataframebuilder/input_mapping.go +++ b/graphqlapi/dataframe/input_mapping.go @@ -1,10 +1,10 @@ -package dataframebuilder +package dataframeapi import ( "strings" + "github.com/calypr/loom/graphqlapi/model" "github.com/calypr/loom/internal/dataframe" - "github.com/calypr/loom/internal/graphqlapi/model" ) func BuilderFromInput(in model.FhirDataframeInput) dataframe.Builder { diff --git a/internal/dataframebuilder/input_mapping_test.go b/graphqlapi/dataframe/input_mapping_test.go similarity index 96% rename from internal/dataframebuilder/input_mapping_test.go rename to graphqlapi/dataframe/input_mapping_test.go index 175c345..510294c 100644 --- a/internal/dataframebuilder/input_mapping_test.go +++ b/graphqlapi/dataframe/input_mapping_test.go @@ -1,9 +1,9 @@ -package dataframebuilder +package dataframeapi import ( "testing" - "github.com/calypr/loom/internal/graphqlapi/model" + "github.com/calypr/loom/graphqlapi/model" ) func TestBuilderFromInputMapsAggregatesSlicesAndFallbacks(t *testing.T) { diff --git a/internal/dataframebuilder/input_resolution.go b/graphqlapi/dataframe/input_resolution.go similarity index 99% rename from internal/dataframebuilder/input_resolution.go rename to graphqlapi/dataframe/input_resolution.go index 53694a6..ec31711 100644 --- a/internal/dataframebuilder/input_resolution.go +++ b/graphqlapi/dataframe/input_resolution.go @@ -1,13 +1,13 @@ -package dataframebuilder +package dataframeapi import ( "context" "fmt" "strings" + "github.com/calypr/loom/graphqlapi/model" "github.com/calypr/loom/internal/authscope" "github.com/calypr/loom/internal/catalog" - "github.com/calypr/loom/internal/graphqlapi/model" ) func (s *Service) PrepareRunInput(ctx context.Context, input model.FhirDataframeInput) (model.FhirDataframeInput, error) { diff --git a/internal/dataframebuilder/introspection.go b/graphqlapi/dataframe/introspection.go similarity index 99% rename from internal/dataframebuilder/introspection.go rename to graphqlapi/dataframe/introspection.go index 4fd976e..452bcbf 100644 --- a/internal/dataframebuilder/introspection.go +++ b/graphqlapi/dataframe/introspection.go @@ -1,4 +1,4 @@ -package dataframebuilder +package dataframeapi import ( "context" diff --git a/internal/dataframebuilder/introspection_test.go b/graphqlapi/dataframe/introspection_test.go similarity index 99% rename from internal/dataframebuilder/introspection_test.go rename to graphqlapi/dataframe/introspection_test.go index f03c22f..a38f1b4 100644 --- a/internal/dataframebuilder/introspection_test.go +++ b/graphqlapi/dataframe/introspection_test.go @@ -1,4 +1,4 @@ -package dataframebuilder +package dataframeapi import ( "context" diff --git a/internal/dataframebuilder/service.go b/graphqlapi/dataframe/service.go similarity index 87% rename from internal/dataframebuilder/service.go rename to graphqlapi/dataframe/service.go index fb2e13e..8c715e2 100644 --- a/internal/dataframebuilder/service.go +++ b/graphqlapi/dataframe/service.go @@ -1,13 +1,14 @@ -package dataframebuilder +package dataframeapi import ( "context" + "time" + "github.com/calypr/loom/graphqlapi/model" "github.com/calypr/loom/internal/authscope" "github.com/calypr/loom/internal/catalog" "github.com/calypr/loom/internal/dataframe" "github.com/calypr/loom/internal/dataset" - "github.com/calypr/loom/internal/graphqlapi/model" arangostore "github.com/calypr/loom/internal/store/arango" ) @@ -63,6 +64,7 @@ func NewService(cfg Config) *Service { } func (s *Service) Run(ctx context.Context, input model.FhirDataframeInput, limit *int) (*dataframe.Result, error) { + started := time.Now() normalizedInput, scope, generation, err := s.prepareRunInput(ctx, input) if err != nil { return nil, err @@ -79,8 +81,17 @@ func (s *Service) Run(ctx context.Context, input model.FhirDataframeInput, limit // matters when no catalog paths survive a restricted caller's intersection: // an empty list alone would otherwise be legacy-unrestricted downstream. builder.AuthScopeMode = scope.Mode - return s.dataframes.Run(ctx, dataframe.RunRequest{ + result, err := s.dataframes.Run(ctx, dataframe.RunRequest{ Builder: builder, Limit: rowLimit, }) + if err != nil { + return nil, err + } + result.Diagnostics.InputResolution = time.Since(started) - result.Diagnostics.Total + if result.Diagnostics.InputResolution < 0 { + result.Diagnostics.InputResolution = 0 + } + result.Diagnostics.Total = time.Since(started) + return result, nil } diff --git a/internal/dataframebuilder/types.go b/graphqlapi/dataframe/types.go similarity index 96% rename from internal/dataframebuilder/types.go rename to graphqlapi/dataframe/types.go index d1f9d39..ff6de69 100644 --- a/internal/dataframebuilder/types.go +++ b/graphqlapi/dataframe/types.go @@ -1,4 +1,4 @@ -package dataframebuilder +package dataframeapi import "github.com/calypr/loom/internal/catalog" diff --git a/graphqlapi/dataframe_diagnostics.go b/graphqlapi/dataframe_diagnostics.go new file mode 100644 index 0000000..efc0634 --- /dev/null +++ b/graphqlapi/dataframe_diagnostics.go @@ -0,0 +1,55 @@ +package graphqlapi + +import ( + "time" + + "github.com/calypr/loom/graphqlapi/model" + "github.com/calypr/loom/internal/dataframe" +) + +func dataframeDiagnostics(in dataframe.QueryDiagnostics) *model.DataframeQueryDiagnostics { + return &model.DataframeQueryDiagnostics{ + InputResolutionMs: milliseconds(in.InputResolution), + RequestPreparationMs: milliseconds(in.RequestPreparation), + CompilationMs: milliseconds(in.Compilation), + ArangoQueryMs: milliseconds(in.ArangoQuery), + RowMaterializationMs: milliseconds(in.RowMaterialization), + ResultAssemblyMs: milliseconds(in.ResultAssembly), + TotalMs: milliseconds(in.Total), + Plan: compilerPlanDiagnostics(in.Plan), + } +} + +func milliseconds(value time.Duration) float64 { return float64(value) / float64(time.Millisecond) } + +func compilerPlanDiagnostics(in dataframe.CompilerPlanDiagnostics) *model.DataframeCompilerPlanDiagnostics { + out := &model.DataframeCompilerPlanDiagnostics{ + TraversalSets: in.TraversalSets, + SharedTraversalCount: in.SharedTraversalCount, + RequiredMatchReuseCount: in.RequiredMatchReuseCount, + ScopedSharingCandidateGroups: in.ScopedSharingCandidateGroups, + ScopedSharingCandidateSets: in.ScopedSharingCandidateSets, + PotentialSharingOpportunityGroups: in.PotentialSharingOpportunityGroups, + PotentialSharingOpportunitySets: in.PotentialSharingOpportunitySets, + OptimizationPolicy: optimizationPolicy(in.OptimizationPolicy), + RichSourceReuse: make([]*model.DataframeRichSourceReuse, 0, len(in.RichSourceReuse)), + } + for _, reuse := range in.RichSourceReuse { + out.RichSourceReuse = append(out.RichSourceReuse, &model.DataframeRichSourceReuse{ + SourceSet: reuse.SourceSet, + AggregateConsumers: reuse.AggregateConsumers, + PivotConsumers: reuse.PivotConsumers, + SliceConsumers: reuse.SliceConsumers, + TotalConsumers: reuse.TotalConsumers(), + }) + } + return out +} + +func optimizationPolicy(in dataframe.PhysicalOptimizationReport) *model.DataframeOptimizationPolicy { + out := &model.DataframeOptimizationPolicy{Name: in.Policy, Enabled: in.Enabled, MinimumSavings: in.MinimumSavings, Decisions: make([]*model.DataframeOptimizationDecision, 0, len(in.Decisions))} + for _, decision := range in.Decisions { + out.Decisions = append(out.Decisions, &model.DataframeOptimizationDecision{Rule: decision.Rule, Enabled: decision.Enabled, CandidateSets: decision.CandidateSets, EstimatedBaselineWork: decision.EstimatedBaselineWork, EstimatedOptimizedWork: decision.EstimatedOptimizedWork, EstimatedSavings: decision.EstimatedSavings, Reason: decision.Reason}) + } + return out +} diff --git a/internal/graphqlapi/generated.go b/graphqlapi/generated.go similarity index 71% rename from internal/graphqlapi/generated.go rename to graphqlapi/generated.go index 62d8281..b9cf81b 100644 --- a/internal/graphqlapi/generated.go +++ b/graphqlapi/generated.go @@ -9,13 +9,13 @@ import ( "encoding/json" "errors" "fmt" - "github.com/calypr/loom/internal/graphqlapi/model" "strconv" "sync" "sync/atomic" "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/introspection" + "github.com/calypr/loom/graphqlapi/model" gqlparser "github.com/vektah/gqlparser/v2" "github.com/vektah/gqlparser/v2/ast" ) @@ -59,6 +59,18 @@ type ComplexityRoot struct { Traversals func(childComplexity int) int } + DataframeCompilerPlanDiagnostics struct { + OptimizationPolicy func(childComplexity int) int + PotentialSharingOpportunityGroups func(childComplexity int) int + PotentialSharingOpportunitySets func(childComplexity int) int + RequiredMatchReuseCount func(childComplexity int) int + RichSourceReuse func(childComplexity int) int + ScopedSharingCandidateGroups func(childComplexity int) int + ScopedSharingCandidateSets func(childComplexity int) int + SharedTraversalCount func(childComplexity int) int + TraversalSets func(childComplexity int) int + } + DataframeFieldHint struct { DefaultPivotColumnSelector func(childComplexity int) int DefaultPivotValueSelector func(childComplexity int) int @@ -90,6 +102,34 @@ type ComplexityRoot struct { Where func(childComplexity int) int } + DataframeOptimizationDecision struct { + CandidateSets func(childComplexity int) int + Enabled func(childComplexity int) int + EstimatedBaselineWork func(childComplexity int) int + EstimatedOptimizedWork func(childComplexity int) int + EstimatedSavings func(childComplexity int) int + Reason func(childComplexity int) int + Rule func(childComplexity int) int + } + + DataframeOptimizationPolicy struct { + Decisions func(childComplexity int) int + Enabled func(childComplexity int) int + MinimumSavings func(childComplexity int) int + Name func(childComplexity int) int + } + + DataframeQueryDiagnostics struct { + ArangoQueryMs func(childComplexity int) int + CompilationMs func(childComplexity int) int + InputResolutionMs func(childComplexity int) int + Plan func(childComplexity int) int + RequestPreparationMs func(childComplexity int) int + ResultAssemblyMs func(childComplexity int) int + RowMaterializationMs func(childComplexity int) int + TotalMs func(childComplexity int) int + } + DataframeRelatedResourceHints struct { EdgeCount func(childComplexity int) int Target func(childComplexity int) int @@ -103,6 +143,14 @@ type ComplexityRoot struct { Traversals func(childComplexity int) int } + DataframeRichSourceReuse struct { + AggregateConsumers func(childComplexity int) int + PivotConsumers func(childComplexity int) int + SliceConsumers func(childComplexity int) int + SourceSet func(childComplexity int) int + TotalConsumers func(childComplexity int) int + } + DataframeTraversalHint struct { EdgeCount func(childComplexity int) int FromType func(childComplexity int) int @@ -111,9 +159,10 @@ type ComplexityRoot struct { } FhirDataframeResult struct { - Columns func(childComplexity int) int - RowCount func(childComplexity int) int - Rows func(childComplexity int) int + Columns func(childComplexity int) int + Diagnostics func(childComplexity int) int + RowCount func(childComplexity int) int + Rows func(childComplexity int) int } Mutation struct { @@ -207,6 +256,69 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.DataframeBuilderIntrospection.Traversals(childComplexity), true + case "DataframeCompilerPlanDiagnostics.optimizationPolicy": + if e.complexity.DataframeCompilerPlanDiagnostics.OptimizationPolicy == nil { + break + } + + return e.complexity.DataframeCompilerPlanDiagnostics.OptimizationPolicy(childComplexity), true + + case "DataframeCompilerPlanDiagnostics.potentialSharingOpportunityGroups": + if e.complexity.DataframeCompilerPlanDiagnostics.PotentialSharingOpportunityGroups == nil { + break + } + + return e.complexity.DataframeCompilerPlanDiagnostics.PotentialSharingOpportunityGroups(childComplexity), true + + case "DataframeCompilerPlanDiagnostics.potentialSharingOpportunitySets": + if e.complexity.DataframeCompilerPlanDiagnostics.PotentialSharingOpportunitySets == nil { + break + } + + return e.complexity.DataframeCompilerPlanDiagnostics.PotentialSharingOpportunitySets(childComplexity), true + + case "DataframeCompilerPlanDiagnostics.requiredMatchReuseCount": + if e.complexity.DataframeCompilerPlanDiagnostics.RequiredMatchReuseCount == nil { + break + } + + return e.complexity.DataframeCompilerPlanDiagnostics.RequiredMatchReuseCount(childComplexity), true + + case "DataframeCompilerPlanDiagnostics.richSourceReuse": + if e.complexity.DataframeCompilerPlanDiagnostics.RichSourceReuse == nil { + break + } + + return e.complexity.DataframeCompilerPlanDiagnostics.RichSourceReuse(childComplexity), true + + case "DataframeCompilerPlanDiagnostics.scopedSharingCandidateGroups": + if e.complexity.DataframeCompilerPlanDiagnostics.ScopedSharingCandidateGroups == nil { + break + } + + return e.complexity.DataframeCompilerPlanDiagnostics.ScopedSharingCandidateGroups(childComplexity), true + + case "DataframeCompilerPlanDiagnostics.scopedSharingCandidateSets": + if e.complexity.DataframeCompilerPlanDiagnostics.ScopedSharingCandidateSets == nil { + break + } + + return e.complexity.DataframeCompilerPlanDiagnostics.ScopedSharingCandidateSets(childComplexity), true + + case "DataframeCompilerPlanDiagnostics.sharedTraversalCount": + if e.complexity.DataframeCompilerPlanDiagnostics.SharedTraversalCount == nil { + break + } + + return e.complexity.DataframeCompilerPlanDiagnostics.SharedTraversalCount(childComplexity), true + + case "DataframeCompilerPlanDiagnostics.traversalSets": + if e.complexity.DataframeCompilerPlanDiagnostics.TraversalSets == nil { + break + } + + return e.complexity.DataframeCompilerPlanDiagnostics.TraversalSets(childComplexity), true + case "DataframeFieldHint.defaultPivotColumnSelector": if e.complexity.DataframeFieldHint.DefaultPivotColumnSelector == nil { break @@ -361,6 +473,139 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.DataframeFieldSelector.Where(childComplexity), true + case "DataframeOptimizationDecision.candidateSets": + if e.complexity.DataframeOptimizationDecision.CandidateSets == nil { + break + } + + return e.complexity.DataframeOptimizationDecision.CandidateSets(childComplexity), true + + case "DataframeOptimizationDecision.enabled": + if e.complexity.DataframeOptimizationDecision.Enabled == nil { + break + } + + return e.complexity.DataframeOptimizationDecision.Enabled(childComplexity), true + + case "DataframeOptimizationDecision.estimatedBaselineWork": + if e.complexity.DataframeOptimizationDecision.EstimatedBaselineWork == nil { + break + } + + return e.complexity.DataframeOptimizationDecision.EstimatedBaselineWork(childComplexity), true + + case "DataframeOptimizationDecision.estimatedOptimizedWork": + if e.complexity.DataframeOptimizationDecision.EstimatedOptimizedWork == nil { + break + } + + return e.complexity.DataframeOptimizationDecision.EstimatedOptimizedWork(childComplexity), true + + case "DataframeOptimizationDecision.estimatedSavings": + if e.complexity.DataframeOptimizationDecision.EstimatedSavings == nil { + break + } + + return e.complexity.DataframeOptimizationDecision.EstimatedSavings(childComplexity), true + + case "DataframeOptimizationDecision.reason": + if e.complexity.DataframeOptimizationDecision.Reason == nil { + break + } + + return e.complexity.DataframeOptimizationDecision.Reason(childComplexity), true + + case "DataframeOptimizationDecision.rule": + if e.complexity.DataframeOptimizationDecision.Rule == nil { + break + } + + return e.complexity.DataframeOptimizationDecision.Rule(childComplexity), true + + case "DataframeOptimizationPolicy.decisions": + if e.complexity.DataframeOptimizationPolicy.Decisions == nil { + break + } + + return e.complexity.DataframeOptimizationPolicy.Decisions(childComplexity), true + + case "DataframeOptimizationPolicy.enabled": + if e.complexity.DataframeOptimizationPolicy.Enabled == nil { + break + } + + return e.complexity.DataframeOptimizationPolicy.Enabled(childComplexity), true + + case "DataframeOptimizationPolicy.minimumSavings": + if e.complexity.DataframeOptimizationPolicy.MinimumSavings == nil { + break + } + + return e.complexity.DataframeOptimizationPolicy.MinimumSavings(childComplexity), true + + case "DataframeOptimizationPolicy.name": + if e.complexity.DataframeOptimizationPolicy.Name == nil { + break + } + + return e.complexity.DataframeOptimizationPolicy.Name(childComplexity), true + + case "DataframeQueryDiagnostics.arangoQueryMs": + if e.complexity.DataframeQueryDiagnostics.ArangoQueryMs == nil { + break + } + + return e.complexity.DataframeQueryDiagnostics.ArangoQueryMs(childComplexity), true + + case "DataframeQueryDiagnostics.compilationMs": + if e.complexity.DataframeQueryDiagnostics.CompilationMs == nil { + break + } + + return e.complexity.DataframeQueryDiagnostics.CompilationMs(childComplexity), true + + case "DataframeQueryDiagnostics.inputResolutionMs": + if e.complexity.DataframeQueryDiagnostics.InputResolutionMs == nil { + break + } + + return e.complexity.DataframeQueryDiagnostics.InputResolutionMs(childComplexity), true + + case "DataframeQueryDiagnostics.plan": + if e.complexity.DataframeQueryDiagnostics.Plan == nil { + break + } + + return e.complexity.DataframeQueryDiagnostics.Plan(childComplexity), true + + case "DataframeQueryDiagnostics.requestPreparationMs": + if e.complexity.DataframeQueryDiagnostics.RequestPreparationMs == nil { + break + } + + return e.complexity.DataframeQueryDiagnostics.RequestPreparationMs(childComplexity), true + + case "DataframeQueryDiagnostics.resultAssemblyMs": + if e.complexity.DataframeQueryDiagnostics.ResultAssemblyMs == nil { + break + } + + return e.complexity.DataframeQueryDiagnostics.ResultAssemblyMs(childComplexity), true + + case "DataframeQueryDiagnostics.rowMaterializationMs": + if e.complexity.DataframeQueryDiagnostics.RowMaterializationMs == nil { + break + } + + return e.complexity.DataframeQueryDiagnostics.RowMaterializationMs(childComplexity), true + + case "DataframeQueryDiagnostics.totalMs": + if e.complexity.DataframeQueryDiagnostics.TotalMs == nil { + break + } + + return e.complexity.DataframeQueryDiagnostics.TotalMs(childComplexity), true + case "DataframeRelatedResourceHints.edgeCount": if e.complexity.DataframeRelatedResourceHints.EdgeCount == nil { break @@ -410,6 +655,41 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.DataframeResourceHints.Traversals(childComplexity), true + case "DataframeRichSourceReuse.aggregateConsumers": + if e.complexity.DataframeRichSourceReuse.AggregateConsumers == nil { + break + } + + return e.complexity.DataframeRichSourceReuse.AggregateConsumers(childComplexity), true + + case "DataframeRichSourceReuse.pivotConsumers": + if e.complexity.DataframeRichSourceReuse.PivotConsumers == nil { + break + } + + return e.complexity.DataframeRichSourceReuse.PivotConsumers(childComplexity), true + + case "DataframeRichSourceReuse.sliceConsumers": + if e.complexity.DataframeRichSourceReuse.SliceConsumers == nil { + break + } + + return e.complexity.DataframeRichSourceReuse.SliceConsumers(childComplexity), true + + case "DataframeRichSourceReuse.sourceSet": + if e.complexity.DataframeRichSourceReuse.SourceSet == nil { + break + } + + return e.complexity.DataframeRichSourceReuse.SourceSet(childComplexity), true + + case "DataframeRichSourceReuse.totalConsumers": + if e.complexity.DataframeRichSourceReuse.TotalConsumers == nil { + break + } + + return e.complexity.DataframeRichSourceReuse.TotalConsumers(childComplexity), true + case "DataframeTraversalHint.edgeCount": if e.complexity.DataframeTraversalHint.EdgeCount == nil { break @@ -445,6 +725,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.FhirDataframeResult.Columns(childComplexity), true + case "FhirDataframeResult.diagnostics": + if e.complexity.FhirDataframeResult.Diagnostics == nil { + break + } + + return e.complexity.FhirDataframeResult.Diagnostics(childComplexity), true + case "FhirDataframeResult.rowCount": if e.complexity.FhirDataframeResult.RowCount == nil { break @@ -642,7 +929,7 @@ func (ec *executionContext) field_Mutation_runFhirDataframe_argsInput( ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) if tmp, ok := rawArgs["input"]; ok { - return ec.unmarshalNFhirDataframeInput2arangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirDataframeInput(ctx, tmp) + return ec.unmarshalNFhirDataframeInput2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirDataframeInput(ctx, tmp) } var zeroVal model.FhirDataframeInput @@ -716,7 +1003,7 @@ func (ec *executionContext) field_Query_dataframeBuilderIntrospection_argsInput( ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) if tmp, ok := rawArgs["input"]; ok { - return ec.unmarshalNDataframeBuilderIntrospectionInput2arangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeBuilderIntrospectionInput(ctx, tmp) + return ec.unmarshalNDataframeBuilderIntrospectionInput2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeBuilderIntrospectionInput(ctx, tmp) } var zeroVal model.DataframeBuilderIntrospectionInput @@ -1003,7 +1290,7 @@ func (ec *executionContext) _DataframeBuilderIntrospection_root(ctx context.Cont } res := resTmp.(*model.DataframeResourceHints) fc.Result = res - return ec.marshalNDataframeResourceHints2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeResourceHints(ctx, field.Selections, res) + return ec.marshalNDataframeResourceHints2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeResourceHints(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_DataframeBuilderIntrospection_root(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -1057,7 +1344,7 @@ func (ec *executionContext) _DataframeBuilderIntrospection_relatedResources(ctx } res := resTmp.([]*model.DataframeRelatedResourceHints) fc.Result = res - return ec.marshalNDataframeRelatedResourceHints2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeRelatedResourceHintsᚄ(ctx, field.Selections, res) + return ec.marshalNDataframeRelatedResourceHints2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeRelatedResourceHintsᚄ(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_DataframeBuilderIntrospection_relatedResources(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -1109,7 +1396,7 @@ func (ec *executionContext) _DataframeBuilderIntrospection_traversals(ctx contex } res := resTmp.([]*model.DataframeTraversalHint) fc.Result = res - return ec.marshalNDataframeTraversalHint2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeTraversalHintᚄ(ctx, field.Selections, res) + return ec.marshalNDataframeTraversalHint2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeTraversalHintᚄ(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_DataframeBuilderIntrospection_traversals(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -1163,7 +1450,7 @@ func (ec *executionContext) _DataframeBuilderIntrospection_fields(ctx context.Co } res := resTmp.([]*model.DataframeFieldHint) fc.Result = res - return ec.marshalNDataframeFieldHint2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeFieldHintᚄ(ctx, field.Selections, res) + return ec.marshalNDataframeFieldHint2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeFieldHintᚄ(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_DataframeBuilderIntrospection_fields(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -1241,7 +1528,7 @@ func (ec *executionContext) _DataframeBuilderIntrospection_pivotFields(ctx conte } res := resTmp.([]*model.DataframeFieldHint) fc.Result = res - return ec.marshalNDataframeFieldHint2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeFieldHintᚄ(ctx, field.Selections, res) + return ec.marshalNDataframeFieldHint2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeFieldHintᚄ(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_DataframeBuilderIntrospection_pivotFields(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -1291,8 +1578,8 @@ func (ec *executionContext) fieldContext_DataframeBuilderIntrospection_pivotFiel return fc, nil } -func (ec *executionContext) _DataframeFieldHint_resourceType(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeFieldHint_resourceType(ctx, field) +func (ec *executionContext) _DataframeCompilerPlanDiagnostics_traversalSets(ctx context.Context, field graphql.CollectedField, obj *model.DataframeCompilerPlanDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeCompilerPlanDiagnostics_traversalSets(ctx, field) if err != nil { return graphql.Null } @@ -1305,7 +1592,7 @@ func (ec *executionContext) _DataframeFieldHint_resourceType(ctx context.Context }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.ResourceType, nil + return obj.TraversalSets, nil }) if err != nil { ec.Error(ctx, err) @@ -1317,26 +1604,26 @@ func (ec *executionContext) _DataframeFieldHint_resourceType(ctx context.Context } return graphql.Null } - res := resTmp.(string) + res := resTmp.(int) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeFieldHint_resourceType(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeCompilerPlanDiagnostics_traversalSets(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeFieldHint", + Object: "DataframeCompilerPlanDiagnostics", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + return nil, errors.New("field of type Int does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeFieldHint_fieldRef(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeFieldHint_fieldRef(ctx, field) +func (ec *executionContext) _DataframeCompilerPlanDiagnostics_sharedTraversalCount(ctx context.Context, field graphql.CollectedField, obj *model.DataframeCompilerPlanDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeCompilerPlanDiagnostics_sharedTraversalCount(ctx, field) if err != nil { return graphql.Null } @@ -1349,7 +1636,7 @@ func (ec *executionContext) _DataframeFieldHint_fieldRef(ctx context.Context, fi }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.FieldRef, nil + return obj.SharedTraversalCount, nil }) if err != nil { ec.Error(ctx, err) @@ -1361,26 +1648,26 @@ func (ec *executionContext) _DataframeFieldHint_fieldRef(ctx context.Context, fi } return graphql.Null } - res := resTmp.(string) + res := resTmp.(int) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeFieldHint_fieldRef(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeCompilerPlanDiagnostics_sharedTraversalCount(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeFieldHint", + Object: "DataframeCompilerPlanDiagnostics", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + return nil, errors.New("field of type Int does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeFieldHint_label(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeFieldHint_label(ctx, field) +func (ec *executionContext) _DataframeCompilerPlanDiagnostics_requiredMatchReuseCount(ctx context.Context, field graphql.CollectedField, obj *model.DataframeCompilerPlanDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeCompilerPlanDiagnostics_requiredMatchReuseCount(ctx, field) if err != nil { return graphql.Null } @@ -1393,7 +1680,7 @@ func (ec *executionContext) _DataframeFieldHint_label(ctx context.Context, field }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.Label, nil + return obj.RequiredMatchReuseCount, nil }) if err != nil { ec.Error(ctx, err) @@ -1405,26 +1692,26 @@ func (ec *executionContext) _DataframeFieldHint_label(ctx context.Context, field } return graphql.Null } - res := resTmp.(string) + res := resTmp.(int) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeFieldHint_label(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeCompilerPlanDiagnostics_requiredMatchReuseCount(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeFieldHint", + Object: "DataframeCompilerPlanDiagnostics", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + return nil, errors.New("field of type Int does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeFieldHint_path(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeFieldHint_path(ctx, field) +func (ec *executionContext) _DataframeCompilerPlanDiagnostics_scopedSharingCandidateGroups(ctx context.Context, field graphql.CollectedField, obj *model.DataframeCompilerPlanDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeCompilerPlanDiagnostics_scopedSharingCandidateGroups(ctx, field) if err != nil { return graphql.Null } @@ -1437,7 +1724,7 @@ func (ec *executionContext) _DataframeFieldHint_path(ctx context.Context, field }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.Path, nil + return obj.ScopedSharingCandidateGroups, nil }) if err != nil { ec.Error(ctx, err) @@ -1449,26 +1736,26 @@ func (ec *executionContext) _DataframeFieldHint_path(ctx context.Context, field } return graphql.Null } - res := resTmp.(string) + res := resTmp.(int) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeFieldHint_path(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeCompilerPlanDiagnostics_scopedSharingCandidateGroups(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeFieldHint", + Object: "DataframeCompilerPlanDiagnostics", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + return nil, errors.New("field of type Int does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeFieldHint_selector(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeFieldHint_selector(ctx, field) +func (ec *executionContext) _DataframeCompilerPlanDiagnostics_scopedSharingCandidateSets(ctx context.Context, field graphql.CollectedField, obj *model.DataframeCompilerPlanDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeCompilerPlanDiagnostics_scopedSharingCandidateSets(ctx, field) if err != nil { return graphql.Null } @@ -1481,7 +1768,7 @@ func (ec *executionContext) _DataframeFieldHint_selector(ctx context.Context, fi }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.Selector, nil + return obj.ScopedSharingCandidateSets, nil }) if err != nil { ec.Error(ctx, err) @@ -1493,34 +1780,26 @@ func (ec *executionContext) _DataframeFieldHint_selector(ctx context.Context, fi } return graphql.Null } - res := resTmp.(*model.DataframeFieldSelector) + res := resTmp.(int) fc.Result = res - return ec.marshalNDataframeFieldSelector2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeFieldSelector(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeFieldHint_selector(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeCompilerPlanDiagnostics_scopedSharingCandidateSets(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeFieldHint", + Object: "DataframeCompilerPlanDiagnostics", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "sourcePath": - return ec.fieldContext_DataframeFieldSelector_sourcePath(ctx, field) - case "where": - return ec.fieldContext_DataframeFieldSelector_where(ctx, field) - case "valuePath": - return ec.fieldContext_DataframeFieldSelector_valuePath(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type DataframeFieldSelector", field.Name) + return nil, errors.New("field of type Int does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeFieldHint_kind(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeFieldHint_kind(ctx, field) +func (ec *executionContext) _DataframeCompilerPlanDiagnostics_potentialSharingOpportunityGroups(ctx context.Context, field graphql.CollectedField, obj *model.DataframeCompilerPlanDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeCompilerPlanDiagnostics_potentialSharingOpportunityGroups(ctx, field) if err != nil { return graphql.Null } @@ -1533,7 +1812,7 @@ func (ec *executionContext) _DataframeFieldHint_kind(ctx context.Context, field }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.Kind, nil + return obj.PotentialSharingOpportunityGroups, nil }) if err != nil { ec.Error(ctx, err) @@ -1545,26 +1824,26 @@ func (ec *executionContext) _DataframeFieldHint_kind(ctx context.Context, field } return graphql.Null } - res := resTmp.(string) + res := resTmp.(int) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeFieldHint_kind(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeCompilerPlanDiagnostics_potentialSharingOpportunityGroups(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeFieldHint", + Object: "DataframeCompilerPlanDiagnostics", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + return nil, errors.New("field of type Int does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeFieldHint_docCount(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeFieldHint_docCount(ctx, field) +func (ec *executionContext) _DataframeCompilerPlanDiagnostics_potentialSharingOpportunitySets(ctx context.Context, field graphql.CollectedField, obj *model.DataframeCompilerPlanDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeCompilerPlanDiagnostics_potentialSharingOpportunitySets(ctx, field) if err != nil { return graphql.Null } @@ -1577,7 +1856,7 @@ func (ec *executionContext) _DataframeFieldHint_docCount(ctx context.Context, fi }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.DocCount, nil + return obj.PotentialSharingOpportunitySets, nil }) if err != nil { ec.Error(ctx, err) @@ -1594,9 +1873,9 @@ func (ec *executionContext) _DataframeFieldHint_docCount(ctx context.Context, fi return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeFieldHint_docCount(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeCompilerPlanDiagnostics_potentialSharingOpportunitySets(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeFieldHint", + Object: "DataframeCompilerPlanDiagnostics", Field: field, IsMethod: false, IsResolver: false, @@ -1607,8 +1886,8 @@ func (ec *executionContext) fieldContext_DataframeFieldHint_docCount(_ context.C return fc, nil } -func (ec *executionContext) _DataframeFieldHint_sampleCount(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeFieldHint_sampleCount(ctx, field) +func (ec *executionContext) _DataframeCompilerPlanDiagnostics_optimizationPolicy(ctx context.Context, field graphql.CollectedField, obj *model.DataframeCompilerPlanDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeCompilerPlanDiagnostics_optimizationPolicy(ctx, field) if err != nil { return graphql.Null } @@ -1621,7 +1900,7 @@ func (ec *executionContext) _DataframeFieldHint_sampleCount(ctx context.Context, }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.SampleCount, nil + return obj.OptimizationPolicy, nil }) if err != nil { ec.Error(ctx, err) @@ -1633,26 +1912,36 @@ func (ec *executionContext) _DataframeFieldHint_sampleCount(ctx context.Context, } return graphql.Null } - res := resTmp.(int) + res := resTmp.(*model.DataframeOptimizationPolicy) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNDataframeOptimizationPolicy2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeOptimizationPolicy(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeFieldHint_sampleCount(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeCompilerPlanDiagnostics_optimizationPolicy(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeFieldHint", + Object: "DataframeCompilerPlanDiagnostics", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") + switch field.Name { + case "name": + return ec.fieldContext_DataframeOptimizationPolicy_name(ctx, field) + case "enabled": + return ec.fieldContext_DataframeOptimizationPolicy_enabled(ctx, field) + case "minimumSavings": + return ec.fieldContext_DataframeOptimizationPolicy_minimumSavings(ctx, field) + case "decisions": + return ec.fieldContext_DataframeOptimizationPolicy_decisions(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DataframeOptimizationPolicy", field.Name) }, } return fc, nil } -func (ec *executionContext) _DataframeFieldHint_distinctValues(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeFieldHint_distinctValues(ctx, field) +func (ec *executionContext) _DataframeCompilerPlanDiagnostics_richSourceReuse(ctx context.Context, field graphql.CollectedField, obj *model.DataframeCompilerPlanDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeCompilerPlanDiagnostics_richSourceReuse(ctx, field) if err != nil { return graphql.Null } @@ -1665,7 +1954,7 @@ func (ec *executionContext) _DataframeFieldHint_distinctValues(ctx context.Conte }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.DistinctValues, nil + return obj.RichSourceReuse, nil }) if err != nil { ec.Error(ctx, err) @@ -1677,26 +1966,38 @@ func (ec *executionContext) _DataframeFieldHint_distinctValues(ctx context.Conte } return graphql.Null } - res := resTmp.([]string) + res := resTmp.([]*model.DataframeRichSourceReuse) fc.Result = res - return ec.marshalNString2ᚕstringᚄ(ctx, field.Selections, res) + return ec.marshalNDataframeRichSourceReuse2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeRichSourceReuseᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeFieldHint_distinctValues(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeCompilerPlanDiagnostics_richSourceReuse(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeFieldHint", + Object: "DataframeCompilerPlanDiagnostics", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + switch field.Name { + case "sourceSet": + return ec.fieldContext_DataframeRichSourceReuse_sourceSet(ctx, field) + case "aggregateConsumers": + return ec.fieldContext_DataframeRichSourceReuse_aggregateConsumers(ctx, field) + case "pivotConsumers": + return ec.fieldContext_DataframeRichSourceReuse_pivotConsumers(ctx, field) + case "sliceConsumers": + return ec.fieldContext_DataframeRichSourceReuse_sliceConsumers(ctx, field) + case "totalConsumers": + return ec.fieldContext_DataframeRichSourceReuse_totalConsumers(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DataframeRichSourceReuse", field.Name) }, } return fc, nil } -func (ec *executionContext) _DataframeFieldHint_distinctTruncated(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeFieldHint_distinctTruncated(ctx, field) +func (ec *executionContext) _DataframeFieldHint_resourceType(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeFieldHint_resourceType(ctx, field) if err != nil { return graphql.Null } @@ -1709,7 +2010,7 @@ func (ec *executionContext) _DataframeFieldHint_distinctTruncated(ctx context.Co }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.DistinctTruncated, nil + return obj.ResourceType, nil }) if err != nil { ec.Error(ctx, err) @@ -1721,26 +2022,26 @@ func (ec *executionContext) _DataframeFieldHint_distinctTruncated(ctx context.Co } return graphql.Null } - res := resTmp.(bool) + res := resTmp.(string) fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeFieldHint_distinctTruncated(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeFieldHint_resourceType(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DataframeFieldHint", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Boolean does not have child fields") + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeFieldHint_pivotCandidate(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeFieldHint_pivotCandidate(ctx, field) +func (ec *executionContext) _DataframeFieldHint_fieldRef(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeFieldHint_fieldRef(ctx, field) if err != nil { return graphql.Null } @@ -1753,7 +2054,7 @@ func (ec *executionContext) _DataframeFieldHint_pivotCandidate(ctx context.Conte }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.PivotCandidate, nil + return obj.FieldRef, nil }) if err != nil { ec.Error(ctx, err) @@ -1765,26 +2066,26 @@ func (ec *executionContext) _DataframeFieldHint_pivotCandidate(ctx context.Conte } return graphql.Null } - res := resTmp.(bool) + res := resTmp.(string) fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeFieldHint_pivotCandidate(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeFieldHint_fieldRef(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DataframeFieldHint", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Boolean does not have child fields") + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeFieldHint_pivotKind(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeFieldHint_pivotKind(ctx, field) +func (ec *executionContext) _DataframeFieldHint_label(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeFieldHint_label(ctx, field) if err != nil { return graphql.Null } @@ -1797,21 +2098,24 @@ func (ec *executionContext) _DataframeFieldHint_pivotKind(ctx context.Context, f }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.PivotKind, nil + return obj.Label, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*string) + res := resTmp.(string) fc.Result = res - return ec.marshalOString2ᚖstring(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeFieldHint_pivotKind(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeFieldHint_label(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DataframeFieldHint", Field: field, @@ -1824,8 +2128,8 @@ func (ec *executionContext) fieldContext_DataframeFieldHint_pivotKind(_ context. return fc, nil } -func (ec *executionContext) _DataframeFieldHint_pivotColumns(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeFieldHint_pivotColumns(ctx, field) +func (ec *executionContext) _DataframeFieldHint_path(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeFieldHint_path(ctx, field) if err != nil { return graphql.Null } @@ -1838,7 +2142,7 @@ func (ec *executionContext) _DataframeFieldHint_pivotColumns(ctx context.Context }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.PivotColumns, nil + return obj.Path, nil }) if err != nil { ec.Error(ctx, err) @@ -1850,12 +2154,12 @@ func (ec *executionContext) _DataframeFieldHint_pivotColumns(ctx context.Context } return graphql.Null } - res := resTmp.([]string) + res := resTmp.(string) fc.Result = res - return ec.marshalNString2ᚕstringᚄ(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeFieldHint_pivotColumns(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeFieldHint_path(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DataframeFieldHint", Field: field, @@ -1868,8 +2172,8 @@ func (ec *executionContext) fieldContext_DataframeFieldHint_pivotColumns(_ conte return fc, nil } -func (ec *executionContext) _DataframeFieldHint_pivotFamily(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeFieldHint_pivotFamily(ctx, field) +func (ec *executionContext) _DataframeFieldHint_selector(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeFieldHint_selector(ctx, field) if err != nil { return graphql.Null } @@ -1882,35 +2186,46 @@ func (ec *executionContext) _DataframeFieldHint_pivotFamily(ctx context.Context, }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.PivotFamily, nil + return obj.Selector, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*model.FhirPivotFamily) + res := resTmp.(*model.DataframeFieldSelector) fc.Result = res - return ec.marshalOFhirPivotFamily2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirPivotFamily(ctx, field.Selections, res) + return ec.marshalNDataframeFieldSelector2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeFieldSelector(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeFieldHint_pivotFamily(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeFieldHint_selector(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DataframeFieldHint", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type FhirPivotFamily does not have child fields") + switch field.Name { + case "sourcePath": + return ec.fieldContext_DataframeFieldSelector_sourcePath(ctx, field) + case "where": + return ec.fieldContext_DataframeFieldSelector_where(ctx, field) + case "valuePath": + return ec.fieldContext_DataframeFieldSelector_valuePath(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DataframeFieldSelector", field.Name) }, } return fc, nil } -func (ec *executionContext) _DataframeFieldHint_defaultPivotColumnSelector(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeFieldHint_defaultPivotColumnSelector(ctx, field) +func (ec *executionContext) _DataframeFieldHint_kind(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeFieldHint_kind(ctx, field) if err != nil { return graphql.Null } @@ -1923,43 +2238,38 @@ func (ec *executionContext) _DataframeFieldHint_defaultPivotColumnSelector(ctx c }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.DefaultPivotColumnSelector, nil + return obj.Kind, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*model.DataframeFieldSelector) + res := resTmp.(string) fc.Result = res - return ec.marshalODataframeFieldSelector2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeFieldSelector(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeFieldHint_defaultPivotColumnSelector(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeFieldHint_kind(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DataframeFieldHint", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "sourcePath": - return ec.fieldContext_DataframeFieldSelector_sourcePath(ctx, field) - case "where": - return ec.fieldContext_DataframeFieldSelector_where(ctx, field) - case "valuePath": - return ec.fieldContext_DataframeFieldSelector_valuePath(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type DataframeFieldSelector", field.Name) + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeFieldHint_defaultPivotValueSelector(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeFieldHint_defaultPivotValueSelector(ctx, field) +func (ec *executionContext) _DataframeFieldHint_docCount(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeFieldHint_docCount(ctx, field) if err != nil { return graphql.Null } @@ -1972,43 +2282,1292 @@ func (ec *executionContext) _DataframeFieldHint_defaultPivotValueSelector(ctx co }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.DefaultPivotValueSelector, nil + return obj.DocCount, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*model.DataframeFieldSelector) + res := resTmp.(int) fc.Result = res - return ec.marshalODataframeFieldSelector2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeFieldSelector(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeFieldHint_defaultPivotValueSelector(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeFieldHint_docCount(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DataframeFieldHint", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "sourcePath": - return ec.fieldContext_DataframeFieldSelector_sourcePath(ctx, field) - case "where": - return ec.fieldContext_DataframeFieldSelector_where(ctx, field) - case "valuePath": - return ec.fieldContext_DataframeFieldSelector_valuePath(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type DataframeFieldSelector", field.Name) + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeFieldHint_sampleCount(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeFieldHint_sampleCount(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.SampleCount, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeFieldHint_sampleCount(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeFieldHint", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeFieldHint_distinctValues(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeFieldHint_distinctValues(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.DistinctValues, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]string) + fc.Result = res + return ec.marshalNString2ᚕstringᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeFieldHint_distinctValues(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeFieldHint", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeFieldHint_distinctTruncated(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeFieldHint_distinctTruncated(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.DistinctTruncated, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeFieldHint_distinctTruncated(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeFieldHint", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeFieldHint_pivotCandidate(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeFieldHint_pivotCandidate(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.PivotCandidate, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeFieldHint_pivotCandidate(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeFieldHint", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeFieldHint_pivotKind(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeFieldHint_pivotKind(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.PivotKind, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeFieldHint_pivotKind(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeFieldHint", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeFieldHint_pivotColumns(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeFieldHint_pivotColumns(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.PivotColumns, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]string) + fc.Result = res + return ec.marshalNString2ᚕstringᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeFieldHint_pivotColumns(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeFieldHint", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeFieldHint_pivotFamily(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeFieldHint_pivotFamily(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.PivotFamily, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.FhirPivotFamily) + fc.Result = res + return ec.marshalOFhirPivotFamily2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirPivotFamily(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeFieldHint_pivotFamily(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeFieldHint", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type FhirPivotFamily does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeFieldHint_defaultPivotColumnSelector(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeFieldHint_defaultPivotColumnSelector(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.DefaultPivotColumnSelector, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.DataframeFieldSelector) + fc.Result = res + return ec.marshalODataframeFieldSelector2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeFieldSelector(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeFieldHint_defaultPivotColumnSelector(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeFieldHint", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "sourcePath": + return ec.fieldContext_DataframeFieldSelector_sourcePath(ctx, field) + case "where": + return ec.fieldContext_DataframeFieldSelector_where(ctx, field) + case "valuePath": + return ec.fieldContext_DataframeFieldSelector_valuePath(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DataframeFieldSelector", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeFieldHint_defaultPivotValueSelector(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldHint) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeFieldHint_defaultPivotValueSelector(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.DefaultPivotValueSelector, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.DataframeFieldSelector) + fc.Result = res + return ec.marshalODataframeFieldSelector2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeFieldSelector(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeFieldHint_defaultPivotValueSelector(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeFieldHint", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "sourcePath": + return ec.fieldContext_DataframeFieldSelector_sourcePath(ctx, field) + case "where": + return ec.fieldContext_DataframeFieldSelector_where(ctx, field) + case "valuePath": + return ec.fieldContext_DataframeFieldSelector_valuePath(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DataframeFieldSelector", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeFieldPredicate_path(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldPredicate) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeFieldPredicate_path(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Path, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeFieldPredicate_path(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeFieldPredicate", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeFieldPredicate_op(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldPredicate) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeFieldPredicate_op(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Op, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(model.FhirFieldPredicateOperation) + fc.Result = res + return ec.marshalNFhirFieldPredicateOperation2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirFieldPredicateOperation(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeFieldPredicate_op(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeFieldPredicate", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type FhirFieldPredicateOperation does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeFieldPredicate_value(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldPredicate) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeFieldPredicate_value(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Value, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeFieldPredicate_value(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeFieldPredicate", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeFieldSelector_sourcePath(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldSelector) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeFieldSelector_sourcePath(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.SourcePath, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeFieldSelector_sourcePath(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeFieldSelector", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeFieldSelector_where(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldSelector) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeFieldSelector_where(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Where, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.DataframeFieldPredicate) + fc.Result = res + return ec.marshalODataframeFieldPredicate2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeFieldPredicate(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeFieldSelector_where(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeFieldSelector", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "path": + return ec.fieldContext_DataframeFieldPredicate_path(ctx, field) + case "op": + return ec.fieldContext_DataframeFieldPredicate_op(ctx, field) + case "value": + return ec.fieldContext_DataframeFieldPredicate_value(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DataframeFieldPredicate", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeFieldSelector_valuePath(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldSelector) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeFieldSelector_valuePath(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.ValuePath, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeFieldSelector_valuePath(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeFieldSelector", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeOptimizationDecision_rule(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationDecision) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeOptimizationDecision_rule(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Rule, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeOptimizationDecision_rule(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeOptimizationDecision", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeOptimizationDecision_enabled(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationDecision) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeOptimizationDecision_enabled(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Enabled, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeOptimizationDecision_enabled(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeOptimizationDecision", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeOptimizationDecision_candidateSets(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationDecision) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeOptimizationDecision_candidateSets(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.CandidateSets, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeOptimizationDecision_candidateSets(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeOptimizationDecision", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeOptimizationDecision_estimatedBaselineWork(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationDecision) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeOptimizationDecision_estimatedBaselineWork(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.EstimatedBaselineWork, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeOptimizationDecision_estimatedBaselineWork(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeOptimizationDecision", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeOptimizationDecision_estimatedOptimizedWork(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationDecision) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeOptimizationDecision_estimatedOptimizedWork(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.EstimatedOptimizedWork, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeOptimizationDecision_estimatedOptimizedWork(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeOptimizationDecision", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeOptimizationDecision_estimatedSavings(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationDecision) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeOptimizationDecision_estimatedSavings(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.EstimatedSavings, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeOptimizationDecision_estimatedSavings(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeOptimizationDecision", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeOptimizationDecision_reason(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationDecision) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeOptimizationDecision_reason(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Reason, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeOptimizationDecision_reason(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeOptimizationDecision", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeOptimizationPolicy_name(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationPolicy) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeOptimizationPolicy_name(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeOptimizationPolicy_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeOptimizationPolicy", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeOptimizationPolicy_enabled(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationPolicy) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeOptimizationPolicy_enabled(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Enabled, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeOptimizationPolicy_enabled(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeOptimizationPolicy", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeOptimizationPolicy_minimumSavings(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationPolicy) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeOptimizationPolicy_minimumSavings(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.MinimumSavings, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeOptimizationPolicy_minimumSavings(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeOptimizationPolicy", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeOptimizationPolicy_decisions(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationPolicy) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeOptimizationPolicy_decisions(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Decisions, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.DataframeOptimizationDecision) + fc.Result = res + return ec.marshalNDataframeOptimizationDecision2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeOptimizationDecisionᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeOptimizationPolicy_decisions(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeOptimizationPolicy", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "rule": + return ec.fieldContext_DataframeOptimizationDecision_rule(ctx, field) + case "enabled": + return ec.fieldContext_DataframeOptimizationDecision_enabled(ctx, field) + case "candidateSets": + return ec.fieldContext_DataframeOptimizationDecision_candidateSets(ctx, field) + case "estimatedBaselineWork": + return ec.fieldContext_DataframeOptimizationDecision_estimatedBaselineWork(ctx, field) + case "estimatedOptimizedWork": + return ec.fieldContext_DataframeOptimizationDecision_estimatedOptimizedWork(ctx, field) + case "estimatedSavings": + return ec.fieldContext_DataframeOptimizationDecision_estimatedSavings(ctx, field) + case "reason": + return ec.fieldContext_DataframeOptimizationDecision_reason(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DataframeOptimizationDecision", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeQueryDiagnostics_inputResolutionMs(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeQueryDiagnostics_inputResolutionMs(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.InputResolutionMs, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(float64) + fc.Result = res + return ec.marshalNFloat2float64(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_inputResolutionMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeQueryDiagnostics", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Float does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeQueryDiagnostics_requestPreparationMs(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeQueryDiagnostics_requestPreparationMs(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.RequestPreparationMs, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(float64) + fc.Result = res + return ec.marshalNFloat2float64(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_requestPreparationMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeQueryDiagnostics", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Float does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeFieldPredicate_path(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldPredicate) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeFieldPredicate_path(ctx, field) +func (ec *executionContext) _DataframeQueryDiagnostics_compilationMs(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeQueryDiagnostics_compilationMs(ctx, field) if err != nil { return graphql.Null } @@ -2021,7 +3580,7 @@ func (ec *executionContext) _DataframeFieldPredicate_path(ctx context.Context, f }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.Path, nil + return obj.CompilationMs, nil }) if err != nil { ec.Error(ctx, err) @@ -2033,26 +3592,26 @@ func (ec *executionContext) _DataframeFieldPredicate_path(ctx context.Context, f } return graphql.Null } - res := resTmp.(string) + res := resTmp.(float64) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNFloat2float64(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeFieldPredicate_path(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_compilationMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeFieldPredicate", + Object: "DataframeQueryDiagnostics", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + return nil, errors.New("field of type Float does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeFieldPredicate_op(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldPredicate) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeFieldPredicate_op(ctx, field) +func (ec *executionContext) _DataframeQueryDiagnostics_arangoQueryMs(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeQueryDiagnostics_arangoQueryMs(ctx, field) if err != nil { return graphql.Null } @@ -2065,7 +3624,7 @@ func (ec *executionContext) _DataframeFieldPredicate_op(ctx context.Context, fie }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.Op, nil + return obj.ArangoQueryMs, nil }) if err != nil { ec.Error(ctx, err) @@ -2077,26 +3636,26 @@ func (ec *executionContext) _DataframeFieldPredicate_op(ctx context.Context, fie } return graphql.Null } - res := resTmp.(model.FhirFieldPredicateOperation) + res := resTmp.(float64) fc.Result = res - return ec.marshalNFhirFieldPredicateOperation2arangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirFieldPredicateOperation(ctx, field.Selections, res) + return ec.marshalNFloat2float64(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeFieldPredicate_op(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_arangoQueryMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeFieldPredicate", + Object: "DataframeQueryDiagnostics", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type FhirFieldPredicateOperation does not have child fields") + return nil, errors.New("field of type Float does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeFieldPredicate_value(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldPredicate) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeFieldPredicate_value(ctx, field) +func (ec *executionContext) _DataframeQueryDiagnostics_rowMaterializationMs(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeQueryDiagnostics_rowMaterializationMs(ctx, field) if err != nil { return graphql.Null } @@ -2109,7 +3668,7 @@ func (ec *executionContext) _DataframeFieldPredicate_value(ctx context.Context, }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.Value, nil + return obj.RowMaterializationMs, nil }) if err != nil { ec.Error(ctx, err) @@ -2121,26 +3680,26 @@ func (ec *executionContext) _DataframeFieldPredicate_value(ctx context.Context, } return graphql.Null } - res := resTmp.(string) + res := resTmp.(float64) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNFloat2float64(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeFieldPredicate_value(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_rowMaterializationMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeFieldPredicate", + Object: "DataframeQueryDiagnostics", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + return nil, errors.New("field of type Float does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeFieldSelector_sourcePath(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldSelector) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeFieldSelector_sourcePath(ctx, field) +func (ec *executionContext) _DataframeQueryDiagnostics_resultAssemblyMs(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeQueryDiagnostics_resultAssemblyMs(ctx, field) if err != nil { return graphql.Null } @@ -2153,35 +3712,38 @@ func (ec *executionContext) _DataframeFieldSelector_sourcePath(ctx context.Conte }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.SourcePath, nil + return obj.ResultAssemblyMs, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*string) + res := resTmp.(float64) fc.Result = res - return ec.marshalOString2ᚖstring(ctx, field.Selections, res) + return ec.marshalNFloat2float64(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeFieldSelector_sourcePath(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_resultAssemblyMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeFieldSelector", + Object: "DataframeQueryDiagnostics", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + return nil, errors.New("field of type Float does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeFieldSelector_where(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldSelector) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeFieldSelector_where(ctx, field) +func (ec *executionContext) _DataframeQueryDiagnostics_totalMs(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeQueryDiagnostics_totalMs(ctx, field) if err != nil { return graphql.Null } @@ -2194,43 +3756,38 @@ func (ec *executionContext) _DataframeFieldSelector_where(ctx context.Context, f }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.Where, nil + return obj.TotalMs, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*model.DataframeFieldPredicate) + res := resTmp.(float64) fc.Result = res - return ec.marshalODataframeFieldPredicate2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeFieldPredicate(ctx, field.Selections, res) + return ec.marshalNFloat2float64(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeFieldSelector_where(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_totalMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeFieldSelector", + Object: "DataframeQueryDiagnostics", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "path": - return ec.fieldContext_DataframeFieldPredicate_path(ctx, field) - case "op": - return ec.fieldContext_DataframeFieldPredicate_op(ctx, field) - case "value": - return ec.fieldContext_DataframeFieldPredicate_value(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type DataframeFieldPredicate", field.Name) + return nil, errors.New("field of type Float does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeFieldSelector_valuePath(ctx context.Context, field graphql.CollectedField, obj *model.DataframeFieldSelector) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeFieldSelector_valuePath(ctx, field) +func (ec *executionContext) _DataframeQueryDiagnostics_plan(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeQueryDiagnostics_plan(ctx, field) if err != nil { return graphql.Null } @@ -2243,7 +3800,7 @@ func (ec *executionContext) _DataframeFieldSelector_valuePath(ctx context.Contex }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.ValuePath, nil + return obj.Plan, nil }) if err != nil { ec.Error(ctx, err) @@ -2255,19 +3812,39 @@ func (ec *executionContext) _DataframeFieldSelector_valuePath(ctx context.Contex } return graphql.Null } - res := resTmp.(string) + res := resTmp.(*model.DataframeCompilerPlanDiagnostics) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNDataframeCompilerPlanDiagnostics2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeCompilerPlanDiagnostics(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeFieldSelector_valuePath(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_plan(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeFieldSelector", + Object: "DataframeQueryDiagnostics", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + switch field.Name { + case "traversalSets": + return ec.fieldContext_DataframeCompilerPlanDiagnostics_traversalSets(ctx, field) + case "sharedTraversalCount": + return ec.fieldContext_DataframeCompilerPlanDiagnostics_sharedTraversalCount(ctx, field) + case "requiredMatchReuseCount": + return ec.fieldContext_DataframeCompilerPlanDiagnostics_requiredMatchReuseCount(ctx, field) + case "scopedSharingCandidateGroups": + return ec.fieldContext_DataframeCompilerPlanDiagnostics_scopedSharingCandidateGroups(ctx, field) + case "scopedSharingCandidateSets": + return ec.fieldContext_DataframeCompilerPlanDiagnostics_scopedSharingCandidateSets(ctx, field) + case "potentialSharingOpportunityGroups": + return ec.fieldContext_DataframeCompilerPlanDiagnostics_potentialSharingOpportunityGroups(ctx, field) + case "potentialSharingOpportunitySets": + return ec.fieldContext_DataframeCompilerPlanDiagnostics_potentialSharingOpportunitySets(ctx, field) + case "optimizationPolicy": + return ec.fieldContext_DataframeCompilerPlanDiagnostics_optimizationPolicy(ctx, field) + case "richSourceReuse": + return ec.fieldContext_DataframeCompilerPlanDiagnostics_richSourceReuse(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DataframeCompilerPlanDiagnostics", field.Name) }, } return fc, nil @@ -2389,7 +3966,7 @@ func (ec *executionContext) _DataframeRelatedResourceHints_target(ctx context.Co } res := resTmp.(*model.DataframeResourceHints) fc.Result = res - return ec.marshalNDataframeResourceHints2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeResourceHints(ctx, field.Selections, res) + return ec.marshalNDataframeResourceHints2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeResourceHints(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_DataframeRelatedResourceHints_target(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -2487,7 +4064,7 @@ func (ec *executionContext) _DataframeResourceHints_fields(ctx context.Context, } res := resTmp.([]*model.DataframeFieldHint) fc.Result = res - return ec.marshalNDataframeFieldHint2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeFieldHintᚄ(ctx, field.Selections, res) + return ec.marshalNDataframeFieldHint2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeFieldHintᚄ(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_DataframeResourceHints_fields(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -2565,7 +4142,7 @@ func (ec *executionContext) _DataframeResourceHints_pivotFields(ctx context.Cont } res := resTmp.([]*model.DataframeFieldHint) fc.Result = res - return ec.marshalNDataframeFieldHint2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeFieldHintᚄ(ctx, field.Selections, res) + return ec.marshalNDataframeFieldHint2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeFieldHintᚄ(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_DataframeResourceHints_pivotFields(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -2643,7 +4220,7 @@ func (ec *executionContext) _DataframeResourceHints_traversals(ctx context.Conte } res := resTmp.([]*model.DataframeTraversalHint) fc.Result = res - return ec.marshalNDataframeTraversalHint2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeTraversalHintᚄ(ctx, field.Selections, res) + return ec.marshalNDataframeTraversalHint2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeTraversalHintᚄ(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_DataframeResourceHints_traversals(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -2669,6 +4246,226 @@ func (ec *executionContext) fieldContext_DataframeResourceHints_traversals(_ con return fc, nil } +func (ec *executionContext) _DataframeRichSourceReuse_sourceSet(ctx context.Context, field graphql.CollectedField, obj *model.DataframeRichSourceReuse) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeRichSourceReuse_sourceSet(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.SourceSet, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeRichSourceReuse_sourceSet(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeRichSourceReuse", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeRichSourceReuse_aggregateConsumers(ctx context.Context, field graphql.CollectedField, obj *model.DataframeRichSourceReuse) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeRichSourceReuse_aggregateConsumers(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.AggregateConsumers, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeRichSourceReuse_aggregateConsumers(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeRichSourceReuse", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeRichSourceReuse_pivotConsumers(ctx context.Context, field graphql.CollectedField, obj *model.DataframeRichSourceReuse) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeRichSourceReuse_pivotConsumers(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.PivotConsumers, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeRichSourceReuse_pivotConsumers(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeRichSourceReuse", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeRichSourceReuse_sliceConsumers(ctx context.Context, field graphql.CollectedField, obj *model.DataframeRichSourceReuse) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeRichSourceReuse_sliceConsumers(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.SliceConsumers, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeRichSourceReuse_sliceConsumers(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeRichSourceReuse", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeRichSourceReuse_totalConsumers(ctx context.Context, field graphql.CollectedField, obj *model.DataframeRichSourceReuse) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeRichSourceReuse_totalConsumers(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.TotalConsumers, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeRichSourceReuse_totalConsumers(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeRichSourceReuse", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _DataframeTraversalHint_fromType(ctx context.Context, field graphql.CollectedField, obj *model.DataframeTraversalHint) (ret graphql.Marshaler) { fc, err := ec.fieldContext_DataframeTraversalHint_fromType(ctx, field) if err != nil { @@ -2977,6 +4774,68 @@ func (ec *executionContext) fieldContext_FhirDataframeResult_rowCount(_ context. return fc, nil } +func (ec *executionContext) _FhirDataframeResult_diagnostics(ctx context.Context, field graphql.CollectedField, obj *model.FhirDataframeResult) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_FhirDataframeResult_diagnostics(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Diagnostics, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.DataframeQueryDiagnostics) + fc.Result = res + return ec.marshalNDataframeQueryDiagnostics2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeQueryDiagnostics(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_FhirDataframeResult_diagnostics(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "FhirDataframeResult", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "inputResolutionMs": + return ec.fieldContext_DataframeQueryDiagnostics_inputResolutionMs(ctx, field) + case "requestPreparationMs": + return ec.fieldContext_DataframeQueryDiagnostics_requestPreparationMs(ctx, field) + case "compilationMs": + return ec.fieldContext_DataframeQueryDiagnostics_compilationMs(ctx, field) + case "arangoQueryMs": + return ec.fieldContext_DataframeQueryDiagnostics_arangoQueryMs(ctx, field) + case "rowMaterializationMs": + return ec.fieldContext_DataframeQueryDiagnostics_rowMaterializationMs(ctx, field) + case "resultAssemblyMs": + return ec.fieldContext_DataframeQueryDiagnostics_resultAssemblyMs(ctx, field) + case "totalMs": + return ec.fieldContext_DataframeQueryDiagnostics_totalMs(ctx, field) + case "plan": + return ec.fieldContext_DataframeQueryDiagnostics_plan(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DataframeQueryDiagnostics", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _Mutation_runFhirDataframe(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Mutation_runFhirDataframe(ctx, field) if err != nil { @@ -3005,7 +4864,7 @@ func (ec *executionContext) _Mutation_runFhirDataframe(ctx context.Context, fiel } res := resTmp.(*model.FhirDataframeResult) fc.Result = res - return ec.marshalNFhirDataframeResult2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirDataframeResult(ctx, field.Selections, res) + return ec.marshalNFhirDataframeResult2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirDataframeResult(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_Mutation_runFhirDataframe(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -3022,6 +4881,8 @@ func (ec *executionContext) fieldContext_Mutation_runFhirDataframe(ctx context.C return ec.fieldContext_FhirDataframeResult_rows(ctx, field) case "rowCount": return ec.fieldContext_FhirDataframeResult_rowCount(ctx, field) + case "diagnostics": + return ec.fieldContext_FhirDataframeResult_diagnostics(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type FhirDataframeResult", field.Name) }, @@ -3068,7 +4929,7 @@ func (ec *executionContext) _Query_dataframeBuilderIntrospection(ctx context.Con } res := resTmp.(*model.DataframeBuilderIntrospection) fc.Result = res - return ec.marshalNDataframeBuilderIntrospection2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeBuilderIntrospection(ctx, field.Selections, res) + return ec.marshalNDataframeBuilderIntrospection2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeBuilderIntrospection(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_Query_dataframeBuilderIntrospection(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -5274,7 +7135,7 @@ func (ec *executionContext) unmarshalInputFhirAggregateInput(ctx context.Context it.Name = data case "operation": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("operation")) - data, err := ec.unmarshalNFhirAggregateOperation2arangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirAggregateOperation(ctx, v) + data, err := ec.unmarshalNFhirAggregateOperation2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirAggregateOperation(ctx, v) if err != nil { return it, err } @@ -5316,7 +7177,7 @@ func (ec *executionContext) unmarshalInputFhirAggregateInput(ctx context.Context it.PredicateEquals = data case "valueMode": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("valueMode")) - data, err := ec.unmarshalNFhirValueMode2arangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirValueMode(ctx, v) + data, err := ec.unmarshalNFhirValueMode2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirValueMode(ctx, v) if err != nil { return it, err } @@ -5371,35 +7232,35 @@ func (ec *executionContext) unmarshalInputFhirDataframeInput(ctx context.Context it.RootResourceType = data case "rootFields": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("rootFields")) - data, err := ec.unmarshalOFhirFieldSelectInput2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirFieldSelectInputᚄ(ctx, v) + data, err := ec.unmarshalOFhirFieldSelectInput2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirFieldSelectInputᚄ(ctx, v) if err != nil { return it, err } it.RootFields = data case "rootPivots": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("rootPivots")) - data, err := ec.unmarshalOFhirPivotInput2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirPivotInputᚄ(ctx, v) + data, err := ec.unmarshalOFhirPivotInput2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirPivotInputᚄ(ctx, v) if err != nil { return it, err } it.RootPivots = data case "rootAggregates": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("rootAggregates")) - data, err := ec.unmarshalOFhirAggregateInput2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirAggregateInputᚄ(ctx, v) + data, err := ec.unmarshalOFhirAggregateInput2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirAggregateInputᚄ(ctx, v) if err != nil { return it, err } it.RootAggregates = data case "rootSlices": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("rootSlices")) - data, err := ec.unmarshalOFhirRepresentativeSliceInput2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirRepresentativeSliceInputᚄ(ctx, v) + data, err := ec.unmarshalOFhirRepresentativeSliceInput2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirRepresentativeSliceInputᚄ(ctx, v) if err != nil { return it, err } it.RootSlices = data case "traverse": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("traverse")) - data, err := ec.unmarshalOFhirTraversalStepInput2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirTraversalStepInputᚄ(ctx, v) + data, err := ec.unmarshalOFhirTraversalStepInput2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirTraversalStepInputᚄ(ctx, v) if err != nil { return it, err } @@ -5451,7 +7312,7 @@ func (ec *executionContext) unmarshalInputFhirFieldPredicateInput(ctx context.Co it.Path = data case "op": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("op")) - data, err := ec.unmarshalNFhirFieldPredicateOperation2arangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirFieldPredicateOperation(ctx, v) + data, err := ec.unmarshalNFhirFieldPredicateOperation2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirFieldPredicateOperation(ctx, v) if err != nil { return it, err } @@ -5509,7 +7370,7 @@ func (ec *executionContext) unmarshalInputFhirFieldSelectInput(ctx context.Conte it.FieldRef = data case "selector": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("selector")) - data, err := ec.unmarshalOFhirFieldSelectorInput2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirFieldSelectorInput(ctx, v) + data, err := ec.unmarshalOFhirFieldSelectorInput2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirFieldSelectorInput(ctx, v) if err != nil { return it, err } @@ -5530,14 +7391,14 @@ func (ec *executionContext) unmarshalInputFhirFieldSelectInput(ctx context.Conte it.FallbackFieldRefs = data case "fallbackSelectors": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("fallbackSelectors")) - data, err := ec.unmarshalNFhirFieldSelectorInput2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirFieldSelectorInputᚄ(ctx, v) + data, err := ec.unmarshalNFhirFieldSelectorInput2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirFieldSelectorInputᚄ(ctx, v) if err != nil { return it, err } it.FallbackSelectors = data case "valueMode": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("valueMode")) - data, err := ec.unmarshalNFhirValueMode2arangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirValueMode(ctx, v) + data, err := ec.unmarshalNFhirValueMode2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirValueMode(ctx, v) if err != nil { return it, err } @@ -5571,7 +7432,7 @@ func (ec *executionContext) unmarshalInputFhirFieldSelectorInput(ctx context.Con it.SourcePath = data case "where": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("where")) - data, err := ec.unmarshalOFhirFieldPredicateInput2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirFieldPredicateInput(ctx, v) + data, err := ec.unmarshalOFhirFieldPredicateInput2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirFieldPredicateInput(ctx, v) if err != nil { return it, err } @@ -5623,14 +7484,14 @@ func (ec *executionContext) unmarshalInputFhirPivotInput(ctx context.Context, ob it.FieldRef = data case "columnSelector": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("columnSelector")) - data, err := ec.unmarshalOFhirFieldSelectorInput2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirFieldSelectorInput(ctx, v) + data, err := ec.unmarshalOFhirFieldSelectorInput2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirFieldSelectorInput(ctx, v) if err != nil { return it, err } it.ColumnSelector = data case "valueSelector": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("valueSelector")) - data, err := ec.unmarshalOFhirFieldSelectorInput2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirFieldSelectorInput(ctx, v) + data, err := ec.unmarshalOFhirFieldSelectorInput2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirFieldSelectorInput(ctx, v) if err != nil { return it, err } @@ -5703,7 +7564,7 @@ func (ec *executionContext) unmarshalInputFhirRepresentativeSliceInput(ctx conte it.WhereEquals = data case "fields": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("fields")) - data, err := ec.unmarshalNFhirFieldSelectInput2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirFieldSelectInputᚄ(ctx, v) + data, err := ec.unmarshalNFhirFieldSelectInput2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirFieldSelectInputᚄ(ctx, v) if err != nil { return it, err } @@ -5767,35 +7628,35 @@ func (ec *executionContext) unmarshalInputFhirTraversalStepInput(ctx context.Con it.Alias = data case "fields": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("fields")) - data, err := ec.unmarshalNFhirFieldSelectInput2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirFieldSelectInputᚄ(ctx, v) + data, err := ec.unmarshalNFhirFieldSelectInput2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirFieldSelectInputᚄ(ctx, v) if err != nil { return it, err } it.Fields = data case "pivots": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("pivots")) - data, err := ec.unmarshalOFhirPivotInput2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirPivotInputᚄ(ctx, v) + data, err := ec.unmarshalOFhirPivotInput2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirPivotInputᚄ(ctx, v) if err != nil { return it, err } it.Pivots = data case "aggregates": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("aggregates")) - data, err := ec.unmarshalOFhirAggregateInput2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirAggregateInputᚄ(ctx, v) + data, err := ec.unmarshalOFhirAggregateInput2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirAggregateInputᚄ(ctx, v) if err != nil { return it, err } it.Aggregates = data case "slices": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("slices")) - data, err := ec.unmarshalOFhirRepresentativeSliceInput2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirRepresentativeSliceInputᚄ(ctx, v) + data, err := ec.unmarshalOFhirRepresentativeSliceInput2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirRepresentativeSliceInputᚄ(ctx, v) if err != nil { return it, err } it.Slices = data case "traverse": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("traverse")) - data, err := ec.unmarshalOFhirTraversalStepInput2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirTraversalStepInputᚄ(ctx, v) + data, err := ec.unmarshalOFhirTraversalStepInput2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirTraversalStepInputᚄ(ctx, v) if err != nil { return it, err } @@ -5888,6 +7749,85 @@ func (ec *executionContext) _DataframeBuilderIntrospection(ctx context.Context, return out } +var dataframeCompilerPlanDiagnosticsImplementors = []string{"DataframeCompilerPlanDiagnostics"} + +func (ec *executionContext) _DataframeCompilerPlanDiagnostics(ctx context.Context, sel ast.SelectionSet, obj *model.DataframeCompilerPlanDiagnostics) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, dataframeCompilerPlanDiagnosticsImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("DataframeCompilerPlanDiagnostics") + case "traversalSets": + out.Values[i] = ec._DataframeCompilerPlanDiagnostics_traversalSets(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "sharedTraversalCount": + out.Values[i] = ec._DataframeCompilerPlanDiagnostics_sharedTraversalCount(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "requiredMatchReuseCount": + out.Values[i] = ec._DataframeCompilerPlanDiagnostics_requiredMatchReuseCount(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "scopedSharingCandidateGroups": + out.Values[i] = ec._DataframeCompilerPlanDiagnostics_scopedSharingCandidateGroups(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "scopedSharingCandidateSets": + out.Values[i] = ec._DataframeCompilerPlanDiagnostics_scopedSharingCandidateSets(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "potentialSharingOpportunityGroups": + out.Values[i] = ec._DataframeCompilerPlanDiagnostics_potentialSharingOpportunityGroups(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "potentialSharingOpportunitySets": + out.Values[i] = ec._DataframeCompilerPlanDiagnostics_potentialSharingOpportunitySets(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "optimizationPolicy": + out.Values[i] = ec._DataframeCompilerPlanDiagnostics_optimizationPolicy(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "richSourceReuse": + out.Values[i] = ec._DataframeCompilerPlanDiagnostics_richSourceReuse(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var dataframeFieldHintImplementors = []string{"DataframeFieldHint"} func (ec *executionContext) _DataframeFieldHint(ctx context.Context, sel ast.SelectionSet, obj *model.DataframeFieldHint) graphql.Marshaler { @@ -5929,44 +7869,205 @@ func (ec *executionContext) _DataframeFieldHint(ctx context.Context, sel ast.Sel if out.Values[i] == graphql.Null { out.Invalids++ } - case "docCount": - out.Values[i] = ec._DataframeFieldHint_docCount(ctx, field, obj) + case "docCount": + out.Values[i] = ec._DataframeFieldHint_docCount(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "sampleCount": + out.Values[i] = ec._DataframeFieldHint_sampleCount(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "distinctValues": + out.Values[i] = ec._DataframeFieldHint_distinctValues(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "distinctTruncated": + out.Values[i] = ec._DataframeFieldHint_distinctTruncated(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "pivotCandidate": + out.Values[i] = ec._DataframeFieldHint_pivotCandidate(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "pivotKind": + out.Values[i] = ec._DataframeFieldHint_pivotKind(ctx, field, obj) + case "pivotColumns": + out.Values[i] = ec._DataframeFieldHint_pivotColumns(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "pivotFamily": + out.Values[i] = ec._DataframeFieldHint_pivotFamily(ctx, field, obj) + case "defaultPivotColumnSelector": + out.Values[i] = ec._DataframeFieldHint_defaultPivotColumnSelector(ctx, field, obj) + case "defaultPivotValueSelector": + out.Values[i] = ec._DataframeFieldHint_defaultPivotValueSelector(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var dataframeFieldPredicateImplementors = []string{"DataframeFieldPredicate"} + +func (ec *executionContext) _DataframeFieldPredicate(ctx context.Context, sel ast.SelectionSet, obj *model.DataframeFieldPredicate) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, dataframeFieldPredicateImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("DataframeFieldPredicate") + case "path": + out.Values[i] = ec._DataframeFieldPredicate_path(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "op": + out.Values[i] = ec._DataframeFieldPredicate_op(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "value": + out.Values[i] = ec._DataframeFieldPredicate_value(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var dataframeFieldSelectorImplementors = []string{"DataframeFieldSelector"} + +func (ec *executionContext) _DataframeFieldSelector(ctx context.Context, sel ast.SelectionSet, obj *model.DataframeFieldSelector) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, dataframeFieldSelectorImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("DataframeFieldSelector") + case "sourcePath": + out.Values[i] = ec._DataframeFieldSelector_sourcePath(ctx, field, obj) + case "where": + out.Values[i] = ec._DataframeFieldSelector_where(ctx, field, obj) + case "valuePath": + out.Values[i] = ec._DataframeFieldSelector_valuePath(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var dataframeOptimizationDecisionImplementors = []string{"DataframeOptimizationDecision"} + +func (ec *executionContext) _DataframeOptimizationDecision(ctx context.Context, sel ast.SelectionSet, obj *model.DataframeOptimizationDecision) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, dataframeOptimizationDecisionImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("DataframeOptimizationDecision") + case "rule": + out.Values[i] = ec._DataframeOptimizationDecision_rule(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "enabled": + out.Values[i] = ec._DataframeOptimizationDecision_enabled(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } - case "sampleCount": - out.Values[i] = ec._DataframeFieldHint_sampleCount(ctx, field, obj) + case "candidateSets": + out.Values[i] = ec._DataframeOptimizationDecision_candidateSets(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } - case "distinctValues": - out.Values[i] = ec._DataframeFieldHint_distinctValues(ctx, field, obj) + case "estimatedBaselineWork": + out.Values[i] = ec._DataframeOptimizationDecision_estimatedBaselineWork(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } - case "distinctTruncated": - out.Values[i] = ec._DataframeFieldHint_distinctTruncated(ctx, field, obj) + case "estimatedOptimizedWork": + out.Values[i] = ec._DataframeOptimizationDecision_estimatedOptimizedWork(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } - case "pivotCandidate": - out.Values[i] = ec._DataframeFieldHint_pivotCandidate(ctx, field, obj) + case "estimatedSavings": + out.Values[i] = ec._DataframeOptimizationDecision_estimatedSavings(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } - case "pivotKind": - out.Values[i] = ec._DataframeFieldHint_pivotKind(ctx, field, obj) - case "pivotColumns": - out.Values[i] = ec._DataframeFieldHint_pivotColumns(ctx, field, obj) + case "reason": + out.Values[i] = ec._DataframeOptimizationDecision_reason(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } - case "pivotFamily": - out.Values[i] = ec._DataframeFieldHint_pivotFamily(ctx, field, obj) - case "defaultPivotColumnSelector": - out.Values[i] = ec._DataframeFieldHint_defaultPivotColumnSelector(ctx, field, obj) - case "defaultPivotValueSelector": - out.Values[i] = ec._DataframeFieldHint_defaultPivotValueSelector(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -5990,29 +8091,34 @@ func (ec *executionContext) _DataframeFieldHint(ctx context.Context, sel ast.Sel return out } -var dataframeFieldPredicateImplementors = []string{"DataframeFieldPredicate"} +var dataframeOptimizationPolicyImplementors = []string{"DataframeOptimizationPolicy"} -func (ec *executionContext) _DataframeFieldPredicate(ctx context.Context, sel ast.SelectionSet, obj *model.DataframeFieldPredicate) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, dataframeFieldPredicateImplementors) +func (ec *executionContext) _DataframeOptimizationPolicy(ctx context.Context, sel ast.SelectionSet, obj *model.DataframeOptimizationPolicy) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, dataframeOptimizationPolicyImplementors) out := graphql.NewFieldSet(fields) deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("DataframeFieldPredicate") - case "path": - out.Values[i] = ec._DataframeFieldPredicate_path(ctx, field, obj) + out.Values[i] = graphql.MarshalString("DataframeOptimizationPolicy") + case "name": + out.Values[i] = ec._DataframeOptimizationPolicy_name(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } - case "op": - out.Values[i] = ec._DataframeFieldPredicate_op(ctx, field, obj) + case "enabled": + out.Values[i] = ec._DataframeOptimizationPolicy_enabled(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } - case "value": - out.Values[i] = ec._DataframeFieldPredicate_value(ctx, field, obj) + case "minimumSavings": + out.Values[i] = ec._DataframeOptimizationPolicy_minimumSavings(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "decisions": + out.Values[i] = ec._DataframeOptimizationPolicy_decisions(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } @@ -6039,23 +8145,54 @@ func (ec *executionContext) _DataframeFieldPredicate(ctx context.Context, sel as return out } -var dataframeFieldSelectorImplementors = []string{"DataframeFieldSelector"} +var dataframeQueryDiagnosticsImplementors = []string{"DataframeQueryDiagnostics"} -func (ec *executionContext) _DataframeFieldSelector(ctx context.Context, sel ast.SelectionSet, obj *model.DataframeFieldSelector) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, dataframeFieldSelectorImplementors) +func (ec *executionContext) _DataframeQueryDiagnostics(ctx context.Context, sel ast.SelectionSet, obj *model.DataframeQueryDiagnostics) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, dataframeQueryDiagnosticsImplementors) out := graphql.NewFieldSet(fields) deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("DataframeFieldSelector") - case "sourcePath": - out.Values[i] = ec._DataframeFieldSelector_sourcePath(ctx, field, obj) - case "where": - out.Values[i] = ec._DataframeFieldSelector_where(ctx, field, obj) - case "valuePath": - out.Values[i] = ec._DataframeFieldSelector_valuePath(ctx, field, obj) + out.Values[i] = graphql.MarshalString("DataframeQueryDiagnostics") + case "inputResolutionMs": + out.Values[i] = ec._DataframeQueryDiagnostics_inputResolutionMs(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "requestPreparationMs": + out.Values[i] = ec._DataframeQueryDiagnostics_requestPreparationMs(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "compilationMs": + out.Values[i] = ec._DataframeQueryDiagnostics_compilationMs(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "arangoQueryMs": + out.Values[i] = ec._DataframeQueryDiagnostics_arangoQueryMs(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "rowMaterializationMs": + out.Values[i] = ec._DataframeQueryDiagnostics_rowMaterializationMs(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "resultAssemblyMs": + out.Values[i] = ec._DataframeQueryDiagnostics_resultAssemblyMs(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "totalMs": + out.Values[i] = ec._DataframeQueryDiagnostics_totalMs(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "plan": + out.Values[i] = ec._DataframeQueryDiagnostics_plan(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } @@ -6185,6 +8322,65 @@ func (ec *executionContext) _DataframeResourceHints(ctx context.Context, sel ast return out } +var dataframeRichSourceReuseImplementors = []string{"DataframeRichSourceReuse"} + +func (ec *executionContext) _DataframeRichSourceReuse(ctx context.Context, sel ast.SelectionSet, obj *model.DataframeRichSourceReuse) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, dataframeRichSourceReuseImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("DataframeRichSourceReuse") + case "sourceSet": + out.Values[i] = ec._DataframeRichSourceReuse_sourceSet(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "aggregateConsumers": + out.Values[i] = ec._DataframeRichSourceReuse_aggregateConsumers(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "pivotConsumers": + out.Values[i] = ec._DataframeRichSourceReuse_pivotConsumers(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "sliceConsumers": + out.Values[i] = ec._DataframeRichSourceReuse_sliceConsumers(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "totalConsumers": + out.Values[i] = ec._DataframeRichSourceReuse_totalConsumers(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var dataframeTraversalHintImplementors = []string{"DataframeTraversalHint"} func (ec *executionContext) _DataframeTraversalHint(ctx context.Context, sel ast.SelectionSet, obj *model.DataframeTraversalHint) graphql.Marshaler { @@ -6265,6 +8461,11 @@ func (ec *executionContext) _FhirDataframeResult(ctx context.Context, sel ast.Se if out.Values[i] == graphql.Null { out.Invalids++ } + case "diagnostics": + out.Values[i] = ec._FhirDataframeResult_diagnostics(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -6759,11 +8960,11 @@ func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.Se return res } -func (ec *executionContext) marshalNDataframeBuilderIntrospection2arangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeBuilderIntrospection(ctx context.Context, sel ast.SelectionSet, v model.DataframeBuilderIntrospection) graphql.Marshaler { +func (ec *executionContext) marshalNDataframeBuilderIntrospection2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeBuilderIntrospection(ctx context.Context, sel ast.SelectionSet, v model.DataframeBuilderIntrospection) graphql.Marshaler { return ec._DataframeBuilderIntrospection(ctx, sel, &v) } -func (ec *executionContext) marshalNDataframeBuilderIntrospection2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeBuilderIntrospection(ctx context.Context, sel ast.SelectionSet, v *model.DataframeBuilderIntrospection) graphql.Marshaler { +func (ec *executionContext) marshalNDataframeBuilderIntrospection2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeBuilderIntrospection(ctx context.Context, sel ast.SelectionSet, v *model.DataframeBuilderIntrospection) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") @@ -6773,12 +8974,22 @@ func (ec *executionContext) marshalNDataframeBuilderIntrospection2ᚖarangodbᚑ return ec._DataframeBuilderIntrospection(ctx, sel, v) } -func (ec *executionContext) unmarshalNDataframeBuilderIntrospectionInput2arangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeBuilderIntrospectionInput(ctx context.Context, v any) (model.DataframeBuilderIntrospectionInput, error) { +func (ec *executionContext) unmarshalNDataframeBuilderIntrospectionInput2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeBuilderIntrospectionInput(ctx context.Context, v any) (model.DataframeBuilderIntrospectionInput, error) { res, err := ec.unmarshalInputDataframeBuilderIntrospectionInput(ctx, v) return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) marshalNDataframeFieldHint2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeFieldHintᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.DataframeFieldHint) graphql.Marshaler { +func (ec *executionContext) marshalNDataframeCompilerPlanDiagnostics2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeCompilerPlanDiagnostics(ctx context.Context, sel ast.SelectionSet, v *model.DataframeCompilerPlanDiagnostics) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._DataframeCompilerPlanDiagnostics(ctx, sel, v) +} + +func (ec *executionContext) marshalNDataframeFieldHint2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeFieldHintᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.DataframeFieldHint) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -6802,7 +9013,7 @@ func (ec *executionContext) marshalNDataframeFieldHint2ᚕᚖarangodbᚑprotoᚋ if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNDataframeFieldHint2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeFieldHint(ctx, sel, v[i]) + ret[i] = ec.marshalNDataframeFieldHint2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeFieldHint(ctx, sel, v[i]) } if isLen1 { f(i) @@ -6822,7 +9033,7 @@ func (ec *executionContext) marshalNDataframeFieldHint2ᚕᚖarangodbᚑprotoᚋ return ret } -func (ec *executionContext) marshalNDataframeFieldHint2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeFieldHint(ctx context.Context, sel ast.SelectionSet, v *model.DataframeFieldHint) graphql.Marshaler { +func (ec *executionContext) marshalNDataframeFieldHint2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeFieldHint(ctx context.Context, sel ast.SelectionSet, v *model.DataframeFieldHint) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") @@ -6832,7 +9043,7 @@ func (ec *executionContext) marshalNDataframeFieldHint2ᚖarangodbᚑprotoᚋint return ec._DataframeFieldHint(ctx, sel, v) } -func (ec *executionContext) marshalNDataframeFieldSelector2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeFieldSelector(ctx context.Context, sel ast.SelectionSet, v *model.DataframeFieldSelector) graphql.Marshaler { +func (ec *executionContext) marshalNDataframeFieldSelector2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeFieldSelector(ctx context.Context, sel ast.SelectionSet, v *model.DataframeFieldSelector) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") @@ -6842,7 +9053,81 @@ func (ec *executionContext) marshalNDataframeFieldSelector2ᚖarangodbᚑproto return ec._DataframeFieldSelector(ctx, sel, v) } -func (ec *executionContext) marshalNDataframeRelatedResourceHints2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeRelatedResourceHintsᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.DataframeRelatedResourceHints) graphql.Marshaler { +func (ec *executionContext) marshalNDataframeOptimizationDecision2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeOptimizationDecisionᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.DataframeOptimizationDecision) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNDataframeOptimizationDecision2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeOptimizationDecision(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNDataframeOptimizationDecision2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeOptimizationDecision(ctx context.Context, sel ast.SelectionSet, v *model.DataframeOptimizationDecision) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._DataframeOptimizationDecision(ctx, sel, v) +} + +func (ec *executionContext) marshalNDataframeOptimizationPolicy2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeOptimizationPolicy(ctx context.Context, sel ast.SelectionSet, v *model.DataframeOptimizationPolicy) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._DataframeOptimizationPolicy(ctx, sel, v) +} + +func (ec *executionContext) marshalNDataframeQueryDiagnostics2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeQueryDiagnostics(ctx context.Context, sel ast.SelectionSet, v *model.DataframeQueryDiagnostics) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._DataframeQueryDiagnostics(ctx, sel, v) +} + +func (ec *executionContext) marshalNDataframeRelatedResourceHints2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeRelatedResourceHintsᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.DataframeRelatedResourceHints) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -6866,7 +9151,7 @@ func (ec *executionContext) marshalNDataframeRelatedResourceHints2ᚕᚖarangodb if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNDataframeRelatedResourceHints2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeRelatedResourceHints(ctx, sel, v[i]) + ret[i] = ec.marshalNDataframeRelatedResourceHints2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeRelatedResourceHints(ctx, sel, v[i]) } if isLen1 { f(i) @@ -6886,7 +9171,7 @@ func (ec *executionContext) marshalNDataframeRelatedResourceHints2ᚕᚖarangodb return ret } -func (ec *executionContext) marshalNDataframeRelatedResourceHints2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeRelatedResourceHints(ctx context.Context, sel ast.SelectionSet, v *model.DataframeRelatedResourceHints) graphql.Marshaler { +func (ec *executionContext) marshalNDataframeRelatedResourceHints2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeRelatedResourceHints(ctx context.Context, sel ast.SelectionSet, v *model.DataframeRelatedResourceHints) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") @@ -6896,7 +9181,7 @@ func (ec *executionContext) marshalNDataframeRelatedResourceHints2ᚖarangodbᚑ return ec._DataframeRelatedResourceHints(ctx, sel, v) } -func (ec *executionContext) marshalNDataframeResourceHints2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeResourceHints(ctx context.Context, sel ast.SelectionSet, v *model.DataframeResourceHints) graphql.Marshaler { +func (ec *executionContext) marshalNDataframeResourceHints2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeResourceHints(ctx context.Context, sel ast.SelectionSet, v *model.DataframeResourceHints) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") @@ -6906,7 +9191,61 @@ func (ec *executionContext) marshalNDataframeResourceHints2ᚖarangodbᚑproto return ec._DataframeResourceHints(ctx, sel, v) } -func (ec *executionContext) marshalNDataframeTraversalHint2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeTraversalHintᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.DataframeTraversalHint) graphql.Marshaler { +func (ec *executionContext) marshalNDataframeRichSourceReuse2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeRichSourceReuseᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.DataframeRichSourceReuse) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNDataframeRichSourceReuse2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeRichSourceReuse(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNDataframeRichSourceReuse2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeRichSourceReuse(ctx context.Context, sel ast.SelectionSet, v *model.DataframeRichSourceReuse) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._DataframeRichSourceReuse(ctx, sel, v) +} + +func (ec *executionContext) marshalNDataframeTraversalHint2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeTraversalHintᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.DataframeTraversalHint) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -6930,7 +9269,7 @@ func (ec *executionContext) marshalNDataframeTraversalHint2ᚕᚖarangodbᚑprot if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNDataframeTraversalHint2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeTraversalHint(ctx, sel, v[i]) + ret[i] = ec.marshalNDataframeTraversalHint2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeTraversalHint(ctx, sel, v[i]) } if isLen1 { f(i) @@ -6950,7 +9289,7 @@ func (ec *executionContext) marshalNDataframeTraversalHint2ᚕᚖarangodbᚑprot return ret } -func (ec *executionContext) marshalNDataframeTraversalHint2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeTraversalHint(ctx context.Context, sel ast.SelectionSet, v *model.DataframeTraversalHint) graphql.Marshaler { +func (ec *executionContext) marshalNDataframeTraversalHint2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeTraversalHint(ctx context.Context, sel ast.SelectionSet, v *model.DataframeTraversalHint) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") @@ -6960,31 +9299,31 @@ func (ec *executionContext) marshalNDataframeTraversalHint2ᚖarangodbᚑproto return ec._DataframeTraversalHint(ctx, sel, v) } -func (ec *executionContext) unmarshalNFhirAggregateInput2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirAggregateInput(ctx context.Context, v any) (*model.FhirAggregateInput, error) { +func (ec *executionContext) unmarshalNFhirAggregateInput2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirAggregateInput(ctx context.Context, v any) (*model.FhirAggregateInput, error) { res, err := ec.unmarshalInputFhirAggregateInput(ctx, v) return &res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) unmarshalNFhirAggregateOperation2arangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirAggregateOperation(ctx context.Context, v any) (model.FhirAggregateOperation, error) { +func (ec *executionContext) unmarshalNFhirAggregateOperation2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirAggregateOperation(ctx context.Context, v any) (model.FhirAggregateOperation, error) { var res model.FhirAggregateOperation err := res.UnmarshalGQL(v) return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) marshalNFhirAggregateOperation2arangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirAggregateOperation(ctx context.Context, sel ast.SelectionSet, v model.FhirAggregateOperation) graphql.Marshaler { +func (ec *executionContext) marshalNFhirAggregateOperation2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirAggregateOperation(ctx context.Context, sel ast.SelectionSet, v model.FhirAggregateOperation) graphql.Marshaler { return v } -func (ec *executionContext) unmarshalNFhirDataframeInput2arangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirDataframeInput(ctx context.Context, v any) (model.FhirDataframeInput, error) { +func (ec *executionContext) unmarshalNFhirDataframeInput2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirDataframeInput(ctx context.Context, v any) (model.FhirDataframeInput, error) { res, err := ec.unmarshalInputFhirDataframeInput(ctx, v) return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) marshalNFhirDataframeResult2arangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirDataframeResult(ctx context.Context, sel ast.SelectionSet, v model.FhirDataframeResult) graphql.Marshaler { +func (ec *executionContext) marshalNFhirDataframeResult2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirDataframeResult(ctx context.Context, sel ast.SelectionSet, v model.FhirDataframeResult) graphql.Marshaler { return ec._FhirDataframeResult(ctx, sel, &v) } -func (ec *executionContext) marshalNFhirDataframeResult2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirDataframeResult(ctx context.Context, sel ast.SelectionSet, v *model.FhirDataframeResult) graphql.Marshaler { +func (ec *executionContext) marshalNFhirDataframeResult2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirDataframeResult(ctx context.Context, sel ast.SelectionSet, v *model.FhirDataframeResult) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") @@ -6994,17 +9333,17 @@ func (ec *executionContext) marshalNFhirDataframeResult2ᚖarangodbᚑprotoᚋin return ec._FhirDataframeResult(ctx, sel, v) } -func (ec *executionContext) unmarshalNFhirFieldPredicateOperation2arangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirFieldPredicateOperation(ctx context.Context, v any) (model.FhirFieldPredicateOperation, error) { +func (ec *executionContext) unmarshalNFhirFieldPredicateOperation2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirFieldPredicateOperation(ctx context.Context, v any) (model.FhirFieldPredicateOperation, error) { var res model.FhirFieldPredicateOperation err := res.UnmarshalGQL(v) return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) marshalNFhirFieldPredicateOperation2arangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirFieldPredicateOperation(ctx context.Context, sel ast.SelectionSet, v model.FhirFieldPredicateOperation) graphql.Marshaler { +func (ec *executionContext) marshalNFhirFieldPredicateOperation2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirFieldPredicateOperation(ctx context.Context, sel ast.SelectionSet, v model.FhirFieldPredicateOperation) graphql.Marshaler { return v } -func (ec *executionContext) unmarshalNFhirFieldSelectInput2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirFieldSelectInputᚄ(ctx context.Context, v any) ([]*model.FhirFieldSelectInput, error) { +func (ec *executionContext) unmarshalNFhirFieldSelectInput2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirFieldSelectInputᚄ(ctx context.Context, v any) ([]*model.FhirFieldSelectInput, error) { var vSlice []any if v != nil { vSlice = graphql.CoerceList(v) @@ -7013,7 +9352,7 @@ func (ec *executionContext) unmarshalNFhirFieldSelectInput2ᚕᚖarangodbᚑprot res := make([]*model.FhirFieldSelectInput, len(vSlice)) for i := range vSlice { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNFhirFieldSelectInput2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirFieldSelectInput(ctx, vSlice[i]) + res[i], err = ec.unmarshalNFhirFieldSelectInput2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirFieldSelectInput(ctx, vSlice[i]) if err != nil { return nil, err } @@ -7021,12 +9360,12 @@ func (ec *executionContext) unmarshalNFhirFieldSelectInput2ᚕᚖarangodbᚑprot return res, nil } -func (ec *executionContext) unmarshalNFhirFieldSelectInput2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirFieldSelectInput(ctx context.Context, v any) (*model.FhirFieldSelectInput, error) { +func (ec *executionContext) unmarshalNFhirFieldSelectInput2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirFieldSelectInput(ctx context.Context, v any) (*model.FhirFieldSelectInput, error) { res, err := ec.unmarshalInputFhirFieldSelectInput(ctx, v) return &res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) unmarshalNFhirFieldSelectorInput2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirFieldSelectorInputᚄ(ctx context.Context, v any) ([]*model.FhirFieldSelectorInput, error) { +func (ec *executionContext) unmarshalNFhirFieldSelectorInput2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirFieldSelectorInputᚄ(ctx context.Context, v any) ([]*model.FhirFieldSelectorInput, error) { var vSlice []any if v != nil { vSlice = graphql.CoerceList(v) @@ -7035,7 +9374,7 @@ func (ec *executionContext) unmarshalNFhirFieldSelectorInput2ᚕᚖarangodbᚑpr res := make([]*model.FhirFieldSelectorInput, len(vSlice)) for i := range vSlice { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNFhirFieldSelectorInput2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirFieldSelectorInput(ctx, vSlice[i]) + res[i], err = ec.unmarshalNFhirFieldSelectorInput2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirFieldSelectorInput(ctx, vSlice[i]) if err != nil { return nil, err } @@ -7043,36 +9382,51 @@ func (ec *executionContext) unmarshalNFhirFieldSelectorInput2ᚕᚖarangodbᚑpr return res, nil } -func (ec *executionContext) unmarshalNFhirFieldSelectorInput2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirFieldSelectorInput(ctx context.Context, v any) (*model.FhirFieldSelectorInput, error) { +func (ec *executionContext) unmarshalNFhirFieldSelectorInput2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirFieldSelectorInput(ctx context.Context, v any) (*model.FhirFieldSelectorInput, error) { res, err := ec.unmarshalInputFhirFieldSelectorInput(ctx, v) return &res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) unmarshalNFhirPivotInput2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirPivotInput(ctx context.Context, v any) (*model.FhirPivotInput, error) { +func (ec *executionContext) unmarshalNFhirPivotInput2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirPivotInput(ctx context.Context, v any) (*model.FhirPivotInput, error) { res, err := ec.unmarshalInputFhirPivotInput(ctx, v) return &res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) unmarshalNFhirRepresentativeSliceInput2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirRepresentativeSliceInput(ctx context.Context, v any) (*model.FhirRepresentativeSliceInput, error) { +func (ec *executionContext) unmarshalNFhirRepresentativeSliceInput2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirRepresentativeSliceInput(ctx context.Context, v any) (*model.FhirRepresentativeSliceInput, error) { res, err := ec.unmarshalInputFhirRepresentativeSliceInput(ctx, v) return &res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) unmarshalNFhirTraversalStepInput2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirTraversalStepInput(ctx context.Context, v any) (*model.FhirTraversalStepInput, error) { +func (ec *executionContext) unmarshalNFhirTraversalStepInput2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirTraversalStepInput(ctx context.Context, v any) (*model.FhirTraversalStepInput, error) { res, err := ec.unmarshalInputFhirTraversalStepInput(ctx, v) return &res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) unmarshalNFhirValueMode2arangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirValueMode(ctx context.Context, v any) (model.FhirValueMode, error) { +func (ec *executionContext) unmarshalNFhirValueMode2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirValueMode(ctx context.Context, v any) (model.FhirValueMode, error) { var res model.FhirValueMode err := res.UnmarshalGQL(v) return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) marshalNFhirValueMode2arangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirValueMode(ctx context.Context, sel ast.SelectionSet, v model.FhirValueMode) graphql.Marshaler { +func (ec *executionContext) marshalNFhirValueMode2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirValueMode(ctx context.Context, sel ast.SelectionSet, v model.FhirValueMode) graphql.Marshaler { return v } +func (ec *executionContext) unmarshalNFloat2float64(ctx context.Context, v any) (float64, error) { + res, err := graphql.UnmarshalFloatContext(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNFloat2float64(ctx context.Context, sel ast.SelectionSet, v float64) graphql.Marshaler { + res := graphql.MarshalFloatContext(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return graphql.WrapContextMarshaler(ctx, res) +} + func (ec *executionContext) unmarshalNInt2int(ctx context.Context, v any) (int, error) { res, err := graphql.UnmarshalInt(v) return res, graphql.ErrorOnPath(ctx, err) @@ -7429,21 +9783,21 @@ func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast return res } -func (ec *executionContext) marshalODataframeFieldPredicate2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeFieldPredicate(ctx context.Context, sel ast.SelectionSet, v *model.DataframeFieldPredicate) graphql.Marshaler { +func (ec *executionContext) marshalODataframeFieldPredicate2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeFieldPredicate(ctx context.Context, sel ast.SelectionSet, v *model.DataframeFieldPredicate) graphql.Marshaler { if v == nil { return graphql.Null } return ec._DataframeFieldPredicate(ctx, sel, v) } -func (ec *executionContext) marshalODataframeFieldSelector2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐDataframeFieldSelector(ctx context.Context, sel ast.SelectionSet, v *model.DataframeFieldSelector) graphql.Marshaler { +func (ec *executionContext) marshalODataframeFieldSelector2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeFieldSelector(ctx context.Context, sel ast.SelectionSet, v *model.DataframeFieldSelector) graphql.Marshaler { if v == nil { return graphql.Null } return ec._DataframeFieldSelector(ctx, sel, v) } -func (ec *executionContext) unmarshalOFhirAggregateInput2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirAggregateInputᚄ(ctx context.Context, v any) ([]*model.FhirAggregateInput, error) { +func (ec *executionContext) unmarshalOFhirAggregateInput2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirAggregateInputᚄ(ctx context.Context, v any) ([]*model.FhirAggregateInput, error) { if v == nil { return nil, nil } @@ -7455,7 +9809,7 @@ func (ec *executionContext) unmarshalOFhirAggregateInput2ᚕᚖarangodbᚑproto res := make([]*model.FhirAggregateInput, len(vSlice)) for i := range vSlice { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNFhirAggregateInput2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirAggregateInput(ctx, vSlice[i]) + res[i], err = ec.unmarshalNFhirAggregateInput2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirAggregateInput(ctx, vSlice[i]) if err != nil { return nil, err } @@ -7463,7 +9817,7 @@ func (ec *executionContext) unmarshalOFhirAggregateInput2ᚕᚖarangodbᚑproto return res, nil } -func (ec *executionContext) unmarshalOFhirFieldPredicateInput2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirFieldPredicateInput(ctx context.Context, v any) (*model.FhirFieldPredicateInput, error) { +func (ec *executionContext) unmarshalOFhirFieldPredicateInput2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirFieldPredicateInput(ctx context.Context, v any) (*model.FhirFieldPredicateInput, error) { if v == nil { return nil, nil } @@ -7471,7 +9825,7 @@ func (ec *executionContext) unmarshalOFhirFieldPredicateInput2ᚖarangodbᚑprot return &res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) unmarshalOFhirFieldSelectInput2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirFieldSelectInputᚄ(ctx context.Context, v any) ([]*model.FhirFieldSelectInput, error) { +func (ec *executionContext) unmarshalOFhirFieldSelectInput2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirFieldSelectInputᚄ(ctx context.Context, v any) ([]*model.FhirFieldSelectInput, error) { if v == nil { return nil, nil } @@ -7483,7 +9837,7 @@ func (ec *executionContext) unmarshalOFhirFieldSelectInput2ᚕᚖarangodbᚑprot res := make([]*model.FhirFieldSelectInput, len(vSlice)) for i := range vSlice { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNFhirFieldSelectInput2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirFieldSelectInput(ctx, vSlice[i]) + res[i], err = ec.unmarshalNFhirFieldSelectInput2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirFieldSelectInput(ctx, vSlice[i]) if err != nil { return nil, err } @@ -7491,7 +9845,7 @@ func (ec *executionContext) unmarshalOFhirFieldSelectInput2ᚕᚖarangodbᚑprot return res, nil } -func (ec *executionContext) unmarshalOFhirFieldSelectorInput2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirFieldSelectorInput(ctx context.Context, v any) (*model.FhirFieldSelectorInput, error) { +func (ec *executionContext) unmarshalOFhirFieldSelectorInput2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirFieldSelectorInput(ctx context.Context, v any) (*model.FhirFieldSelectorInput, error) { if v == nil { return nil, nil } @@ -7499,7 +9853,7 @@ func (ec *executionContext) unmarshalOFhirFieldSelectorInput2ᚖarangodbᚑproto return &res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) unmarshalOFhirPivotFamily2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirPivotFamily(ctx context.Context, v any) (*model.FhirPivotFamily, error) { +func (ec *executionContext) unmarshalOFhirPivotFamily2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirPivotFamily(ctx context.Context, v any) (*model.FhirPivotFamily, error) { if v == nil { return nil, nil } @@ -7508,14 +9862,14 @@ func (ec *executionContext) unmarshalOFhirPivotFamily2ᚖarangodbᚑprotoᚋinte return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) marshalOFhirPivotFamily2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirPivotFamily(ctx context.Context, sel ast.SelectionSet, v *model.FhirPivotFamily) graphql.Marshaler { +func (ec *executionContext) marshalOFhirPivotFamily2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirPivotFamily(ctx context.Context, sel ast.SelectionSet, v *model.FhirPivotFamily) graphql.Marshaler { if v == nil { return graphql.Null } return v } -func (ec *executionContext) unmarshalOFhirPivotInput2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirPivotInputᚄ(ctx context.Context, v any) ([]*model.FhirPivotInput, error) { +func (ec *executionContext) unmarshalOFhirPivotInput2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirPivotInputᚄ(ctx context.Context, v any) ([]*model.FhirPivotInput, error) { if v == nil { return nil, nil } @@ -7527,7 +9881,7 @@ func (ec *executionContext) unmarshalOFhirPivotInput2ᚕᚖarangodbᚑprotoᚋin res := make([]*model.FhirPivotInput, len(vSlice)) for i := range vSlice { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNFhirPivotInput2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirPivotInput(ctx, vSlice[i]) + res[i], err = ec.unmarshalNFhirPivotInput2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirPivotInput(ctx, vSlice[i]) if err != nil { return nil, err } @@ -7535,7 +9889,7 @@ func (ec *executionContext) unmarshalOFhirPivotInput2ᚕᚖarangodbᚑprotoᚋin return res, nil } -func (ec *executionContext) unmarshalOFhirRepresentativeSliceInput2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirRepresentativeSliceInputᚄ(ctx context.Context, v any) ([]*model.FhirRepresentativeSliceInput, error) { +func (ec *executionContext) unmarshalOFhirRepresentativeSliceInput2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirRepresentativeSliceInputᚄ(ctx context.Context, v any) ([]*model.FhirRepresentativeSliceInput, error) { if v == nil { return nil, nil } @@ -7547,7 +9901,7 @@ func (ec *executionContext) unmarshalOFhirRepresentativeSliceInput2ᚕᚖarangod res := make([]*model.FhirRepresentativeSliceInput, len(vSlice)) for i := range vSlice { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNFhirRepresentativeSliceInput2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirRepresentativeSliceInput(ctx, vSlice[i]) + res[i], err = ec.unmarshalNFhirRepresentativeSliceInput2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirRepresentativeSliceInput(ctx, vSlice[i]) if err != nil { return nil, err } @@ -7555,7 +9909,7 @@ func (ec *executionContext) unmarshalOFhirRepresentativeSliceInput2ᚕᚖarangod return res, nil } -func (ec *executionContext) unmarshalOFhirTraversalStepInput2ᚕᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirTraversalStepInputᚄ(ctx context.Context, v any) ([]*model.FhirTraversalStepInput, error) { +func (ec *executionContext) unmarshalOFhirTraversalStepInput2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirTraversalStepInputᚄ(ctx context.Context, v any) ([]*model.FhirTraversalStepInput, error) { if v == nil { return nil, nil } @@ -7567,7 +9921,7 @@ func (ec *executionContext) unmarshalOFhirTraversalStepInput2ᚕᚖarangodbᚑpr res := make([]*model.FhirTraversalStepInput, len(vSlice)) for i := range vSlice { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNFhirTraversalStepInput2ᚖarangodbᚑprotoᚋinternalᚋgraphqlapiᚋmodelᚐFhirTraversalStepInput(ctx, vSlice[i]) + res[i], err = ec.unmarshalNFhirTraversalStepInput2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirTraversalStepInput(ctx, vSlice[i]) if err != nil { return nil, err } diff --git a/internal/graphqlapi/handler.go b/graphqlapi/handler.go similarity index 100% rename from internal/graphqlapi/handler.go rename to graphqlapi/handler.go diff --git a/internal/graphqlapi/http_integration_test.go b/graphqlapi/http_integration_test.go similarity index 90% rename from internal/graphqlapi/http_integration_test.go rename to graphqlapi/http_integration_test.go index 84fd815..f88e709 100644 --- a/internal/graphqlapi/http_integration_test.go +++ b/graphqlapi/http_integration_test.go @@ -8,11 +8,11 @@ import ( "strings" "testing" - "github.com/calypr/loom/internal/api" + "github.com/calypr/loom/graphqlapi" "github.com/calypr/loom/internal/authscope" "github.com/calypr/loom/internal/catalog" "github.com/calypr/loom/internal/dataframe" - "github.com/calypr/loom/internal/graphqlapi" + api "github.com/calypr/loom/internal/httpapi" "github.com/calypr/loom/internal/ingest" arangostore "github.com/calypr/loom/internal/store/arango" ) @@ -214,8 +214,8 @@ func TestGraphQLRunDataframeMutation(t *testing.T) { return []catalog.PopulatedReference{}, nil }, ExecuteRows: func(ctx context.Context, opts dataframe.ExecuteQueryOptions, query string, bindVars map[string]any, visit func(map[string]any) error) error { - if !strings.Contains(query, "LET generic_root_subject_Patient_neighbors_set") || !strings.Contains(query, "LET generic_condition_set") { - t.Fatalf("expected generic lowered query, got:\n%s", query) + if !strings.Contains(query, "LET child_set_") || !strings.Contains(query, "LENGTH(child_set_") { + t.Fatalf("expected physical child-set query, got:\n%s", query) } return visit(map[string]any{"_key": "p1", "gender": "female", "condition__condition_count": 1}) }, @@ -269,7 +269,7 @@ func TestGraphQLRunDataframeMutation(t *testing.T) { t.Fatal(err) } - queryBody := `{"query":"mutation($input: FhirDataframeInput!, $limit: Int) { runFhirDataframe(input: $input, limit: $limit) { columns rows rowCount } }","variables":{"limit":25,"input":{"project":"P1","rootResourceType":"Patient","rootFields":[{"name":"gender","selector":{"valuePath":"gender"},"valueMode":"AUTO"}],"traverse":[{"edgeLabel":"subject_Patient","toResourceType":"Condition","alias":"condition","aggregates":[{"name":"condition_count","operation":"COUNT"}]},{"edgeLabel":"subject_Patient","toResourceType":"Specimen","alias":"specimen","aggregates":[{"name":"specimen_count","operation":"COUNT"}]}]}}}` + queryBody := `{"query":"mutation($input: FhirDataframeInput!, $limit: Int) { runFhirDataframe(input: $input, limit: $limit) { columns rows rowCount diagnostics { inputResolutionMs requestPreparationMs compilationMs arangoQueryMs rowMaterializationMs resultAssemblyMs totalMs plan { traversalSets sharedTraversalCount scopedSharingCandidateGroups scopedSharingCandidateSets richSourceReuse { sourceSet aggregateConsumers pivotConsumers sliceConsumers totalConsumers } } } } }","variables":{"limit":25,"input":{"project":"P1","rootResourceType":"Patient","rootFields":[{"name":"gender","selector":{"valuePath":"gender"},"valueMode":"AUTO"}],"traverse":[{"edgeLabel":"subject_Patient","toResourceType":"Condition","alias":"condition","aggregates":[{"name":"condition_count","operation":"COUNT"}]},{"edgeLabel":"subject_Patient","toResourceType":"Specimen","alias":"specimen","aggregates":[{"name":"specimen_count","operation":"COUNT"}]}]}}}` req := httptest.NewRequest(http.MethodPost, "/graphql", strings.NewReader(queryBody)) req.Header.Set("Content-Type", "application/json") @@ -285,9 +285,13 @@ func TestGraphQLRunDataframeMutation(t *testing.T) { var payload struct { Data struct { Run struct { - Columns []string `json:"columns"` - Rows []map[string]any `json:"rows"` - RowCount int `json:"rowCount"` + Columns []string `json:"columns"` + Rows []map[string]any `json:"rows"` + RowCount int `json:"rowCount"` + Diagnostics struct { + CompilationMs float64 `json:"compilationMs"` + TotalMs float64 `json:"totalMs"` + } `json:"diagnostics"` } `json:"runFhirDataframe"` } `json:"data"` Errors []map[string]any `json:"errors"` @@ -301,6 +305,9 @@ func TestGraphQLRunDataframeMutation(t *testing.T) { if payload.Data.Run.RowCount != 1 { t.Fatalf("unexpected dataframe payload: %#v", payload.Data.Run) } + if payload.Data.Run.Diagnostics.TotalMs <= 0 || payload.Data.Run.Diagnostics.CompilationMs <= 0 { + t.Fatalf("missing dataframe diagnostics: %#v", payload.Data.Run.Diagnostics) + } } func TestGraphQLRunDataframeTraversalBuilder(t *testing.T) { @@ -336,8 +343,8 @@ func TestGraphQLRunDataframeTraversalBuilder(t *testing.T) { return []catalog.PopulatedReference{}, nil }, ExecuteRows: func(ctx context.Context, opts dataframe.ExecuteQueryOptions, query string, bindVars map[string]any, visit func(map[string]any) error) error { - if !strings.Contains(query, "LET generic_root_subject_Patient_neighbors_set") || !strings.Contains(query, "LET generic_specimen_set") { - t.Fatalf("expected generic lowered query, got:\n%s", query) + if !strings.Contains(query, "LET child_set_") || !strings.Contains(query, "LENGTH(child_set_") { + t.Fatalf("expected physical child-set query, got:\n%s", query) } return visit(map[string]any{ "_key": "p1", diff --git a/internal/graphqlapi/model/models.go b/graphqlapi/model/models.go similarity index 79% rename from internal/graphqlapi/model/models.go rename to graphqlapi/model/models.go index 4a9c5e4..7e1950a 100644 --- a/internal/graphqlapi/model/models.go +++ b/graphqlapi/model/models.go @@ -27,6 +27,18 @@ type DataframeBuilderIntrospectionInput struct { IncludePivotOnlyFields *bool `json:"includePivotOnlyFields,omitempty"` } +type DataframeCompilerPlanDiagnostics struct { + TraversalSets int `json:"traversalSets"` + SharedTraversalCount int `json:"sharedTraversalCount"` + RequiredMatchReuseCount int `json:"requiredMatchReuseCount"` + ScopedSharingCandidateGroups int `json:"scopedSharingCandidateGroups"` + ScopedSharingCandidateSets int `json:"scopedSharingCandidateSets"` + PotentialSharingOpportunityGroups int `json:"potentialSharingOpportunityGroups"` + PotentialSharingOpportunitySets int `json:"potentialSharingOpportunitySets"` + OptimizationPolicy *DataframeOptimizationPolicy `json:"optimizationPolicy"` + RichSourceReuse []*DataframeRichSourceReuse `json:"richSourceReuse"` +} + type DataframeFieldHint struct { ResourceType string `json:"resourceType"` FieldRef string `json:"fieldRef"` @@ -58,6 +70,34 @@ type DataframeFieldSelector struct { ValuePath string `json:"valuePath"` } +type DataframeOptimizationDecision struct { + Rule string `json:"rule"` + Enabled bool `json:"enabled"` + CandidateSets int `json:"candidateSets"` + EstimatedBaselineWork int `json:"estimatedBaselineWork"` + EstimatedOptimizedWork int `json:"estimatedOptimizedWork"` + EstimatedSavings int `json:"estimatedSavings"` + Reason string `json:"reason"` +} + +type DataframeOptimizationPolicy struct { + Name string `json:"name"` + Enabled bool `json:"enabled"` + MinimumSavings int `json:"minimumSavings"` + Decisions []*DataframeOptimizationDecision `json:"decisions"` +} + +type DataframeQueryDiagnostics struct { + InputResolutionMs float64 `json:"inputResolutionMs"` + RequestPreparationMs float64 `json:"requestPreparationMs"` + CompilationMs float64 `json:"compilationMs"` + ArangoQueryMs float64 `json:"arangoQueryMs"` + RowMaterializationMs float64 `json:"rowMaterializationMs"` + ResultAssemblyMs float64 `json:"resultAssemblyMs"` + TotalMs float64 `json:"totalMs"` + Plan *DataframeCompilerPlanDiagnostics `json:"plan"` +} + type DataframeRelatedResourceHints struct { ViaLabel string `json:"viaLabel"` EdgeCount int `json:"edgeCount"` @@ -71,6 +111,14 @@ type DataframeResourceHints struct { Traversals []*DataframeTraversalHint `json:"traversals"` } +type DataframeRichSourceReuse struct { + SourceSet string `json:"sourceSet"` + AggregateConsumers int `json:"aggregateConsumers"` + PivotConsumers int `json:"pivotConsumers"` + SliceConsumers int `json:"sliceConsumers"` + TotalConsumers int `json:"totalConsumers"` +} + type DataframeTraversalHint struct { FromType string `json:"fromType"` Label string `json:"label"` @@ -104,9 +152,10 @@ type FhirDataframeInput struct { } type FhirDataframeResult struct { - Columns []string `json:"columns"` - Rows json.RawMessage `json:"rows"` - RowCount int `json:"rowCount"` + Columns []string `json:"columns"` + Rows json.RawMessage `json:"rows"` + RowCount int `json:"rowCount"` + Diagnostics *DataframeQueryDiagnostics `json:"diagnostics"` } type FhirFieldPredicateInput struct { diff --git a/internal/graphqlapi/output_mapping.go b/graphqlapi/output_mapping.go similarity index 90% rename from internal/graphqlapi/output_mapping.go rename to graphqlapi/output_mapping.go index 356eeb1..e4391e2 100644 --- a/internal/graphqlapi/output_mapping.go +++ b/graphqlapi/output_mapping.go @@ -4,9 +4,9 @@ import ( "encoding/json" "strings" + dataframeapi "github.com/calypr/loom/graphqlapi/dataframe" + "github.com/calypr/loom/graphqlapi/model" "github.com/calypr/loom/internal/catalog" - "github.com/calypr/loom/internal/dataframebuilder" - "github.com/calypr/loom/internal/graphqlapi/model" ) func traversalHints(in []catalog.PopulatedReference) []*model.DataframeTraversalHint { @@ -25,7 +25,7 @@ func traversalHints(in []catalog.PopulatedReference) []*model.DataframeTraversal return out } -func fieldHints(in []dataframebuilder.FieldHint) []*model.DataframeFieldHint { +func fieldHints(in []dataframeapi.FieldHint) []*model.DataframeFieldHint { if len(in) == 0 { return []*model.DataframeFieldHint{} } @@ -78,7 +78,7 @@ func fieldHints(in []dataframebuilder.FieldHint) []*model.DataframeFieldHint { return out } -func resourceHints(in dataframebuilder.ResourceHints) *model.DataframeResourceHints { +func resourceHints(in dataframeapi.ResourceHints) *model.DataframeResourceHints { return &model.DataframeResourceHints{ ResourceType: in.ResourceType, Fields: fieldHints(in.Fields), @@ -87,7 +87,7 @@ func resourceHints(in dataframebuilder.ResourceHints) *model.DataframeResourceHi } } -func relatedResourceHints(in []dataframebuilder.RelatedResourceHints) []*model.DataframeRelatedResourceHints { +func relatedResourceHints(in []dataframeapi.RelatedResourceHints) []*model.DataframeRelatedResourceHints { if len(in) == 0 { return []*model.DataframeRelatedResourceHints{} } @@ -106,7 +106,7 @@ func selectorModelFromExpression(expression string) *model.DataframeFieldSelecto if strings.TrimSpace(expression) == "" { return nil } - parts := dataframebuilder.DecomposeSelector(expression) + parts := dataframeapi.DecomposeSelector(expression) var predicate *model.DataframeFieldPredicate if parts.Where != nil { diff --git a/graphqlapi/resolver.go b/graphqlapi/resolver.go new file mode 100644 index 0000000..8e20d94 --- /dev/null +++ b/graphqlapi/resolver.go @@ -0,0 +1,13 @@ +package graphqlapi + +import dataframeapi "github.com/calypr/loom/graphqlapi/dataframe" + +type Resolver struct { + service *dataframeapi.Service +} + +type ResolverConfig = dataframeapi.Config + +func NewResolver(cfg ResolverConfig) *Resolver { + return &Resolver{service: dataframeapi.NewService(cfg)} +} diff --git a/internal/graphqlapi/scalars.go b/graphqlapi/scalars.go similarity index 100% rename from internal/graphqlapi/scalars.go rename to graphqlapi/scalars.go diff --git a/internal/graphqlapi/schema.graphqls b/graphqlapi/schema.graphqls similarity index 71% rename from internal/graphqlapi/schema.graphqls rename to graphqlapi/schema.graphqls index 3cbc574..5d872da 100644 --- a/internal/graphqlapi/schema.graphqls +++ b/graphqlapi/schema.graphqls @@ -184,4 +184,58 @@ type FhirDataframeResult { columns: [String!]! rows: JSON! rowCount: Int! + diagnostics: DataframeQueryDiagnostics! +} + +# Server-side timings for one dataframe request. `arangoQueryMs` excludes +# Loom's per-row flattening/delivery time; together those two fields identify +# whether the database plan or result materialization is dominant. +type DataframeQueryDiagnostics { + inputResolutionMs: Float! + requestPreparationMs: Float! + compilationMs: Float! + arangoQueryMs: Float! + rowMaterializationMs: Float! + resultAssemblyMs: Float! + totalMs: Float! + plan: DataframeCompilerPlanDiagnostics! +} + +# Compiler facts for deciding which AQL rewrite to implement next. These are +# not Arango estimates; pair them with a live PROFILE for operator-level cost. +type DataframeCompilerPlanDiagnostics { + traversalSets: Int! + sharedTraversalCount: Int! + requiredMatchReuseCount: Int! + scopedSharingCandidateGroups: Int! + scopedSharingCandidateSets: Int! + potentialSharingOpportunityGroups: Int! + potentialSharingOpportunitySets: Int! + optimizationPolicy: DataframeOptimizationPolicy! + richSourceReuse: [DataframeRichSourceReuse!]! +} + +type DataframeOptimizationPolicy { + name: String! + enabled: Boolean! + minimumSavings: Int! + decisions: [DataframeOptimizationDecision!]! +} + +type DataframeOptimizationDecision { + rule: String! + enabled: Boolean! + candidateSets: Int! + estimatedBaselineWork: Int! + estimatedOptimizedWork: Int! + estimatedSavings: Int! + reason: String! +} + +type DataframeRichSourceReuse { + sourceSet: String! + aggregateConsumers: Int! + pivotConsumers: Int! + sliceConsumers: Int! + totalConsumers: Int! } diff --git a/internal/graphqlapi/schema.resolvers.go b/graphqlapi/schema.resolvers.go similarity index 85% rename from internal/graphqlapi/schema.resolvers.go rename to graphqlapi/schema.resolvers.go index 6fe92bb..d285211 100644 --- a/internal/graphqlapi/schema.resolvers.go +++ b/graphqlapi/schema.resolvers.go @@ -6,8 +6,9 @@ package graphqlapi import ( "context" - "github.com/calypr/loom/internal/dataframebuilder" - "github.com/calypr/loom/internal/graphqlapi/model" + + dataframeapi "github.com/calypr/loom/graphqlapi/dataframe" + "github.com/calypr/loom/graphqlapi/model" ) // RunFhirDataframe is the resolver for the runFhirDataframe field. @@ -17,9 +18,10 @@ func (r *mutationResolver) RunFhirDataframe(ctx context.Context, input model.Fhi return nil, err } return &model.FhirDataframeResult{ - Columns: cloneStrings(result.Columns), - Rows: graphqlRows(result.Rows), - RowCount: result.RowCount, + Columns: cloneStrings(result.Columns), + Rows: graphqlRows(result.Rows), + RowCount: result.RowCount, + Diagnostics: dataframeDiagnostics(result.Diagnostics), }, nil } @@ -29,7 +31,7 @@ func (r *queryResolver) DataframeBuilderIntrospection(ctx context.Context, input if input.IncludePivotOnlyFields != nil { includePivotOnlyFields = *input.IncludePivotOnlyFields } - resp, err := r.service.Introspect(ctx, dataframebuilder.IntrospectionRequest{ + resp, err := r.service.Introspect(ctx, dataframeapi.IntrospectionRequest{ Project: input.Project, RootResourceType: input.RootResourceType, AuthResourcePaths: input.AuthResourcePaths, diff --git a/internal/api/doc.go b/internal/api/doc.go deleted file mode 100644 index 7d61328..0000000 --- a/internal/api/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package api owns the HTTP API surface and import ingest orchestration. -package api diff --git a/internal/catalog/cache/cache.go b/internal/catalog/cache.go similarity index 61% rename from internal/catalog/cache/cache.go rename to internal/catalog/cache.go index 75df9a6..8d7085c 100644 --- a/internal/catalog/cache/cache.go +++ b/internal/catalog/cache.go @@ -1,4 +1,4 @@ -package cache +package catalog import ( "context" @@ -7,25 +7,23 @@ import ( "sort" "strings" "sync" - - "github.com/calypr/loom/internal/catalog" ) type Cache struct { mu sync.RWMutex - fields map[string][]catalog.PopulatedField - references map[string][]catalog.PopulatedReference + fields map[string][]PopulatedField + references map[string][]PopulatedReference } -func New() *Cache { +func NewCache() *Cache { return &Cache{ - fields: make(map[string][]catalog.PopulatedField), - references: make(map[string][]catalog.PopulatedReference), + fields: make(map[string][]PopulatedField), + references: make(map[string][]PopulatedReference), } } -func (c *Cache) DiscoverFields(fn func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error)) func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { - return func(ctx context.Context, opts catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { +func (c *Cache) DiscoverFields(fn func(context.Context, PopulatedFieldOptions) ([]PopulatedField, error)) func(context.Context, PopulatedFieldOptions) ([]PopulatedField, error) { + return func(ctx context.Context, opts PopulatedFieldOptions) ([]PopulatedField, error) { key, err := fieldKey(opts) if err != nil { return nil, err @@ -47,8 +45,8 @@ func (c *Cache) DiscoverFields(fn func(context.Context, catalog.PopulatedFieldOp } } -func (c *Cache) DiscoverReferences(fn func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error)) func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { - return func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { +func (c *Cache) DiscoverReferences(fn func(context.Context, PopulatedReferenceOptions) ([]PopulatedReference, error)) func(context.Context, PopulatedReferenceOptions) ([]PopulatedReference, error) { + return func(ctx context.Context, opts PopulatedReferenceOptions) ([]PopulatedReference, error) { key, err := referenceKey(opts) if err != nil { return nil, err @@ -93,11 +91,11 @@ func (c *Cache) InvalidateProject(project string) { func (c *Cache) InvalidateAll() { c.mu.Lock() defer c.mu.Unlock() - c.fields = make(map[string][]catalog.PopulatedField) - c.references = make(map[string][]catalog.PopulatedReference) + c.fields = make(map[string][]PopulatedField) + c.references = make(map[string][]PopulatedReference) } -func fieldKey(opts catalog.PopulatedFieldOptions) (string, error) { +func fieldKey(opts PopulatedFieldOptions) (string, error) { scope, err := authScopeKey(opts.AuthResourcePaths, opts.AuthResourcePathsUnrestricted) if err != nil { return "", err @@ -105,7 +103,7 @@ func fieldKey(opts catalog.PopulatedFieldOptions) (string, error) { return fmt.Sprintf("%s|%s|%t|%s|%s", strings.TrimSpace(opts.Project), strings.TrimSpace(opts.ResourceType), opts.PivotOnly, scope, datasetGenerationKey(opts.DatasetGeneration)), nil } -func referenceKey(opts catalog.PopulatedReferenceOptions) (string, error) { +func referenceKey(opts PopulatedReferenceOptions) (string, error) { scope, err := authScopeKey(opts.AuthResourcePaths, opts.AuthResourcePathsUnrestricted) if err != nil { return "", err @@ -114,8 +112,8 @@ func referenceKey(opts catalog.PopulatedReferenceOptions) (string, error) { } func datasetGenerationKey(generation string) string { - generation = catalog.NormalizeDatasetGeneration(generation) - if !catalog.HasDatasetGeneration(generation) { + generation = NormalizeDatasetGeneration(generation) + if !HasDatasetGeneration(generation) { return "legacy" } encoded, _ := json.Marshal(generation) @@ -123,7 +121,7 @@ func datasetGenerationKey(generation string) string { } func authScopeKey(paths []string, explicitUnrestricted *bool) (string, error) { - if catalog.EffectiveAuthResourcePathsUnrestricted(paths, explicitUnrestricted) { + if EffectiveAuthResourcePathsUnrestricted(paths, explicitUnrestricted) { return "unrestricted", nil } normalized := append([]string(nil), paths...) @@ -135,11 +133,11 @@ func authScopeKey(paths []string, explicitUnrestricted *bool) (string, error) { return "restricted:" + string(encoded), nil } -func cloneFields(in []catalog.PopulatedField) []catalog.PopulatedField { +func cloneFields(in []PopulatedField) []PopulatedField { if len(in) == 0 { - return []catalog.PopulatedField{} + return []PopulatedField{} } - out := make([]catalog.PopulatedField, len(in)) + out := make([]PopulatedField, len(in)) for i := range in { out[i] = in[i] if in[i].DistinctValues != nil { @@ -152,11 +150,11 @@ func cloneFields(in []catalog.PopulatedField) []catalog.PopulatedField { return out } -func cloneReferences(in []catalog.PopulatedReference) []catalog.PopulatedReference { +func cloneReferences(in []PopulatedReference) []PopulatedReference { if len(in) == 0 { - return []catalog.PopulatedReference{} + return []PopulatedReference{} } - out := make([]catalog.PopulatedReference, len(in)) + out := make([]PopulatedReference, len(in)) copy(out, in) return out } diff --git a/internal/catalog/cache/cache_test.go b/internal/catalog/cache_test.go similarity index 63% rename from internal/catalog/cache/cache_test.go rename to internal/catalog/cache_test.go index bd7a83a..9a71450 100644 --- a/internal/catalog/cache/cache_test.go +++ b/internal/catalog/cache_test.go @@ -1,21 +1,19 @@ -package cache +package catalog import ( "context" "testing" - - "github.com/calypr/loom/internal/catalog" ) func TestCacheDiscoverFieldsCachesAndInvalidatesByProject(t *testing.T) { - cache := New() + cache := NewCache() calls := 0 - discover := cache.DiscoverFields(func(ctx context.Context, opts catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + discover := cache.DiscoverFields(func(ctx context.Context, opts PopulatedFieldOptions) ([]PopulatedField, error) { calls++ - return []catalog.PopulatedField{{ResourceType: opts.ResourceType, Path: "gender"}}, nil + return []PopulatedField{{ResourceType: opts.ResourceType, Path: "gender"}}, nil }) - opts := catalog.PopulatedFieldOptions{Project: "P1", ResourceType: "Patient"} + opts := PopulatedFieldOptions{Project: "P1", ResourceType: "Patient"} if _, err := discover(context.Background(), opts); err != nil { t.Fatal(err) } @@ -44,14 +42,14 @@ func TestCacheDiscoverFieldsCachesAndInvalidatesByProject(t *testing.T) { } func TestCacheDiscoverReferencesSeparatesAuthScopes(t *testing.T) { - cache := New() + cache := NewCache() calls := 0 - discover := cache.DiscoverReferences(func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + discover := cache.DiscoverReferences(func(ctx context.Context, opts PopulatedReferenceOptions) ([]PopulatedReference, error) { calls++ - return []catalog.PopulatedReference{{FromType: opts.NodeType, Label: "subject_Patient", ToType: "Specimen"}}, nil + return []PopulatedReference{{FromType: opts.NodeType, Label: "subject_Patient", ToType: "Specimen"}}, nil }) - base := catalog.PopulatedReferenceOptions{Project: "P1", NodeType: "Patient", Mode: catalog.TraversalModeBuilder} + base := PopulatedReferenceOptions{Project: "P1", NodeType: "Patient", Mode: TraversalModeBuilder} withA := base withA.AuthResourcePaths = []string{"a"} withB := base @@ -72,18 +70,18 @@ func TestCacheDiscoverReferencesSeparatesAuthScopes(t *testing.T) { } func TestCacheSeparatesRestrictedEmptyScopeFromUnrestrictedScope(t *testing.T) { - cache := New() + cache := NewCache() calls := 0 - discover := cache.DiscoverFields(func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + discover := cache.DiscoverFields(func(context.Context, PopulatedFieldOptions) ([]PopulatedField, error) { calls++ - return []catalog.PopulatedField{{ResourceType: "Patient", Path: "gender"}}, nil + return []PopulatedField{{ResourceType: "Patient", Path: "gender"}}, nil }) - unrestricted := catalog.PopulatedFieldOptions{Project: "P1", ResourceType: "Patient"} - restrictedEmpty := catalog.PopulatedFieldOptions{ + unrestricted := PopulatedFieldOptions{Project: "P1", ResourceType: "Patient"} + restrictedEmpty := PopulatedFieldOptions{ Project: "P1", ResourceType: "Patient", - AuthResourcePathsUnrestricted: catalog.ExplicitAuthResourcePathsUnrestricted(false), + AuthResourcePathsUnrestricted: ExplicitAuthResourcePathsUnrestricted(false), AuthResourcePaths: []string{}, } @@ -99,20 +97,20 @@ func TestCacheSeparatesRestrictedEmptyScopeFromUnrestrictedScope(t *testing.T) { } func TestCacheSeparatesDatasetGenerationNamespaces(t *testing.T) { - cache := New() + cache := NewCache() fieldCalls := 0 - discoverFields := cache.DiscoverFields(func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + discoverFields := cache.DiscoverFields(func(context.Context, PopulatedFieldOptions) ([]PopulatedField, error) { fieldCalls++ - return []catalog.PopulatedField{{ResourceType: "Patient", Path: "gender"}}, nil + return []PopulatedField{{ResourceType: "Patient", Path: "gender"}}, nil }) referenceCalls := 0 - discoverReferences := cache.DiscoverReferences(func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + discoverReferences := cache.DiscoverReferences(func(context.Context, PopulatedReferenceOptions) ([]PopulatedReference, error) { referenceCalls++ - return []catalog.PopulatedReference{{FromType: "Patient", Label: "subject_Patient", ToType: "Specimen"}}, nil + return []PopulatedReference{{FromType: "Patient", Label: "subject_Patient", ToType: "Specimen"}}, nil }) - fieldBase := catalog.PopulatedFieldOptions{Project: "P1", ResourceType: "Patient"} - referenceBase := catalog.PopulatedReferenceOptions{Project: "P1", NodeType: "Patient", Mode: catalog.TraversalModeBuilder} + fieldBase := PopulatedFieldOptions{Project: "P1", ResourceType: "Patient"} + referenceBase := PopulatedReferenceOptions{Project: "P1", NodeType: "Patient", Mode: TraversalModeBuilder} for _, generation := range []string{"", "generation-a", " generation-a ", "generation-b"} { fields := fieldBase fields.DatasetGeneration = generation diff --git a/internal/catalog/write_profiler.go b/internal/catalog/write_profiler.go index e1e99bf..fe4e80b 100644 --- a/internal/catalog/write_profiler.go +++ b/internal/catalog/write_profiler.go @@ -8,7 +8,7 @@ import ( "strings" "time" - "github.com/calypr/loom/internal/fhirschema" + "github.com/calypr/loom/fhirschema" ) func NewShapePlanCache() *ShapePlanCache { diff --git a/internal/catalog/write_profiler_test.go b/internal/catalog/write_profiler_test.go index 7c2e38f..b11bc76 100644 --- a/internal/catalog/write_profiler_test.go +++ b/internal/catalog/write_profiler_test.go @@ -8,7 +8,7 @@ import ( "strings" "testing" - "github.com/calypr/loom/internal/fhirschema" + "github.com/calypr/loom/fhirschema" ) func TestFieldCatalogProfilerCanonicalPaths(t *testing.T) { diff --git a/internal/dataframe/aggregate_compile_test.go b/internal/dataframe/aggregate_compile_test.go index a224508..367ef7d 100644 --- a/internal/dataframe/aggregate_compile_test.go +++ b/internal/dataframe/aggregate_compile_test.go @@ -16,8 +16,8 @@ func TestGenericExistsAggregateWithoutPredicateTestsSetNonEmptiness(t *testing.T if err != nil { t.Fatal(err) } - if !strings.Contains(compiled.Query, `"file__has_file": LENGTH(generic_file_set) > 0`) { - t.Fatalf("EXISTS aggregate did not compile as set non-emptiness:\n%s", compiled.Query) + if !strings.Contains(compiled.Query, "LENGTH(child_set_1) > 0") { + t.Fatalf("EXISTS aggregate did not compile as physical set non-emptiness:\n%s", compiled.Query) } } @@ -47,7 +47,7 @@ func TestGenericMinAndMaxAggregatesLowerToTypedReductions(t *testing.T) { if err != nil { t.Fatal(err) } - if !strings.Contains(compiled.Query, `"file__min_size": MIN(FLATTEN(`) || !strings.Contains(compiled.Query, `"file__max_size": MAX(FLATTEN(`) { - t.Fatalf("MIN/MAX did not compile through typed aggregate reductions:\n%s", compiled.Query) + if !strings.Contains(compiled.Query, "MIN(FLATTEN(") || !strings.Contains(compiled.Query, "MAX(FLATTEN(") { + t.Fatalf("MIN/MAX did not compile through physical aggregate reductions:\n%s", compiled.Query) } } diff --git a/internal/dataframe/builder_types.go b/internal/dataframe/builder_types.go index b29d204..dbe3eee 100644 --- a/internal/dataframe/builder_types.go +++ b/internal/dataframe/builder_types.go @@ -1,6 +1,10 @@ package dataframe -import "github.com/calypr/loom/internal/authscope" +import ( + "time" + + "github.com/calypr/loom/internal/authscope" +) type Builder struct { Project string @@ -15,21 +19,12 @@ type Builder struct { AuthScopeMode authscope.ReadScopeMode RootResourceType string RowGrain RowGrain - PlanHint *PlanHint Fields []FieldSelect Filters []TypedFilter Pivots []PivotSelect Aggregates []AggregateSelect Slices []RepresentativeSlice Traversals []TraversalStep - Sets []NamedSet - DerivedFields []DerivedField - RepresentativeSlices []RepresentativeSlice - // RequiredTraversalMatches is populated only by compiler lowering from - // TraversalStep.MatchMode. It keeps root-scoped relationship predicates - // separate from materialized traversal sets, so Compile can apply them - // before root SORT/LIMIT. - RequiredTraversalMatches []RequiredTraversalMatch } type TraversalStep struct { @@ -46,9 +41,20 @@ type TraversalStep struct { // post-projection filter. MatchMode TraversalMatchMode Traversals []TraversalStep - Sets []NamedSet - DerivedFields []DerivedField - RepresentativeSlices []RepresentativeSlice +} + +// RepresentativeSlice is a bounded child projection requested by the +// semantic dataframe request. It is consumed directly by the physical plan; +// it is not a lowered named-set artifact. +type RepresentativeSlice struct { + Name string + SourceSet string + Predicate string + PredicateFieldRef string + PredicatePath string + PredicateEquals string + Limit int + Fields []FieldSelect } type FieldSelect struct { @@ -86,9 +92,26 @@ type RunRequest struct { } type Result struct { - Columns []string - Rows []map[string]any - RowCount int + Columns []string + Rows []map[string]any + RowCount int + Diagnostics QueryDiagnostics +} + +// QueryDiagnostics separates the cost of turning a dataframe request into +// rows. ArangoQuery is cursor time excluding Loom's per-row processing; +// RowMaterialization is the time spent flattening and delivering rows. +type QueryDiagnostics struct { + // InputResolution is populated by the GraphQL adapter while resolving field + // references from the catalog before this service is called. + InputResolution time.Duration + RequestPreparation time.Duration + Compilation time.Duration + ArangoQuery time.Duration + RowMaterialization time.Duration + ResultAssembly time.Duration + Total time.Duration + Plan CompilerPlanDiagnostics } // StreamResult describes rows delivered to a streaming caller. Columns are @@ -96,8 +119,9 @@ type Result struct { // data-dependent output keys. The streaming callback itself receives each // flattened row as it is read from Arango. type StreamResult struct { - Columns []string - RowCount int + Columns []string + RowCount int + Diagnostics QueryDiagnostics } func cloneStrings(in []string) []string { diff --git a/internal/dataframe/compile.go b/internal/dataframe/compile.go index bc5c407..77a1a1b 100644 --- a/internal/dataframe/compile.go +++ b/internal/dataframe/compile.go @@ -9,125 +9,40 @@ type CompiledQuery struct { AuthResourcePaths []string PlanMode string PlanProfile string - NamedSetCount int + TraversalCount int FileSummaries bool StudyLookup bool OptimizationRules []string // RowIdentity describes the stable resource identity behind each returned // row. It is metadata for exporters and recipe consumers; the existing row // object keeps its backwards-compatible _key column. - RowIdentity *RowIdentity - Query string - BindVars map[string]any - Columns []string - PivotFields []string - Limit int -} - -func Compile(builder Builder, limit int) (CompiledQuery, error) { - if !usesLoweredBuilder(builder) { - return CompiledQuery{}, fmt.Errorf("unsupported dataframe query shape: request was not lowered into the optimized lowered plan") - } - // Compile is intentionally safe for callers that receive a pre-lowered - // builder (for example, persisted recipes or conformance fixtures). The - // renderer interpolates only a generated resource collection name; validate - // that boundary here rather than relying on a service caller to have done so. - if err := validateLoweredBuilder(builder); err != nil { - return CompiledQuery{}, err - } - return compileLowered(builder, limit) -} - -// CompileRequest is the public compiler entrypoint for a dataframe request. -// It preserves the validated semantic plan alongside the compatibility -// lowered Builder so generic navigation requests can execute through the typed -// physical renderer. Requests whose selections or shaping are not represented -// by the physical IR retain the established lowered renderer. + RowIdentity *RowIdentity + Query string + BindVars map[string]any + Columns []string + PivotFields []string + Limit int + PlanDiagnostics CompilerPlanDiagnostics +} + +// CompileRequest is the sole production compiler entrypoint for a dataframe +// request. It validates semantic meaning, lowers to typed physical operators, +// applies semantics-preserving physical rewrites, and renders parameterized +// AQL. Unsupported shapes fail explicitly. func CompileRequest(builder Builder, limit int) (CompiledQuery, error) { semantic, err := BuildSemanticPlan(builder) if err != nil { return CompiledQuery{}, err } - planned, err := lowerSemanticBuilder(builder, semantic) + // The physical route owns navigation-only requests directly from semantic + // meaning. + physical, err := BuildPhysicalPlan(semantic) if err != nil { - return CompiledQuery{}, err + return CompiledQuery{}, fmt.Errorf("unsupported physical dataframe shape: %w", err) } - return compileRequestPlans(semantic, planned, limit) -} - -// compileRequestPlans selects the typed execution path only when the semantic -// plan is wholly represented by the frozen generic navigation physical IR. -// The compatibility lowered renderer remains the explicit fallback for every -// richer request; it must never receive a partial physical plan that silently -// drops a user field, filter, pivot, aggregate, slice, or required match. -func compileRequestPlans(semantic SemanticPlan, planned Builder, limit int) (CompiledQuery, error) { - if !usesLoweredBuilder(planned) { - return CompiledQuery{}, fmt.Errorf("unsupported dataframe query shape: request was not lowered into the optimized lowered plan") - } - if err := validateLoweredBuilder(planned); err != nil { - return CompiledQuery{}, err - } - if planProfile(planned.PlanHint) == "generic_fhir_graph" && genericPhysicalPlanUnavailableReason(semantic.Root) == "" { - return compileGenericPhysicalExecution(semantic, planned, limit) - } - return Compile(planned, limit) -} - -func planMode(hint *PlanHint) string { - if hint == nil || hint.Mode == "" { - return "unsupported" - } - return hint.Mode -} - -func planProfile(hint *PlanHint) string { - if hint == nil { - return "" - } - return hint.Profile -} - -func planNamedSetCount(hint *PlanHint) int { - if hint == nil { - return 0 - } - return hint.NamedSetCount -} - -func planFileSummaries(hint *PlanHint) bool { - if hint == nil { - return false - } - return hint.ClassifiedFileSummaries -} - -func planStudyLookup(hint *PlanHint) bool { - if hint == nil { - return false - } - return hint.StudyLookup -} - -func planRowIdentity(hint *PlanHint) *RowIdentity { - if hint == nil { - return nil - } - return cloneRowIdentity(hint.RowIdentity) -} - -func planAppliedRules(hint *PlanHint) []string { - if hint == nil || len(hint.AppliedRules) == 0 { - return nil + physical, err = OptimizePhysicalPlan(physical) + if err != nil { + return CompiledQuery{}, fmt.Errorf("optimize physical plan: %w", err) } - return append([]string(nil), hint.AppliedRules...) -} - -type compiler struct { - builder Builder - bindVars map[string]any - columns []string - pivotFields []string - bindCount int - pivotExprs map[string]string - genericSetRoutes map[string]storageRoute + return compilePhysicalExecution(physical, semantic, limit) } diff --git a/internal/dataframe/compile_fields.go b/internal/dataframe/compile_fields.go deleted file mode 100644 index cffbc3d..0000000 --- a/internal/dataframe/compile_fields.go +++ /dev/null @@ -1,227 +0,0 @@ -package dataframe - -import ( - "fmt" - "strings" -) - -func (c *compiler) compileTraversal(parentVar string, parentIsArray bool, step TraversalStep, lets *[]string, objectLines *[]string) error { - labelBind := c.newBind(step.Alias+"_label", step.Label) - toBind := c.newBind(step.Alias+"_to", step.ToResourceType) - nodeVar := sanitizeColumnName(step.Alias) + "_nodes" - var let string - if parentIsArray { - let = fmt.Sprintf(" LET %s = UNIQUE(FLATTEN(FOR __parent IN %s FOR __node, __edge IN 1..1 INBOUND __parent fhir_edge FILTER __edge.project == @project FILTER __node.project == @project FILTER __edge.%s == @%s FILTER __node.%s == @%s FILTER @auth_resource_paths_unrestricted == true OR (__edge.auth_resource_path IN @auth_resource_paths AND __node.auth_resource_path IN @auth_resource_paths) FILTER __edge.label == @%s FILTER __node.resourceType == @%s RETURN [__node]))", nodeVar, parentVar, datasetGenerationField, datasetGenerationBindKey, datasetGenerationField, datasetGenerationBindKey, labelBind, toBind) - } else { - let = fmt.Sprintf(" LET %s = UNIQUE(FOR __node, __edge IN 1..1 INBOUND %s fhir_edge FILTER __edge.project == @project FILTER __node.project == @project FILTER __edge.%s == @%s FILTER __node.%s == @%s FILTER @auth_resource_paths_unrestricted == true OR (__edge.auth_resource_path IN @auth_resource_paths AND __node.auth_resource_path IN @auth_resource_paths) FILTER __edge.label == @%s FILTER __node.resourceType == @%s RETURN __node)", nodeVar, parentVar, datasetGenerationField, datasetGenerationBindKey, datasetGenerationField, datasetGenerationBindKey, labelBind, toBind) - } - *lets = append(*lets, let) - for _, field := range step.Fields { - sel, err := ParseSelector(field.Select) - if err != nil { - return fmt.Errorf("traversal %q field %q selector: %w", step.Alias, field.Name, err) - } - expr, err := c.compileTraversalFieldSelect(nodeVar, field, sel) - if err != nil { - return err - } - colName := sanitizeColumnName(step.Alias + "__" + field.Name) - *objectLines = append(*objectLines, fmt.Sprintf(" %s: %s", quoteKey(colName), expr)) - c.columns = append(c.columns, colName) - } - for _, pivot := range step.Pivots { - keySel, err := ParseSelector(pivot.ColumnSelect) - if err != nil { - return fmt.Errorf("traversal %q pivot %q key selector: %w", step.Alias, pivot.Name, err) - } - valueSel, err := ParseSelector(pivot.ValueSelect) - if err != nil { - return fmt.Errorf("traversal %q pivot %q value selector: %w", step.Alias, pivot.Name, err) - } - colName := sanitizeColumnName(step.Alias + "__" + pivot.Name) - expr, err := c.compileTraversalPivot(nodeVar, keySel, valueSel, pivot.Columns) - if err != nil { - return err - } - *objectLines = append(*objectLines, fmt.Sprintf(" %s: %s", quoteKey(colName), expr)) - c.columns = append(c.columns, colName) - c.pivotFields = append(c.pivotFields, colName) - } - for _, agg := range step.Aggregates { - expr, err := c.compileSetAggregateExpr(nodeVar, agg) - if err != nil { - return err - } - colName := sanitizeColumnName(step.Alias + "__" + agg.Name) - *objectLines = append(*objectLines, fmt.Sprintf(" %s: %s", quoteKey(colName), expr)) - c.columns = append(c.columns, colName) - } - for _, slice := range step.Slices { - expr, err := c.compileSetSlice(nodeVar, setModeNode, slice) - if err != nil { - return err - } - colName := sanitizeColumnName(step.Alias + "__" + slice.Name) - *objectLines = append(*objectLines, fmt.Sprintf(" %s: %s", quoteKey(colName), expr)) - c.columns = append(c.columns, colName) - } - for _, child := range step.Traversals { - if err := c.compileTraversal(nodeVar, true, child, lets, objectLines); err != nil { - return err - } - } - return nil -} - -func (c *compiler) compileRootFieldSelect(payloadVar string, field FieldSelect, sel Selector) (string, error) { - switch normalizeValueMode(field.ValueMode) { - case "ALL": - return c.compileSelectorArrayForSelects(payloadVar, append([]string{field.Select}, field.FallbackSelects...)), nil - case "DISTINCT": - return fmt.Sprintf("SORTED_UNIQUE(%s)", c.compileSelectorArrayForSelects(payloadVar, append([]string{field.Select}, field.FallbackSelects...))), nil - case "FIRST": - return c.compileFirstNonNullExpr(payloadVar, append([]string{field.Select}, field.FallbackSelects...)), nil - } - if len(field.FallbackSelects) > 0 { - return c.compileFirstNonNullExpr(payloadVar, append([]string{field.Select}, field.FallbackSelects...)), nil - } - return c.compileRootField(payloadVar, sel) -} - -func (c *compiler) compileRootField(payloadVar string, sel Selector) (string, error) { - if sel.Filter == nil && selectorHasNoArrays(sel) { - return compileDirectExpr(payloadVar, sel.Steps), nil - } - return "FIRST" + compileSelectorArrayExpr(payloadVar, sel, c), nil -} - -func (c *compiler) compileTraversalFieldSelect(nodeVar string, field FieldSelect, sel Selector) (string, error) { - switch normalizeValueMode(field.ValueMode) { - case "FIRST": - tmp := DerivedField{Source: nodeVar, Operation: DerivedOpFirstNonNull, Select: field.Select, FallbackSelects: field.FallbackSelects} - return c.compileFirstNonNullField("", tmp, map[string]setMode{nodeVar: setModeNode}) - case "ALL": - tmp := DerivedField{Source: nodeVar, Operation: DerivedOpAll, Select: field.Select, FallbackSelects: field.FallbackSelects} - return c.compileAllField("", tmp, map[string]setMode{nodeVar: setModeNode}) - } - if len(field.FallbackSelects) > 0 { - tmp := DerivedField{ - Source: nodeVar, - Select: field.Select, - FallbackSelects: field.FallbackSelects, - } - return c.compileUniqueField("", tmp, map[string]setMode{nodeVar: setModeNode}) - } - return c.compileTraversalField(nodeVar, sel) -} - -func (c *compiler) compileTraversalField(nodeVar string, sel Selector) (string, error) { - return fmt.Sprintf("SORTED_UNIQUE(FLATTEN(FOR __n IN %s RETURN %s))", nodeVar, compileSelectorArrayExpr("__n.payload", sel, c)), nil -} - -func (c *compiler) compileRootPivot(payloadVar string, keySel Selector, valueSel Selector, columns []string) (string, error) { - return c.compilePivotMapExpr("FOR __item IN ["+payloadVar+"]", "__item", keySel, valueSel, columns) -} - -func (c *compiler) compileTraversalPivot(nodeVar string, keySel Selector, valueSel Selector, columns []string) (string, error) { - return c.compilePivotMapExpr("FOR __item IN "+nodeVar, "__item.payload", keySel, valueSel, columns) -} - -func selectorHasNoArrays(sel Selector) bool { - for _, step := range sel.Steps { - if step.Iterate || step.Index != nil { - return false - } - } - return true -} - -func compileDirectExpr(rootVar string, steps []SelectorStep) string { - cur := rootVar - for _, step := range steps { - if step.Index != nil { - cur = fmt.Sprintf("((%s.%s ? %s.%s : [])[%d])", cur, step.Field, cur, step.Field, *step.Index) - continue - } - cur = fmt.Sprintf("%s.%s", cur, step.Field) - } - return cur -} - -func compileSelectorArrayExpr(rootVar string, sel Selector, c *compiler) string { - prefix := sel.Steps - if len(prefix) == 0 { - return "[]" - } - last := prefix[len(prefix)-1] - prefix = prefix[:len(prefix)-1] - lines := []string{fmt.Sprintf("FOR __root IN [%s]", rootVar)} - cur := "__root" - tmpCount := 0 - for _, step := range prefix { - next := fmt.Sprintf("__s%d", tmpCount) - tmpCount++ - switch { - case step.Iterate: - lines = append(lines, fmt.Sprintf(" FOR %s IN (%s.%s ? %s.%s : [])", next, cur, step.Field, cur, step.Field)) - case step.Index != nil: - lines = append(lines, fmt.Sprintf(" LET %s = ((%s.%s ? %s.%s : [])[%d])", next, cur, step.Field, cur, step.Field, *step.Index)) - lines = append(lines, fmt.Sprintf(" FILTER %s != null", next)) - default: - lines = append(lines, fmt.Sprintf(" LET %s = %s.%s", next, cur, step.Field)) - lines = append(lines, fmt.Sprintf(" FILTER %s != null", next)) - } - cur = next - } - if sel.Filter != nil { - filterBind := c.newBind("contains", sel.Filter.Needle) - lines = append(lines, fmt.Sprintf(" FILTER CONTAINS(%s.%s ? %s.%s : \"\", @%s)", cur, sel.Filter.Field, cur, sel.Filter.Field, filterBind)) - } - finalExpr := extractFinalExpr(cur, last) - lines = append(lines, fmt.Sprintf(" LET __value = %s", finalExpr)) - lines = append(lines, " FILTER __value != null") - lines = append(lines, " RETURN __value") - return "(\n " + strings.Join(lines, "\n ") + "\n )" -} - -func (c *compiler) compilePivotMapExpr(itemLoop string, payloadVar string, keySel Selector, valueSel Selector, columns []string) (string, error) { - keyExpr := compileSelectorArrayExpr(payloadVar, keySel, c) - valueExpr := compileSelectorArrayExpr(payloadVar, valueSel, c) - filterLine := "" - if len(columns) > 0 { - colBind := c.newBind("pivot_cols", append([]string(nil), columns...)) - filterLine = fmt.Sprintf("\n FILTER POSITION(@%s, __key, true)", colBind) - } - return fmt.Sprintf(`MERGE( - FOR __pair IN ( - %s - LET __keys = UNIQUE(%s) - LET __values = %s - FILTER LENGTH(__values) > 0 - FOR __key IN __keys%s - RETURN { key: __key, values: __values } - ) - COLLECT __key = __pair.key INTO __group - LET __flat_values = SORTED_UNIQUE(FLATTEN(__group[*].__pair.values)) - FILTER LENGTH(__flat_values) > 0 - RETURN { [__key]: FIRST(__flat_values) } - )`, itemLoop, keyExpr, valueExpr, filterLine), nil -} - -func extractFinalExpr(cur string, step SelectorStep) string { - switch { - case step.Iterate: - return fmt.Sprintf("(%s.%s ? %s.%s : [])", cur, step.Field, cur, step.Field) - case step.Index != nil: - return fmt.Sprintf("((%s.%s ? %s.%s : [])[%d])", cur, step.Field, cur, step.Field, *step.Index) - default: - return fmt.Sprintf("%s.%s", cur, step.Field) - } -} - -func (c *compiler) newBind(prefix string, value any) string { - name := fmt.Sprintf("__%s_%d", sanitizeColumnName(prefix), c.bindCount) - c.bindCount++ - c.bindVars[name] = value - return name -} diff --git a/internal/dataframe/compile_validation_test.go b/internal/dataframe/compile_validation_test.go deleted file mode 100644 index f40fc43..0000000 --- a/internal/dataframe/compile_validation_test.go +++ /dev/null @@ -1,75 +0,0 @@ -package dataframe - -import ( - "strings" - "testing" -) - -func TestCompileRejectsMalformedSelectorsInManualLoweredBuilders(t *testing.T) { - _, err := Compile(Builder{ - Project: "P1", - RootResourceType: "Patient", - PlanHint: &PlanHint{Mode: "lowered", Profile: "test"}, - Fields: []FieldSelect{{Name: "bad", Select: "name[not-an-index]"}}, - }, 1) - if err == nil || !strings.Contains(err.Error(), "root field") { - t.Fatalf("expected malformed selector error, got %v", err) - } -} - -func TestCompileTraverseSetHonorsExplicitUniqueFlag(t *testing.T) { - compiled, err := Compile(Builder{ - Project: "P1", - RootResourceType: "Patient", - PlanHint: &PlanHint{Mode: "lowered", Profile: "test"}, - Sets: []NamedSet{{ - Name: "raw_children", Kind: SetKindTraverse, Label: "subject_Patient", ToResourceType: "Condition", Unique: false, - }}, - }, 1) - if err != nil { - t.Fatal(err) - } - if strings.Contains(compiled.Query, "LET raw_children = UNIQUE") { - t.Fatalf("unexpected deduplication for explicit non-unique set:\n%s", compiled.Query) - } -} - -func TestCompileRejectsUnknownOrUnsafeRootCollection(t *testing.T) { - _, err := Compile(Builder{ - Project: "P1", - RootResourceType: "Patient RETURN SLEEP(1)", - PlanHint: &PlanHint{Mode: "lowered", Profile: "test"}, - }, 1) - if err == nil || !strings.Contains(err.Error(), "not represented by the active generated FHIR schema") { - t.Fatalf("expected generated-schema root validation error, got %v", err) - } -} - -func TestCompileRejectsUnsafeInternalSortField(t *testing.T) { - _, err := Compile(Builder{ - Project: "P1", - RootResourceType: "Patient", - PlanHint: &PlanHint{Mode: "lowered", Profile: "test"}, - Sets: []NamedSet{{ - Name: "children", Kind: SetKindTraverse, Label: "subject_Patient", ToResourceType: "Condition", - SortField: "_key RETURN SLEEP(1)", - }}, - }, 1) - if err == nil || !strings.Contains(err.Error(), "unsafe sort field") { - t.Fatalf("expected sort-field validation error, got %v", err) - } -} - -func TestCompileRejectsRemovedRawAQLDerivedField(t *testing.T) { - _, err := Compile(Builder{ - Project: "P1", - RootResourceType: "Patient", - PlanHint: &PlanHint{Mode: "lowered", Profile: "test"}, - DerivedFields: []DerivedField{{ - Name: "unsafe", Operation: "RAW_EXPR", - }}, - }, 1) - if err == nil || !strings.Contains(err.Error(), "unsupported operation") { - t.Fatalf("expected removed raw AQL operation rejection, got %v", err) - } -} diff --git a/internal/dataframe/compiler_arango_integration_test.go b/internal/dataframe/compiler_arango_integration_test.go index e0e3e41..538da05 100644 --- a/internal/dataframe/compiler_arango_integration_test.go +++ b/internal/dataframe/compiler_arango_integration_test.go @@ -129,62 +129,11 @@ func TestGenericRootPreviewUsesScopedSortIndexAgainstArango(t *testing.T) { t.Fatalf("ExplainCompiledQuery() error = %v", err) } assessment := arangostore.AssessExplainResult(explain) - if !hasExplainIndex(assessment, "Patient", []string{"project", "_key"}) { + if !hasScopedRootPreviewIndex(assessment, "Patient") { t.Fatalf("root preview did not use the project/_key index; assessment=%#v", assessment) } } -// TestGenericPhysicalExecutionHasLoweredResultParityAgainstArango compares -// the executable typed navigation renderer with the compatibility lowered -// renderer against one locally loaded fixture. Optional navigation must not -// change root membership or row shape, and both renderers must select the same -// stable root-key preview window. -func TestGenericPhysicalExecutionHasLoweredResultParityAgainstArango(t *testing.T) { - if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { - t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run compiler/Arango integration") - } - url, database, project := compilerArangoTarget() - builder := Builder{ - Project: project, - RootResourceType: "Patient", - Traversals: []TraversalStep{{ - Label: "subject_Patient", - ToResourceType: "Specimen", - Alias: "specimen", - }}, - } - physical, err := CompileRequest(builder, 25) - if err != nil { - t.Fatalf("CompileRequest() error = %v", err) - } - if !strings.Contains(physical.Query, "FOR root IN @@root_collection") || !strings.Contains(physical.Query, "LET __loom_physical_set_1") { - t.Fatalf("generic navigation did not execute through physical renderer:\n%s", physical.Query) - } - lowered, err := Lower(builder) - if err != nil { - t.Fatalf("Lower() error = %v", err) - } - legacy, err := Compile(lowered, 25) - if err != nil { - t.Fatalf("Compile(lowered) error = %v", err) - } - - opts := arangostore.ConnectionOptions{URL: url, Database: database} - physicalRows, err := executeCompiledRows(context.Background(), opts, physical) - if err != nil { - t.Fatalf("execute physical navigation: %v\nAQL:\n%s", err, physical.Query) - } - legacyRows, err := executeCompiledRows(context.Background(), opts, legacy) - if err != nil { - t.Fatalf("execute lowered navigation: %v\nAQL:\n%s", err, legacy.Query) - } - sortRowsByKey(physicalRows) - sortRowsByKey(legacyRows) - if difference := firstRowDifference(physicalRows, legacyRows); difference != "" { - t.Fatalf("physical/lowered navigation result mismatch: %s", difference) - } -} - // TestRenderedGenericPhysicalNavigationExplainsAgainstArango verifies the // typed navigation renderer against the real Arango parser without replacing // the legacy dataframe renderer yet. It protects collection-bind handling, @@ -225,11 +174,80 @@ func TestRenderedGenericPhysicalNavigationExplainsAgainstArango(t *testing.T) { if len(assessment.FullCollectionScans) != 0 { t.Fatalf("rendered physical navigation unexpectedly full-scanned a collection: assessment=%#v", assessment) } - if !hasExplainIndex(assessment, "Patient", []string{"project", "_key"}) && !hasExplainIndex(assessment, "Patient", []string{"project", "auth_resource_path", "_key"}) { + if !hasScopedRootPreviewIndex(assessment, "Patient") { t.Fatalf("rendered physical navigation did not use a scoped root index; assessment=%#v", assessment) } } +// BenchmarkGenericCompilerAgainstArango measures two different costs against +// the locally loaded META fixture: AQL compilation in-process and execution +// of the already-compiled AQL over one reusable Arango client. The latter is +// intentionally an end-to-end database benchmark, not a Go allocation proxy. +// It is opt-in so normal unit test runs never require a local database. +func BenchmarkGenericCompilerAgainstArango(b *testing.B) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + b.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to benchmark against local Arango/META") + } + url, database, project := compilerArangoTarget() + builder := genericMetaSpecimenBuilder(project) + + b.Run("compile_specimen_file", func(b *testing.B) { + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + if _, err := CompileRequest(builder, 25); err != nil { + b.Fatal(err) + } + } + }) + + compiled, err := CompileRequest(builder, 25) + if err != nil { + b.Fatal(err) + } + client, err := arangostore.Open(context.Background(), url, database) + if err != nil { + b.Fatal(err) + } + defer client.Close(context.Background()) + b.Run("execute_specimen_file", func(b *testing.B) { + b.ReportAllocs() + rows := 0 + b.ResetTimer() + for i := 0; i < b.N; i++ { + rows = 0 + err := client.QueryRows(context.Background(), compiled.Query, 25, compiled.BindVars, func(map[string]any) error { + rows++ + return nil + }) + if err != nil { + b.Fatal(err) + } + } + b.ReportMetric(float64(rows), "rows/op") + }) +} + +func genericMetaSpecimenBuilder(project string) Builder { + return Builder{ + Project: project, + RootResourceType: "Specimen", + Filters: []TypedFilter{{ + FieldRef: "Specimen.type_display", Selector: "type.coding[].display", FieldKind: FilterString, + Repeated: true, Quantifier: QuantifierAny, Operator: FilterExists, + }}, + Fields: []FieldSelect{{Name: "specimen_type", Select: "type.coding[].display"}}, + Traversals: []TraversalStep{{ + Label: "subject_Specimen", ToResourceType: "DocumentReference", Alias: "file", + Filters: []TypedFilter{{ + FieldRef: "DocumentReference.file_name", Selector: "content[].attachment.title", FieldKind: FilterString, + Repeated: true, Quantifier: QuantifierAny, Operator: FilterExists, + }}, + Aggregates: []AggregateSelect{{Name: "file_count", Operation: "COUNT"}}, + }}, + } +} + func compilerArangoTarget() (url, database, project string) { url = os.Getenv("LOOM_ARANGO_URL") if url == "" { @@ -321,3 +339,15 @@ func hasExplainIndex(assessment arangostore.ExplainAssessment, collection string } return false } + +func hasScopedRootPreviewIndex(assessment arangostore.ExplainAssessment, collection string) bool { + for _, index := range assessment.Indexes { + if index.Collection != collection || len(index.Fields) < 2 { + continue + } + if index.Fields[0] == "project" && index.Fields[len(index.Fields)-1] == "_key" { + return true + } + } + return false +} diff --git a/internal/dataframe/compiler_explanation.go b/internal/dataframe/compiler_explanation.go deleted file mode 100644 index 87e8099..0000000 --- a/internal/dataframe/compiler_explanation.go +++ /dev/null @@ -1,478 +0,0 @@ -package dataframe - -import "strings" - -// CompilerExplanationVersion is incremented only when the public structure of -// CompilerExplanation changes incompatibly. -const CompilerExplanationVersion = 1 - -// CompilerExplanation is a pure, renderer-independent inspection result for a -// dataframe Builder. It captures the validated semantic request, normalized -// selection behavior, and safe metadata from the lowered and compiled plans. -// -// It deliberately does not expose a lowered Builder, rendered AQL, or bind -// variables. Those are renderer internals, and older lowered forms can contain -// raw expressions. The identifiers here are FHIR/schema semantics, stable -// compiler rule IDs, or compiler-generated physical-plan variables. -type CompilerExplanation struct { - Version int - SemanticPlan SemanticPlan - Selections []SelectionSemanticSpec - Lowered LoweredPlanMetadata - Compiled CompiledQueryMetadata - GenericPhysicalPlan GenericPhysicalPlanExplanation -} - -// LoweredPlanMetadata is the safe, stable portion of a lowered Builder. It -// intentionally omits named-set and derived-field internals so explain callers -// cannot couple to a renderer representation while that representation evolves. -type LoweredPlanMetadata struct { - PlanMode string - PlanProfile string - NamedSetCount int - FileSummaries bool - StudyLookup bool - RowIdentity *RowIdentity - OptimizationRules []string -} - -// CompiledQueryMetadata describes the public result shape of a successfully -// compiled request without exposing rendered AQL or bind values. -type CompiledQueryMetadata struct { - DatasetGeneration string - RootResourceType string - PlanMode string - PlanProfile string - NamedSetCount int - FileSummaries bool - StudyLookup bool - RowIdentity *RowIdentity - OptimizationRules []string - Columns []string - PivotFields []string - Limit int -} - -// GenericPhysicalPlanReason records why the current navigation-only generic -// physical-plan builder cannot faithfully represent a semantic request. -// Empty means the generic plan is available. -type GenericPhysicalPlanReason string - -const ( - GenericPhysicalPlanReasonSelections GenericPhysicalPlanReason = "SELECTIONS_NOT_SUPPORTED" - GenericPhysicalPlanReasonFilters GenericPhysicalPlanReason = "FILTERS_NOT_SUPPORTED" - GenericPhysicalPlanReasonShaping GenericPhysicalPlanReason = "SHAPING_NOT_SUPPORTED" - GenericPhysicalPlanReasonRelationshipMatch GenericPhysicalPlanReason = "RELATIONSHIP_MATCH_NOT_SUPPORTED" -) - -// GenericPhysicalPlanExplanation makes partial physical support explicit. A -// nil Plan always accompanies Available=false; callers must not infer a -// navigation plan that would silently omit fields, filters, or shaping. -type GenericPhysicalPlanExplanation struct { - Available bool - Reason GenericPhysicalPlanReason - Plan *PhysicalPlan -} - -// ExplainCompilerRequest validates, lowers, and compiles a Builder without -// performing dataset I/O. It returns an all-or-nothing inspection artifact: -// semantic, lowering, and compilation errors return the zero explanation. -// -// The generic physical-plan skeleton is intentionally optional. Requests that -// compile through the current renderer but include features the skeleton cannot -// yet represent still return successful compiled metadata with an explicit -// unavailable reason rather than a misleading partial PhysicalPlan. -func ExplainCompilerRequest(builder Builder, limit int) (CompilerExplanation, error) { - semantic, err := BuildSemanticPlan(builder) - if err != nil { - return CompilerExplanation{}, err - } - selections, err := NormalizeSelectionPlan(semantic) - if err != nil { - return CompilerExplanation{}, err - } - lowered, err := lowerSemanticBuilder(builder, semantic) - if err != nil { - return CompilerExplanation{}, err - } - compiled, err := compileRequestPlans(semantic, lowered, limit) - if err != nil { - return CompilerExplanation{}, err - } - physical, err := explainGenericPhysicalPlan(semantic, limit) - if err != nil { - return CompilerExplanation{}, err - } - - return CompilerExplanation{ - Version: CompilerExplanationVersion, - SemanticPlan: cloneCompilerSemanticPlan(semantic), - Selections: cloneCompilerSelectionSemantics(selections), - Lowered: loweredPlanMetadata(lowered), - Compiled: compiledQueryMetadata(compiled), - GenericPhysicalPlan: physical, - }, nil -} - -func loweredPlanMetadata(lowered Builder) LoweredPlanMetadata { - return LoweredPlanMetadata{ - PlanMode: planMode(lowered.PlanHint), - PlanProfile: planProfile(lowered.PlanHint), - NamedSetCount: planNamedSetCount(lowered.PlanHint), - FileSummaries: planFileSummaries(lowered.PlanHint), - StudyLookup: planStudyLookup(lowered.PlanHint), - RowIdentity: cloneRowIdentity(planRowIdentity(lowered.PlanHint)), - OptimizationRules: normalizeCompilerRules(planAppliedRules(lowered.PlanHint)), - } -} - -func compiledQueryMetadata(compiled CompiledQuery) CompiledQueryMetadata { - return CompiledQueryMetadata{ - DatasetGeneration: compiled.DatasetGeneration, - RootResourceType: compiled.RootResourceType, - PlanMode: compiled.PlanMode, - PlanProfile: compiled.PlanProfile, - NamedSetCount: compiled.NamedSetCount, - FileSummaries: compiled.FileSummaries, - StudyLookup: compiled.StudyLookup, - RowIdentity: cloneRowIdentity(compiled.RowIdentity), - OptimizationRules: normalizeCompilerRules(compiled.OptimizationRules), - Columns: cloneStrings(compiled.Columns), - PivotFields: cloneStrings(compiled.PivotFields), - Limit: compiled.Limit, - } -} - -func normalizeCompilerRules(rules []string) []string { - if len(rules) == 0 { - return nil - } - trimmed := make([]string, 0, len(rules)) - for _, rule := range rules { - if rule = strings.TrimSpace(rule); rule != "" { - trimmed = append(trimmed, rule) - } - } - if len(trimmed) == 0 { - return nil - } - return sortedUniqueStrings(trimmed) -} - -func explainGenericPhysicalPlan(semantic SemanticPlan, limit int) (GenericPhysicalPlanExplanation, error) { - if reason := genericPhysicalPlanUnavailableReason(semantic.Root); reason != "" { - return GenericPhysicalPlanExplanation{Reason: reason}, nil - } - plan, err := BuildGenericPhysicalPlan(semantic) - if err != nil { - return GenericPhysicalPlanExplanation{}, err - } - plan, err = withGenericPhysicalExecutionWindow(plan, limit) - if err != nil { - return GenericPhysicalPlanExplanation{}, err - } - planCopy := cloneCompilerPhysicalPlan(plan) - return GenericPhysicalPlanExplanation{Available: true, Plan: &planCopy}, nil -} - -func genericPhysicalPlanUnavailableReason(node SemanticNode) GenericPhysicalPlanReason { - if node.MatchMode.required() { - return GenericPhysicalPlanReasonRelationshipMatch - } - if len(node.Fields) != 0 { - return GenericPhysicalPlanReasonSelections - } - if len(node.Filters) != 0 { - return GenericPhysicalPlanReasonFilters - } - if len(node.Pivots) != 0 || len(node.Aggregates) != 0 || len(node.Slices) != 0 { - return GenericPhysicalPlanReasonShaping - } - for _, child := range node.Children { - if reason := genericPhysicalPlanUnavailableReason(child); reason != "" { - return reason - } - } - return "" -} - -func cloneCompilerSemanticPlan(plan SemanticPlan) SemanticPlan { - copy := plan - copy.AuthResourcePaths = cloneStrings(plan.AuthResourcePaths) - copy.RowIdentity = cloneRowIdentity(plan.RowIdentity) - copy.Root = cloneCompilerSemanticNode(plan.Root) - return copy -} - -func cloneCompilerSemanticNode(node SemanticNode) SemanticNode { - copy := node - copy.Fields = make([]SemanticField, len(node.Fields)) - for index, field := range node.Fields { - copy.Fields[index] = cloneCompilerSemanticField(field) - } - copy.Filters = cloneCompilerTypedFilters(node.Filters) - copy.Pivots = make([]SemanticPivot, len(node.Pivots)) - for index, pivot := range node.Pivots { - copy.Pivots[index] = cloneCompilerSemanticPivot(pivot) - } - copy.Aggregates = make([]SemanticAggregate, len(node.Aggregates)) - for index, aggregate := range node.Aggregates { - copy.Aggregates[index] = cloneCompilerSemanticAggregate(aggregate) - } - copy.Slices = make([]SemanticSlice, len(node.Slices)) - for index, slice := range node.Slices { - copy.Slices[index] = cloneCompilerSemanticSlice(slice) - } - copy.Children = make([]SemanticNode, len(node.Children)) - for index, child := range node.Children { - copy.Children[index] = cloneCompilerSemanticNode(child) - } - return copy -} - -func cloneCompilerSemanticField(field SemanticField) SemanticField { - copy := field - copy.Selector = cloneCompilerSelector(field.Selector) - copy.Fallbacks = make([]Selector, len(field.Fallbacks)) - for index, fallback := range field.Fallbacks { - copy.Fallbacks[index] = cloneCompilerSelector(fallback) - } - return copy -} - -func cloneCompilerSemanticPivot(pivot SemanticPivot) SemanticPivot { - copy := pivot - copy.ColumnSelector = cloneCompilerSelector(pivot.ColumnSelector) - copy.ValueSelector = cloneCompilerSelector(pivot.ValueSelector) - copy.Columns = cloneStrings(pivot.Columns) - return copy -} - -func cloneCompilerSemanticAggregate(aggregate SemanticAggregate) SemanticAggregate { - copy := aggregate - copy.Selector = cloneCompilerSelectorPointer(aggregate.Selector) - copy.Predicate = cloneCompilerSelectorPointer(aggregate.Predicate) - return copy -} - -func cloneCompilerSemanticSlice(slice SemanticSlice) SemanticSlice { - copy := slice - copy.Predicate = cloneCompilerSelectorPointer(slice.Predicate) - copy.Fields = make([]SemanticField, len(slice.Fields)) - for index, field := range slice.Fields { - copy.Fields[index] = cloneCompilerSemanticField(field) - } - return copy -} - -func cloneCompilerSelectionSemantics(in []SelectionSemanticSpec) []SelectionSemanticSpec { - if in == nil { - return nil - } - out := make([]SelectionSemanticSpec, len(in)) - for index, selection := range in { - copy := selection - copy.Selector = cloneCompilerSelector(selection.Selector) - copy.Fallbacks = make([]Selector, len(selection.Fallbacks)) - for fallbackIndex, fallback := range selection.Fallbacks { - copy.Fallbacks[fallbackIndex] = cloneCompilerSelector(fallback) - } - copy.RepeatedPaths = cloneStrings(selection.RepeatedPaths) - out[index] = copy - } - return out -} - -func cloneCompilerSelectorPointer(selector *Selector) *Selector { - if selector == nil { - return nil - } - copy := cloneCompilerSelector(*selector) - return © -} - -func cloneCompilerSelector(selector Selector) Selector { - copy := selector - copy.Steps = make([]SelectorStep, len(selector.Steps)) - for index, step := range selector.Steps { - stepCopy := step - if step.Index != nil { - indexCopy := *step.Index - stepCopy.Index = &indexCopy - } - copy.Steps[index] = stepCopy - } - if selector.Filter != nil { - filterCopy := *selector.Filter - copy.Filter = &filterCopy - } - return copy -} - -func cloneCompilerTypedFilters(filters []TypedFilter) []TypedFilter { - if filters == nil { - return nil - } - out := make([]TypedFilter, len(filters)) - for index, filter := range filters { - copy := filter - copy.Values = make([]FilterValue, len(filter.Values)) - for valueIndex, value := range filter.Values { - copy.Values[valueIndex] = cloneCompilerFilterValue(value) - } - out[index] = copy - } - return out -} - -func cloneCompilerFilterValue(value FilterValue) FilterValue { - copy := value - copy.String = cloneCompilerStringPointer(value.String) - if value.Code != nil { - codeCopy := *value.Code - copy.Code = &codeCopy - } - copy.Boolean = cloneCompilerBoolPointer(value.Boolean) - copy.Integer = cloneCompilerInt64Pointer(value.Integer) - copy.Decimal = cloneCompilerFloat64Pointer(value.Decimal) - copy.Date = cloneCompilerStringPointer(value.Date) - copy.DateTime = cloneCompilerStringPointer(value.DateTime) - return copy -} - -func cloneCompilerStringPointer(value *string) *string { - if value == nil { - return nil - } - copy := *value - return © -} - -func cloneCompilerBoolPointer(value *bool) *bool { - if value == nil { - return nil - } - copy := *value - return © -} - -func cloneCompilerInt64Pointer(value *int64) *int64 { - if value == nil { - return nil - } - copy := *value - return © -} - -func cloneCompilerFloat64Pointer(value *float64) *float64 { - if value == nil { - return nil - } - copy := *value - return © -} - -func cloneCompilerPhysicalPlan(plan PhysicalPlan) PhysicalPlan { - copy := plan - copy.BindVars = cloneCompilerBindVars(plan.BindVars) - copy.Operations = make([]PhysicalOperation, len(plan.Operations)) - for index, operation := range plan.Operations { - copy.Operations[index] = cloneCompilerPhysicalOperation(operation) - } - return copy -} - -func cloneCompilerBindVars(bindVars map[string]any) map[string]any { - if bindVars == nil { - return nil - } - copy := make(map[string]any, len(bindVars)) - for key, value := range bindVars { - copy[key] = cloneCompilerBindValue(value) - } - return copy -} - -func cloneCompilerBindValue(value any) any { - switch value := value.(type) { - case []string: - return cloneStrings(value) - case []any: - copy := make([]any, len(value)) - for index, item := range value { - copy[index] = cloneCompilerBindValue(item) - } - return copy - case map[string]any: - return cloneCompilerBindVars(value) - case map[string]string: - copy := make(map[string]string, len(value)) - for key, item := range value { - copy[key] = item - } - return copy - default: - return value - } -} - -func cloneCompilerPhysicalOperation(operation PhysicalOperation) PhysicalOperation { - copy := operation - if operation.RootScan != nil { - rootScanCopy := *operation.RootScan - copy.RootScan = &rootScanCopy - } - if operation.Traversal != nil { - traversalCopy := *operation.Traversal - copy.Traversal = &traversalCopy - } - if operation.Filter != nil { - filterCopy := *operation.Filter - filterCopy.Predicate = cloneCompilerPhysicalPredicate(operation.Filter.Predicate) - copy.Filter = &filterCopy - } - if operation.DerivedLet != nil { - derivedCopy := *operation.DerivedLet - derivedCopy.Inputs = make([]PhysicalValue, len(operation.DerivedLet.Inputs)) - for index, input := range operation.DerivedLet.Inputs { - derivedCopy.Inputs[index] = cloneCompilerPhysicalValue(input) - } - copy.DerivedLet = &derivedCopy - } - if operation.Sort != nil { - sortCopy := *operation.Sort - sortCopy.Value = cloneCompilerPhysicalValue(operation.Sort.Value) - copy.Sort = &sortCopy - } - if operation.Limit != nil { - limitCopy := *operation.Limit - copy.Limit = &limitCopy - } - if operation.Return != nil { - returnCopy := *operation.Return - returnCopy.Projections = make([]PhysicalProjection, len(operation.Return.Projections)) - for index, projection := range operation.Return.Projections { - projectionCopy := projection - projectionCopy.Value = cloneCompilerPhysicalValue(projection.Value) - returnCopy.Projections[index] = projectionCopy - } - copy.Return = &returnCopy - } - return copy -} - -func cloneCompilerPhysicalPredicate(predicate PhysicalPredicate) PhysicalPredicate { - copy := predicate - copy.Left = cloneCompilerPhysicalValue(predicate.Left) - if predicate.Right != nil { - rightCopy := cloneCompilerPhysicalValue(*predicate.Right) - copy.Right = &rightCopy - } - return copy -} - -func cloneCompilerPhysicalValue(value PhysicalValue) PhysicalValue { - copy := value - copy.Path = cloneStrings(value.Path) - return copy -} diff --git a/internal/dataframe/compiler_explanation_test.go b/internal/dataframe/compiler_explanation_test.go deleted file mode 100644 index a89beed..0000000 --- a/internal/dataframe/compiler_explanation_test.go +++ /dev/null @@ -1,218 +0,0 @@ -package dataframe - -import ( - "reflect" - "testing" -) - -func TestExplainCompilerRequestIncludesNavigationOnlyGenericPhysicalPlan(t *testing.T) { - explanation, err := ExplainCompilerRequest(Builder{ - Project: "P1", - AuthResourcePaths: []string{"/programs/p1"}, - RootResourceType: "Patient", - }, 25) - if err != nil { - t.Fatal(err) - } - if explanation.Version != CompilerExplanationVersion { - t.Fatalf("explanation version = %d", explanation.Version) - } - if explanation.SemanticPlan.RowIdentity == nil || explanation.SemanticPlan.RowIdentity.Grain != RowGrainPatient { - t.Fatalf("semantic row identity = %#v", explanation.SemanticPlan.RowIdentity) - } - if !explanation.GenericPhysicalPlan.Available || explanation.GenericPhysicalPlan.Reason != "" || explanation.GenericPhysicalPlan.Plan == nil { - t.Fatalf("generic physical plan availability = %#v", explanation.GenericPhysicalPlan) - } - if err := explanation.GenericPhysicalPlan.Plan.Validate(); err != nil { - t.Fatalf("explained generic physical plan does not validate: %v", err) - } - if got := explanation.GenericPhysicalPlan.Plan.BindVars["root_collection"]; got != "Patient" { - t.Fatalf("root collection = %#v", got) - } - operations := explanation.GenericPhysicalPlan.Plan.Operations - if len(operations) < 8 || operations[5].Kind != PhysicalSortOp || operations[6].Kind != PhysicalLimitOp || explanation.GenericPhysicalPlan.Plan.BindVars[genericPhysicalExecutionLimitBind] != 25 { - t.Fatalf("explained physical execution window = %#v / %#v", operations, explanation.GenericPhysicalPlan.Plan.BindVars) - } - if !reflect.DeepEqual(explanation.Compiled.Columns, []string{"_key"}) || explanation.Compiled.Limit != 25 { - t.Fatalf("compiled metadata = %#v", explanation.Compiled) - } -} - -func TestExplainCompilerRequestReportsSelectionPhysicalUnavailabilityAfterCompile(t *testing.T) { - explanation, err := ExplainCompilerRequest(Builder{ - Project: "P1", - RootResourceType: "Patient", - Fields: []FieldSelect{{ - Name: "gender", FieldRef: "Patient.gender", Select: "gender", - }}, - }, 5) - if err != nil { - t.Fatal(err) - } - if explanation.GenericPhysicalPlan.Available || explanation.GenericPhysicalPlan.Plan != nil { - t.Fatalf("selection request unexpectedly received generic physical plan: %#v", explanation.GenericPhysicalPlan) - } - if explanation.GenericPhysicalPlan.Reason != GenericPhysicalPlanReasonSelections { - t.Fatalf("physical reason = %q", explanation.GenericPhysicalPlan.Reason) - } - if !reflect.DeepEqual(explanation.Compiled.Columns, []string{"_key", "gender"}) { - t.Fatalf("compiled columns = %#v", explanation.Compiled.Columns) - } - if len(explanation.Selections) != 1 || explanation.Selections[0].Alias != "root.gender" || explanation.Selections[0].Projection != ProjectionScalar { - t.Fatalf("normalized selections = %#v", explanation.Selections) - } -} - -func TestExplainCompilerRequestCarriesFilterRowGrainAndOptimizerProvenance(t *testing.T) { - female := "female" - explanation, err := ExplainCompilerRequest(Builder{ - Project: "P1", - RootResourceType: "Patient", - RowGrain: RowGrainPatient, - Filters: []TypedFilter{{ - FieldRef: "Patient.gender", Selector: "gender", FieldKind: FilterString, Operator: FilterEquals, - Values: []FilterValue{{Kind: FilterString, String: &female}}, - }}, - }, 0) - if err != nil { - t.Fatal(err) - } - for _, identity := range []*RowIdentity{ - explanation.SemanticPlan.RowIdentity, - explanation.Lowered.RowIdentity, - explanation.Compiled.RowIdentity, - } { - if identity == nil || identity.Grain != RowGrainPatient || !reflect.DeepEqual(identity.Fields, []string{"project", "_key"}) { - t.Fatalf("row identity provenance = %#v", identity) - } - } - if explanation.Lowered.PlanProfile != "generic_fhir_graph" || explanation.Compiled.PlanProfile != "generic_fhir_graph" { - t.Fatalf("plan profile provenance = %#v / %#v", explanation.Lowered, explanation.Compiled) - } - if !reflect.DeepEqual(explanation.Lowered.OptimizationRules, []string{OptimizerRuleFilterPushdown}) || - !reflect.DeepEqual(explanation.Compiled.OptimizationRules, []string{OptimizerRuleFilterPushdown}) { - t.Fatalf("optimizer provenance = %#v / %#v", explanation.Lowered.OptimizationRules, explanation.Compiled.OptimizationRules) - } - if explanation.GenericPhysicalPlan.Available || explanation.GenericPhysicalPlan.Reason != GenericPhysicalPlanReasonFilters { - t.Fatalf("filter request physical availability = %#v", explanation.GenericPhysicalPlan) - } -} - -func TestExplainCompilerRequestReportsRequiredRelationshipPhysicalUnavailability(t *testing.T) { - explanation, err := ExplainCompilerRequest(Builder{ - Project: "P1", - RootResourceType: "Patient", - Traversals: []TraversalStep{{ - Label: "subject_Patient", ToResourceType: "Condition", Alias: "diagnosis", MatchMode: TraversalMatchRequired, - }}, - }, 5) - if err != nil { - t.Fatal(err) - } - if explanation.GenericPhysicalPlan.Available || explanation.GenericPhysicalPlan.Reason != GenericPhysicalPlanReasonRelationshipMatch || explanation.GenericPhysicalPlan.Plan != nil { - t.Fatalf("required relationship physical availability = %#v", explanation.GenericPhysicalPlan) - } - if !reflect.DeepEqual(explanation.Compiled.OptimizationRules, []string{OptimizerRuleRelationshipSemiJoin}) { - t.Fatalf("required relationship optimizer provenance = %#v", explanation.Compiled.OptimizationRules) - } -} - -func TestExplainCompilerRequestReturnsDeterministicDefensiveCopies(t *testing.T) { - female := "female" - builder := Builder{ - Project: "P1", - AuthResourcePaths: []string{"/programs/p1"}, - RootResourceType: "Patient", - Filters: []TypedFilter{{ - FieldRef: "Patient.gender", Selector: "gender", FieldKind: FilterString, Operator: FilterEquals, - Values: []FilterValue{{Kind: FilterString, String: &female}}, - }}, - Fields: []FieldSelect{ - {Name: "z_gender", FieldRef: "Patient.gender", Select: "gender"}, - {Name: "a_birth_date", FieldRef: "Patient.birth_date", Select: "birthDate"}, - }, - } - first, err := ExplainCompilerRequest(builder, 3) - if err != nil { - t.Fatal(err) - } - second, err := ExplainCompilerRequest(builder, 3) - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(first, second) { - t.Fatalf("same request produced non-deterministic explanations:\nfirst=%#v\nsecond=%#v", first, second) - } - if got := []string{first.Selections[0].Alias, first.Selections[1].Alias}; !reflect.DeepEqual(got, []string{"root.a_birth_date", "root.z_gender"}) { - t.Fatalf("selection order = %#v", got) - } - - *first.SemanticPlan.Root.Filters[0].Values[0].String = "mutated" - first.SemanticPlan.AuthResourcePaths[0] = "mutated" - first.Selections[0].Selector.Steps[0].Field = "mutated" - first.Lowered.RowIdentity.Fields[0] = "mutated" - first.Compiled.Columns[0] = "mutated" - if *builder.Filters[0].Values[0].String != "female" || builder.AuthResourcePaths[0] != "/programs/p1" { - t.Fatalf("explanation mutation escaped into input builder: %#v", builder) - } - if second.SemanticPlan.Root.Fields[1].Selector.Steps[0].Field == "mutated" || - second.Compiled.Columns[0] != "_key" || - second.Lowered.RowIdentity.Fields[0] != "project" { - t.Fatalf("explanation mutation escaped into another result: %#v", second) - } - - rootOnly, err := ExplainCompilerRequest(Builder{Project: "P1", RootResourceType: "Patient", AuthResourcePaths: []string{"/programs/p1"}}, 1) - if err != nil { - t.Fatal(err) - } - rootOnly.GenericPhysicalPlan.Plan.BindVars["project"] = "mutated" - rootOnly.GenericPhysicalPlan.Plan.Operations[0].RootScan.Variable = "mutated" - freshRootOnly, err := ExplainCompilerRequest(Builder{Project: "P1", RootResourceType: "Patient", AuthResourcePaths: []string{"/programs/p1"}}, 1) - if err != nil { - t.Fatal(err) - } - if freshRootOnly.GenericPhysicalPlan.Plan.BindVars["project"] != "P1" || freshRootOnly.GenericPhysicalPlan.Plan.Operations[0].RootScan.Variable != "root" { - t.Fatalf("physical plan mutation escaped into a fresh result: %#v", freshRootOnly.GenericPhysicalPlan.Plan) - } -} - -func TestExplainCompilerRequestReturnsNoPartialResultOnInvalidInput(t *testing.T) { - tests := []struct { - name string - builder Builder - }{ - { - name: "semantic validation", - builder: Builder{ - Project: "P1", - RootResourceType: "Patient", - Fields: []FieldSelect{{Name: "bad", Select: "identifier[nope]"}}, - }, - }, - { - // Semantic aliases are valid FHIR graph identifiers, but these two - // distinct aliases collide in the current lowered AQL identifier - // scheme. This exercises the all-or-nothing lower/compile boundary. - name: "lowering validation", - builder: Builder{ - Project: "P1", - RootResourceType: "Specimen", - Traversals: []TraversalStep{ - {Label: "subject_Specimen", ToResourceType: "DocumentReference", Alias: "file-a"}, - {Label: "subject_Specimen", ToResourceType: "DocumentReference", Alias: "file_a"}, - }, - }, - }, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - explanation, err := ExplainCompilerRequest(test.builder, 1) - if err == nil { - t.Fatal("invalid request unexpectedly explained") - } - if !reflect.DeepEqual(explanation, CompilerExplanation{}) { - t.Fatalf("invalid request returned partial explanation: %#v", explanation) - } - }) - } -} diff --git a/internal/dataframe/dataframe_test.go b/internal/dataframe/dataframe_test.go deleted file mode 100644 index 01ca85c..0000000 --- a/internal/dataframe/dataframe_test.go +++ /dev/null @@ -1,456 +0,0 @@ -package dataframe - -import ( - "context" - "slices" - "strings" - "testing" - - "github.com/calypr/loom/internal/authscope" - "github.com/calypr/loom/internal/catalog" - arangostore "github.com/calypr/loom/internal/store/arango" -) - -func TestParseSelector(t *testing.T) { - sel, err := ParseSelector(`identifier[].value where system contains "case_id"`) - if err != nil { - t.Fatal(err) - } - if got := sel.CanonicalPath(); got != "identifier[].value" { - t.Fatalf("canonical path = %q", got) - } - if sel.Filter == nil || sel.Filter.Field != "system" || sel.Filter.Needle != "case_id" { - t.Fatalf("unexpected filter: %#v", sel.Filter) - } -} - -func TestCompileRejectsNonLoweredBuilder(t *testing.T) { - _, err := Compile(Builder{ - Project: "P1", - RootResourceType: "Patient", - Fields: []FieldSelect{{Name: "gender", Select: "gender"}}, - }, 25) - if err == nil || !strings.Contains(err.Error(), "unsupported dataframe query shape") { - t.Fatalf("expected unsupported lowering error, got %v", err) - } -} - -func TestLowerGraphQLBuilderUsesGenericCompilerForComplexPatientGraph(t *testing.T) { - builder := Builder{ - Project: "P1", - RootResourceType: "Patient", - Fields: []FieldSelect{{Name: "gender", Select: "gender"}}, - Traversals: []TraversalStep{ - {Label: "subject_Patient", ToResourceType: "Condition", Alias: "condition", Fields: []FieldSelect{{Name: "id", Select: "id"}}}, - {Label: "subject_Patient", ToResourceType: "ResearchSubject", Alias: "research_subject", Fields: []FieldSelect{{Name: "status", Select: "status"}}}, - { - Label: "subject_Patient", - ToResourceType: "Specimen", - Alias: "specimen", - Fields: []FieldSelect{{Name: "type_display", Select: "type.coding[].display"}}, - Traversals: []TraversalStep{ - {Label: "subject_Specimen", ToResourceType: "DocumentReference", Alias: "specimen_file", Fields: []FieldSelect{{Name: "file_name", Select: "content[].attachment.title"}}}, - { - Label: "member_entity_Specimen", - ToResourceType: "Group", - Alias: "group", - Traversals: []TraversalStep{ - {Label: "subject_Group", ToResourceType: "DocumentReference", Alias: "group_file", Fields: []FieldSelect{{Name: "id", Select: "id"}}}, - }, - }, - }, - }, - {Label: "subject_Patient", ToResourceType: "MedicationAdministration", Alias: "treatment", Fields: []FieldSelect{{Name: "status", Select: "status"}}}, - }, - } - planned, err := lowerGraphQLBuilder(builder) - if err != nil { - t.Fatalf("expected generic graph lowering, got %v", err) - } - if !usesLoweredBuilder(planned) { - t.Fatal("expected planner to return lowered builder") - } - if planned.PlanHint == nil || planned.PlanHint.Profile != "generic_fhir_graph" { - t.Fatalf("unexpected plan hint: %#v", planned.PlanHint) - } - if len(planned.DerivedFields) == 0 { - t.Fatalf("expected lowered derived fields, got %#v", planned.DerivedFields) - } - if containsDerivedField(planned.DerivedFields, "recipe") { - t.Fatalf("did not expect canned recipe field in lowered builder: %#v", planned.DerivedFields) - } - for _, expectedSet := range []string{"generic_root_subject_Patient_neighbors_set", "generic_condition_set", "generic_specimen_set", "generic_group_set"} { - if !containsNamedSet(planned.Sets, expectedSet) { - t.Fatalf("expected lowered set %q, got %#v", expectedSet, planned.Sets) - } - } -} - -func TestLowerGraphQLBuilderUsesGenericPlanForSimpleTraversal(t *testing.T) { - builder := Builder{ - Project: "P1", - RootResourceType: "Patient", - Traversals: []TraversalStep{ - {Label: "subject_Patient", ToResourceType: "Specimen", Alias: "specimen"}, - }, - } - planned, err := lowerGraphQLBuilder(builder) - if err != nil { - t.Fatalf("lowerGraphQLBuilder() error = %v", err) - } - if planned.PlanHint == nil || planned.PlanHint.Profile != "generic_fhir_graph" { - t.Fatalf("expected generic plan, got %#v", planned.PlanHint) - } -} - -func TestLowerGraphQLBuilderKeepsDocumentReferenceSelectorsInGenericFHIR(t *testing.T) { - builder := Builder{ - Project: "P1", - RootResourceType: "Patient", - Traversals: []TraversalStep{ - { - Label: "subject_Patient", - ToResourceType: "Specimen", - Alias: "specimen", - Traversals: []TraversalStep{ - { - Label: "subject_Specimen", - ToResourceType: "DocumentReference", - Alias: "specimen_file", - Fields: []FieldSelect{ - {Name: "data_category", Select: `category[].coding[].display where system contains "data_category"`}, - }, - }, - }, - }, - }, - } - planned, err := lowerGraphQLBuilder(builder) - if err != nil { - t.Fatalf("expected generic lowering, got %v", err) - } - if planned.PlanHint == nil || planned.PlanHint.Profile != "generic_fhir_graph" { - t.Fatalf("expected generic plan, got %#v", planned.PlanHint) - } - if !containsDerivedFieldWithSelect(planned.DerivedFields, "specimen_file__data_category", `category[].coding[].display where system contains "data_category"`) { - t.Fatalf("expected raw FHIR selector, got %#v", planned.DerivedFields) - } -} - -func TestLowerGraphQLBuilderSupportsExpandedPatientRootFamily(t *testing.T) { - builder := Builder{ - Project: "P1", - RootResourceType: "Patient", - Fields: []FieldSelect{{Name: "gender", Select: "gender"}}, - Traversals: []TraversalStep{ - {Label: "subject_Patient", ToResourceType: "Observation", Alias: "subject_observation", Fields: []FieldSelect{{Name: "status", Select: "status"}}}, - {Label: "focus_Patient", ToResourceType: "Observation", Alias: "focus_observation", Fields: []FieldSelect{{Name: "status", Select: "status"}}}, - {Label: "subject_Patient", ToResourceType: "ImagingStudy", Alias: "imaging_study", Fields: []FieldSelect{{Name: "status", Select: "status"}}}, - { - Label: "member_entity_Patient", - ToResourceType: "Group", - Alias: "patient_group", - Traversals: []TraversalStep{ - {Label: "subject_Group", ToResourceType: "DocumentReference", Alias: "group_file", Fields: []FieldSelect{{Name: "file_name", Select: "content[].attachment.title"}}}, - }, - }, - }, - } - planned, err := lowerGraphQLBuilder(builder) - if err != nil { - t.Fatalf("expected expanded patient-root family to lower, got %v", err) - } - for _, expectedSet := range []string{ - "generic_subject_observation_set", - "generic_focus_observation_set", - "generic_imaging_study_set", - "generic_patient_group_set", - "generic_group_file_set", - } { - if !containsNamedSet(planned.Sets, expectedSet) { - t.Fatalf("expected lowered set %q, got %#v", expectedSet, planned.Sets) - } - } -} - -func TestCompilePrecomputesPivotMapForDerivedPivots(t *testing.T) { - builder := Builder{ - Project: "P1", - RootResourceType: "Patient", - Fields: []FieldSelect{{Name: "gender", Select: "gender"}}, - Traversals: []TraversalStep{ - { - Label: "subject_Patient", - ToResourceType: "Condition", - Alias: "condition", - Aggregates: []AggregateSelect{{Name: "condition_count", Operation: "COUNT"}}, - }, - { - Label: "subject_Patient", - ToResourceType: "Observation", - Alias: "observation", - Pivots: []PivotSelect{ - { - Name: "observation_values", - ColumnSelect: "code.coding[].display", - ValueSelect: "valueQuantity.value", - Columns: []string{"Tumor Purity", "Adenocarcinoma"}, - }, - }, - }, - }, - } - - planned, err := lowerGraphQLBuilder(builder) - if err != nil { - t.Fatalf("expected supported lowering, got %v", err) - } - compiled, err := Compile(planned, 25) - if err != nil { - t.Fatalf("compile failed: %v", err) - } - if !strings.Contains(compiled.Query, "LET __pivot_map_0 = MERGE(") { - t.Fatalf("expected precomputed pivot map, got query:\n%s", compiled.Query) - } - if !strings.Contains(compiled.Query, `"observation__observation_values": MERGE(`) { - t.Fatalf("expected pivot output to be a sparse object column, got query:\n%s", compiled.Query) - } - if !strings.Contains(compiled.Query, "FILTER LENGTH(__values) > 0") { - t.Fatalf("expected pivot query to suppress empty-value keys, got query:\n%s", compiled.Query) - } - if !strings.Contains(compiled.Query, "RETURN { [__key]: FIRST(__flat_values) }") { - t.Fatalf("expected pivot query to emit scalar key/value pairs, got query:\n%s", compiled.Query) - } - if !strings.Contains(compiled.Query, `FILTER HAS(__pivot_map_0, __key)`) { - t.Fatalf("expected pivot projection to keep only requested keys that exist, got query:\n%s", compiled.Query) - } - if !slices.Contains(compiled.PivotFields, "observation__observation_values") { - t.Fatalf("expected derived pivot field to be marked flattenable, got %#v", compiled.PivotFields) - } -} - -func TestLowerGraphQLBuilderPreservesUnrestrictedAuthScope(t *testing.T) { - builder := Builder{ - Project: "P1", - RootResourceType: "Patient", - Fields: []FieldSelect{{Name: "gender", Select: "gender"}}, - Traversals: []TraversalStep{ - {Label: "subject_Patient", ToResourceType: "Condition", Alias: "condition", Aggregates: []AggregateSelect{{Name: "condition_count", Operation: "COUNT"}}}, - {Label: "subject_Patient", ToResourceType: "Specimen", Alias: "specimen", Aggregates: []AggregateSelect{{Name: "specimen_count", Operation: "COUNT"}}}, - }, - } - - planned, err := lowerGraphQLBuilder(builder) - if err != nil { - t.Fatalf("expected structural lowering to match, got %v", err) - } - if planned.AuthResourcePaths != nil { - t.Fatalf("expected unrestricted auth scope to stay nil, got %#v", planned.AuthResourcePaths) - } - - compiled, err := Compile(planned, 3) - if err != nil { - t.Fatal(err) - } - if got := compiled.BindVars["auth_resource_paths_unrestricted"]; got != true { - t.Fatalf("expected unrestricted auth bind var to be true, got %#v", got) - } -} - -func TestServiceRunsGenericSimpleQuery(t *testing.T) { - svc := NewService(ServiceConfig{ - ConnectionOptions: arangostore.ConnectionOptions{}, - DiscoverReferences: func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { - return []catalog.PopulatedReference{{FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 1}}, nil - }, - DiscoverFields: func(ctx context.Context, opts catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { - if opts.PivotOnly { - return []catalog.PopulatedField{}, nil - } - if opts.ResourceType == "Patient" { - return []catalog.PopulatedField{{ResourceType: "Patient", Path: "gender", Kind: "scalar"}}, nil - } - return []catalog.PopulatedField{{ResourceType: "Specimen", Path: "type.coding[].display", Kind: "scalar"}}, nil - }, - ExecuteRows: func(ctx context.Context, opts ExecuteQueryOptions, query string, bindVars map[string]any, visit func(map[string]any) error) error { - return visit(map[string]any{"_key": "p1", "gender": "female", "specimen__specimen_type": []string{"Blood"}}) - }, - }) - ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{ - Projects: []string{"P1"}, - AuthResourcePaths: []string{"pathA"}, - }) - result, err := svc.Run(ctx, RunRequest{ - Builder: Builder{ - Project: "P1", - RootResourceType: "Patient", - AuthResourcePaths: []string{"pathA"}, - Fields: []FieldSelect{{Name: "gender", Select: "gender"}}, - Traversals: []TraversalStep{{ - Label: "subject_Patient", - ToResourceType: "Specimen", - Alias: "specimen", - Fields: []FieldSelect{{Name: "specimen_type", Select: "type.coding[].display"}}, - }}, - }, - }) - if err != nil { - t.Fatalf("Run() error = %v", err) - } - if result.RowCount != 1 || !slices.Contains(result.Columns, "specimen__specimen_type") { - t.Fatalf("unexpected generic result: %#v", result) - } -} - -func TestServiceRunCaseAssayRecipe(t *testing.T) { - svc := NewService(ServiceConfig{ - ConnectionOptions: arangostore.ConnectionOptions{}, - DiscoverReferences: func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { - switch opts.NodeType { - case "Patient": - return []catalog.PopulatedReference{ - {FromType: "Patient", Label: "subject_Patient", ToType: "Condition", EdgeCount: 1}, - {FromType: "Patient", Label: "subject_Patient", ToType: "ResearchSubject", EdgeCount: 1}, - {FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 1}, - {FromType: "Patient", Label: "subject_Patient", ToType: "MedicationAdministration", EdgeCount: 1}, - }, nil - case "Specimen": - return []catalog.PopulatedReference{ - {FromType: "Specimen", Label: "subject_Specimen", ToType: "DocumentReference", EdgeCount: 1}, - {FromType: "Specimen", Label: "member_entity_Specimen", ToType: "Group", EdgeCount: 1}, - }, nil - case "Group": - return []catalog.PopulatedReference{ - {FromType: "Group", Label: "subject_Group", ToType: "DocumentReference", EdgeCount: 1}, - }, nil - default: - return []catalog.PopulatedReference{}, nil - } - }, - DiscoverFields: func(ctx context.Context, opts catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { - return []catalog.PopulatedField{ - {ResourceType: opts.ResourceType, Path: "gender", Kind: "scalar"}, - {ResourceType: opts.ResourceType, Path: "id", Kind: "scalar"}, - {ResourceType: opts.ResourceType, Path: "status", Kind: "scalar"}, - }, nil - }, - ExecuteRows: func(ctx context.Context, opts ExecuteQueryOptions, query string, bindVars map[string]any, visit func(map[string]any) error) error { - if !strings.Contains(query, "LET generic_root_subject_Patient_neighbors_set") || !strings.Contains(query, "LET generic_condition_set") || !strings.Contains(query, "LET generic_group_set") { - t.Fatalf("expected advanced planned query, got:\n%s", query) - } - if strings.Contains(query, `"recipe"`) { - t.Fatalf("unexpected canned recipe field in lowered query:\n%s", query) - } - return visit(map[string]any{"_key": "p1", "gender": "female"}) - }, - }) - ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{ - Projects: []string{"P1"}, - AuthResourcePaths: []string{"pathA"}, - }) - _, err := svc.Run(ctx, RunRequest{ - Builder: Builder{ - Project: "P1", - RootResourceType: "Patient", - Fields: []FieldSelect{{Name: "gender", Select: "gender"}}, - Traversals: []TraversalStep{ - {Label: "subject_Patient", ToResourceType: "Condition", Alias: "condition", Fields: []FieldSelect{{Name: "id", Select: "id"}}}, - {Label: "subject_Patient", ToResourceType: "ResearchSubject", Alias: "research_subject", Fields: []FieldSelect{{Name: "status", Select: "status"}}}, - { - Label: "subject_Patient", - ToResourceType: "Specimen", - Alias: "specimen", - Traversals: []TraversalStep{ - {Label: "subject_Specimen", ToResourceType: "DocumentReference", Alias: "specimen_file", Fields: []FieldSelect{{Name: "id", Select: "id"}}}, - { - Label: "member_entity_Specimen", - ToResourceType: "Group", - Alias: "group", - Traversals: []TraversalStep{ - {Label: "subject_Group", ToResourceType: "DocumentReference", Alias: "group_file", Fields: []FieldSelect{{Name: "id", Select: "id"}}}, - }, - }, - }, - }, - {Label: "subject_Patient", ToResourceType: "MedicationAdministration", Alias: "treatment", Fields: []FieldSelect{{Name: "status", Select: "status"}}}, - }, - }, - }) - if err != nil { - t.Fatal(err) - } -} - -func containsNamedSet(sets []NamedSet, want string) bool { - for _, set := range sets { - if set.Name == want { - return true - } - } - return false -} - -func containsDerivedField(fields []DerivedField, want string) bool { - for _, field := range fields { - if field.Name == want { - return true - } - } - return false -} - -func containsDerivedFieldWithSelect(fields []DerivedField, wantName, wantSelect string) bool { - for _, field := range fields { - if field.Name == wantName && field.Select == wantSelect { - return true - } - } - return false -} - -func TestServiceRunsGenericRootOnlyQuery(t *testing.T) { - svc := NewService(ServiceConfig{ - ConnectionOptions: arangostore.ConnectionOptions{}, - DiscoverReferences: func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { - return []catalog.PopulatedReference{}, nil - }, - DiscoverFields: func(ctx context.Context, opts catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { - return []catalog.PopulatedField{{ResourceType: "Patient", Path: "gender", Kind: "scalar"}}, nil - }, - ExecuteRows: func(ctx context.Context, opts ExecuteQueryOptions, query string, bindVars map[string]any, visit func(map[string]any) error) error { - return visit(map[string]any{"_key": "p1", "gender": "female"}) - }, - }) - result, err := svc.Run(context.Background(), RunRequest{ - Builder: Builder{ - Project: "P1", - RootResourceType: "Patient", - Fields: []FieldSelect{{Name: "gender", Select: "gender"}}, - }, - }) - if err != nil { - t.Fatalf("Run() error = %v", err) - } - if result.RowCount != 1 || !slices.Contains(result.Columns, "gender") { - t.Fatalf("unexpected generic result: %#v", result) - } -} - -func TestServiceRejectsUnauthorizedAuthPath(t *testing.T) { - svc := NewService(ServiceConfig{ConnectionOptions: arangostore.ConnectionOptions{}}) - ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{ - Projects: []string{"P1"}, - AuthResourcePaths: []string{"pathA"}, - }) - _, err := svc.Run(ctx, RunRequest{ - Builder: Builder{ - Project: "P1", - RootResourceType: "Patient", - AuthResourcePaths: []string{"pathB"}, - Fields: []FieldSelect{{Name: "gender", Select: "gender"}}, - }, - }) - if err == nil { - t.Fatal("expected auth path error") - } -} diff --git a/internal/dataframe/dataset_generation_test.go b/internal/dataframe/dataset_generation_test.go index 150cc63..6ff6367 100644 --- a/internal/dataframe/dataset_generation_test.go +++ b/internal/dataframe/dataset_generation_test.go @@ -31,10 +31,8 @@ func TestDatasetGenerationCompilesRootTraversalAndRequiredMatch(t *testing.T) { } for _, want := range []string{ "root.dataset_generation == @dataset_generation", - "__edge.dataset_generation == @dataset_generation", - "__node.dataset_generation == @dataset_generation", - "__match_edge_0_0.dataset_generation == @dataset_generation", - "__match_0_0.dataset_generation == @dataset_generation", + "required_0_edge_0.dataset_generation == @dataset_generation", + "required_0_node_0.dataset_generation == @dataset_generation", } { if !strings.Contains(compiled.Query, want) { t.Fatalf("compiled query is missing generation predicate %q:\n%s", want, compiled.Query) diff --git a/internal/dataframe/execution.go b/internal/dataframe/execution.go index 88ceeb9..a8eecc1 100644 --- a/internal/dataframe/execution.go +++ b/internal/dataframe/execution.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "sort" + "time" ) func (s *Service) runQuery(ctx context.Context, compiled CompiledQuery) (*Result, error) { @@ -16,9 +17,10 @@ func (s *Service) runQuery(ctx context.Context, compiled CompiledQuery) (*Result return nil, err } return &Result{ - Columns: streamed.Columns, - Rows: rows, - RowCount: streamed.RowCount, + Columns: streamed.Columns, + Rows: rows, + RowCount: streamed.RowCount, + Diagnostics: streamed.Diagnostics, }, nil } @@ -30,11 +32,21 @@ func (s *Service) Stream(ctx context.Context, req RunRequest, visit func(map[str if visit == nil { return StreamResult{}, fmt.Errorf("row visitor is required") } - compiled, err := s.compileRunRequest(ctx, req) + started := time.Now() + compiled, diagnostics, err := s.compileRunRequestWithDiagnostics(ctx, req) if err != nil { return StreamResult{}, err } - return s.streamQuery(ctx, compiled, visit) + result, err := s.streamQuery(ctx, compiled, visit) + if err != nil { + return result, err + } + diagnostics.ArangoQuery = result.Diagnostics.ArangoQuery + diagnostics.RowMaterialization = result.Diagnostics.RowMaterialization + diagnostics.ResultAssembly = result.Diagnostics.ResultAssembly + diagnostics.Total = time.Since(started) + result.Diagnostics = diagnostics + return result, nil } func (s *Service) streamQuery(ctx context.Context, compiled CompiledQuery, visit func(map[string]any) error) (StreamResult, error) { @@ -49,10 +61,14 @@ func (s *Service) streamQuery(ctx context.Context, compiled CompiledQuery, visit extraColumns := map[string]struct{}{} rowCount := 0 + var rowMaterialization time.Duration + queryStarted := time.Now() err := s.executeRows(ctx, ExecuteQueryOptions{ ConnectionOptions: s.connOpts, BatchSize: 1000, }, compiled.Query, compiled.BindVars, func(row map[string]any) error { + rowStarted := time.Now() + defer func() { rowMaterialization += time.Since(rowStarted) }() flatRow := flattenPivotFields(cloneRow(row), compiled.PivotFields) for key := range flatRow { if _, ok := seenColumns[key]; ok { @@ -67,6 +83,12 @@ func (s *Service) streamQuery(ctx context.Context, compiled CompiledQuery, visit rowCount++ return nil }) + queryElapsed := time.Since(queryStarted) + arangoQuery := queryElapsed - rowMaterialization + if arangoQuery < 0 { + arangoQuery = 0 + } + assemblyStarted := time.Now() newColumns := make([]string, 0, len(extraColumns)) for column := range extraColumns { newColumns = append(newColumns, column) @@ -76,6 +98,11 @@ func (s *Service) streamQuery(ctx context.Context, compiled CompiledQuery, visit result := StreamResult{ Columns: columns, RowCount: rowCount, + Diagnostics: QueryDiagnostics{ + ArangoQuery: arangoQuery, + RowMaterialization: rowMaterialization, + ResultAssembly: time.Since(assemblyStarted), + }, } if err != nil { return result, err diff --git a/internal/dataframe/filter.go b/internal/dataframe/filter.go index 3feffd5..987a3f3 100644 --- a/internal/dataframe/filter.go +++ b/internal/dataframe/filter.go @@ -6,7 +6,7 @@ import ( "strings" "time" - "github.com/calypr/loom/internal/fhir" + fhir "github.com/calypr/loom/fhirstructs" ) // FilterOperator is the closed set of operations accepted by the typed filter diff --git a/internal/dataframe/filter_compile.go b/internal/dataframe/filter_compile.go deleted file mode 100644 index 85c4d21..0000000 --- a/internal/dataframe/filter_compile.go +++ /dev/null @@ -1,134 +0,0 @@ -package dataframe - -import ( - "fmt" - "strings" -) - -func (c *compiler) compileTypedFilters(payloadVar string, filters []TypedFilter) (string, error) { - if len(filters) == 0 { - return "true", nil - } - parts := make([]string, 0, len(filters)) - for _, filter := range filters { - expr, err := c.compileTypedFilter(payloadVar, filter) - if err != nil { - return "", err - } - parts = append(parts, "("+expr+")") - } - return strings.Join(parts, " AND "), nil -} - -func (c *compiler) compileTypedFilter(payloadVar string, filter TypedFilter) (string, error) { - if err := filter.Validate(); err != nil { - return "", err - } - if strings.TrimSpace(filter.Selector) == "" { - return "", fmt.Errorf("filter %q requires a resolved selector", filter.FieldRef) - } - selector, err := ParseSelector(filter.Selector) - if err != nil { - return "", fmt.Errorf("filter %q selector: %w", filter.FieldRef, err) - } - values := compileSelectorArrayExpr(payloadVar, selector, c) - if filter.Operator == FilterExists { - return fmt.Sprintf("LENGTH(%s) > 0", values), nil - } - if filter.Operator == FilterMissing { - return fmt.Sprintf("LENGTH(%s) == 0", values), nil - } - - match, err := c.compileTypedFilterMatch("__value", filter) - if err != nil { - return "", err - } - quantifier := filter.Quantifier - if !filter.Repeated { - quantifier = QuantifierAny - } - switch quantifier { - case QuantifierAny: - return fmt.Sprintf("LENGTH(FOR __value IN %s FILTER %s LIMIT 1 RETURN 1) > 0", values, match), nil - case QuantifierNone: - return fmt.Sprintf("LENGTH(FOR __value IN %s FILTER %s LIMIT 1 RETURN 1) == 0", values, match), nil - case QuantifierAll: - return fmt.Sprintf("LENGTH(%s) > 0 AND LENGTH(FOR __value IN %s FILTER NOT (%s) LIMIT 1 RETURN 1) == 0", values, values, match), nil - default: - return "", fmt.Errorf("filter %q has unsupported quantifier %q", filter.FieldRef, quantifier) - } -} - -func (c *compiler) compileTypedFilterMatch(valueVar string, filter TypedFilter) (string, error) { - if filter.Operator == FilterIn { - values := make([]any, 0, len(filter.Values)) - for _, value := range filter.Values { - literal, err := filterLiteral(value) - if err != nil { - return "", err - } - values = append(values, literal) - } - bind := c.newBind("filter_in", values) - return fmt.Sprintf("POSITION(@%s, %s, true)", bind, valueVar), nil - } - if len(filter.Values) != 1 { - return "", fmt.Errorf("filter %q requires one value", filter.FieldRef) - } - literal, err := filterLiteral(filter.Values[0]) - if err != nil { - return "", err - } - bind := c.newBind("filter_value", literal) - left := valueVar - right := "@" + bind - if filter.FieldKind == FilterDate || filter.FieldKind == FilterDateTime { - switch filter.Operator { - case FilterGreaterThan, FilterGreaterEq, FilterLessThan, FilterLessEq: - left = "DATE_TIMESTAMP(" + valueVar + ")" - right = "DATE_TIMESTAMP(@" + bind + ")" - } - } - switch filter.Operator { - case FilterEquals: - return fmt.Sprintf("%s == @%s", left, bind), nil - case FilterNotEquals: - return fmt.Sprintf("%s != @%s", left, bind), nil - case FilterContains: - return fmt.Sprintf("CONTAINS(TO_STRING(%s), @%s)", valueVar, bind), nil - case FilterGreaterThan: - return fmt.Sprintf("%s > %s", left, right), nil - case FilterGreaterEq: - return fmt.Sprintf("%s >= %s", left, right), nil - case FilterLessThan: - return fmt.Sprintf("%s < %s", left, right), nil - case FilterLessEq: - return fmt.Sprintf("%s <= %s", left, right), nil - default: - return "", fmt.Errorf("filter %q uses unsupported operator %q", filter.FieldRef, filter.Operator) - } -} - -func filterLiteral(value FilterValue) (any, error) { - if err := value.Validate(); err != nil { - return nil, err - } - switch value.Kind { - case FilterString: - return *value.String, nil - case FilterCode: - return value.Code.Code, nil - case FilterBoolean: - return *value.Boolean, nil - case FilterInteger: - return *value.Integer, nil - case FilterDecimal: - return *value.Decimal, nil - case FilterDate: - return *value.Date, nil - case FilterDateTime: - return *value.DateTime, nil - default: - return nil, fmt.Errorf("unsupported filter value kind %q", value.Kind) - } -} diff --git a/internal/dataframe/filter_compile_test.go b/internal/dataframe/filter_compile_test.go deleted file mode 100644 index eb481d5..0000000 --- a/internal/dataframe/filter_compile_test.go +++ /dev/null @@ -1,102 +0,0 @@ -package dataframe - -import ( - "strings" - "testing" -) - -func TestCompileTypedFilterUsesBindVariables(t *testing.T) { - value := "female" - c := &compiler{bindVars: map[string]any{}} - expr, err := c.compileTypedFilter("root.payload", TypedFilter{ - FieldRef: "Patient.gender", - Selector: "gender", - FieldKind: FilterString, - Operator: FilterEquals, - Values: []FilterValue{{Kind: FilterString, String: &value}}, - }) - if err != nil { - t.Fatal(err) - } - if strings.Contains(expr, value) || !strings.Contains(expr, "@__filter_value_0") { - t.Fatalf("filter expression does not use a bind variable: %s", expr) - } - if got := c.bindVars["__filter_value_0"]; got != value { - t.Fatalf("bind value = %#v, want %q", got, value) - } -} - -func TestCompileTypedFilterQuantifiers(t *testing.T) { - value := "BAM" - for _, quantifier := range []ArrayQuantifier{QuantifierAny, QuantifierAll, QuantifierNone} { - t.Run(string(quantifier), func(t *testing.T) { - c := &compiler{bindVars: map[string]any{}} - expr, err := c.compileTypedFilter("node.payload", TypedFilter{ - FieldRef: "DocumentReference.type", - Selector: "type.coding[].display", - FieldKind: FilterString, - Repeated: true, - Quantifier: quantifier, - Operator: FilterEquals, - Values: []FilterValue{{Kind: FilterString, String: &value}}, - }) - if err != nil { - t.Fatal(err) - } - if !strings.Contains(expr, "FOR __value") { - t.Fatalf("unexpected quantifier expression: %s", expr) - } - }) - } -} - -func TestCompileTypedFilterNormalizesOrderedTemporalComparison(t *testing.T) { - date := "2025-01-01" - c := &compiler{bindVars: map[string]any{}} - expr, err := c.compileTypedFilter("root.payload", TypedFilter{ - FieldRef: "Patient.birth_date", Selector: "birthDate", FieldKind: FilterDate, - Operator: FilterGreaterEq, Values: []FilterValue{{Kind: FilterDate, Date: &date}}, - }) - if err != nil { - t.Fatal(err) - } - if !strings.Contains(expr, "DATE_TIMESTAMP(__value)") || !strings.Contains(expr, "DATE_TIMESTAMP(@__filter_value_0)") { - t.Fatalf("ordered temporal filter did not normalize timestamps: %s", expr) - } -} - -func TestGenericLoweringPushesRootAndChildFiltersIntoAQL(t *testing.T) { - gender := "female" - bam := "BAM" - compiled, err := CompileRequest(Builder{ - Project: "P1", - RootResourceType: "Patient", - Filters: []TypedFilter{{ - FieldRef: "Patient.gender", Selector: "gender", FieldKind: FilterString, Operator: FilterEquals, - Values: []FilterValue{{Kind: FilterString, String: &gender}}, - }}, - Traversals: []TraversalStep{{ - Label: "subject_Patient", ToResourceType: "DocumentReference", Alias: "file", - Filters: []TypedFilter{{ - FieldRef: "DocumentReference.type", Selector: "type.coding[].display", FieldKind: FilterString, - Repeated: true, Quantifier: QuantifierAny, Operator: FilterEquals, - Values: []FilterValue{{Kind: FilterString, String: &bam}}, - }}, - }}, - }, 25) - if err != nil { - t.Fatal(err) - } - if compiled.PlanProfile != "generic_fhir_graph" { - t.Fatalf("expected generic filtered plan, got %q", compiled.PlanProfile) - } - if !containsOptimizerRule(compiled.OptimizationRules, OptimizerRuleFilterPushdown) { - t.Fatalf("expected filter-pushdown optimizer provenance, got %#v", compiled.OptimizationRules) - } - if strings.Count(compiled.Query, "FILTER (LENGTH(FOR __value") < 2 { - t.Fatalf("expected root and child pushed filters, got:\n%s", compiled.Query) - } - if len(compiled.BindVars) < 6 { - t.Fatalf("expected selector and value bind variables, got %#v", compiled.BindVars) - } -} diff --git a/internal/dataframe/filter_literal.go b/internal/dataframe/filter_literal.go new file mode 100644 index 0000000..eb623c4 --- /dev/null +++ b/internal/dataframe/filter_literal.go @@ -0,0 +1,31 @@ +package dataframe + +import "fmt" + +// filterLiteral converts the typed filter value into the scalar representation +// bound to AQL. Validation has already established the active member and its +// kind; retaining this conversion beside the physical planner keeps the old +// string renderer out of the execution path. +func filterLiteral(value FilterValue) (any, error) { + if err := value.Validate(); err != nil { + return nil, err + } + switch value.Kind { + case FilterString: + return *value.String, nil + case FilterCode: + return value.Code.Code, nil + case FilterBoolean: + return *value.Boolean, nil + case FilterInteger: + return *value.Integer, nil + case FilterDecimal: + return *value.Decimal, nil + case FilterDate: + return *value.Date, nil + case FilterDateTime: + return *value.DateTime, nil + default: + return nil, fmt.Errorf("unsupported filter literal kind %q", value.Kind) + } +} diff --git a/internal/dataframe/filter_semantics.go b/internal/dataframe/filter_semantics.go index c05882f..51823d9 100644 --- a/internal/dataframe/filter_semantics.go +++ b/internal/dataframe/filter_semantics.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/calypr/loom/internal/fhirschema" + "github.com/calypr/loom/fhirschema" ) // ValidateTypedFilterForResource proves that a resolved filter selector has a diff --git a/internal/dataframe/generic_lowering.go b/internal/dataframe/generic_lowering.go deleted file mode 100644 index 3005d79..0000000 --- a/internal/dataframe/generic_lowering.go +++ /dev/null @@ -1,316 +0,0 @@ -package dataframe - -import ( - "encoding/json" - "fmt" - "strings" - - "github.com/calypr/loom/internal/fhirschema" -) - -// lowerGenericGraphQLBuilder produces a correct, conservative plan for any -// root and populated traversal represented in the generated FHIR graph schema. -// -// The generic plan uses the compiler-owned fhir_edge storage route. Most -// populated relationships are generated builder routes that reach a referring -// child with an INBOUND traversal. The explicit ResearchSubject --study--> -// ResearchStudy contract is the currently proven forward exception. Generated -// traversal metadata validates FHIR semantics but does not by itself define a -// safe physical AQL direction, so every other forward/ANY route remains -// rejected until its edge-layout evidence is added to storage_route.go. -func lowerGenericGraphQLBuilder(builder Builder, request logicalRequest) (Builder, error) { - if !fhirschema.HasResource(request.Root.ResourceType) { - return Builder{}, unsupportedLoweringError(fmt.Sprintf("root resource type %q is not represented by the active generated FHIR schema", request.Root.ResourceType)) - } - requiredMatches, err := requiredTraversalMatches(request.Root) - if err != nil { - return Builder{}, unsupportedLoweringError(err.Error()) - } - - ctx := &loweringContext{ - request: request, - builder: Builder{ - Project: request.Project, - DatasetGeneration: request.DatasetGeneration, - AuthResourcePaths: request.AuthResourcePaths, - AuthScopeMode: request.AuthScopeMode, - RootResourceType: request.Root.ResourceType, - Fields: append([]FieldSelect(nil), request.Root.Fields...), - Filters: append([]TypedFilter(nil), request.Root.Filters...), - Pivots: append([]PivotSelect(nil), request.Root.Pivots...), - Aggregates: append([]AggregateSelect(nil), request.Root.Aggregates...), - Slices: append([]RepresentativeSlice(nil), request.Root.Slices...), - Sets: []NamedSet{}, - DerivedFields: []DerivedField{}, - RequiredTraversalMatches: requiredMatches, - }, - setsByName: map[string]struct{}{}, - modes: map[string]string{}, - genericSetsBySignature: map[string]string{}, - genericFilterSetsBySig: map[string]string{}, - genericAliasesBySetName: map[string]string{}, - } - - if err := ctx.lowerGenericChildren(request.Root, ""); err != nil { - return Builder{}, err - } - appliedRules := make([]string, 0, 3) - if requestHasTypedFilters(request.Root) { - appliedRules = append(appliedRules, OptimizerRuleFilterPushdown) - } - if ctx.genericTraversalShareCount > 0 { - appliedRules = append(appliedRules, OptimizerRuleTraversalSharing) - } - if len(requiredMatches) > 0 { - appliedRules = append(appliedRules, OptimizerRuleRelationshipSemiJoin) - } - if len(appliedRules) == 0 { - appliedRules = nil - } - ctx.builder.PlanHint = &PlanHint{ - Mode: "lowered", - Profile: "generic_fhir_graph", - NamedSetCount: len(ctx.builder.Sets), - AppliedRules: appliedRules, - } - return ctx.builder, nil -} - -func (ctx *loweringContext) lowerGenericChildren(parent logicalNode, parentSet string) error { - children, groups, groupOrder, err := ctx.prepareGenericChildren(parent, parentSet) - if err != nil { - return err - } - - // Materialize every shareable prefix before lowering the individual child - // selections. The shared set intentionally has no target-type predicate: - // its per-resource-type subsets are built below. This is the same physical - // shape as the Patient optimizer's root_patient_neighbor_set, but it is - // now available at every generic parent node. - for _, key := range groupOrder { - group := groups[key] - if !group.canSharePrefix() { - continue - } - baseName := ctx.nextGenericSharedTraversalSetName(parentSet, group.label) - group.baseSet = ctx.ensureSet(NamedSet{ - Name: baseName, - Kind: SetKindTraverse, - Source: parentSet, - Direction: group.route.namedSetDirection(), - Label: group.label, - // ToResourceType remains a generated-route validation anchor. The - // physical traversal deliberately includes every target type with - // this label; each child gets a typed filter subset below. - ToResourceType: children[group.indices[0]].node.ResourceType, - AllTargetTypes: true, - Unique: true, - }, "node") - ctx.genericTraversalShareCount += len(group.indices) - 1 - } - - // Preserve request order for derived fields and nested traversals. Prefix - // discovery may be grouped, but user-visible output ordering must not be. - for _, child := range children { - group := groups[child.groupKey] - setName := child.setName - if group.baseSet != "" { - var reused bool - setName, reused, err = ctx.ensureGenericFilteredSubset(group.baseSet, child.node) - if err != nil { - return err - } - if reused { - ctx.genericTraversalShareCount++ - } - } else { - setName, err = ctx.ensureGenericTraversalSet(parentSet, child.node, child.route, setName) - if err != nil { - return err - } - } - - ctx.lowerNodeSelections(child.node, setName) - if err := ctx.lowerGenericChildren(child.node, setName); err != nil { - return err - } - } - return nil -} - -type genericTraversalChild struct { - node logicalNode - route storageRoute - setName string - groupKey string -} - -type genericTraversalGroup struct { - label string - route storageRoute - indices []int - resourceTypes map[string]struct{} - baseSet string -} - -func (group genericTraversalGroup) canSharePrefix() bool { - return len(group.indices) > 1 && len(group.resourceTypes) > 1 -} - -func (ctx *loweringContext) prepareGenericChildren(parent logicalNode, parentSet string) ([]genericTraversalChild, map[string]*genericTraversalGroup, []string, error) { - children := make([]genericTraversalChild, 0, len(parent.Children)) - groups := make(map[string]*genericTraversalGroup, len(parent.Children)) - groupOrder := make([]string, 0, len(parent.Children)) - for _, child := range parent.Children { - setName, err := ctx.genericSetNameForAlias(child.Alias) - if err != nil { - return nil, nil, nil, err - } - route, err := resolveStorageRoute(parent.ResourceType, child.Label, child.ResourceType) - if err != nil { - return nil, nil, nil, unsupportedLoweringError(err.Error()) - } - key := genericSiblingTraversalKey(parentSet, child.Label, route) - group, exists := groups[key] - if !exists { - group = &genericTraversalGroup{ - label: child.Label, - route: route, - resourceTypes: map[string]struct{}{}, - } - groups[key] = group - groupOrder = append(groupOrder, key) - } - group.indices = append(group.indices, len(children)) - group.resourceTypes[child.ResourceType] = struct{}{} - children = append(children, genericTraversalChild{ - node: child, - route: route, - setName: setName, - groupKey: key, - }) - } - return children, groups, groupOrder, nil -} - -func (ctx *loweringContext) genericSetNameForAlias(alias string) (string, error) { - if strings.TrimSpace(alias) == "" { - return "", unsupportedLoweringError("generic lowering requires a traversal alias") - } - setName := "generic_" + sanitizeColumnName(alias) + "_set" - if priorAlias, exists := ctx.genericAliasesBySetName[setName]; exists && priorAlias != alias { - return "", unsupportedLoweringError(fmt.Sprintf("traversal aliases collide after identifier normalization: %q", alias)) - } - if _, exists := ctx.setsByName[setName]; exists { - return "", unsupportedLoweringError(fmt.Sprintf("traversal alias %q collides with an existing generic set after identifier normalization", alias)) - } - ctx.genericAliasesBySetName[setName] = alias - return setName, nil -} - -func (ctx *loweringContext) nextGenericSharedTraversalSetName(parentSet, label string) string { - parentName := "root" - if strings.TrimSpace(parentSet) != "" { - parentName = sanitizeColumnName(parentSet) - } - base := "generic_" + parentName + "_" + sanitizeColumnName(label) + "_neighbors_set" - name := base - for suffix := 2; ; suffix++ { - _, usedBySet := ctx.setsByName[name] - _, usedByAlias := ctx.genericAliasesBySetName[name] - if !usedBySet && !usedByAlias { - return name - } - name = fmt.Sprintf("%s_%d", base, suffix) - } -} - -func (ctx *loweringContext) ensureGenericTraversalSet(parentSet string, child logicalNode, route storageRoute, setName string) (string, error) { - signature, err := genericTraversalSignature(parentSet, child, route) - if err != nil { - return "", err - } - if sharedSet, exists := ctx.genericSetsBySignature[signature]; exists { - ctx.genericTraversalShareCount++ - return sharedSet, nil - } - ctx.ensureSet(NamedSet{ - Name: setName, - Kind: SetKindTraverse, - Source: parentSet, - Direction: route.namedSetDirection(), - Label: child.Label, - ToResourceType: child.ResourceType, - Filters: append([]TypedFilter(nil), child.Filters...), - Unique: true, - SortField: genericTraversalRequiresStableOrder(child), - }, "node") - ctx.genericSetsBySignature[signature] = setName - return setName, nil -} - -func (ctx *loweringContext) ensureGenericFilteredSubset(source string, child logicalNode) (string, bool, error) { - signature, err := genericFilteredSubsetSignature(source, child) - if err != nil { - return "", false, err - } - if sharedSet, exists := ctx.genericFilterSetsBySig[signature]; exists { - return sharedSet, true, nil - } - setName, err := ctx.genericSetNameForAlias(child.Alias) - if err != nil { - return "", false, err - } - // The shared base is deduplicated before this subset is evaluated. Sort the - // subset after it is typed and filtered so FIRST/ALL projections are stable - // and aliases observing the same subset see exactly the same order. - ctx.ensureSet(NamedSet{ - Name: setName, - Kind: SetKindFilter, - Source: source, - MatchResourceType: child.ResourceType, - Filters: append([]TypedFilter(nil), child.Filters...), - // The all-target base is already UNIQUE. Repeating it here would add a - // second hash-deduplication pass without changing the typed subset. - Unique: false, - SortField: "_key", - }, "node") - ctx.genericFilterSetsBySig[signature] = setName - return setName, false, nil -} - -func genericTraversalRequiresStableOrder(node logicalNode) string { - for _, field := range node.Fields { - switch normalizeValueMode(field.ValueMode) { - case "FIRST", "ALL", "AUTO": - return "_key" - } - } - if len(node.Slices) > 0 { - return "_key" - } - return "" -} - -func genericTraversalSignature(parentSet string, child logicalNode, route storageRoute) (string, error) { - filters, err := json.Marshal(child.Filters) - if err != nil { - return "", fmt.Errorf("serialize traversal filters for %s -> %s (%s): %w", child.ResourceType, child.Alias, child.Label, err) - } - return strings.Join([]string{parentSet, child.Label, child.ResourceType, route.namedSetDirection(), genericTraversalRequiresStableOrder(child), string(filters)}, "\x00"), nil -} - -func genericSiblingTraversalKey(parentSet, label string, route storageRoute) string { - return strings.Join([]string{parentSet, label, route.namedSetDirection()}, "\x00") -} - -func genericFilteredSubsetSignature(source string, child logicalNode) (string, error) { - filters, err := json.Marshal(child.Filters) - if err != nil { - return "", fmt.Errorf("serialize shared traversal filters for %s -> %s: %w", child.ResourceType, child.Alias, err) - } - // Shared generic subsets always sort by _key. This makes all selection - // modes deterministic and lets aliases with identical type/filter semantics - // reuse the same materialized subset. - return strings.Join([]string{source, child.ResourceType, "_key", string(filters)}, "\x00"), nil -} diff --git a/internal/dataframe/generic_lowering_test.go b/internal/dataframe/generic_lowering_test.go deleted file mode 100644 index 14ddc68..0000000 --- a/internal/dataframe/generic_lowering_test.go +++ /dev/null @@ -1,111 +0,0 @@ -package dataframe - -import ( - "strings" - "testing" - - "github.com/calypr/loom/internal/fhirschema" -) - -func TestLowerGraphQLBuilderFallsBackToGenericRootOnlyPlan(t *testing.T) { - planned, err := lowerGraphQLBuilder(Builder{ - Project: "P1", - RootResourceType: "Patient", - Fields: []FieldSelect{{Name: "gender", Select: "gender"}}, - }) - if err != nil { - t.Fatalf("lowerGraphQLBuilder() error = %v", err) - } - if planned.PlanHint == nil || planned.PlanHint.Profile != "generic_fhir_graph" { - t.Fatalf("expected generic plan hint, got %#v", planned.PlanHint) - } - compiled, err := Compile(planned, 25) - if err != nil { - t.Fatalf("Compile() error = %v", err) - } - if !strings.Contains(compiled.Query, "FOR root IN Patient") || !strings.Contains(compiled.Query, "root.payload.gender") { - t.Fatalf("unexpected generic root query:\n%s", compiled.Query) - } -} - -func TestLowerGraphQLBuilderFallsBackToGenericNonPatientTraversal(t *testing.T) { - planned, err := lowerGraphQLBuilder(Builder{ - Project: "P1", - RootResourceType: "Specimen", - Fields: []FieldSelect{{Name: "id", Select: "id"}}, - Traversals: []TraversalStep{{ - Label: "subject_Specimen", - ToResourceType: "DocumentReference", - Alias: "file", - Fields: []FieldSelect{{Name: "file_name", Select: "content[].attachment.title"}}, - }}, - }) - if err != nil { - t.Fatalf("lowerGraphQLBuilder() error = %v", err) - } - if planned.PlanHint == nil || planned.PlanHint.Profile != "generic_fhir_graph" { - t.Fatalf("expected generic plan hint, got %#v", planned.PlanHint) - } - if len(planned.Sets) != 1 || planned.Sets[0].Direction != "INBOUND" || planned.Sets[0].Source != "" { - t.Fatalf("unexpected generic set: %#v", planned.Sets) - } - compiled, err := Compile(planned, 25) - if err != nil { - t.Fatalf("Compile() error = %v", err) - } - if !strings.Contains(compiled.Query, "1..1 INBOUND root fhir_edge") || !strings.Contains(compiled.Query, "generic_file_set") { - t.Fatalf("unexpected generic traversal query:\n%s", compiled.Query) - } -} - -func TestGenericLoweringUsesInboundForNestedSchemaTraversal(t *testing.T) { - planned, err := lowerGraphQLBuilder(Builder{ - Project: "P1", - RootResourceType: "Patient", - Traversals: []TraversalStep{{ - Label: "subject_Patient", - ToResourceType: "Specimen", - Alias: "specimen", - Traversals: []TraversalStep{{ - Label: "subject_Specimen", - ToResourceType: "DocumentReference", - Alias: "file", - Fields: []FieldSelect{{Name: "id", Select: "id"}}, - }}, - }}, - }) - if err != nil { - t.Fatalf("lowerGraphQLBuilder() error = %v", err) - } - if planned.PlanHint == nil || planned.PlanHint.Profile != "generic_fhir_graph" { - t.Fatalf("ordinary Patient navigation must use generic lowering, got %#v", planned.PlanHint) - } - compiled, err := Compile(planned, 10) - if err != nil { - t.Fatal(err) - } - if strings.Count(compiled.Query, " INBOUND ") != 2 { - t.Fatalf("expected two generic INBOUND traversals, got:\n%s", compiled.Query) - } -} - -func TestGenericLoweringCompilesEveryGeneratedRootType(t *testing.T) { - for _, resourceType := range fhirschema.ResourceTypes() { - t.Run(resourceType, func(t *testing.T) { - planned, err := lowerGraphQLBuilder(Builder{Project: "P1", RootResourceType: resourceType}) - if err != nil { - t.Fatalf("lowerGraphQLBuilder() error = %v", err) - } - if planned.PlanHint == nil || planned.PlanHint.Profile != "generic_fhir_graph" { - t.Fatalf("expected generic plan, got %#v", planned.PlanHint) - } - compiled, err := Compile(planned, 1) - if err != nil { - t.Fatalf("Compile() error = %v", err) - } - if !strings.Contains(compiled.Query, "FOR root IN "+resourceType) { - t.Fatalf("query does not use expected root collection:\n%s", compiled.Query) - } - }) - } -} diff --git a/internal/dataframe/generic_physical_plan.go b/internal/dataframe/generic_physical_plan.go index 304c43f..c92e483 100644 --- a/internal/dataframe/generic_physical_plan.go +++ b/internal/dataframe/generic_physical_plan.go @@ -2,15 +2,14 @@ package dataframe import ( "fmt" + "sort" "strings" - "github.com/calypr/loom/internal/fhirschema" + "github.com/calypr/loom/fhirschema" ) -// BuildGenericPhysicalPlan lowers only the navigation skeleton of an already -// validated semantic plan. Selection, user filtering, pivots, aggregation, and -// slicing remain intentionally unsupported until their physical operators are -// frozen. The returned plan is inspectable and renderer-independent. +// BuildGenericPhysicalPlan lowers generic navigation plus root and optional +// child selections into the typed physical IR. func BuildGenericPhysicalPlan(semantic SemanticPlan) (PhysicalPlan, error) { if strings.TrimSpace(semantic.Project) == "" { return PhysicalPlan{}, fmt.Errorf("semantic plan project is required") @@ -21,7 +20,7 @@ func BuildGenericPhysicalPlan(semantic SemanticPlan) (PhysicalPlan, error) { if !fhirschema.ResourceExists(semantic.Root.ResourceType) { return PhysicalPlan{}, fmt.Errorf("root resource type %q is not represented by the generated FHIR schema", semantic.Root.ResourceType) } - if err := validateNavigationOnlyNode(semantic.Root); err != nil { + if err := validateGenericPhysicalNode(semantic.Root, true); err != nil { return PhysicalPlan{}, err } @@ -50,61 +49,105 @@ func BuildGenericPhysicalPlan(semantic SemanticPlan) (PhysicalPlan, error) { physical.Operations = appendProjectScope(physical.Operations, []string{"root"}, "", semantic.Root) physical.Operations = appendDatasetGenerationScope(physical.Operations, []string{"root"}, "", semantic.Root) physical.Operations = appendAuthScope(physical.Operations, []PhysicalValue{{Variable: "root", Path: []string{"auth_resource_path"}}}, "root_scope_allowed", semantic.Root) + if err := appendRootPhysicalFilters(&physical, semantic.Root); err != nil { + return PhysicalPlan{}, err + } + if err := appendRequiredTraversalMatchFilters(&physical, semantic.Root); err != nil { + return PhysicalPlan{}, err + } - nextTraversal := 0 - var walk func(parent SemanticNode, parentVariable string) error - walk = func(parent SemanticNode, parentVariable string) error { + childSetIndex := 0 + returnProjections := []PhysicalProjection{} + var walk func(parent SemanticNode, parentVariable, projectionPrefix string) error + walk = func(parent SemanticNode, parentVariable, projectionPrefix string) error { for _, child := range parent.Children { - route, err := resolveStorageRoute(parent.ResourceType, child.EdgeLabel, child.ResourceType) + if child.MatchMode.required() { + // Required routes are represented by the root semi-join emitted + // above for membership, but they may still need a materialized + // child set for selected fields or nested shaping. The second + // physical set is post-window output work; it cannot change root + // membership because the semi-join remains before SORT/LIMIT. + if physicalNodeNeedsMaterializedSet(child) { + childSetIndex++ + childProjectionPrefix := child.Alias + if projectionPrefix != "" { + childProjectionPrefix = projectionPrefix + "__" + child.Alias + } + set, projections, err := buildOptionalChildPhysicalSet(&physical, childSetIndex, parent, parentVariable, child, childProjectionPrefix) + if err != nil { + return err + } + physical.Operations = append(physical.Operations, PhysicalOperation{Kind: PhysicalSetOp, Source: PhysicalSource{SemanticNode: child.Alias, ResourceType: child.ResourceType, Relationship: child.EdgeLabel}, Set: &set}) + returnProjections = append(returnProjections, projections...) + if err := walk(child, set.Variable, childProjectionPrefix); err != nil { + return err + } + } + continue + } + if !physicalNodeNeedsMaterializedSet(child) { + route, err := resolveStorageRoute(parent.ResourceType, child.EdgeLabel, child.ResourceType) + if err != nil { + return err + } + traversalIndex := 1 + for _, operation := range physical.Operations { + if operation.Kind == PhysicalTraversalOp { + traversalIndex++ + } + } + nodeVariable := fmt.Sprintf("node_%d", traversalIndex) + edgeVariable := fmt.Sprintf("edge_%d", traversalIndex) + labelBind := fmt.Sprintf("traversal_%d_label", traversalIndex) + typeBind := fmt.Sprintf("traversal_%d_target_type", traversalIndex) + edgeCollectionBind := fmt.Sprintf("traversal_%d_edge_collection", traversalIndex) + physical.BindVars[labelBind] = child.EdgeLabel + physical.BindVars[typeBind] = child.ResourceType + physical.BindVars[edgeCollectionBind] = "fhir_edge" + physical.Operations = append(physical.Operations, PhysicalOperation{Kind: PhysicalTraversalOp, + Source: PhysicalSource{SemanticNode: child.Alias, ResourceType: child.ResourceType, Relationship: child.EdgeLabel}, + Traversal: &PhysicalTraversal{SourceVariable: parentVariable, TargetVariable: nodeVariable, EdgeVariable: edgeVariable, Direction: route.Direction, + EdgeCollectionBindKey: edgeCollectionBind, EdgeLabelBindKey: labelBind, TargetTypeBindKey: typeBind, EdgeTargetTypeField: route.targetEdgeTypeField()}}) + physical.Operations = appendProjectScope(physical.Operations, []string{edgeVariable, nodeVariable}, child.EdgeLabel, child) + physical.Operations = appendDatasetGenerationScope(physical.Operations, []string{edgeVariable, nodeVariable}, child.EdgeLabel, child) + physical.Operations = appendAuthScope(physical.Operations, []PhysicalValue{{Variable: edgeVariable, Path: []string{"auth_resource_path"}}, {Variable: nodeVariable, Path: []string{"auth_resource_path"}}}, fmt.Sprintf("traversal_%d_scope_allowed", traversalIndex), child) + if err := walk(child, nodeVariable, projectionPrefix); err != nil { + return err + } + continue + } + // Optional children are correlated sets. Keeping them in a LET + // subquery preserves the parent row grain while allowing typed child + // filters and projections to be applied before materialization. + childSetIndex++ + childProjectionPrefix := child.Alias + if projectionPrefix != "" { + childProjectionPrefix = projectionPrefix + "__" + child.Alias + } + set, projections, err := buildOptionalChildPhysicalSet(&physical, childSetIndex, parent, parentVariable, child, childProjectionPrefix) if err != nil { return err } - nextTraversal++ - nodeVariable := fmt.Sprintf("node_%d", nextTraversal) - edgeVariable := fmt.Sprintf("edge_%d", nextTraversal) - labelBind := fmt.Sprintf("traversal_%d_label", nextTraversal) - typeBind := fmt.Sprintf("traversal_%d_target_type", nextTraversal) - edgeCollectionBind := fmt.Sprintf("traversal_%d_edge_collection", nextTraversal) - physical.BindVars[labelBind] = child.EdgeLabel - physical.BindVars[typeBind] = child.ResourceType - physical.BindVars[edgeCollectionBind] = "fhir_edge" - source := PhysicalSource{SemanticNode: child.Alias, ResourceType: child.ResourceType, Relationship: child.EdgeLabel} - physical.Operations = append(physical.Operations, PhysicalOperation{ - Kind: PhysicalTraversalOp, - Source: source, - Traversal: &PhysicalTraversal{ - SourceVariable: parentVariable, - TargetVariable: nodeVariable, - EdgeVariable: edgeVariable, - Direction: route.Direction, - EdgeCollectionBindKey: edgeCollectionBind, - EdgeLabelBindKey: labelBind, - TargetTypeBindKey: typeBind, - EdgeTargetTypeField: route.targetEdgeTypeField(), - }, - }) - // Edge metadata is not a substitute for the target resource's - // tenant boundary. Scope both documents before any subsequent - // traversal or return can observe the target node. - physical.Operations = appendProjectScope(physical.Operations, []string{edgeVariable, nodeVariable}, child.EdgeLabel, child) - physical.Operations = appendDatasetGenerationScope(physical.Operations, []string{edgeVariable, nodeVariable}, child.EdgeLabel, child) - physical.Operations = appendAuthScope(physical.Operations, []PhysicalValue{ - {Variable: edgeVariable, Path: []string{"auth_resource_path"}}, - {Variable: nodeVariable, Path: []string{"auth_resource_path"}}, - }, fmt.Sprintf("traversal_%d_scope_allowed", nextTraversal), child) - if err := walk(child, nodeVariable); err != nil { + physical.Operations = append(physical.Operations, PhysicalOperation{Kind: PhysicalSetOp, Source: PhysicalSource{SemanticNode: child.Alias, ResourceType: child.ResourceType, Relationship: child.EdgeLabel}, Set: &set}) + returnProjections = append(returnProjections, projections...) + if err := walk(child, set.Variable, childProjectionPrefix); err != nil { return err } } return nil } - if err := walk(semantic.Root, "root"); err != nil { + if err := walk(semantic.Root, "root", ""); err != nil { return PhysicalPlan{}, err } + projections, err := rootPhysicalProjections(&physical, semantic.Root) + if err != nil { + return PhysicalPlan{}, err + } + projections = append(projections, returnProjections...) physical.Operations = append(physical.Operations, PhysicalOperation{ Kind: PhysicalReturnOp, Source: PhysicalSource{SemanticNode: semantic.Root.Alias, ResourceType: semantic.Root.ResourceType, SemanticField: "_key"}, - Return: &PhysicalReturn{Projections: []PhysicalProjection{{Name: "_key", Value: PhysicalValue{Variable: "root", Path: []string{"_key"}}}}}, + Return: &PhysicalReturn{Projections: projections}, }) if err := physical.Validate(); err != nil { return PhysicalPlan{}, fmt.Errorf("validate generic physical plan: %w", err) @@ -115,6 +158,21 @@ func BuildGenericPhysicalPlan(semantic SemanticPlan) (PhysicalPlan, error) { return physical, nil } +// physicalNodeNeedsMaterializedSet reports whether a node or any optional +// descendant has shaped output. Materializing an otherwise unselected parent +// is necessary to give nested sets a stable correlated source variable. +func physicalNodeNeedsMaterializedSet(node SemanticNode) bool { + if len(node.Fields) != 0 || len(node.Filters) != 0 || len(node.Pivots) != 0 || len(node.Aggregates) != 0 || len(node.Slices) != 0 { + return true + } + for _, child := range node.Children { + if child.MatchMode.required() || physicalNodeNeedsMaterializedSet(child) { + return true + } + } + return false +} + func appendProjectScope(operations []PhysicalOperation, variables []string, relationship string, node SemanticNode) []PhysicalOperation { right := PhysicalValue{BindKey: "project"} for _, variable := range variables { @@ -167,17 +225,469 @@ func appendAuthScope(operations []PhysicalOperation, scopedValues []PhysicalValu }) } -func validateNavigationOnlyNode(node SemanticNode) error { - if node.MatchMode.required() { - return fmt.Errorf("semantic node %q requires a relationship match, which is not supported by the navigation-only physical plan", node.Alias) - } - if len(node.Fields) != 0 || len(node.Filters) != 0 || len(node.Pivots) != 0 || len(node.Aggregates) != 0 || len(node.Slices) != 0 { - return fmt.Errorf("semantic node %q contains selections or filters not supported by generic physical navigation", node.Alias) - } +func validateGenericPhysicalNode(node SemanticNode, root bool) error { for _, child := range node.Children { - if err := validateNavigationOnlyNode(child); err != nil { + if err := validateGenericPhysicalNode(child, false); err != nil { return err } } return nil } + +func rootPhysicalProjections(physical *PhysicalPlan, root SemanticNode) ([]PhysicalProjection, error) { + projections := []PhysicalProjection{{Name: "_key", Value: PhysicalValue{Variable: "root", Path: []string{"_key"}}}} + for index, field := range root.Fields { + selection, err := ResolveSemanticField(root.ResourceType, root.Alias, index, field) + if err != nil { + return nil, err + } + cardinality, distinct := PhysicalScalarCardinality, false + switch selection.Projection { + case ProjectionArray: + cardinality = PhysicalArrayCardinality + case ProjectionDistinctArray: + cardinality, distinct = PhysicalArrayCardinality, true + case ProjectionScalar, ProjectionFirst: + default: + return nil, fmt.Errorf("root field %q has unsupported projection %q", field.Name, selection.Projection) + } + expression := PhysicalExpression{ + Kind: PhysicalExtractExpression, Cardinality: cardinality, NullBehavior: PhysicalPreserveNull, + Extract: &PhysicalExtract{Source: PhysicalValue{Variable: "root", Path: []string{"payload"}}, ResourceType: root.ResourceType, Selector: field.Selector, Fallbacks: append([]Selector(nil), field.Fallbacks...), Distinct: distinct}, + } + if cardinality == PhysicalArrayCardinality { + expression.NullBehavior = PhysicalEmptyOnNull + } + projections = append(projections, PhysicalProjection{Name: field.Name, Expression: &expression}) + } + for _, aggregate := range root.Aggregates { + expression, err := physicalAggregateExpression(physical, root.ResourceType, PhysicalValue{Variable: "root"}, aggregate, false) + if err != nil { + return nil, err + } + projections = append(projections, PhysicalProjection{Name: aggregate.Name, Expression: &expression}) + } + for _, pivot := range root.Pivots { + expression, err := physicalPivotExpression(physical, root.ResourceType, PhysicalValue{Variable: "root"}, pivot, false) + if err != nil { + return nil, err + } + projections = append(projections, PhysicalProjection{Name: pivot.Name, Expression: &expression}) + } + for _, slice := range root.Slices { + expression, err := physicalSliceExpression(physical, root.ResourceType, PhysicalValue{Variable: "root"}, slice, false) + if err != nil { + return nil, err + } + projections = append(projections, PhysicalProjection{Name: slice.Name, Expression: &expression}) + } + return projections, nil +} + +func physicalPivotExpression(physical *PhysicalPlan, resourceType string, source PhysicalValue, pivot SemanticPivot, sourceIsSet bool) (PhysicalExpression, error) { + if len(pivot.Columns) == 0 { + return PhysicalExpression{}, fmt.Errorf("pivot %q requires bounded columns", pivot.Name) + } + // Pivot sources are resource documents (root or correlated child set), not + // payload values. The renderer applies selectors against each item's + // payload, preserving the same semantics for singleton and set sources. + key := "pivot_" + sanitizeColumnName(source.Variable) + "_" + sanitizeColumnName(pivot.Name) + "_columns" + physical.BindVars[key] = append([]string(nil), pivot.Columns...) + return PhysicalExpression{ + Kind: PhysicalPivotExpression, Cardinality: PhysicalObjectCardinality, NullBehavior: PhysicalPreserveNull, + Pivot: &PhysicalPivotMap{Source: source, ResourceType: resourceType, KeySelector: pivot.ColumnSelector, ValueSelector: pivot.ValueSelector, ColumnsBindKey: key}, + }, nil +} + +// physicalAggregateExpression lowers one semantic aggregate into the typed +// aggregate IR. A root source is a singleton document; child sources are +// correlated PhysicalSet variables. Selector extraction remains typed so the +// renderer can choose the correct payload iteration without embedding user +// paths in AQL. +func physicalAggregateExpression(physical *PhysicalPlan, resourceType string, source PhysicalValue, aggregate SemanticAggregate, sourceIsSet bool) (PhysicalExpression, error) { + op := PhysicalAggregateOperation(strings.ToUpper(strings.TrimSpace(aggregate.Operation))) + switch op { + case PhysicalCountAggregate, PhysicalCountDistinctAggregate, PhysicalExistsAggregate, PhysicalDistinctValuesAggregate, PhysicalMinAggregate, PhysicalMaxAggregate, PhysicalFirstAggregate: + default: + return PhysicalExpression{}, fmt.Errorf("aggregate %q uses unsupported operation %q", aggregate.Name, aggregate.Operation) + } + aggregatePhysical := PhysicalAggregate{Source: source, Operation: op} + if aggregate.Selector != nil { + valueSource := source + if !sourceIsSet && source.Variable != "" && len(source.Path) == 0 { + valueSource = PhysicalValue{Variable: source.Variable, Path: []string{"payload"}} + } + value := PhysicalExpression{Kind: PhysicalExtractExpression, Cardinality: PhysicalArrayCardinality, NullBehavior: PhysicalEmptyOnNull, + Extract: &PhysicalExtract{Source: valueSource, ResourceType: resourceType, Selector: *aggregate.Selector}} + aggregatePhysical.Value = &value + } + if aggregate.Predicate != nil { + leftSource := source + if !sourceIsSet && source.Variable != "" && len(source.Path) == 0 { + leftSource = PhysicalValue{Variable: source.Variable, Path: []string{"payload"}} + } + left := PhysicalExpression{Kind: PhysicalExtractExpression, Cardinality: PhysicalArrayCardinality, NullBehavior: PhysicalEmptyOnNull, + Extract: &PhysicalExtract{Source: leftSource, ResourceType: resourceType, Selector: *aggregate.Predicate}} + comparison := &PhysicalPredicate{Operator: "EXISTS", LeftExpression: &left} + if aggregate.PredicateEquals != "" { + comparison.Operator = "EQUALS" + comparison.ValueKind = FilterString + key := "aggregate_" + sanitizeColumnName(source.Variable) + "_" + sanitizeColumnName(aggregate.Name) + "_predicate_equals" + physical.BindVars[key] = aggregate.PredicateEquals + comparison.Right = &PhysicalValue{BindKey: key} + } + aggregatePhysical.Predicate = &PhysicalPredicateExpression{Kind: PhysicalComparisonPredicate, Comparison: comparison} + } + cardinality := PhysicalScalarCardinality + nullBehavior := PhysicalEmptyOnNull + if op == PhysicalDistinctValuesAggregate { + cardinality = PhysicalArrayCardinality + } + return PhysicalExpression{Kind: PhysicalAggregateExpression, Cardinality: cardinality, NullBehavior: nullBehavior, Aggregate: &aggregatePhysical}, nil +} + +// physicalSliceExpression lowers a representative slice into a typed, +// bounded projection over either the singleton root document or a correlated +// child set. The source set is already materialized in stable _key order; +// the explicit sort expression below makes that ordering part of the slice +// contract and gives the renderer a deterministic tie-break. +func physicalSliceExpression(physical *PhysicalPlan, resourceType string, source PhysicalValue, slice SemanticSlice, sourceIsSet bool) (PhysicalExpression, error) { + _ = sourceIsSet + if slice.Limit <= 0 { + return PhysicalExpression{}, fmt.Errorf("slice %q requires positive limit", slice.Name) + } + limitKey := "slice_" + sanitizeColumnName(source.Variable) + "_" + sanitizeColumnName(slice.Name) + "_limit" + physical.BindVars[limitKey] = slice.Limit + // Expressions are anchored to the declared source variable for validation; + // the renderer rebinds them to its per-item loop variable. + leftSource := source + physicalSlice := PhysicalSlice{ + Source: source, + LimitBindKey: limitKey, + Sort: &PhysicalExpression{Kind: PhysicalValueExpression, Cardinality: PhysicalScalarCardinality, NullBehavior: PhysicalPreserveNull, Value: &PhysicalValue{Variable: source.Variable, Path: []string{"_key"}}}, + Projections: make([]PhysicalExpressionProjection, 0, len(slice.Fields)), + } + if slice.Predicate != nil { + left := PhysicalExpression{Kind: PhysicalExtractExpression, Cardinality: PhysicalArrayCardinality, NullBehavior: PhysicalEmptyOnNull, + Extract: &PhysicalExtract{Source: leftSource, ResourceType: resourceType, Selector: *slice.Predicate}} + comparison := &PhysicalPredicate{Operator: "EXISTS", LeftExpression: &left} + if slice.PredicateEquals != "" { + key := "slice_" + sanitizeColumnName(source.Variable) + "_" + sanitizeColumnName(slice.Name) + "_predicate_equals" + physical.BindVars[key] = slice.PredicateEquals + comparison.Operator = "EQUALS" + comparison.ValueKind = FilterString + comparison.Right = &PhysicalValue{BindKey: key} + } + physicalSlice.Predicate = &PhysicalPredicateExpression{Kind: PhysicalComparisonPredicate, Comparison: comparison} + } + for index, field := range slice.Fields { + selection := field + if selection.Name == "" { + return PhysicalExpression{}, fmt.Errorf("slice %q field %d requires name", slice.Name, index) + } + physicalSlice.Projections = append(physicalSlice.Projections, PhysicalExpressionProjection{ + Name: selection.Name, + Expression: PhysicalExpression{Kind: PhysicalExtractExpression, Cardinality: PhysicalScalarCardinality, NullBehavior: PhysicalPreserveNull, + Extract: &PhysicalExtract{Source: leftSource, ResourceType: resourceType, Selector: selection.Selector, Fallbacks: append([]Selector(nil), selection.Fallbacks...)}}, + }) + } + return PhysicalExpression{Kind: PhysicalSliceExpression, Cardinality: PhysicalArrayCardinality, NullBehavior: PhysicalEmptyOnNull, Slice: &physicalSlice}, nil +} + +func appendRootPhysicalFilters(physical *PhysicalPlan, root SemanticNode) error { + for index, filter := range root.Filters { + if err := ValidateTypedFilterForResource(root.ResourceType, filter); err != nil { + return fmt.Errorf("root filter %q: %w", filter.FieldRef, err) + } + selector, err := ParseSelector(filter.Selector) + if err != nil { + return fmt.Errorf("root filter %q selector: %w", filter.FieldRef, err) + } + predicate := PhysicalPredicate{ + Operator: string(filter.Operator), Quantifier: filter.Quantifier, ValueKind: filter.FieldKind, + LeftExpression: &PhysicalExpression{Kind: PhysicalExtractExpression, Cardinality: PhysicalArrayCardinality, NullBehavior: PhysicalEmptyOnNull, + Extract: &PhysicalExtract{Source: PhysicalValue{Variable: "root", Path: []string{"payload"}}, ResourceType: root.ResourceType, Selector: selector}}, + } + if filter.Operator != FilterExists && filter.Operator != FilterMissing { + key := fmt.Sprintf("root_filter_%d_value", index+1) + if filter.Operator == FilterIn { + values := make([]any, 0, len(filter.Values)) + for _, value := range filter.Values { + literal, err := filterLiteral(value) + if err != nil { + return err + } + values = append(values, literal) + } + physical.BindVars[key] = values + } else { + literal, err := filterLiteral(filter.Values[0]) + if err != nil { + return err + } + physical.BindVars[key] = literal + } + predicate.Right = &PhysicalValue{BindKey: key} + } + physical.Operations = append(physical.Operations, PhysicalOperation{Kind: PhysicalFilterOp, + Source: PhysicalSource{SemanticNode: root.Alias, ResourceType: root.ResourceType, SemanticField: filter.FieldRef}, + Filter: &PhysicalFilter{Expression: &PhysicalPredicateExpression{Kind: PhysicalComparisonPredicate, Comparison: &predicate}}}) + } + return nil +} + +// buildOptionalChildPhysicalSet lowers one root-relative optional traversal. +// The set retains resource documents (rather than pre-shaped maps), allowing +// the renderer to apply each child selector against the document payload at +// the outer return while preserving root row grain. +func buildOptionalChildPhysicalSet(physical *PhysicalPlan, setIndex int, parent SemanticNode, parentVariable string, child SemanticNode, projectionPrefix string) (PhysicalSet, []PhysicalProjection, error) { + route, err := resolveStorageRoute(parent.ResourceType, child.EdgeLabel, child.ResourceType) + if err != nil { + return PhysicalSet{}, nil, err + } + prefix := fmt.Sprintf("child_set_%d", setIndex) + labelBind := prefix + "_label" + typeBind := prefix + "_target_type" + edgeCollectionBind := prefix + "_edge_collection" + physical.BindVars[labelBind] = child.EdgeLabel + physical.BindVars[typeBind] = child.ResourceType + physical.BindVars[edgeCollectionBind] = "fhir_edge" + targetVariable := fmt.Sprintf("%s_node", prefix) + edgeVariable := fmt.Sprintf("%s_edge", prefix) + source := PhysicalSource{SemanticNode: child.Alias, ResourceType: child.ResourceType, Relationship: child.EdgeLabel} + subplan := PhysicalSubplan{Captures: []string{parentVariable}, Operations: []PhysicalOperation{{ + Kind: PhysicalTraversalOp, Source: source, + Traversal: &PhysicalTraversal{SourceVariable: parentVariable, TargetVariable: targetVariable, EdgeVariable: edgeVariable, Direction: route.Direction, EdgeCollectionBindKey: edgeCollectionBind, EdgeLabelBindKey: labelBind, TargetTypeBindKey: typeBind, EdgeTargetTypeField: route.targetEdgeTypeField()}, + }}} + subplan.Operations = appendProjectScope(subplan.Operations, []string{edgeVariable, targetVariable}, child.EdgeLabel, child) + subplan.Operations = appendDatasetGenerationScope(subplan.Operations, []string{edgeVariable, targetVariable}, child.EdgeLabel, child) + subplan.Operations = appendAuthScope(subplan.Operations, []PhysicalValue{{Variable: edgeVariable, Path: []string{"auth_resource_path"}}, {Variable: targetVariable, Path: []string{"auth_resource_path"}}}, prefix+"_scope_allowed", child) + for index, filter := range child.Filters { + if err := ValidateTypedFilterForResource(child.ResourceType, filter); err != nil { + return PhysicalSet{}, nil, fmt.Errorf("child filter %q: %w", filter.FieldRef, err) + } + selector, err := ParseSelector(filter.Selector) + if err != nil { + return PhysicalSet{}, nil, fmt.Errorf("child filter %q selector: %w", filter.FieldRef, err) + } + predicate := PhysicalPredicate{Operator: string(filter.Operator), Quantifier: filter.Quantifier, ValueKind: filter.FieldKind, LeftExpression: &PhysicalExpression{Kind: PhysicalExtractExpression, Cardinality: PhysicalArrayCardinality, NullBehavior: PhysicalEmptyOnNull, Extract: &PhysicalExtract{Source: PhysicalValue{Variable: targetVariable, Path: []string{"payload"}}, ResourceType: child.ResourceType, Selector: selector}}} + if filter.Operator != FilterExists && filter.Operator != FilterMissing { + key := fmt.Sprintf("%s_filter_%d_value", prefix, index+1) + if filter.Operator == FilterIn { + values := make([]any, 0, len(filter.Values)) + for _, value := range filter.Values { + literal, err := filterLiteral(value) + if err != nil { + return PhysicalSet{}, nil, err + } + values = append(values, literal) + } + physical.BindVars[key] = values + } else { + if len(filter.Values) == 0 { + return PhysicalSet{}, nil, fmt.Errorf("child filter %q has no value", filter.FieldRef) + } + literal, err := filterLiteral(filter.Values[0]) + if err != nil { + return PhysicalSet{}, nil, err + } + physical.BindVars[key] = literal + } + predicate.Right = &PhysicalValue{BindKey: key} + } + subplan.Operations = append(subplan.Operations, PhysicalOperation{Kind: PhysicalFilterOp, Source: PhysicalSource{SemanticNode: child.Alias, ResourceType: child.ResourceType, SemanticField: filter.FieldRef}, Filter: &PhysicalFilter{Expression: &PhysicalPredicateExpression{Kind: PhysicalComparisonPredicate, Comparison: &predicate}}}) + } + subplan.Return = PhysicalExpression{Kind: PhysicalValueExpression, Cardinality: PhysicalObjectCardinality, NullBehavior: PhysicalPreserveNull, Value: &PhysicalValue{Variable: targetVariable}} + set := PhysicalSet{Variable: prefix, Subplan: subplan, Unique: true, SortByKey: true} + projections := make([]PhysicalProjection, 0, len(child.Fields)) + for index, field := range child.Fields { + selection, err := ResolveSemanticField(child.ResourceType, child.Alias, index, field) + if err != nil { + return PhysicalSet{}, nil, err + } + projections = append(projections, PhysicalProjection{Name: projectionPrefix + "__" + field.Name, Expression: &PhysicalExpression{Kind: PhysicalExtractExpression, Cardinality: PhysicalArrayCardinality, NullBehavior: PhysicalEmptyOnNull, Extract: &PhysicalExtract{Source: PhysicalValue{Variable: set.Variable}, ResourceType: child.ResourceType, Selector: selection.Selector, Fallbacks: append([]Selector(nil), selection.Fallbacks...), Distinct: selection.Projection == ProjectionDistinctArray}}}) + } + for _, aggregate := range child.Aggregates { + expression, err := physicalAggregateExpression(physical, child.ResourceType, PhysicalValue{Variable: set.Variable}, aggregate, true) + if err != nil { + return PhysicalSet{}, nil, err + } + projections = append(projections, PhysicalProjection{Name: projectionPrefix + "__" + aggregate.Name, Expression: &expression}) + } + for _, pivot := range child.Pivots { + expression, err := physicalPivotExpression(physical, child.ResourceType, PhysicalValue{Variable: set.Variable}, pivot, true) + if err != nil { + return PhysicalSet{}, nil, err + } + projections = append(projections, PhysicalProjection{Name: projectionPrefix + "__" + pivot.Name, Expression: &expression}) + } + for _, slice := range child.Slices { + expression, err := physicalSliceExpression(physical, child.ResourceType, PhysicalValue{Variable: set.Variable}, slice, true) + if err != nil { + return PhysicalSet{}, nil, err + } + projections = append(projections, PhysicalProjection{Name: projectionPrefix + "__" + slice.Name, Expression: &expression}) + } + prepareRichChildSet(&set, child.ResourceType, projections) + return set, projections, nil +} + +// prepareRichChildSet adds a generic selector cache when at least two rich +// consumers read the same child relationship set. The cache is deliberately +// selector-based (not FHIR-resource-specific): any generated resource type +// with repeated aggregate, pivot, or slice selectors can use it. +func prepareRichChildSet(set *PhysicalSet, resourceType string, projections []PhysicalProjection) { + counts := map[string]int{} + selectors := map[string]Selector{} + add := func(selector Selector) { + key := physicalSelectorIdentity(selector) + counts[key]++ + selectors[key] = selector + } + var collect func(*PhysicalExpression) + collect = func(expression *PhysicalExpression) { + if expression == nil { + return + } + switch expression.Kind { + case PhysicalAggregateExpression: + if expression.Aggregate != nil { + if expression.Aggregate.Value != nil { + collect(expression.Aggregate.Value) + } + if expression.Aggregate.Predicate != nil && expression.Aggregate.Predicate.Comparison != nil { + collect(expression.Aggregate.Predicate.Comparison.LeftExpression) + } + } + case PhysicalPivotExpression: + if expression.Pivot != nil { + add(expression.Pivot.KeySelector) + add(expression.Pivot.ValueSelector) + } + case PhysicalSliceExpression: + if expression.Slice != nil { + if expression.Slice.Predicate != nil && expression.Slice.Predicate.Comparison != nil { + collect(expression.Slice.Predicate.Comparison.LeftExpression) + } + for index := range expression.Slice.Projections { + collect(&expression.Slice.Projections[index].Expression) + } + } + case PhysicalExtractExpression: + if expression.Extract != nil { + add(expression.Extract.Selector) + } + case PhysicalObjectExpression: + if expression.Object != nil { + for index := range expression.Object.Fields { + collect(&expression.Object.Fields[index].Expression) + } + } + } + } + for index := range projections { + collect(projections[index].Expression) + } + eligible := map[string]string{} + fields := make([]PhysicalPreparedField, 0) + // Map iteration order must not influence the physical plan. Stable field + // allocation keeps generated AQL and bind-variable names deterministic, + // which is important for explain fixtures and cache keys. + keys := make([]string, 0, len(counts)) + for key := range counts { + keys = append(keys, key) + } + sort.Strings(keys) + for _, key := range keys { + count := counts[key] + _, _, savings := estimatePreparedSelectorWork(count) + if savings <= 0 { + continue + } + field := fmt.Sprintf("__loom_prepared_%d", len(fields)) + eligible[key] = field + fields = append(fields, PhysicalPreparedField{Name: field, ResourceType: resourceType, Selector: selectors[key]}) + } + if len(fields) == 0 { + return + } + set.Prepared = &PhysicalPreparedSet{Variable: set.Variable + "_prepared", SourceSetVariable: set.Variable, Fields: fields} + var annotate func(*PhysicalExpression) + annotate = func(expression *PhysicalExpression) { + if expression == nil { + return + } + annotateExtract := func(extract *PhysicalExtract) { + if extract == nil || extract.Source.Variable != set.Variable { + return + } + // Fallback selectors are an ordered fallback chain. A prepared + // primary value alone cannot preserve that contract, so leave these + // extracts on the original renderer path until the prepared schema + // can represent fallback alternatives explicitly. + if len(extract.Fallbacks) == 0 { + if field, ok := eligible[physicalSelectorIdentity(extract.Selector)]; ok { + extract.Prepared = &PhysicalPreparedReference{SetVariable: set.Prepared.Variable, Field: field} + } + } + } + switch expression.Kind { + case PhysicalAggregateExpression: + if expression.Aggregate != nil { + if expression.Aggregate.Value != nil { + annotate(expression.Aggregate.Value) + } + if expression.Aggregate.Predicate != nil && expression.Aggregate.Predicate.Comparison != nil { + annotate(expression.Aggregate.Predicate.Comparison.LeftExpression) + } + } + case PhysicalPivotExpression: + if expression.Pivot != nil { + if field, ok := eligible[physicalSelectorIdentity(expression.Pivot.KeySelector)]; ok { + expression.Pivot.PreparedKey = &PhysicalPreparedReference{SetVariable: set.Prepared.Variable, Field: field} + } + if field, ok := eligible[physicalSelectorIdentity(expression.Pivot.ValueSelector)]; ok { + expression.Pivot.PreparedValue = &PhysicalPreparedReference{SetVariable: set.Prepared.Variable, Field: field} + } + } + case PhysicalSliceExpression: + if expression.Slice != nil { + if expression.Slice.Predicate != nil && expression.Slice.Predicate.Comparison != nil { + annotate(expression.Slice.Predicate.Comparison.LeftExpression) + } + for index := range expression.Slice.Projections { + annotate(&expression.Slice.Projections[index].Expression) + } + } + case PhysicalExtractExpression: + annotateExtract(expression.Extract) + case PhysicalObjectExpression: + if expression.Object != nil { + for index := range expression.Object.Fields { + annotate(&expression.Object.Fields[index].Expression) + } + } + } + } + for index := range projections { + annotate(projections[index].Expression) + } +} + +func physicalSelectorIdentity(selector Selector) string { + var b strings.Builder + for _, step := range selector.Steps { + b.WriteString(step.Field) + if step.Iterate { + b.WriteString("[]") + } + if step.Index != nil { + fmt.Fprintf(&b, "[%d]", *step.Index) + } + b.WriteByte('.') + } + if selector.Filter != nil { + b.WriteString("?" + selector.Filter.Field + "=" + selector.Filter.Needle) + } + return b.String() +} diff --git a/internal/dataframe/generic_physical_plan_test.go b/internal/dataframe/generic_physical_plan_test.go index 5110c09..35603b7 100644 --- a/internal/dataframe/generic_physical_plan_test.go +++ b/internal/dataframe/generic_physical_plan_test.go @@ -70,6 +70,334 @@ func TestBuildGenericPhysicalPlanEmptyAuthScopeIsExplicit(t *testing.T) { } } +func TestBuildAndRenderGenericPhysicalPlanOptionalChildFieldsAndFilters(t *testing.T) { + wantID := "file-1" + plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, Project: "p", Root: SemanticNode{Alias: "root", ResourceType: "Patient", Children: []SemanticNode{{ + Alias: "file", ResourceType: "DocumentReference", EdgeLabel: "subject_Patient", + Fields: []SemanticField{{Name: "file_id", FieldRef: "DocumentReference.id", Selector: Selector{Steps: []SelectorStep{{Field: "id"}}}, ValueMode: "FIRST"}}, + Filters: []TypedFilter{{FieldRef: "DocumentReference.id", Selector: "id", FieldKind: FilterString, Operator: FilterEquals, Values: []FilterValue{{Kind: FilterString, String: &wantID}}}}, + }}}, + }) + if err != nil { + t.Fatal(err) + } + var sets int + for _, operation := range plan.Operations { + if operation.Kind == PhysicalSetOp { + sets++ + } + } + if sets != 1 { + t.Fatalf("optional child was not lowered to one physical set: %#v", plan.Operations) + } + rendered, err := RenderPhysicalPlan(plan) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(rendered.Query, "LET child_set_1 = UNIQUE") || !strings.Contains(rendered.Query, "@child_set_1_filter_1_value") || !strings.Contains(rendered.Query, "FOR __item IN child_set_1") { + t.Fatalf("optional child fields/filter were not rendered:\n%s", rendered.Query) + } + if rendered.BindVars["child_set_1_filter_1_value"] != wantID { + t.Fatalf("child filter bind = %#v", rendered.BindVars["child_set_1_filter_1_value"]) + } +} + +func TestBuildAndRenderGenericPhysicalPlanNestedOptionalFieldsAndAggregates(t *testing.T) { + id := "file-1" + plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, Project: "p", Root: SemanticNode{ + Alias: "root", ResourceType: "Patient", + Children: []SemanticNode{{ + Alias: "specimen", ResourceType: "Specimen", EdgeLabel: "subject_Patient", + Children: []SemanticNode{{ + Alias: "file", ResourceType: "DocumentReference", EdgeLabel: "subject_Specimen", + Fields: []SemanticField{{Name: "id", Selector: Selector{Steps: []SelectorStep{{Field: "id"}}}, ValueMode: "FIRST"}}, + Filters: []TypedFilter{{FieldRef: "DocumentReference.id", Selector: "id", FieldKind: FilterString, Operator: FilterEquals, Values: []FilterValue{{Kind: FilterString, String: &id}}}}, + Aggregates: []SemanticAggregate{{Name: "count", Operation: "COUNT"}}, + }}, + }}, + }, + }) + if err != nil { + t.Fatal(err) + } + if err := plan.Validate(); err != nil { + t.Fatalf("nested physical plan does not validate: %v", err) + } + rendered, err := RenderPhysicalPlan(plan) + if err != nil { + t.Fatal(err) + } + for _, want := range []string{ + "LET child_set_1 = UNIQUE((", "FOR child_set_2_node, child_set_2_edge IN 1..1 INBOUND __loom_physical_parent_set_2 @@child_set_2_edge_collection", + "@child_set_2_filter_1_value", "LENGTH(child_set_2)", "FOR __item IN child_set_2", + } { + if !strings.Contains(rendered.Query, want) { + t.Fatalf("nested physical query missing %q:\n%s", want, rendered.Query) + } + } + foundNestedName := false + for key, value := range rendered.BindVars { + if strings.HasPrefix(key, "__loom_physical_projection_") && value == "specimen__file__id" { + foundNestedName = true + } + } + if !foundNestedName { + t.Fatalf("nested field projection did not retain path-qualified name: %#v\n%s", rendered.BindVars, rendered.Query) + } +} + +func TestBuildAndRenderGenericPhysicalPlanAggregates(t *testing.T) { + gender := Selector{Steps: []SelectorStep{{Field: "gender"}}} + plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, Project: "p", Root: SemanticNode{ + Alias: "root", ResourceType: "Patient", + Aggregates: []SemanticAggregate{ + {Name: "patient_count", Operation: "COUNT"}, + {Name: "genders", Operation: "DISTINCT_VALUES", Selector: &gender}, + }, + Children: []SemanticNode{{ + Alias: "specimen", ResourceType: "Specimen", EdgeLabel: "subject_Patient", + Aggregates: []SemanticAggregate{{Name: "count", Operation: "COUNT"}}, + }}, + }, + }) + if err != nil { + t.Fatal(err) + } + rendered, err := RenderPhysicalPlan(plan) + if err != nil { + t.Fatal(err) + } + for _, want := range []string{"LENGTH([root])", "SORTED_UNIQUE(FLATTEN(", "LENGTH(child_set_1)", "[@__loom_physical_projection_1_name]"} { + if !strings.Contains(rendered.Query, want) { + t.Fatalf("aggregate query missing %q:\n%s", want, rendered.Query) + } + } + if got := rendered.BindVars["__loom_physical_projection_2_name"]; got != "genders" { + t.Fatalf("projection bind = %#v", got) + } +} + +func TestBuildAndRenderGenericPhysicalPlanRepresentativeSlices(t *testing.T) { + gender := Selector{Steps: []SelectorStep{{Field: "gender"}}} + title := Selector{Steps: []SelectorStep{{Field: "content", Iterate: true}, {Field: "attachment"}, {Field: "title"}}} + plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, Project: "p", Root: SemanticNode{ + Alias: "root", ResourceType: "Patient", + Slices: []SemanticSlice{{Name: "representative", Limit: 2, Predicate: &gender, PredicateEquals: "female", Fields: []SemanticField{{Name: "gender", Selector: gender, ValueMode: "FIRST"}}}}, + Children: []SemanticNode{{Alias: "file", ResourceType: "DocumentReference", EdgeLabel: "subject_Patient", Slices: []SemanticSlice{{Name: "representative_files", Limit: 1, Fields: []SemanticField{{Name: "title", Selector: title, ValueMode: "FIRST"}}}}}}, + }, + }) + if err != nil { + t.Fatal(err) + } + rendered, err := RenderPhysicalPlan(plan) + if err != nil { + t.Fatal(err) + } + for _, want := range []string{"SORT __loom_physical_slice_item._key ASC", "LIMIT @slice_root_representative_limit", "LIMIT @slice_child_set_1_representative_files_limit", "@slice_root_representative_predicate_equals", "FOR __loom_physical_slice_item_1 IN child_set_1"} { + if !strings.Contains(rendered.Query, want) { + t.Fatalf("slice query missing %q:\n%s", want, rendered.Query) + } + } + if got := rendered.BindVars["slice_root_representative_limit"]; got != 2 { + t.Fatalf("root slice limit bind = %#v", got) + } + if got := rendered.BindVars["slice_child_set_1_representative_files_limit"]; got != 1 { + t.Fatalf("child slice limit bind = %#v", got) + } +} + +func TestBuildAndRenderGenericPhysicalPlanAggregatePredicates(t *testing.T) { + status := Selector{Steps: []SelectorStep{{Field: "id"}}} + gender := Selector{Steps: []SelectorStep{{Field: "gender"}}} + plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, Project: "p", Root: SemanticNode{ + Alias: "root", ResourceType: "Patient", + Aggregates: []SemanticAggregate{{Name: "female_count", Operation: "COUNT", Predicate: &gender, PredicateEquals: "female"}}, + Children: []SemanticNode{{ + Alias: "specimen", ResourceType: "Specimen", EdgeLabel: "subject_Patient", + Aggregates: []SemanticAggregate{{Name: "available_count", Operation: "COUNT_DISTINCT", Selector: &status, Predicate: &status, PredicateEquals: "available"}}, + }}, + }, + }) + if err != nil { + t.Fatal(err) + } + rendered, err := RenderPhysicalPlan(plan) + if err != nil { + t.Fatal(err) + } + if strings.Count(rendered.Query, "FOR __loom_physical_aggregate_item") < 2 { + t.Fatalf("aggregate predicates did not render per-item filters:\n%s", rendered.Query) + } + if rendered.BindVars["aggregate_root_female_count_predicate_equals"] != "female" || rendered.BindVars["aggregate_child_set_1_available_count_predicate_equals"] != "available" { + t.Fatalf("predicate binds missing: %#v", rendered.BindVars) + } + compiled, err := CompileRequest(Builder{ + Project: "p", RootResourceType: "Patient", + Aggregates: []AggregateSelect{{Name: "female_count", Operation: "COUNT", PredicatePath: "gender", PredicateEquals: "female"}}, + }, 1) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(compiled.Query, "FOR __loom_physical_aggregate_item") { + t.Fatalf("aggregate predicate request did not use physical renderer:\n%s", compiled.Query) + } +} + +func TestBuildGenericPhysicalPlanPreparesSelectorsAcrossRichConsumers(t *testing.T) { + status := Selector{Steps: []SelectorStep{{Field: "id"}}} + plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, Project: "p", Root: SemanticNode{ + Alias: "root", ResourceType: "Patient", + Children: []SemanticNode{{ + Alias: "condition", ResourceType: "Condition", EdgeLabel: "subject_Patient", + Aggregates: []SemanticAggregate{{Name: "status_count", Operation: "COUNT_DISTINCT", Selector: &status}}, + Pivots: []SemanticPivot{{Name: "status_values", ColumnSelector: status, ValueSelector: status, Columns: []string{"active", "resolved"}}}, + Slices: []SemanticSlice{{Name: "representative", Limit: 1, Fields: []SemanticField{{Name: "status", Selector: status}}}}, + }}, + }, + }) + if err != nil { + t.Fatal(err) + } + if err := plan.Validate(); err != nil { + t.Fatalf("prepared physical plan does not validate: %v", err) + } + var child *PhysicalSet + for index := range plan.Operations { + if plan.Operations[index].Kind == PhysicalSetOp && plan.Operations[index].Set != nil { + child = plan.Operations[index].Set + break + } + } + if child == nil || child.Prepared == nil { + t.Fatalf("expected rich child set to have a prepared selector projection: %#v", child) + } + if len(child.Prepared.Fields) != 1 || child.Prepared.Fields[0].Selector.CanonicalPath() != "id" { + t.Fatalf("prepared selector fields = %#v, want one stable id field", child.Prepared.Fields) + } + preparedSet := child.Prepared.Variable + var preparedRefs int + var check func(PhysicalExpression) + check = func(expression PhysicalExpression) { + switch expression.Kind { + case PhysicalAggregateExpression: + if expression.Aggregate != nil && expression.Aggregate.Value != nil && expression.Aggregate.Value.Extract != nil && expression.Aggregate.Value.Extract.Prepared != nil { + preparedRefs++ + } + case PhysicalPivotExpression: + if expression.Pivot != nil && expression.Pivot.PreparedKey != nil && expression.Pivot.PreparedValue != nil { + preparedRefs += 2 + } + case PhysicalSliceExpression: + if expression.Slice != nil { + for _, projection := range expression.Slice.Projections { + if projection.Expression.Extract != nil && projection.Expression.Extract.Prepared != nil { + preparedRefs++ + } + } + } + } + } + for _, operation := range plan.Operations { + if operation.Kind != PhysicalReturnOp || operation.Return == nil { + continue + } + for _, projection := range operation.Return.Projections { + if projection.Expression != nil { + check(*projection.Expression) + } + } + } + if preparedRefs != 4 { + t.Fatalf("prepared rich consumer references = %d, want 4", preparedRefs) + } + renderedA, err := RenderPhysicalPlan(plan) + if err != nil { + t.Fatal(err) + } + renderedB, err := RenderPhysicalPlan(plan) + if err != nil { + t.Fatal(err) + } + if renderedA.Query != renderedB.Query { + t.Fatalf("prepared rendering is nondeterministic:\nA:\n%s\nB:\n%s", renderedA.Query, renderedB.Query) + } + if !strings.Contains(renderedA.Query, "LET "+preparedSet+" = (") { + t.Fatalf("prepared selector set was not rendered:\n%s", renderedA.Query) + } +} + +func TestPreparedSelectorsPreserveFallbackExtraction(t *testing.T) { + primary := Selector{Steps: []SelectorStep{{Field: "id"}}} + fallback := Selector{Steps: []SelectorStep{{Field: "code"}}} + plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, Project: "p", Root: SemanticNode{ + Alias: "root", ResourceType: "Patient", + Children: []SemanticNode{{ + Alias: "condition", ResourceType: "Condition", EdgeLabel: "subject_Patient", + Fields: []SemanticField{{Name: "status_with_fallback", Selector: primary, Fallbacks: []Selector{fallback}}}, + Aggregates: []SemanticAggregate{{Name: "status_count", Operation: "COUNT_DISTINCT", Selector: &primary}}, + }}, + }, + }) + if err != nil { + t.Fatal(err) + } + var child *PhysicalSet + for index := range plan.Operations { + if plan.Operations[index].Kind == PhysicalSetOp && plan.Operations[index].Set != nil { + child = plan.Operations[index].Set + break + } + } + if child == nil || child.Prepared == nil { + t.Fatalf("expected primary selector to be prepared: %#v", child) + } + for _, operation := range plan.Operations { + if operation.Kind != PhysicalReturnOp || operation.Return == nil { + continue + } + for _, projection := range operation.Return.Projections { + if projection.Name == "condition__status_with_fallback" && projection.Expression != nil && projection.Expression.Extract != nil { + if projection.Expression.Extract.Prepared != nil { + t.Fatalf("fallback field incorrectly used prepared primary value: %#v", projection.Expression.Extract.Prepared) + } + if len(projection.Expression.Extract.Fallbacks) != 1 { + t.Fatalf("fallback field lost fallback selectors: %#v", projection.Expression.Extract.Fallbacks) + } + } + } + } +} + +func TestBuildAndRenderGenericPhysicalPlanPivots(t *testing.T) { + key := Selector{Steps: []SelectorStep{{Field: "code"}, {Field: "coding", Iterate: true}, {Field: "display"}}} + value := Selector{Steps: []SelectorStep{{Field: "text"}}} + plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, Project: "p", Root: SemanticNode{Alias: "root", ResourceType: "Condition", Pivots: []SemanticPivot{{Name: "lab_values", ColumnSelector: key, ValueSelector: value, Columns: []string{"female", "male"}}}}, + }) + if err != nil { + t.Fatal(err) + } + rendered, err := RenderPhysicalPlan(plan) + if err != nil { + t.Fatal(err) + } + for _, want := range []string{"MERGE(", "COLLECT __pivot_key = __pair.key", "POSITION(@pivot_root_lab_values_columns", "lab_values"} { + if !strings.Contains(rendered.Query, want) && want != "lab_values" { + t.Fatalf("pivot query missing %q:\n%s", want, rendered.Query) + } + } + if got := rendered.BindVars["pivot_root_lab_values_columns"]; got == nil { + t.Fatalf("pivot columns bind missing: %#v", rendered.BindVars) + } +} + func TestBuildGenericPhysicalPlanRejectsUnsupportedSemanticFeatures(t *testing.T) { tests := []struct { name string @@ -77,8 +405,7 @@ func TestBuildGenericPhysicalPlanRejectsUnsupportedSemanticFeatures(t *testing.T want string }{ {"unknown root", SemanticNode{Alias: "root", ResourceType: "Unknown"}, "not represented"}, - {"root field", SemanticNode{Alias: "root", ResourceType: "Patient", Fields: []SemanticField{{Name: "gender"}}}, "not supported"}, - {"child filter", SemanticNode{Alias: "root", ResourceType: "Patient", Children: []SemanticNode{{Alias: "specimen", ResourceType: "Specimen", EdgeLabel: "subject_Patient", Filters: []TypedFilter{{FieldRef: "status"}}}}}, "not supported"}, + {"child filter with incomplete type metadata", SemanticNode{Alias: "root", ResourceType: "Patient", Children: []SemanticNode{{Alias: "specimen", ResourceType: "Specimen", EdgeLabel: "subject_Patient", Filters: []TypedFilter{{FieldRef: "status"}}}}}, "unknown filter field kind"}, {"unknown traversal", SemanticNode{Alias: "root", ResourceType: "Patient", Children: []SemanticNode{{Alias: "medication", ResourceType: "Medication", EdgeLabel: "missing"}}}, "not represented"}, } for _, test := range tests { diff --git a/internal/dataframe/grain.go b/internal/dataframe/grain.go index 9d63511..c6ab723 100644 --- a/internal/dataframe/grain.go +++ b/internal/dataframe/grain.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/calypr/loom/internal/fhirschema" + "github.com/calypr/loom/fhirschema" ) // RowGrain identifies the resource represented by one output row. diff --git a/internal/dataframe/lowered_compile.go b/internal/dataframe/lowered_compile.go deleted file mode 100644 index d3bc38a..0000000 --- a/internal/dataframe/lowered_compile.go +++ /dev/null @@ -1,839 +0,0 @@ -package dataframe - -import ( - "encoding/json" - "fmt" - "strings" -) - -type setMode string - -const ( - setModeNode setMode = "node" - setModeObject setMode = "object" -) - -func compileLowered(builder Builder, limit int) (CompiledQuery, error) { - genericSetRoutes, err := resolveGenericLoweredStorageRoutes(builder) - if err != nil { - return CompiledQuery{}, err - } - c := &compiler{ - builder: builder, - bindVars: map[string]any{ - "project": builder.Project, - datasetGenerationBindKey: datasetGenerationBindValue(builder.DatasetGeneration), - "auth_resource_paths": builder.AuthResourcePaths, - "auth_resource_paths_unrestricted": builderAuthScopeUnrestricted(builder), - }, - columns: []string{"_key"}, - pivotFields: []string{}, - pivotExprs: map[string]string{}, - genericSetRoutes: genericSetRoutes, - } - if limit > 0 { - c.bindVars["limit"] = limit - } - setModes := map[string]setMode{} - rootVar := "root" - lets := []string{} - objectLines := []string{} - - for _, set := range builder.Sets { - let, mode, err := c.compileNamedSet(rootVar, set, setModes) - if err != nil { - return CompiledQuery{}, err - } - lets = append(lets, let) - setModes[set.Name] = mode - } - rootFilter, err := c.compileTypedFilters(rootVar+".payload", builder.Filters) - if err != nil { - return CompiledQuery{}, err - } - requiredMatchFilters, err := c.compileRequiredTraversalMatches(rootVar, builder.RequiredTraversalMatches) - if err != nil { - return CompiledQuery{}, err - } - - for _, field := range builder.Fields { - sel, err := ParseSelector(field.Select) - if err != nil { - return CompiledQuery{}, fmt.Errorf("root field %q selector: %w", field.Name, err) - } - expr, err := c.compileRootFieldSelect(rootVar+".payload", field, sel) - if err != nil { - return CompiledQuery{}, err - } - objectLines = append(objectLines, fmt.Sprintf(" %s: %s", quoteKey(field.Name), expr)) - c.columns = append(c.columns, field.Name) - } - for _, pivot := range builder.Pivots { - keySel, err := ParseSelector(pivot.ColumnSelect) - if err != nil { - return CompiledQuery{}, fmt.Errorf("root pivot %q key selector: %w", pivot.Name, err) - } - valueSel, err := ParseSelector(pivot.ValueSelect) - if err != nil { - return CompiledQuery{}, fmt.Errorf("root pivot %q value selector: %w", pivot.Name, err) - } - colName := sanitizeColumnName(pivot.Name) - expr, err := c.compileRootPivot(rootVar+".payload", keySel, valueSel, pivot.Columns) - if err != nil { - return CompiledQuery{}, err - } - objectLines = append(objectLines, fmt.Sprintf(" %s: %s", quoteKey(colName), expr)) - c.columns = append(c.columns, colName) - c.pivotFields = append(c.pivotFields, colName) - } - for _, agg := range builder.Aggregates { - expr, err := c.compileRootAggregateExpr(rootVar+".payload", agg) - if err != nil { - return CompiledQuery{}, err - } - objectLines = append(objectLines, fmt.Sprintf(" %s: %s", quoteKey(agg.Name), expr)) - c.columns = append(c.columns, agg.Name) - } - for _, step := range builder.Traversals { - if err := c.compileTraversal(rootVar, false, step, &lets, &objectLines); err != nil { - return CompiledQuery{}, err - } - } - pivotLets, pivotExprs, err := c.compileDerivedPivotMapLets(rootVar, builder.DerivedFields, setModes) - if err != nil { - return CompiledQuery{}, err - } - lets = append(lets, pivotLets...) - for key, value := range pivotExprs { - c.pivotExprs[key] = value - } - for _, field := range builder.DerivedFields { - expr, err := c.compileDerivedField(rootVar, field, setModes) - if err != nil { - return CompiledQuery{}, err - } - objectLines = append(objectLines, fmt.Sprintf(" %s: %s", quoteKey(field.Name), expr)) - c.columns = append(c.columns, field.Name) - if strings.ToUpper(strings.TrimSpace(field.Operation)) == DerivedOpPivot { - c.pivotFields = append(c.pivotFields, field.Name) - } - } - for _, slice := range builder.RepresentativeSlices { - expr, err := c.compileRepresentativeSlice(slice, setModes) - if err != nil { - return CompiledQuery{}, err - } - objectLines = append(objectLines, fmt.Sprintf(" %s: %s", quoteKey(slice.Name), expr)) - c.columns = append(c.columns, slice.Name) - } - for _, slice := range builder.Slices { - expr, err := c.compileRootSlice(rootVar, slice) - if err != nil { - return CompiledQuery{}, err - } - objectLines = append(objectLines, fmt.Sprintf(" %s: %s", quoteKey(slice.Name), expr)) - c.columns = append(c.columns, slice.Name) - } - - var sb strings.Builder - sb.WriteString(fmt.Sprintf("FOR %s IN %s\n", rootVar, builder.RootResourceType)) - sb.WriteString(fmt.Sprintf(" FILTER %s.project == @project\n", rootVar)) - sb.WriteString(fmt.Sprintf(" FILTER %s.%s == @%s\n", rootVar, datasetGenerationField, datasetGenerationBindKey)) - sb.WriteString(fmt.Sprintf(" FILTER @auth_resource_paths_unrestricted == true OR %s.auth_resource_path IN @auth_resource_paths\n", rootVar)) - if rootFilter != "true" { - sb.WriteString(fmt.Sprintf(" FILTER %s\n", rootFilter)) - } - for _, matchFilter := range requiredMatchFilters { - sb.WriteString(fmt.Sprintf(" FILTER %s\n", matchFilter)) - } - sb.WriteString(fmt.Sprintf(" SORT %s._key\n", rootVar)) - if limit > 0 { - sb.WriteString(" LIMIT @limit\n") - } - for _, let := range lets { - sb.WriteString(let) - sb.WriteByte('\n') - } - sb.WriteString(" RETURN {\n") - sb.WriteString(fmt.Sprintf(" %s: %s._key", quoteKey("_key"), rootVar)) - for _, line := range objectLines { - sb.WriteString(",\n") - sb.WriteString(line) - } - sb.WriteString("\n }\n") - return CompiledQuery{ - Project: builder.Project, - DatasetGeneration: normalizeDatasetGeneration(builder.DatasetGeneration), - RootResourceType: builder.RootResourceType, - AuthResourcePaths: append([]string(nil), builder.AuthResourcePaths...), - PlanMode: planMode(builder.PlanHint), - PlanProfile: planProfile(builder.PlanHint), - NamedSetCount: planNamedSetCount(builder.PlanHint), - FileSummaries: planFileSummaries(builder.PlanHint), - StudyLookup: planStudyLookup(builder.PlanHint), - OptimizationRules: planAppliedRules(builder.PlanHint), - RowIdentity: planRowIdentity(builder.PlanHint), - Query: sb.String(), - BindVars: c.bindVars, - Columns: append([]string(nil), c.columns...), - PivotFields: append([]string(nil), c.pivotFields...), - Limit: limit, - }, nil -} - -func (c *compiler) compileNamedSet(rootVar string, set NamedSet, modes map[string]setMode) (string, setMode, error) { - name := sanitizeColumnName(set.Name) - switch strings.ToUpper(strings.TrimSpace(set.Kind)) { - case SetKindTraverse: - source := rootVar - sourceMode := setModeNode - if set.Source != "" && set.Source != "root" { - source = sanitizeColumnName(set.Source) - sourceMode = modes[set.Source] - _ = sourceMode - } - labelBind := c.newBind(name+"_label", set.Label) - var toFilter string - if set.ToResourceType != "" && !set.AllTargetTypes { - toBind := c.newBind(name+"_to", set.ToResourceType) - toFilter = fmt.Sprintf(" FILTER __node.resourceType == @%s", toBind) - } - filters, err := c.compileTypedFilters("__node.payload", set.Filters) - if err != nil { - return "", "", fmt.Errorf("compile filters for set %q: %w", set.Name, err) - } - if filters != "true" { - toFilter += " FILTER " + filters - } - edgeTypeFilter := "" - // A shared sibling prefix intentionally spans several target resource - // types. Its ToResourceType is only a route-validation anchor, so an - // edge type predicate here would discard every sibling except that - // anchor. Typed subsets apply their resourceType filters afterwards. - if route, generic := c.genericSetRoutes[set.Name]; generic && !set.AllTargetTypes { - edgeTypeField := route.targetEdgeTypeField() - if edgeTypeField == "" { - return "", "", fmt.Errorf("compile generic traversal set %q: %w: route direction %q has no fhir_edge target type field", set.Name, ErrUnsupportedStorageRoute, route.Direction) - } - edgeTypeBind := c.newBind(name+"_edge_target_type", set.ToResourceType) - edgeTypeFilter = fmt.Sprintf(" FILTER __edge.%s == @%s", edgeTypeField, edgeTypeBind) - } - expr := c.compileTraverseSetSource(source, set.Source != "" && set.Source != "root", set.Direction, labelBind, edgeTypeFilter, toFilter) - setExpr := expr - if set.Unique { - setExpr = fmt.Sprintf("UNIQUE(%s)", setExpr) - } - if set.SortField != "" { - setExpr = fmt.Sprintf("(FOR __item IN %s SORT __item.%s RETURN __item)", setExpr, set.SortField) - } - return fmt.Sprintf(" LET %s = %s", name, setExpr), setModeNode, nil - case SetKindFilter: - source := sanitizeColumnName(set.Source) - lines := []string{fmt.Sprintf("FOR __item IN %s", source)} - if set.MatchResourceType != "" { - typeBind := c.newBind(name+"_match", set.MatchResourceType) - lines = append(lines, fmt.Sprintf(" FILTER __item.resourceType == @%s", typeBind)) - } - filters, err := c.compileTypedFilters("__item.payload", set.Filters) - if err != nil { - return "", "", fmt.Errorf("compile filters for set %q: %w", set.Name, err) - } - if filters != "true" { - lines = append(lines, " FILTER "+filters) - } - lines = append(lines, " RETURN __item") - setExpr := "(\n " + strings.Join(lines, "\n ") + "\n )" - if set.Unique { - setExpr = fmt.Sprintf("UNIQUE(%s)", setExpr) - } - // UNIQUE is allowed to choose its own internal implementation order. - // Reapply the requested stable order after deduplication rather than - // assuming the order of the input subquery survives it. - if set.SortField != "" { - setExpr = fmt.Sprintf("(FOR __item IN %s SORT __item.%s RETURN __item)", setExpr, set.SortField) - } - return fmt.Sprintf(" LET %s = %s", name, setExpr), modes[set.Source], nil - case SetKindUnion: - parts := make([]string, 0, len(set.Sources)) - mode := setModeNode - for i, src := range set.Sources { - if i == 0 { - mode = modes[src] - } - parts = append(parts, sanitizeColumnName(src)) - } - return fmt.Sprintf(" LET %s = UNIQUE(FLATTEN([%s]))", name, strings.Join(parts, ", ")), mode, nil - case SetKindClassifyDocumentReference: - source := sanitizeColumnName(set.Source) - return " LET " + name + " = " + compileDocumentReferenceSummarySet(source), setModeObject, nil - case SetKindLookupStudy: - source := sanitizeColumnName(set.Source) - return " LET " + name + " = " + compileStudyLookupSet(rootVar, source), setModeObject, nil - default: - return "", "", fmt.Errorf("unsupported set kind %q", set.Kind) - } -} - -type pivotMapGroup struct { - letName string - sourceExpr string - mode setMode - keySelect string - valueSelect string - columns []string - columnSet map[string]struct{} - unrestricted bool -} - -func (c *compiler) compileDerivedPivotMapLets(rootVar string, fields []DerivedField, modes map[string]setMode) ([]string, map[string]string, error) { - groups := map[string]*pivotMapGroup{} - order := make([]string, 0, 8) - fieldExprs := make(map[string]string) - groupIndex := 0 - - for _, field := range fields { - if strings.ToUpper(strings.TrimSpace(field.Operation)) != DerivedOpPivot { - continue - } - sourceExpr := "" - mode := setModeNode - switch strings.TrimSpace(field.Source) { - case "", "root": - sourceExpr = "[" + rootVar + "]" - mode = setModeNode - default: - sourceExpr = sanitizeColumnName(field.Source) - mode = modes[field.Source] - } - groupKey := strings.Join([]string{sourceExpr, string(mode), field.PivotKeySelect, field.PivotValueSelect}, "|") - group, ok := groups[groupKey] - if !ok { - group = &pivotMapGroup{ - letName: fmt.Sprintf("__pivot_map_%d", groupIndex), - sourceExpr: sourceExpr, - mode: mode, - keySelect: field.PivotKeySelect, - valueSelect: field.PivotValueSelect, - columns: []string{}, - columnSet: map[string]struct{}{}, - } - groupIndex++ - groups[groupKey] = group - order = append(order, groupKey) - } - if len(field.PivotColumns) == 0 { - group.unrestricted = true - } - for _, col := range field.PivotColumns { - if _, ok := group.columnSet[col]; ok { - continue - } - group.columnSet[col] = struct{}{} - group.columns = append(group.columns, col) - } - fieldExprs[field.Name] = c.compilePivotMapProjection(group.letName, field.PivotColumns) - } - - lets := make([]string, 0, len(order)) - for _, key := range order { - group := groups[key] - keySel, err := ParseSelector(group.keySelect) - if err != nil { - return nil, nil, err - } - valueSel, err := ParseSelector(group.valueSelect) - if err != nil { - return nil, nil, err - } - payloadVar := setPayloadVar("__item", group.mode) - keyExpr := compileSelectorArrayExpr(payloadVar, keySel, c) - valueExpr := compileSelectorArrayExpr(payloadVar, valueSel, c) - filterLine := "" - if !group.unrestricted && len(group.columns) > 0 { - colsBind := c.newBind(group.letName+"_cols", append([]string(nil), group.columns...)) - filterLine = fmt.Sprintf("\n FILTER POSITION(@%s, __key, true)", colsBind) - } - let := fmt.Sprintf(` LET %s = MERGE( - FOR __pair IN ( - FOR __item IN %s - LET __keys = UNIQUE(%s) - LET __values = %s - FILTER LENGTH(__values) > 0 - FOR __key IN __keys%s - RETURN { key: __key, values: __values } - ) - COLLECT __key = __pair.key INTO __group - LET __flat_values = SORTED_UNIQUE(FLATTEN(__group[*].__pair.values)) - FILTER LENGTH(__flat_values) > 0 - RETURN { [__key]: FIRST(__flat_values) } - )`, group.letName, group.sourceExpr, keyExpr, valueExpr, filterLine) - lets = append(lets, let) - } - return lets, fieldExprs, nil -} - -func (c *compiler) compilePivotMapProjection(mapVar string, columns []string) string { - if len(columns) == 0 { - return mapVar - } - colsBind := c.newBind(mapVar+"_projection_cols", append([]string(nil), columns...)) - return fmt.Sprintf(`MERGE( - FOR __key IN @%s - FILTER HAS(%s, __key) - RETURN { [__key]: %s[__key] } - )`, colsBind, mapVar, mapVar) -} - -func (c *compiler) compileTraverseSetSource(source string, sourceIsSet bool, direction string, labelBind string, edgeTypeFilter string, toFilter string) string { - direction = strings.ToUpper(strings.TrimSpace(direction)) - if direction == "" { - direction = "INBOUND" - } - if sourceIsSet { - return fmt.Sprintf("(FLATTEN(FOR __parent IN %s FOR __node, __edge IN 1..1 %s __parent fhir_edge FILTER __edge.project == @project FILTER __node.project == @project FILTER __edge.%s == @%s FILTER __node.%s == @%s FILTER @auth_resource_paths_unrestricted == true OR (__edge.auth_resource_path IN @auth_resource_paths AND __node.auth_resource_path IN @auth_resource_paths) FILTER __edge.label == @%s%s%s RETURN [__node]))", source, direction, datasetGenerationField, datasetGenerationBindKey, datasetGenerationField, datasetGenerationBindKey, labelBind, edgeTypeFilter, toFilter) - } - return fmt.Sprintf("(FOR __node, __edge IN 1..1 %s %s fhir_edge FILTER __edge.project == @project FILTER __node.project == @project FILTER __edge.%s == @%s FILTER __node.%s == @%s FILTER @auth_resource_paths_unrestricted == true OR (__edge.auth_resource_path IN @auth_resource_paths AND __node.auth_resource_path IN @auth_resource_paths) FILTER __edge.label == @%s%s%s RETURN __node)", direction, source, datasetGenerationField, datasetGenerationBindKey, datasetGenerationField, datasetGenerationBindKey, labelBind, edgeTypeFilter, toFilter) -} - -func (c *compiler) compileDerivedField(rootVar string, field DerivedField, modes map[string]setMode) (string, error) { - if strings.ToUpper(strings.TrimSpace(field.Operation)) == DerivedOpPivot { - if expr, ok := c.pivotExprs[field.Name]; ok { - return expr, nil - } - } - switch strings.ToUpper(strings.TrimSpace(field.Operation)) { - case DerivedOpConst: - return literalExpr(field.ConstValue), nil - case DerivedOpRootField: - sel, err := ParseSelector(field.Select) - if err != nil { - return "", err - } - if sel.Filter == nil && selectorHasNoArrays(sel) { - return compileDirectExpr(rootVar, sel.Steps), nil - } - return "FIRST" + compileSelectorArrayExpr(rootVar, sel, c), nil - case DerivedOpCount: - return fmt.Sprintf("LENGTH(%s)", sanitizeColumnName(field.Source)), nil - case DerivedOpCountDistinct: - uniqueExpr, err := c.compileUniqueField(rootVar, field, modes) - if err != nil { - return "", err - } - return fmt.Sprintf("LENGTH(%s)", uniqueExpr), nil - case DerivedOpMin, DerivedOpMax: - values, err := c.compileAllField(rootVar, field, modes) - if err != nil { - return "", err - } - return fmt.Sprintf("%s(%s)", strings.ToUpper(strings.TrimSpace(field.Operation)), values), nil - case DerivedOpCountWhere: - return fmt.Sprintf("LENGTH(FOR __item IN %s FILTER %s RETURN 1)", sanitizeColumnName(field.Source), c.compilePredicateExpr("__item", modes[field.Source], field.Predicate, field.PredicatePath, field.PredicateEquals)), nil - case DerivedOpAny: - if strings.TrimSpace(field.Predicate) == "" && strings.TrimSpace(field.PredicatePath) == "" { - return fmt.Sprintf("LENGTH(%s) > 0", sanitizeColumnName(field.Source)), nil - } - return fmt.Sprintf("LENGTH(FOR __item IN %s FILTER %s LIMIT 1 RETURN 1) > 0", sanitizeColumnName(field.Source), c.compilePredicateExpr("__item", modes[field.Source], field.Predicate, field.PredicatePath, field.PredicateEquals)), nil - case DerivedOpFirstNonNull: - return c.compileFirstNonNullField(rootVar, field, modes) - case DerivedOpAll: - return c.compileAllField(rootVar, field, modes) - case DerivedOpUnique: - return c.compileUniqueField(rootVar, field, modes) - case DerivedOpPivot: - return c.compilePivotField(field, modes) - default: - return "", fmt.Errorf("unsupported derived field operation %q", field.Operation) - } -} - -func (c *compiler) compileAllField(rootVar string, field DerivedField, modes map[string]setMode) (string, error) { - selects := append([]string{field.Select}, field.FallbackSelects...) - if field.Source == "root" || field.Source == "" { - return c.compileSelectorArrayForSelects(rootVar+".payload", selects), nil - } - setVar := sanitizeColumnName(field.Source) - mode := modes[field.Source] - return fmt.Sprintf(`FLATTEN( - FOR __item IN %s - RETURN %s - )`, setVar, c.compileSelectorArrayForSelects(setPayloadVar("__item", mode), selects)), nil -} - -func (c *compiler) compileFirstNonNullField(rootVar string, field DerivedField, modes map[string]setMode) (string, error) { - selects := append([]string{field.Select}, field.FallbackSelects...) - if field.Source == "root" || field.Source == "" { - return c.compileFirstNonNullExpr(rootVar+".payload", selects), nil - } - setVar := sanitizeColumnName(field.Source) - mode := modes[field.Source] - return fmt.Sprintf(`FIRST( - FOR __item IN %s - LET __value = %s - FILTER __value != null - RETURN __value - )`, setVar, c.compileFirstNonNullExpr(setPayloadVar("__item", mode), selects)), nil -} - -func (c *compiler) compileUniqueField(rootVar string, field DerivedField, modes map[string]setMode) (string, error) { - selects := append([]string{field.Select}, field.FallbackSelects...) - if field.Source == "root" || field.Source == "" { - return fmt.Sprintf("SORTED_UNIQUE(%s)", c.compileSelectorArrayForSelects(rootVar+".payload", selects)), nil - } - setVar := sanitizeColumnName(field.Source) - mode := modes[field.Source] - return fmt.Sprintf(`SORTED_UNIQUE(FLATTEN( - FOR __item IN %s - RETURN %s - ))`, setVar, c.compileSelectorArrayForSelects(setPayloadVar("__item", mode), selects)), nil -} - -func (c *compiler) compilePivotField(field DerivedField, modes map[string]setMode) (string, error) { - setVar := sanitizeColumnName(field.Source) - mode := modes[field.Source] - keySel, err := ParseSelector(field.PivotKeySelect) - if err != nil { - return "", err - } - valueSel, err := ParseSelector(field.PivotValueSelect) - if err != nil { - return "", err - } - return c.compilePivotMapExpr("FOR __item IN "+setVar, setPayloadVar("__item", mode), keySel, valueSel, field.PivotColumns) -} - -func (c *compiler) compileRepresentativeSlice(slice RepresentativeSlice, modes map[string]setMode) (string, error) { - setVar := sanitizeColumnName(slice.SourceSet) - mode := modes[slice.SourceSet] - filter := "true" - if strings.TrimSpace(slice.Predicate) != "" || strings.TrimSpace(slice.PredicatePath) != "" { - filter = c.compilePredicateExpr("__item", mode, slice.Predicate, slice.PredicatePath, slice.PredicateEquals) - } - return fmt.Sprintf("SLICE(FOR __item IN %s FILTER %s RETURN %s, 0, %d)", setVar, filter, c.compileSliceProjection("__item", mode, slice.Fields), slice.Limit), nil -} - -func (c *compiler) compilePredicateExpr(itemVar string, mode setMode, predicate string, predicatePath string, predicateEquals string) string { - if strings.TrimSpace(predicatePath) != "" { - sel, err := ParseSelector(predicatePath) - if err == nil { - values := compileSelectorArrayExpr(setPayloadVar(itemVar, mode), sel, c) - if predicateEquals != "" { - bind := c.newBind("predicate_equals", predicateEquals) - return fmt.Sprintf("LENGTH(FOR __value IN %s FILTER __value == @%s LIMIT 1 RETURN 1) > 0", values, bind) - } - return fmt.Sprintf("LENGTH(FOR __value IN %s FILTER __value != null LIMIT 1 RETURN 1) > 0", values) - } - } - predicate = strings.TrimSpace(predicate) - if predicate == "" { - return "true" - } - if strings.Contains(predicate, ".") || strings.Contains(predicate, "[") || strings.Contains(predicate, " where ") { - sel, err := ParseSelector(predicate) - if err == nil { - return fmt.Sprintf("FIRST(%s) != null", compileSelectorArrayExpr(setPayloadVar(itemVar, mode), sel, c)) - } - } - return itemVar + "." + predicate -} - -func (c *compiler) compileRootAggregateExpr(payloadVar string, agg AggregateSelect) (string, error) { - switch strings.ToUpper(strings.TrimSpace(agg.Operation)) { - case "COUNT": - if strings.TrimSpace(agg.PredicatePath) == "" { - return "1", nil - } - filter := c.compileRootPredicateExpr(payloadVar, agg.PredicatePath, agg.PredicateEquals) - return fmt.Sprintf("(%s ? 1 : 0)", filter), nil - case "COUNT_DISTINCT": - if strings.TrimSpace(agg.Select) == "" { - return "", fmt.Errorf("aggregate %q requires fhirPath for COUNT_DISTINCT", agg.Name) - } - values, err := c.compileRootSelectorArray(payloadVar, agg.Select) - if err != nil { - return "", err - } - return fmt.Sprintf("LENGTH(SORTED_UNIQUE(%s))", values), nil - case "EXISTS": - if strings.TrimSpace(agg.PredicatePath) != "" { - return c.compileRootPredicateExpr(payloadVar, agg.PredicatePath, agg.PredicateEquals), nil - } - if strings.TrimSpace(agg.Select) == "" { - return "true", nil - } - values, err := c.compileRootSelectorArray(payloadVar, agg.Select) - if err != nil { - return "", err - } - return fmt.Sprintf("LENGTH(FOR __value IN %s FILTER __value != null LIMIT 1 RETURN 1) > 0", values), nil - case "DISTINCT_VALUES": - if strings.TrimSpace(agg.Select) == "" { - return "", fmt.Errorf("aggregate %q requires fhirPath for DISTINCT_VALUES", agg.Name) - } - values, err := c.compileRootSelectorArray(payloadVar, agg.Select) - if err != nil { - return "", err - } - return fmt.Sprintf("SORTED_UNIQUE(%s)", values), nil - case "MIN", "MAX": - if strings.TrimSpace(agg.Select) == "" { - return "", fmt.Errorf("aggregate %q requires fhirPath for %s", agg.Name, strings.ToUpper(strings.TrimSpace(agg.Operation))) - } - values, err := c.compileRootSelectorArray(payloadVar, agg.Select) - if err != nil { - return "", err - } - return fmt.Sprintf("%s(%s)", strings.ToUpper(strings.TrimSpace(agg.Operation)), values), nil - default: - return "", fmt.Errorf("unsupported aggregate operation %q", agg.Operation) - } -} - -func (c *compiler) compileRootSlice(rootVar string, slice RepresentativeSlice) (string, error) { - filter := "true" - if strings.TrimSpace(slice.PredicatePath) != "" || strings.TrimSpace(slice.Predicate) != "" { - filter = c.compilePredicateExpr("__item", setModeNode, slice.Predicate, slice.PredicatePath, slice.PredicateEquals) - } - return fmt.Sprintf("SLICE(FOR __item IN [%s] FILTER %s RETURN %s, 0, %d)", rootVar, filter, c.compileSliceProjection("__item", setModeNode, slice.Fields), slice.Limit), nil -} - -func (c *compiler) compileSliceProjection(itemVar string, mode setMode, fields []FieldSelect) string { - if len(fields) == 0 { - return itemVar - } - lines := make([]string, 0, len(fields)) - payloadVar := setPayloadVar(itemVar, mode) - for _, field := range fields { - sel, err := ParseSelector(field.Select) - if err != nil { - continue - } - var expr string - if len(field.FallbackSelects) > 0 { - expr = c.compileFirstNonNullExpr(payloadVar, append([]string{field.Select}, field.FallbackSelects...)) - } else if sel.Filter == nil && selectorHasNoArrays(sel) { - expr = compileDirectExpr(payloadVar, sel.Steps) - } else { - expr = "FIRST" + compileSelectorArrayExpr(payloadVar, sel, c) - } - lines = append(lines, fmt.Sprintf("%s: %s", quoteKey(field.Name), expr)) - } - if len(lines) == 0 { - return "{}" - } - return "{ " + strings.Join(lines, ", ") + " }" -} - -func (c *compiler) compileRootPredicateExpr(payloadVar string, predicatePath string, predicateEquals string) string { - sel, err := ParseSelector(predicatePath) - if err != nil { - return "false" - } - values := compileSelectorArrayExpr(payloadVar, sel, c) - if predicateEquals != "" { - bind := c.newBind("predicate_equals", predicateEquals) - return fmt.Sprintf("LENGTH(FOR __value IN %s FILTER __value == @%s LIMIT 1 RETURN 1) > 0", values, bind) - } - return fmt.Sprintf("LENGTH(FOR __value IN %s FILTER __value != null LIMIT 1 RETURN 1) > 0", values) -} - -func (c *compiler) compileRootSelectorArray(payloadVar string, selectText string) (string, error) { - sel, err := ParseSelector(selectText) - if err != nil { - return "", err - } - return compileSelectorArrayExpr(payloadVar, sel, c), nil -} - -func (c *compiler) compileSetAggregateExpr(setVar string, agg AggregateSelect) (string, error) { - mode := setModeNode - switch strings.ToUpper(strings.TrimSpace(agg.Operation)) { - case "COUNT": - if strings.TrimSpace(agg.PredicatePath) == "" { - return fmt.Sprintf("LENGTH(%s)", setVar), nil - } - return fmt.Sprintf("LENGTH(FOR __item IN %s FILTER %s RETURN 1)", setVar, c.compilePredicateExpr("__item", mode, "", agg.PredicatePath, agg.PredicateEquals)), nil - case "COUNT_DISTINCT": - if strings.TrimSpace(agg.Select) == "" { - return "", fmt.Errorf("aggregate %q requires fhirPath for COUNT_DISTINCT", agg.Name) - } - sel, err := ParseSelector(agg.Select) - if err != nil { - return "", err - } - return fmt.Sprintf("LENGTH(SORTED_UNIQUE(FLATTEN(FOR __item IN %s RETURN %s)))", setVar, compileSelectorArrayExpr("__item.payload", sel, c)), nil - case "EXISTS": - if strings.TrimSpace(agg.PredicatePath) != "" { - return fmt.Sprintf("LENGTH(FOR __item IN %s FILTER %s LIMIT 1 RETURN 1) > 0", setVar, c.compilePredicateExpr("__item", mode, "", agg.PredicatePath, agg.PredicateEquals)), nil - } - if strings.TrimSpace(agg.Select) == "" { - return fmt.Sprintf("LENGTH(%s) > 0", setVar), nil - } - sel, err := ParseSelector(agg.Select) - if err != nil { - return "", err - } - return fmt.Sprintf("LENGTH(FOR __item IN %s FILTER LENGTH(%s) > 0 LIMIT 1 RETURN 1) > 0", setVar, compileSelectorArrayExpr("__item.payload", sel, c)), nil - case "DISTINCT_VALUES": - if strings.TrimSpace(agg.Select) == "" { - return "", fmt.Errorf("aggregate %q requires fhirPath for DISTINCT_VALUES", agg.Name) - } - sel, err := ParseSelector(agg.Select) - if err != nil { - return "", err - } - return fmt.Sprintf("SORTED_UNIQUE(FLATTEN(FOR __item IN %s RETURN %s))", setVar, compileSelectorArrayExpr("__item.payload", sel, c)), nil - case "MIN", "MAX": - if strings.TrimSpace(agg.Select) == "" { - return "", fmt.Errorf("aggregate %q requires fhirPath for %s", agg.Name, strings.ToUpper(strings.TrimSpace(agg.Operation))) - } - sel, err := ParseSelector(agg.Select) - if err != nil { - return "", err - } - return fmt.Sprintf("%s(FLATTEN(FOR __item IN %s RETURN %s))", strings.ToUpper(strings.TrimSpace(agg.Operation)), setVar, compileSelectorArrayExpr("__item.payload", sel, c)), nil - default: - return "", fmt.Errorf("unsupported aggregate operation %q", agg.Operation) - } -} - -func (c *compiler) compileSetSlice(setVar string, mode setMode, slice RepresentativeSlice) (string, error) { - filter := "true" - if strings.TrimSpace(slice.PredicatePath) != "" || strings.TrimSpace(slice.Predicate) != "" { - filter = c.compilePredicateExpr("__item", mode, slice.Predicate, slice.PredicatePath, slice.PredicateEquals) - } - return fmt.Sprintf("SLICE(FOR __item IN %s FILTER %s RETURN %s, 0, %d)", setVar, filter, c.compileSliceProjection("__item", mode, slice.Fields), slice.Limit), nil -} - -func (c *compiler) compileFirstNonNullExpr(rootVar string, selects []string) string { - parts := make([]string, 0, len(selects)) - for _, selText := range selects { - sel, err := ParseSelector(selText) - if err != nil { - continue - } - if sel.Filter == nil && selectorHasNoArrays(sel) { - parts = append(parts, compileDirectExpr(rootVar, sel.Steps)) - } else { - parts = append(parts, "FIRST"+compileSelectorArrayExpr(rootVar, sel, c)) - } - } - if len(parts) == 0 { - return "null" - } - return fmt.Sprintf("FIRST(FOR __candidate IN [%s] FILTER __candidate != null RETURN __candidate)", strings.Join(parts, ", ")) -} - -func (c *compiler) compileSelectorArrayForSelects(rootVar string, selects []string) string { - if len(selects) == 0 { - return "[]" - } - parts := make([]string, 0, len(selects)) - for _, selText := range selects { - sel, err := ParseSelector(selText) - if err != nil { - continue - } - if sel.Filter == nil && selectorHasNoArrays(sel) { - parts = append(parts, fmt.Sprintf("(FOR __value IN [%s] FILTER __value != null RETURN __value)", compileDirectExpr(rootVar, sel.Steps))) - } else { - parts = append(parts, compileSelectorArrayExpr(rootVar, sel, c)) - } - } - if len(parts) == 1 { - return parts[0] - } - return fmt.Sprintf("FLATTEN([%s])", strings.Join(parts, ", ")) -} - -func setPayloadVar(itemVar string, mode setMode) string { - if mode == setModeNode { - return itemVar + ".payload" - } - return itemVar -} - -func compileDocumentReferenceSummarySet(source string) string { - return fmt.Sprintf(`( - FOR __doc_ref IN %s - LET doc = __doc_ref.payload - LET doc_ids = doc.identifier ? doc.identifier : [] - LET content = LENGTH(doc.content ? doc.content : []) > 0 ? doc.content[0] : {} - LET attachment = content.attachment ? content.attachment : {} - LET type_codings = doc.type && doc.type.coding ? doc.type.coding : [] - LET category_codings = FLATTEN( - FOR category IN doc.category ? doc.category : [] - RETURN category.coding ? category.coding : [] - ) - LET file_id = FIRST(FOR id IN doc_ids FILTER CONTAINS(id.system ? id.system : "", "file_id") RETURN id.value) - LET data_format = FIRST(FOR coding IN type_codings RETURN coding.display ? coding.display : coding.code) - LET data_category = FIRST(FOR coding IN category_codings FILTER CONTAINS(coding.system ? coding.system : "", "data_category") RETURN coding.display ? coding.display : coding.code) - LET data_type = FIRST(FOR coding IN category_codings FILTER CONTAINS(coding.system ? coding.system : "", "data_type") RETURN coding.display ? coding.display : coding.code) - LET experimental_strategy = FIRST(FOR coding IN category_codings FILTER CONTAINS(coding.system ? coding.system : "", "experimental_strategy") RETURN coding.display ? coding.display : coding.code) - LET workflow_type = FIRST(FOR coding IN category_codings FILTER CONTAINS(coding.system ? coding.system : "", "workflow_type") RETURN coding.display ? coding.display : coding.code) - LET platform = FIRST(FOR coding IN category_codings FILTER CONTAINS(coding.system ? coding.system : "", "platform") RETURN coding.display ? coding.display : coding.code) - LET access = FIRST(FOR coding IN category_codings FILTER CONTAINS(coding.system ? coding.system : "", "access") RETURN coding.display ? coding.display : coding.code) - RETURN { - file_did: doc.id, - file_id: file_id, - file_name: attachment.title, - file_url: attachment.url, - file_size: attachment.size, - data_category: data_category, - data_type: data_type, - data_format: data_format, - experimental_strategy: experimental_strategy, - workflow_type: workflow_type, - platform: platform, - access: access, - is_snv: data_category == "Simple Nucleotide Variation", - is_annotated_somatic: data_category == "Simple Nucleotide Variation" && data_type == "Annotated Somatic Mutation", - is_raw_somatic: data_category == "Simple Nucleotide Variation" && data_type == "Raw Simple Somatic Mutation", - is_expression: data_category == "Transcriptome Profiling" && data_type == "Gene Expression Quantification", - is_fusion: data_type == "Transcript Fusion", - is_cnv: data_category == "Copy Number Variation", - is_methylation: data_category == "DNA Methylation", - is_slide: data_type == "Slide Image", - is_aligned_reads: data_type == "Aligned Reads", - is_clinical: data_category == "Clinical", - is_wxs: experimental_strategy == "WXS", - is_wgs: experimental_strategy == "WGS", - is_rnaseq: experimental_strategy == "RNA-Seq" - } - )`, source) -} - -func compileStudyLookupSet(rootVar, researchSubjects string) string { - return fmt.Sprintf(`( - LET __study_ref = FIRST( - FOR __item IN %s - LET __value = __item.payload.study ? __item.payload.study.reference : null - FILTER __value != null - RETURN __value - ) - LET __resolved_ref = __study_ref ? __study_ref : FIRST( - FOR __ext IN ( %s.payload.extension ? %s.payload.extension : [] ) - FILTER CONTAINS(__ext.url ? __ext.url : "", "part-of-study") && __ext.valueReference - RETURN __ext.valueReference.reference - ) - LET __study_parts = __resolved_ref ? SPLIT(__resolved_ref, "/") : [] - LET __study_id = LENGTH(__study_parts) == 2 ? __study_parts[1] : null - LET __study = FIRST( - FOR __candidate IN ResearchStudy - FILTER __study_id != null - FILTER __candidate.project == @project - FILTER __candidate.dataset_generation == @dataset_generation - FILTER @auth_resource_paths_unrestricted == true OR __candidate.auth_resource_path IN @auth_resource_paths - FILTER __candidate.id == __study_id - LIMIT 1 - RETURN __candidate - ) - FILTER __study != null - RETURN __study.payload - )`, researchSubjects, rootVar, rootVar) -} - -func literalExpr(v any) string { - data, _ := json.Marshal(v) - return string(data) -} diff --git a/internal/dataframe/lowered_types.go b/internal/dataframe/lowered_types.go deleted file mode 100644 index 6af8b35..0000000 --- a/internal/dataframe/lowered_types.go +++ /dev/null @@ -1,335 +0,0 @@ -package dataframe - -import ( - "fmt" - "strings" - - "github.com/calypr/loom/internal/fhirschema" -) - -const ( - SetKindTraverse = "TRAVERSE" - SetKindFilter = "FILTER" - SetKindUnion = "UNION" - SetKindClassifyDocumentReference = "CLASSIFY_DOCUMENT_REFERENCE" - SetKindLookupStudy = "LOOKUP_STUDY" - - DerivedOpConst = "CONST" - DerivedOpRootField = "ROOT_FIELD" - DerivedOpFirstNonNull = "FIRST_NON_NULL" - DerivedOpAll = "ALL" - DerivedOpCount = "COUNT" - DerivedOpCountDistinct = "COUNT_DISTINCT" - DerivedOpCountWhere = "COUNT_WHERE" - DerivedOpAny = "ANY" - DerivedOpMin = "MIN" - DerivedOpMax = "MAX" - DerivedOpUnique = "UNIQUE" - DerivedOpPivot = "PIVOT" -) - -type NamedSet struct { - Name string - Kind string - Source string - Sources []string - // Direction is the physical Arango traversal direction for a TRAVERSE set. - // Empty preserves the current optimized-plan default (INBOUND). Generic - // lowering uses the proven INBOUND catalog contract until a direction- - // selection optimization has both catalog and edge-layout evidence. - Direction string - Label string - ToResourceType string - // AllTargetTypes is only used by generic sibling-prefix sharing. The - // ToResourceType above remains a generated-route validation anchor, while - // the physical traversal deliberately collects every target type for the - // shared edge label. Typed FILTER subsets consume that base set. - AllTargetTypes bool - MatchResourceType string - Filters []TypedFilter - Unique bool - SortField string -} - -type DerivedField struct { - Name string - Source string - Operation string - Select string - FallbackSelects []string - Predicate string - PredicatePath string - PredicateEquals string - PivotColumns []string - PivotFamily string - PivotKeySelect string - PivotValueSelect string - ConstValue any -} - -type RepresentativeSlice struct { - Name string - SourceSet string - Predicate string - PredicateFieldRef string - PredicatePath string - PredicateEquals string - Limit int - Fields []FieldSelect -} - -func usesLoweredBuilder(builder Builder) bool { - if builder.PlanHint != nil && strings.TrimSpace(builder.PlanHint.Mode) != "" { - return true - } - if len(builder.Sets) > 0 || len(builder.DerivedFields) > 0 || len(builder.RepresentativeSlices) > 0 { - return true - } - for _, step := range builder.Traversals { - if len(step.Sets) > 0 || len(step.DerivedFields) > 0 || len(step.RepresentativeSlices) > 0 { - return true - } - } - return false -} - -func validateLoweredBuilder(builder Builder) error { - if !fhirschema.HasResource(builder.RootResourceType) { - return fmt.Errorf("root resource type %q is not represented by the active generated FHIR schema", builder.RootResourceType) - } - if builder.RowGrain != "" { - if err := ValidateRootGrain(builder.RootResourceType, builder.RowGrain); err != nil { - return err - } - } - if builder.PlanHint != nil && builder.PlanHint.RowIdentity != nil { - if err := builder.PlanHint.RowIdentity.Validate(); err != nil { - return fmt.Errorf("plan row identity: %w", err) - } - if builder.RowGrain != "" && builder.PlanHint.RowIdentity.Grain != builder.RowGrain { - return fmt.Errorf("plan row identity grain %q does not match builder row grain %q", builder.PlanHint.RowIdentity.Grain, builder.RowGrain) - } - } - for _, filter := range builder.Filters { - if err := ValidateTypedFilterForResource(builder.RootResourceType, filter); err != nil { - return fmt.Errorf("root filter %q: %w", filter.FieldRef, err) - } - } - if err := validateTraversalFilterSemantics(builder.RootResourceType, builder.Traversals); err != nil { - return err - } - if err := validateRequiredTraversalMatches(builder.RootResourceType, builder.RequiredTraversalMatches); err != nil { - return err - } - seenSets := map[string]struct{}{} - for _, set := range builder.Sets { - if strings.TrimSpace(set.Name) == "" { - return fmt.Errorf("set name is required") - } - if _, ok := seenSets[set.Name]; ok { - return fmt.Errorf("set %q is duplicated", set.Name) - } - seenSets[set.Name] = struct{}{} - if set.SortField != "" && !isSafeAQLFieldIdentifier(set.SortField) { - return fmt.Errorf("set %q uses unsafe sort field %q", set.Name, set.SortField) - } - switch strings.ToUpper(strings.TrimSpace(set.Kind)) { - case SetKindTraverse: - if set.Label == "" { - return fmt.Errorf("set %q requires label", set.Name) - } - if set.AllTargetTypes { - if builder.PlanHint == nil || builder.PlanHint.Profile != "generic_fhir_graph" { - return fmt.Errorf("set %q may collect all target types only in the generic FHIR graph profile", set.Name) - } - if strings.TrimSpace(set.ToResourceType) == "" { - return fmt.Errorf("set %q collecting all target types requires a generated-route validation anchor", set.Name) - } - if len(set.Filters) != 0 { - return fmt.Errorf("set %q collecting all target types must apply filters in typed subsets", set.Name) - } - } - switch strings.ToUpper(strings.TrimSpace(set.Direction)) { - case "", "INBOUND", "OUTBOUND", "ANY": - default: - return fmt.Errorf("set %q uses unsupported traversal direction %q", set.Name, set.Direction) - } - for _, filter := range set.Filters { - if err := ValidateTypedFilterForResource(set.ToResourceType, filter); err != nil { - return fmt.Errorf("set %q filter %q: %w", set.Name, filter.FieldRef, err) - } - } - case SetKindFilter: - if set.Source == "" { - return fmt.Errorf("set %q requires source", set.Name) - } - if strings.TrimSpace(set.MatchResourceType) == "" && len(set.Filters) > 0 { - return fmt.Errorf("set %q requires match resource type for typed filters", set.Name) - } - if set.MatchResourceType != "" { - if !fhirschema.HasResource(set.MatchResourceType) { - return fmt.Errorf("set %q match resource type %q is not represented by the active generated FHIR schema", set.Name, set.MatchResourceType) - } - for _, filter := range set.Filters { - if err := ValidateTypedFilterForResource(set.MatchResourceType, filter); err != nil { - return fmt.Errorf("set %q filter %q: %w", set.Name, filter.FieldRef, err) - } - } - } - case SetKindUnion: - if len(set.Sources) == 0 { - return fmt.Errorf("set %q requires sources", set.Name) - } - case SetKindClassifyDocumentReference: - if set.Source == "" { - return fmt.Errorf("set %q requires source", set.Name) - } - case SetKindLookupStudy: - if set.Source == "" { - return fmt.Errorf("set %q requires source research subject set", set.Name) - } - default: - return fmt.Errorf("set %q uses unsupported kind %q", set.Name, set.Kind) - } - } - if err := validateGenericLoweredStorageRoutes(builder); err != nil { - return err - } - - seenDerived := map[string]struct{}{} - for _, field := range builder.DerivedFields { - if field.Name == "" { - return fmt.Errorf("derived field name is required") - } - if _, ok := seenDerived[field.Name]; ok { - return fmt.Errorf("derived field %q is duplicated", field.Name) - } - seenDerived[field.Name] = struct{}{} - switch strings.ToUpper(strings.TrimSpace(field.Operation)) { - case DerivedOpConst: - if field.ConstValue == nil { - return fmt.Errorf("derived field %q requires const value", field.Name) - } - case DerivedOpRootField: - if field.Select == "" { - return fmt.Errorf("derived field %q requires select", field.Name) - } - case DerivedOpFirstNonNull, DerivedOpAll, DerivedOpUnique: - if field.Source == "" { - return fmt.Errorf("derived field %q requires source", field.Name) - } - if field.Select == "" { - return fmt.Errorf("derived field %q requires select", field.Name) - } - if _, err := ParseSelector(field.Select); err != nil { - return fmt.Errorf("derived field %q invalid select: %w", field.Name, err) - } - for _, sel := range field.FallbackSelects { - if _, err := ParseSelector(sel); err != nil { - return fmt.Errorf("derived field %q invalid fallback select: %w", field.Name, err) - } - } - case DerivedOpPivot: - if field.Source == "" { - return fmt.Errorf("derived field %q requires source", field.Name) - } - if strings.TrimSpace(field.PivotKeySelect) == "" || strings.TrimSpace(field.PivotValueSelect) == "" { - return fmt.Errorf("derived field %q requires pivot key/value selectors", field.Name) - } - if _, err := ParseSelector(field.PivotKeySelect); err != nil { - return fmt.Errorf("derived field %q invalid pivot key selector: %w", field.Name, err) - } - if _, err := ParseSelector(field.PivotValueSelect); err != nil { - return fmt.Errorf("derived field %q invalid pivot value selector: %w", field.Name, err) - } - if len(field.PivotColumns) == 0 { - return fmt.Errorf("derived field %q requires bounded pivot columns", field.Name) - } - case DerivedOpCount: - if field.Source == "" { - return fmt.Errorf("derived field %q requires source", field.Name) - } - case DerivedOpCountDistinct, DerivedOpMin, DerivedOpMax: - if field.Source == "" || strings.TrimSpace(field.Select) == "" { - return fmt.Errorf("derived field %q requires source and select", field.Name) - } - if _, err := ParseSelector(field.Select); err != nil { - return fmt.Errorf("derived field %q invalid select: %w", field.Name, err) - } - case DerivedOpCountWhere: - if field.Source == "" { - return fmt.Errorf("derived field %q requires source", field.Name) - } - if strings.TrimSpace(field.Predicate) == "" && strings.TrimSpace(field.PredicatePath) == "" { - return fmt.Errorf("derived field %q requires predicate or predicatePath", field.Name) - } - if strings.TrimSpace(field.PredicatePath) != "" { - if _, err := ParseSelector(field.PredicatePath); err != nil { - return fmt.Errorf("derived field %q invalid predicatePath: %w", field.Name, err) - } - } - case DerivedOpAny: - if field.Source == "" { - return fmt.Errorf("derived field %q requires source", field.Name) - } - if strings.TrimSpace(field.Predicate) != "" || strings.TrimSpace(field.PredicatePath) != "" { - if strings.TrimSpace(field.PredicatePath) != "" { - if _, err := ParseSelector(field.PredicatePath); err != nil { - return fmt.Errorf("derived field %q invalid predicatePath: %w", field.Name, err) - } - } - } - default: - return fmt.Errorf("derived field %q uses unsupported operation %q", field.Name, field.Operation) - } - } - - seenSlices := map[string]struct{}{} - for _, slice := range builder.RepresentativeSlices { - if slice.Name == "" { - return fmt.Errorf("representative slice name is required") - } - if _, ok := seenSlices[slice.Name]; ok { - return fmt.Errorf("representative slice %q is duplicated", slice.Name) - } - seenSlices[slice.Name] = struct{}{} - if slice.SourceSet == "" { - return fmt.Errorf("representative slice %q requires sourceSet", slice.Name) - } - if slice.Limit <= 0 { - return fmt.Errorf("representative slice %q requires positive limit", slice.Name) - } - for _, field := range slice.Fields { - if strings.TrimSpace(field.Name) == "" || strings.TrimSpace(field.Select) == "" { - return fmt.Errorf("representative slice %q requires fields with name and select", slice.Name) - } - if _, err := ParseSelector(field.Select); err != nil { - return fmt.Errorf("representative slice %q invalid field %q: %w", slice.Name, field.Name, err) - } - } - } - return nil -} - -func validateTraversalFilterSemantics(sourceResourceType string, traversals []TraversalStep) error { - for _, step := range traversals { - if err := step.MatchMode.Validate(); err != nil { - return fmt.Errorf("traversal %s -> %s (%s): %w", sourceResourceType, step.ToResourceType, step.Label, err) - } - if !fhirschema.HasResource(step.ToResourceType) { - return fmt.Errorf("traversal target resource type %q is not represented by the active generated FHIR schema", step.ToResourceType) - } - if _, err := resolveStorageRoute(sourceResourceType, step.Label, step.ToResourceType); err != nil { - return fmt.Errorf("traversal %s -> %s (%s): %w", sourceResourceType, step.ToResourceType, step.Label, err) - } - for _, filter := range step.Filters { - if err := ValidateTypedFilterForResource(step.ToResourceType, filter); err != nil { - return fmt.Errorf("traversal %s -> %s filter %q: %w", sourceResourceType, step.ToResourceType, filter.FieldRef, err) - } - } - if err := validateTraversalFilterSemantics(step.ToResourceType, step.Traversals); err != nil { - return err - } - } - return nil -} diff --git a/internal/dataframe/optimizer_traversal_sharing_test.go b/internal/dataframe/optimizer_traversal_sharing_test.go deleted file mode 100644 index 2c900a2..0000000 --- a/internal/dataframe/optimizer_traversal_sharing_test.go +++ /dev/null @@ -1,280 +0,0 @@ -package dataframe - -import ( - "strings" - "testing" -) - -func TestGenericLoweringSharesIdenticalTraversalPrefixes(t *testing.T) { - planned, err := Lower(Builder{ - Project: "P1", RootResourceType: "Specimen", - Traversals: []TraversalStep{ - {Label: "subject_Specimen", ToResourceType: "DocumentReference", Alias: "file_primary", Fields: []FieldSelect{{Name: "title", Select: "content[].attachment.title"}}}, - {Label: "subject_Specimen", ToResourceType: "DocumentReference", Alias: "file_secondary", Fields: []FieldSelect{{Name: "url", Select: "content[].attachment.url"}}}, - }, - }) - if err != nil { - t.Fatal(err) - } - if len(planned.Sets) != 1 { - t.Fatalf("identical generic traversal sets = %#v, want one shared set", planned.Sets) - } - if len(planned.DerivedFields) != 2 || planned.DerivedFields[0].Source != planned.Sets[0].Name || planned.DerivedFields[1].Source != planned.Sets[0].Name { - t.Fatalf("derived fields did not reuse the shared set: %#v / %#v", planned.Sets, planned.DerivedFields) - } - if planned.PlanHint == nil || len(planned.PlanHint.AppliedRules) != 1 || planned.PlanHint.AppliedRules[0] != OptimizerRuleTraversalSharing { - t.Fatalf("applied optimizer rules = %#v", planned.PlanHint) - } - compiled, err := Compile(planned, 1) - if err != nil { - t.Fatal(err) - } - if len(compiled.OptimizationRules) != 1 || compiled.OptimizationRules[0] != OptimizerRuleTraversalSharing { - t.Fatalf("compiled optimizer rules = %#v", compiled.OptimizationRules) - } -} - -func TestGenericLoweringDoesNotShareTraversalsWithDifferentPredicates(t *testing.T) { - first := "first" - second := "second" - planned, err := Lower(Builder{ - Project: "P1", RootResourceType: "Specimen", - Traversals: []TraversalStep{ - { - Label: "subject_Specimen", ToResourceType: "DocumentReference", Alias: "first_file", - Filters: []TypedFilter{{FieldRef: "DocumentReference.title", Selector: "content[].attachment.title", FieldKind: FilterString, Repeated: true, Quantifier: QuantifierAny, Operator: FilterEquals, Values: []FilterValue{{Kind: FilterString, String: &first}}}}, - }, - { - Label: "subject_Specimen", ToResourceType: "DocumentReference", Alias: "second_file", - Filters: []TypedFilter{{FieldRef: "DocumentReference.title", Selector: "content[].attachment.title", FieldKind: FilterString, Repeated: true, Quantifier: QuantifierAny, Operator: FilterEquals, Values: []FilterValue{{Kind: FilterString, String: &second}}}}, - }, - }, - }) - if err != nil { - t.Fatal(err) - } - if len(planned.Sets) != 2 { - t.Fatalf("predicate-distinct traversal sets = %#v, want two sets", planned.Sets) - } - if planned.PlanHint == nil || len(planned.PlanHint.AppliedRules) != 1 || planned.PlanHint.AppliedRules[0] != OptimizerRuleFilterPushdown { - t.Fatalf("unexpected optimizer rules = %#v", planned.PlanHint) - } -} - -func TestGenericLoweringSharesSiblingPrefixAcrossTargetTypes(t *testing.T) { - conditionID := "condition-1" - specimenID := "specimen-1" - observationID := "observation-1" - planned, err := Lower(Builder{ - Project: "P1", RootResourceType: "Patient", - Traversals: []TraversalStep{ - { - Label: "subject_Patient", ToResourceType: "Condition", Alias: "condition", - Fields: []FieldSelect{{Name: "id", Select: "id", ValueMode: "ALL"}}, - Filters: []TypedFilter{{ - FieldRef: "Condition.id", Selector: "id", FieldKind: FilterString, Operator: FilterEquals, - Values: []FilterValue{{Kind: FilterString, String: &conditionID}}, - }}, - }, - { - Label: "subject_Patient", ToResourceType: "Specimen", Alias: "specimen", - Fields: []FieldSelect{{Name: "id", Select: "id", ValueMode: "ALL"}}, - Filters: []TypedFilter{{ - FieldRef: "Specimen.id", Selector: "id", FieldKind: FilterString, Operator: FilterEquals, - Values: []FilterValue{{Kind: FilterString, String: &specimenID}}, - }}, - }, - { - Label: "subject_Patient", ToResourceType: "Observation", Alias: "observation", - Fields: []FieldSelect{{Name: "id", Select: "id", ValueMode: "ALL"}}, - Filters: []TypedFilter{{ - FieldRef: "Observation.id", Selector: "id", FieldKind: FilterString, Operator: FilterEquals, - Values: []FilterValue{{Kind: FilterString, String: &observationID}}, - }}, - }, - }, - }) - if err != nil { - t.Fatal(err) - } - if planned.PlanHint == nil || planned.PlanHint.Profile != "generic_fhir_graph" { - t.Fatalf("expected generic plan, got %#v", planned.PlanHint) - } - if !containsOptimizerRule(planned.PlanHint.AppliedRules, OptimizerRuleTraversalSharing) || !containsOptimizerRule(planned.PlanHint.AppliedRules, OptimizerRuleFilterPushdown) { - t.Fatalf("expected sibling sharing and filter pushdown rules, got %#v", planned.PlanHint) - } - - base, ok := allTargetTraversal(planned.Sets) - if !ok { - t.Fatalf("missing shared sibling traversal: %#v", planned.Sets) - } - if base.Kind != SetKindTraverse || base.Direction != "INBOUND" || base.Label != "subject_Patient" || !base.AllTargetTypes || base.ToResourceType != "Condition" { - t.Fatalf("unexpected shared traversal = %#v", base) - } - if got := countNamedSetKind(planned.Sets, SetKindTraverse); got != 1 { - t.Fatalf("physical generic traversals = %d, want one shared prefix: %#v", got, planned.Sets) - } - - wantSubsets := map[string]string{ - "generic_condition_set": "Condition", - "generic_specimen_set": "Specimen", - "generic_observation_set": "Observation", - } - for name, resourceType := range wantSubsets { - subset, ok := namedSetByName(planned.Sets, name) - if !ok { - t.Fatalf("missing typed subset %q: %#v", name, planned.Sets) - } - if subset.Kind != SetKindFilter || subset.Source != base.Name || subset.MatchResourceType != resourceType || len(subset.Filters) != 1 || subset.Unique || subset.SortField != "_key" { - t.Fatalf("typed subset %q = %#v", name, subset) - } - } - for _, field := range planned.DerivedFields { - if _, ok := wantSubsets[field.Source]; !ok { - t.Fatalf("derived field %q unexpectedly escaped its typed sibling subset: %#v", field.Name, field) - } - } - - compiled, err := Compile(planned, 1) - if err != nil { - t.Fatal(err) - } - if got := strings.Count(compiled.Query, "1..1 INBOUND root fhir_edge"); got != 1 { - t.Fatalf("shared sibling query emitted %d root traversals, want one:\n%s", got, compiled.Query) - } - if strings.Contains(compiled.Query, base.Name+"_to") { - t.Fatalf("shared base accidentally retained its validation-anchor type predicate:\n%s", compiled.Query) - } - if got := strings.Count(compiled.Query, "FILTER __item.resourceType == @"); got != 3 { - t.Fatalf("typed sibling subsets = %d, want three:\n%s", got, compiled.Query) - } - if got := strings.Count(compiled.Query, "__edge.dataset_generation == @dataset_generation"); got != 1 { - t.Fatalf("shared traversal generation scope count = %d, want one:\n%s", got, compiled.Query) - } - if got := strings.Count(compiled.Query, "__edge.auth_resource_path IN @auth_resource_paths"); got != 1 { - t.Fatalf("shared traversal auth scope count = %d, want one:\n%s", got, compiled.Query) - } - for _, want := range []string{conditionID, specimenID, observationID} { - assertBindVarValue(t, compiled.BindVars, want) - } -} - -func TestGenericSiblingPrefixSharingRetainsRequiredMatch(t *testing.T) { - conditionID := "required-condition" - compiled, err := CompileRequest(Builder{ - Project: "P1", RootResourceType: "Patient", - Traversals: []TraversalStep{ - { - Label: "subject_Patient", ToResourceType: "Condition", Alias: "condition", MatchMode: TraversalMatchRequired, - Filters: []TypedFilter{{ - FieldRef: "Condition.id", Selector: "id", FieldKind: FilterString, Operator: FilterEquals, - Values: []FilterValue{{Kind: FilterString, String: &conditionID}}, - }}, - }, - {Label: "subject_Patient", ToResourceType: "Specimen", Alias: "specimen"}, - {Label: "subject_Patient", ToResourceType: "Observation", Alias: "observation"}, - }, - }, 5) - if err != nil { - t.Fatal(err) - } - if !containsOptimizerRule(compiled.OptimizationRules, OptimizerRuleTraversalSharing) || !containsOptimizerRule(compiled.OptimizationRules, OptimizerRuleRelationshipSemiJoin) { - t.Fatalf("missing shared-prefix/required-match provenance: %#v", compiled.OptimizationRules) - } - if !strings.Contains(compiled.Query, "LET generic_root_subject_Patient_neighbors_set") { - t.Fatalf("missing shared materialized sibling set:\n%s", compiled.Query) - } - if !strings.Contains(compiled.Query, "FOR __match_0_0, __match_edge_0_0 IN 1..1 INBOUND root fhir_edge") { - t.Fatalf("required sibling match was lost:\n%s", compiled.Query) - } - assertRootMatchPrecedesLimit(t, compiled.Query) -} - -func TestGenericSiblingPrefixSharingSupportsNestedChildRoutes(t *testing.T) { - gender := "female" - planned, err := Lower(Builder{ - Project: "P1", RootResourceType: "Patient", - Filters: []TypedFilter{{ - FieldRef: "Patient.gender", Selector: "gender", FieldKind: FilterString, Operator: FilterEquals, - Values: []FilterValue{{Kind: FilterString, String: &gender}}, - }}, - Traversals: []TraversalStep{ - {Label: "subject_Patient", ToResourceType: "Condition", Alias: "condition"}, - { - Label: "subject_Patient", ToResourceType: "Specimen", Alias: "specimen", - Traversals: []TraversalStep{{ - Label: "subject_Specimen", ToResourceType: "DocumentReference", Alias: "file", - Fields: []FieldSelect{{Name: "id", Select: "id", ValueMode: "ALL"}}, - }}, - }, - {Label: "subject_Patient", ToResourceType: "Observation", Alias: "observation"}, - }, - }) - if err != nil { - t.Fatal(err) - } - fileSet, ok := namedSetByName(planned.Sets, "generic_file_set") - if !ok || fileSet.Kind != SetKindTraverse || fileSet.Source != "generic_specimen_set" || fileSet.ToResourceType != "DocumentReference" { - t.Fatalf("nested route did not retain typed specimen parent: %#v", planned.Sets) - } - compiled, err := Compile(planned, 1) - if err != nil { - t.Fatalf("compile shared nested route: %v", err) - } - if got := strings.Count(compiled.Query, "1..1 INBOUND root fhir_edge"); got != 1 { - t.Fatalf("shared root prefix emitted %d root traversals, want one:\n%s", got, compiled.Query) - } - if !strings.Contains(compiled.Query, "FOR __parent IN generic_specimen_set FOR __node, __edge IN 1..1 INBOUND __parent fhir_edge") { - t.Fatalf("nested traversal did not use the typed subset parent:\n%s", compiled.Query) - } -} - -func namedSetByName(sets []NamedSet, name string) (NamedSet, bool) { - for _, set := range sets { - if set.Name == name { - return set, true - } - } - return NamedSet{}, false -} - -func countNamedSetKind(sets []NamedSet, kind string) int { - count := 0 - for _, set := range sets { - if set.Kind == kind { - count++ - } - } - return count -} - -func allTargetTraversal(sets []NamedSet) (NamedSet, bool) { - for _, set := range sets { - if set.Kind == SetKindTraverse && set.AllTargetTypes { - return set, true - } - } - return NamedSet{}, false -} - -func filterResourceTypes(sets []NamedSet, source string) map[string]struct{} { - types := map[string]struct{}{} - for _, set := range sets { - if set.Kind == SetKindFilter && set.Source == source && set.MatchResourceType != "" { - types[set.MatchResourceType] = struct{}{} - } - } - return types -} - -func sameStringSet(left, right map[string]struct{}) bool { - if len(left) != len(right) { - return false - } - for value := range left { - if _, ok := right[value]; !ok { - return false - } - } - return true -} diff --git a/internal/dataframe/physical_cost.go b/internal/dataframe/physical_cost.go new file mode 100644 index 0000000..b1e58fb --- /dev/null +++ b/internal/dataframe/physical_cost.go @@ -0,0 +1,129 @@ +package dataframe + +import ( + "os" + "strconv" + "strings" +) + +// PhysicalOptimizationPolicy is the small, explainable policy used by the +// physical optimizer. It deliberately estimates operation work rather than +// pretending to predict Arango's cost; PROFILE remains the authority for +// deciding whether a rewrite is worthwhile on a particular dataset. +type PhysicalOptimizationPolicy struct { + // Enabled is false when the policy is disabled explicitly. Disabling the + // policy never disables validation or changes the physical plan supplied by + // the caller; it only prevents optional traversal-sharing rewrites. Rich + // selector preparation has its own structural gate during lowering. + Enabled bool + // MinimumSavings is the minimum estimated operation-work reduction required + // before an optional rewrite is applied. The default is one operation. + MinimumSavings int +} + +// PhysicalOptimizationDecision explains one candidate rewrite. The values are +// intentionally structural and stable across schemas: they count typed +// physical operations, not FHIR resource names or rendered AQL fragments. +type PhysicalOptimizationDecision struct { + Rule string + Enabled bool + CandidateSets int + EstimatedBaselineWork int + EstimatedOptimizedWork int + EstimatedSavings int + Reason string +} + +// PhysicalOptimizationReport is attached to an optimized plan and copied +// into compiler diagnostics. A rejection is useful evidence: it tells callers +// why a seemingly similar route was left unshared instead of silently hiding +// the decision in rendered AQL. +type PhysicalOptimizationReport struct { + Policy string + Enabled bool + MinimumSavings int + Decisions []PhysicalOptimizationDecision +} + +const physicalOptimizationPolicyName = "conservative-structural-v1" + +// DefaultPhysicalOptimizationPolicy returns the production policy. The +// LOOM_PHYSICAL_COST_POLICY environment variable is intentionally a local +// developer switch, not a user-controlled query input. Set it to "off" (or +// "0"/"false") to compare the unshared physical shape; all validation and +// result semantics remain unchanged. Rich selector preparation is governed by +// its independent repeated-consumer proof. +func DefaultPhysicalOptimizationPolicy() PhysicalOptimizationPolicy { + policy := PhysicalOptimizationPolicy{Enabled: true, MinimumSavings: 1} + switch strings.ToLower(strings.TrimSpace(os.Getenv("LOOM_PHYSICAL_COST_POLICY"))) { + case "off", "0", "false", "disabled": + policy.Enabled = false + } + if raw := strings.TrimSpace(os.Getenv("LOOM_PHYSICAL_COST_MIN_SAVINGS")); raw != "" { + if value, err := strconv.Atoi(raw); err == nil && value >= 0 { + policy.MinimumSavings = value + } + } + return policy +} + +func newPhysicalOptimizationReport(policy PhysicalOptimizationPolicy) PhysicalOptimizationReport { + if policy.MinimumSavings < 0 { + policy.MinimumSavings = 0 + } + return PhysicalOptimizationReport{ + Policy: physicalOptimizationPolicyName, + Enabled: policy.Enabled, + MinimumSavings: policy.MinimumSavings, + } +} + +func (report *PhysicalOptimizationReport) addDecision(decision PhysicalOptimizationDecision) { + if report == nil { + return + } + report.Decisions = append(report.Decisions, decision) +} + +// estimateTraversalSharingWork models the prefix and subset operations that +// the rewrite actually changes. Every original set pays for its traversal and +// scope prefix. The shared plan pays for one prefix plus one typed subset per +// consumer. Consumer-specific operations are present in either plan and are +// therefore intentionally excluded from the estimate. +func estimateTraversalSharingWork(prefix PhysicalTraversalPrefixDecomposition, candidateSets int) (baseline, optimized, savings int) { + if candidateSets < 2 { + return 0, 0, 0 + } + // Traversal plus the canonical scope block. The decomposition carries the + // scope operation count so this estimate remains independent of a specific + // FHIR route or an incidental renderer variable name. + prefixOperations := 1 + prefix.Prefix.ScopeOperationCount + if prefix.Prefix.SourceVariable == "" { + return 0, 0, 0 + } + baseline = prefixOperations * candidateSets + optimized = prefixOperations + candidateSets // one typed subset per set + savings = baseline - optimized + return baseline, optimized, savings +} + +// estimatePreparedSelectorWork uses a deliberately small structural model: +// selector extraction has a source iteration and a value projection, while a +// prepared value pays one projection plus a cheap field read at each consumer. +// It is only used as a lower-bound gate (PROFILE remains authoritative), so a +// selector must have at least two consumers before preparation is allowed. +func estimatePreparedSelectorWork(selectorUseCount int) (baseline, optimized, savings int) { + if selectorUseCount < 2 { + return 0, 0, 0 + } + baseline = selectorUseCount * 2 + optimized = selectorUseCount + 1 + savings = baseline - optimized + return baseline, optimized, savings +} + +func clonePhysicalOptimizationReport(report PhysicalOptimizationReport) PhysicalOptimizationReport { + copy := report + copy.Decisions = append([]PhysicalOptimizationDecision(nil), report.Decisions...) + return copy +} diff --git a/internal/dataframe/physical_diagnostics.go b/internal/dataframe/physical_diagnostics.go new file mode 100644 index 0000000..1e2df5f --- /dev/null +++ b/internal/dataframe/physical_diagnostics.go @@ -0,0 +1,163 @@ +package dataframe + +import "sort" + +// CompilerPlanDiagnostics describes work the physical renderer will ask AQL to +// perform. It deliberately reports compiler facts, not estimated database +// cost: use it alongside Arango PROFILE to decide which rewrite is worthwhile. +type CompilerPlanDiagnostics struct { + TraversalSets int + SharedTraversalCount int + RequiredMatchReuseCount int + ScopedSharingCandidateGroups int + ScopedSharingCandidateSets int + PotentialSharingOpportunityGroups int + PotentialSharingOpportunitySets int + RichSourceReuse []RichSourceReuse + // OptimizationPolicy is the explainable decision record for optional + // physical rewrites. It reports both enabled rewrites and conservative + // rejections so rendered AQL is never the only evidence of a decision. + OptimizationPolicy PhysicalOptimizationReport +} + +// RichSourceReuse identifies a materialized relationship set that is scanned +// repeatedly by rich projections. A high count does not mean the traversal is +// repeated; it means aggregate/pivot/slice operations each loop over the same +// already-materialized child set. +type RichSourceReuse struct { + SourceSet string + AggregateConsumers int + PivotConsumers int + SliceConsumers int +} + +func (r RichSourceReuse) TotalConsumers() int { + return r.AggregateConsumers + r.PivotConsumers + r.SliceConsumers +} + +func physicalPlanDiagnostics(plan PhysicalPlan) CompilerPlanDiagnostics { + diagnostics := CompilerPlanDiagnostics{ + SharedTraversalCount: plan.SharedTraversalCount, + RequiredMatchReuseCount: plan.RequiredMatchReuseCount, + OptimizationPolicy: clonePhysicalOptimizationReport(plan.OptimizationPolicy), + } + groups := map[string][]int{} + potentialGroups := map[string][]int{} + for i, operation := range plan.Operations { + if operation.Kind != PhysicalSetOp || operation.Set == nil { + continue + } + set := operation.Set + if set.SourceSetVariable == "" && len(set.Subplan.Operations) > 0 && set.Subplan.Operations[0].Traversal != nil { + diagnostics.TraversalSets++ + key := physicalTraversalOpportunityKey(plan, *set) + potentialGroups[key] = append(potentialGroups[key], i) + if decomposition, err := DecomposePhysicalTraversalPrefix(plan, *set); err == nil { + groups[decomposition.PrefixKey] = append(groups[decomposition.PrefixKey], i) + } + } + } + for _, indices := range potentialGroups { + if len(indices) < 2 || !multipleTargetTypes(plan, indices) { + continue + } + diagnostics.PotentialSharingOpportunityGroups++ + diagnostics.PotentialSharingOpportunitySets += len(indices) + } + for _, indices := range groups { + if len(indices) < 2 || !multipleTargetTypes(plan, indices) { + continue + } + diagnostics.ScopedSharingCandidateGroups++ + diagnostics.ScopedSharingCandidateSets += len(indices) + } + + uses := map[string]*RichSourceReuse{} + for _, operation := range plan.Operations { + if operation.Kind != PhysicalReturnOp || operation.Return == nil { + continue + } + for _, projection := range operation.Return.Projections { + countRichSourceReuse(projection.Expression, uses) + } + } + for _, use := range uses { + if use.TotalConsumers() > 1 { + diagnostics.RichSourceReuse = append(diagnostics.RichSourceReuse, *use) + } + } + sort.Slice(diagnostics.RichSourceReuse, func(i, j int) bool { + return diagnostics.RichSourceReuse[i].SourceSet < diagnostics.RichSourceReuse[j].SourceSet + }) + return diagnostics +} + +// physicalTraversalOpportunityKey intentionally ignores scoped filters and +// semantic provenance. It identifies broader neighbor traversals that could +// serve multiple typed children once the scope-safe rewrite exists. +func physicalTraversalOpportunityKey(plan PhysicalPlan, set PhysicalSet) string { + traversal := set.Subplan.Operations[0].Traversal + if traversal == nil { + return "" + } + return traversal.SourceVariable + "|" + string(traversal.Direction) + "|" + valueString(plan.BindVars[traversal.EdgeCollectionBindKey]) + "|" + valueString(plan.BindVars[traversal.EdgeLabelBindKey]) + "|" + traversal.EdgeTargetTypeField +} + +func multipleTargetTypes(plan PhysicalPlan, indices []int) bool { + types := map[string]bool{} + for _, index := range indices { + traversal := plan.Operations[index].Set.Subplan.Operations[0].Traversal + if traversal == nil { + continue + } + if value, ok := plan.BindVars[traversal.TargetTypeBindKey].(string); ok { + types[value] = true + } + } + return len(types) > 1 +} + +func countRichSourceReuse(expression *PhysicalExpression, uses map[string]*RichSourceReuse) { + if expression == nil { + return + } + add := func(source string, kind PhysicalExpressionKind) { + if source == "" { + return + } + use := uses[source] + if use == nil { + use = &RichSourceReuse{SourceSet: source} + uses[source] = use + } + switch kind { + case PhysicalAggregateExpression: + use.AggregateConsumers++ + case PhysicalPivotExpression: + use.PivotConsumers++ + case PhysicalSliceExpression: + use.SliceConsumers++ + } + } + switch expression.Kind { + case PhysicalAggregateExpression: + if expression.Aggregate != nil { + add(expression.Aggregate.Source.Variable, expression.Kind) + } + case PhysicalPivotExpression: + if expression.Pivot != nil { + add(expression.Pivot.Source.Variable, expression.Kind) + } + case PhysicalSliceExpression: + if expression.Slice != nil { + add(expression.Slice.Source.Variable, expression.Kind) + } + case PhysicalObjectExpression: + if expression.Object != nil { + for _, field := range expression.Object.Fields { + field := field.Expression + countRichSourceReuse(&field, uses) + } + } + } +} diff --git a/internal/dataframe/physical_execution.go b/internal/dataframe/physical_execution.go index efe6963..26150af 100644 --- a/internal/dataframe/physical_execution.go +++ b/internal/dataframe/physical_execution.go @@ -4,15 +4,11 @@ import "fmt" const genericPhysicalExecutionLimitBind = "limit" -// compileGenericPhysicalExecution is the executable bridge from the generic -// semantic graph to the typed physical renderer. Its caller has already -// established that the request is navigation-only, so the physical return -// shape (_key at the root row grain) is exactly the public dataframe shape. -func compileGenericPhysicalExecution(semantic SemanticPlan, lowered Builder, limit int) (CompiledQuery, error) { - physical, err := BuildGenericPhysicalPlan(semantic) - if err != nil { - return CompiledQuery{}, fmt.Errorf("build generic physical execution plan: %w", err) - } +// compilePhysicalExecution renders a validated semantic physical plan. Its +// caller has already established that the plan represents the complete +// request, so it never needs compatibility named sets or string lowering. +func compilePhysicalExecution(physical PhysicalPlan, semantic SemanticPlan, limit int) (CompiledQuery, error) { + var err error physical, err = withGenericPhysicalExecutionWindow(physical, limit) if err != nil { return CompiledQuery{}, err @@ -22,29 +18,75 @@ func compileGenericPhysicalExecution(semantic SemanticPlan, lowered Builder, lim return CompiledQuery{}, fmt.Errorf("render generic physical execution plan: %w", err) } + columns, pivotFields := physicalProjectionMetadata(physical) return CompiledQuery{ Project: semantic.Project, DatasetGeneration: normalizeDatasetGeneration(semantic.DatasetGeneration), RootResourceType: semantic.Root.ResourceType, AuthResourcePaths: cloneStrings(semantic.AuthResourcePaths), - PlanMode: planMode(lowered.PlanHint), - PlanProfile: planProfile(lowered.PlanHint), - NamedSetCount: planNamedSetCount(lowered.PlanHint), - FileSummaries: planFileSummaries(lowered.PlanHint), - StudyLookup: planStudyLookup(lowered.PlanHint), - OptimizationRules: planAppliedRules(lowered.PlanHint), - RowIdentity: planRowIdentity(lowered.PlanHint), + PlanMode: "physical", + PlanProfile: "generic_fhir_graph", + TraversalCount: physicalTraversalCount(physical), + OptimizationRules: physicalOptimizationRules(semantic.Root), + RowIdentity: cloneRowIdentity(semantic.RowIdentity), Query: rendered.Query, BindVars: rendered.BindVars, - Columns: []string{"_key"}, - PivotFields: nil, + Columns: columns, + PivotFields: pivotFields, Limit: limit, + PlanDiagnostics: physicalPlanDiagnostics(physical), }, nil } +func physicalOptimizationRules(node SemanticNode) []string { + rules := make([]string, 0, 2) + if len(node.Filters) != 0 { + rules = append(rules, OptimizerRuleFilterPushdown) + } + for _, child := range node.Children { + if child.MatchMode.required() { + rules = appendUniqueRule(rules, OptimizerRuleRelationshipSemiJoin) + } + for _, rule := range physicalOptimizationRules(child) { + rules = appendUniqueRule(rules, rule) + } + } + if len(rules) == 0 { + return nil + } + return rules +} + +func physicalProjectionMetadata(plan PhysicalPlan) ([]string, []string) { + for _, operation := range plan.Operations { + if operation.Kind != PhysicalReturnOp || operation.Return == nil { + continue + } + columns := make([]string, 0, len(operation.Return.Projections)) + var pivots []string + for _, projection := range operation.Return.Projections { + columns = append(columns, projection.Name) + if projection.Expression != nil && projection.Expression.Kind == PhysicalPivotExpression { + pivots = append(pivots, projection.Name) + } + } + return columns, pivots + } + return nil, nil +} + +func physicalTraversalCount(plan PhysicalPlan) int { + count := 0 + for _, operation := range plan.Operations { + if operation.Kind == PhysicalTraversalOp { + count++ + } + } + return count +} + // withGenericPhysicalExecutionWindow inserts the deterministic root ordering -// and optional preview bound before any traversal LET subquery. This matches -// the established lowered renderer's row-grain semantics while ensuring an +// and optional preview bound before any traversal LET subquery, ensuring an // expensive optional navigation is evaluated only for selected root rows. func withGenericPhysicalExecutionWindow(plan PhysicalPlan, limit int) (PhysicalPlan, error) { if err := ValidateGenericPhysicalPlanScope(plan); err != nil { @@ -62,7 +104,7 @@ func withGenericPhysicalExecutionWindow(plan PhysicalPlan, limit int) (PhysicalP return PhysicalPlan{}, fmt.Errorf("generic physical execution plan requires a scoped root followed by RETURN or traversal") } - out := cloneCompilerPhysicalPlan(plan) + out := clonePhysicalPlan(plan) root := out.Operations[0].RootScan.Variable window := []PhysicalOperation{{ Kind: PhysicalSortOp, diff --git a/internal/dataframe/physical_execution_test.go b/internal/dataframe/physical_execution_test.go index 504e945..d72abbf 100644 --- a/internal/dataframe/physical_execution_test.go +++ b/internal/dataframe/physical_execution_test.go @@ -1,7 +1,6 @@ package dataframe import ( - "reflect" "strings" "testing" ) @@ -43,24 +42,12 @@ func TestCompileRequestUsesPhysicalExecutionForNavigationOnlyGenericPlan(t *test t.Fatalf("root limit must occur before optional navigation materialization:\n%s", physical.Query) } if strings.Contains(physical.Query, "FOR root IN Specimen") || strings.Contains(physical.Query, "generic_file_set") { - t.Fatalf("navigation-only request unexpectedly used lowered string renderer:\n%s", physical.Query) + t.Fatalf("physical request unexpectedly used a compatibility string renderer:\n%s", physical.Query) } - lowered, err := Lower(builder) - if err != nil { - t.Fatalf("Lower() error = %v", err) - } - legacy, err := Compile(lowered, 7) - if err != nil { - t.Fatalf("Compile(lowered) error = %v", err) - } - if physical.Query == legacy.Query { - t.Fatalf("physical execution path did not render a distinct typed plan:\n%s", physical.Query) - } - assertPhysicalExecutionMetadataParity(t, physical, legacy) } -func TestCompileRequestFallsBackForGenericSelectionUntilPhysicalProjectionExists(t *testing.T) { +func TestCompileRequestUsesPhysicalExecutionForRootSelection(t *testing.T) { compiled, err := CompileRequest(Builder{ Project: "P1", RootResourceType: "Specimen", @@ -69,11 +56,11 @@ func TestCompileRequestFallsBackForGenericSelectionUntilPhysicalProjectionExists if err != nil { t.Fatalf("CompileRequest() error = %v", err) } - if !strings.Contains(compiled.Query, "FOR root IN Specimen") || !strings.Contains(compiled.Query, "root.payload.id") { - t.Fatalf("selection request did not use the full lowered fallback:\n%s", compiled.Query) + if !strings.Contains(compiled.Query, "FOR root IN @@root_collection") || !strings.Contains(compiled.Query, "root.payload.id") { + t.Fatalf("selection request did not use the physical renderer:\n%s", compiled.Query) } - if strings.Contains(compiled.Query, "@@root_collection") { - t.Fatalf("selection request was incorrectly routed through the navigation-only physical renderer:\n%s", compiled.Query) + if !strings.Contains(compiled.Query, "@@root_collection") { + t.Fatalf("selection request was not routed through the physical renderer:\n%s", compiled.Query) } } @@ -117,23 +104,3 @@ func buildPhysicalPlanForTest(t *testing.T, semantic SemanticPlan) PhysicalPlan } return plan } - -func assertPhysicalExecutionMetadataParity(t *testing.T, physical, lowered CompiledQuery) { - t.Helper() - if physical.Project != lowered.Project || - physical.DatasetGeneration != lowered.DatasetGeneration || - physical.RootResourceType != lowered.RootResourceType || - physical.PlanMode != lowered.PlanMode || - physical.PlanProfile != lowered.PlanProfile || - physical.NamedSetCount != lowered.NamedSetCount || - physical.FileSummaries != lowered.FileSummaries || - physical.StudyLookup != lowered.StudyLookup || - physical.Limit != lowered.Limit || - !reflect.DeepEqual(physical.AuthResourcePaths, lowered.AuthResourcePaths) || - !reflect.DeepEqual(physical.OptimizationRules, lowered.OptimizationRules) || - !reflect.DeepEqual(physical.RowIdentity, lowered.RowIdentity) || - !reflect.DeepEqual(physical.Columns, lowered.Columns) || - !reflect.DeepEqual(physical.PivotFields, lowered.PivotFields) { - t.Fatalf("physical metadata does not match lowered renderer:\nphysical=%#v\nlowered=%#v", physical, lowered) - } -} diff --git a/internal/dataframe/physical_helpers.go b/internal/dataframe/physical_helpers.go new file mode 100644 index 0000000..7eccc2b --- /dev/null +++ b/internal/dataframe/physical_helpers.go @@ -0,0 +1,179 @@ +package dataframe + +// genericPhysicalPlanUnavailableReason reports whether a semantic node needs +// an operation the navigation-only physical plan does not yet represent. +func genericPhysicalPlanUnavailableReason(node SemanticNode) string { + return genericPhysicalNodeUnavailableReason(node, true) +} + +func genericPhysicalNodeUnavailableReason(node SemanticNode, root bool) string { + for _, child := range node.Children { + if reason := genericPhysicalNodeUnavailableReason(child, false); reason != "" { + return reason + } + } + return "" +} + +func clonePhysicalPlan(plan PhysicalPlan) PhysicalPlan { + copy := plan + copy.BindVars = clonePhysicalBindVars(plan.BindVars) + copy.OptimizationPolicy = clonePhysicalOptimizationReport(plan.OptimizationPolicy) + copy.Operations = make([]PhysicalOperation, len(plan.Operations)) + for index, operation := range plan.Operations { + copy.Operations[index] = clonePhysicalOperation(operation) + } + return copy +} + +func clonePhysicalBindVars(bindVars map[string]any) map[string]any { + if bindVars == nil { + return nil + } + copy := make(map[string]any, len(bindVars)) + for key, value := range bindVars { + copy[key] = clonePhysicalBindValue(value) + } + return copy +} + +func clonePhysicalOperation(operation PhysicalOperation) PhysicalOperation { + copy := operation + if operation.RootScan != nil { + rootScanCopy := *operation.RootScan + copy.RootScan = &rootScanCopy + } + if operation.Traversal != nil { + traversalCopy := *operation.Traversal + copy.Traversal = &traversalCopy + } + if operation.Filter != nil { + filterCopy := *operation.Filter + filterCopy.Predicate = clonePhysicalPredicate(operation.Filter.Predicate) + if operation.Filter.Expression != nil { + expression := clonePhysicalPredicateExpression(*operation.Filter.Expression) + filterCopy.Expression = &expression + } + copy.Filter = &filterCopy + } + if operation.Set != nil { + setCopy := *operation.Set + setCopy.Subplan = clonePhysicalSubplan(operation.Set.Subplan) + copy.Set = &setCopy + } + if operation.DerivedLet != nil { + derivedCopy := *operation.DerivedLet + derivedCopy.Inputs = make([]PhysicalValue, len(operation.DerivedLet.Inputs)) + for index, input := range operation.DerivedLet.Inputs { + derivedCopy.Inputs[index] = clonePhysicalValue(input) + } + copy.DerivedLet = &derivedCopy + } + if operation.Sort != nil { + sortCopy := *operation.Sort + sortCopy.Value = clonePhysicalValue(operation.Sort.Value) + copy.Sort = &sortCopy + } + if operation.Limit != nil { + limitCopy := *operation.Limit + copy.Limit = &limitCopy + } + if operation.Return != nil { + returnCopy := *operation.Return + returnCopy.Projections = make([]PhysicalProjection, len(operation.Return.Projections)) + for index, projection := range operation.Return.Projections { + projectionCopy := projection + projectionCopy.Value = clonePhysicalValue(projection.Value) + returnCopy.Projections[index] = projectionCopy + } + copy.Return = &returnCopy + } + return copy +} + +func clonePhysicalPredicate(predicate PhysicalPredicate) PhysicalPredicate { + copy := predicate + copy.Left = clonePhysicalValue(predicate.Left) + if predicate.LeftExpression != nil { + leftExpression := clonePhysicalExpression(*predicate.LeftExpression) + copy.LeftExpression = &leftExpression + } + if predicate.Right != nil { + rightCopy := clonePhysicalValue(*predicate.Right) + copy.Right = &rightCopy + } + return copy +} + +func clonePhysicalPredicateExpression(predicate PhysicalPredicateExpression) PhysicalPredicateExpression { + copy := predicate + if predicate.Comparison != nil { + comparison := clonePhysicalPredicate(*predicate.Comparison) + copy.Comparison = &comparison + } + if predicate.Exists != nil { + subplan := clonePhysicalSubplan(*predicate.Exists) + copy.Exists = &subplan + } + copy.Children = make([]PhysicalPredicateExpression, len(predicate.Children)) + for index, child := range predicate.Children { + copy.Children[index] = clonePhysicalPredicateExpression(child) + } + return copy +} + +func clonePhysicalExpression(expression PhysicalExpression) PhysicalExpression { + copy := expression + if expression.Value != nil { + value := clonePhysicalValue(*expression.Value) + copy.Value = &value + } + if expression.Extract != nil { + extract := *expression.Extract + extract.Source = clonePhysicalValue(extract.Source) + extract.Fallbacks = append([]Selector(nil), extract.Fallbacks...) + copy.Extract = &extract + } + if expression.Pivot != nil { + pivot := *expression.Pivot + pivot.Source = clonePhysicalValue(expression.Pivot.Source) + pivot.ColumnsBindKey = expression.Pivot.ColumnsBindKey + copy.Pivot = &pivot + } + if expression.Aggregate != nil { + aggregate := *expression.Aggregate + aggregate.Source = clonePhysicalValue(aggregate.Source) + if aggregate.Value != nil { + value := clonePhysicalExpression(*aggregate.Value) + aggregate.Value = &value + } + copy.Aggregate = &aggregate + } + if expression.Slice != nil { + slice := *expression.Slice + slice.Source = clonePhysicalValue(slice.Source) + if slice.Sort != nil { + sort := clonePhysicalExpression(*slice.Sort) + slice.Sort = &sort + } + copy.Slice = &slice + } + return copy +} + +func clonePhysicalSubplan(subplan PhysicalSubplan) PhysicalSubplan { + copy := subplan + copy.Captures = cloneStrings(subplan.Captures) + copy.Operations = make([]PhysicalOperation, len(subplan.Operations)) + for i, op := range subplan.Operations { + copy.Operations[i] = clonePhysicalOperation(op) + } + copy.Return = clonePhysicalExpression(subplan.Return) + return copy +} + +func clonePhysicalValue(value PhysicalValue) PhysicalValue { + copy := value + copy.Path = cloneStrings(value.Path) + return copy +} diff --git a/internal/dataframe/physical_lowering.go b/internal/dataframe/physical_lowering.go new file mode 100644 index 0000000..2eaa745 --- /dev/null +++ b/internal/dataframe/physical_lowering.go @@ -0,0 +1,17 @@ +package dataframe + +import "fmt" + +// BuildPhysicalPlan is the compiler's direct semantic-to-physical boundary. +// +// It deliberately accepts SemanticPlan rather than the public request +// builder, keeping storage and AQL details out of semantic validation. +func BuildPhysicalPlan(semantic SemanticPlan) (PhysicalPlan, error) { + if err := ValidateSemanticGraph(semantic); err != nil { + return PhysicalPlan{}, fmt.Errorf("validate semantic plan: %w", err) + } + if reason := genericPhysicalPlanUnavailableReason(semantic.Root); reason != "" { + return PhysicalPlan{}, fmt.Errorf("physical lowering does not yet support %s", reason) + } + return BuildGenericPhysicalPlan(semantic) +} diff --git a/internal/dataframe/physical_lowering_test.go b/internal/dataframe/physical_lowering_test.go new file mode 100644 index 0000000..3d95077 --- /dev/null +++ b/internal/dataframe/physical_lowering_test.go @@ -0,0 +1,52 @@ +package dataframe + +import "testing" + +func TestBuildPhysicalPlanUsesSemanticPlanDirectly(t *testing.T) { + plan, err := BuildPhysicalPlan(SemanticPlan{ + Version: 1, + Project: "project-1", + Root: SemanticNode{ + Alias: "root", + ResourceType: "Patient", + Children: []SemanticNode{{ + Alias: "specimen", + ResourceType: "Specimen", + EdgeLabel: "subject_Patient", + }}, + }, + }) + if err != nil { + t.Fatalf("BuildPhysicalPlan() error = %v", err) + } + if err := plan.Validate(); err != nil { + t.Fatalf("physical plan validation: %v", err) + } +} + +func TestBuildPhysicalPlanLowersRootSelection(t *testing.T) { + selector, err := ParseSelector("gender") + if err != nil { + t.Fatal(err) + } + plan, err := BuildPhysicalPlan(SemanticPlan{ + Version: 1, + Project: "project-1", + Root: SemanticNode{ + Alias: "root", + ResourceType: "Patient", + Fields: []SemanticField{{ + Name: "gender", + FieldRef: "gender", + Selector: selector, + }}, + }, + }) + if err != nil { + t.Fatalf("BuildPhysicalPlan() error = %v", err) + } + projections := plan.Operations[len(plan.Operations)-1].Return.Projections + if len(projections) != 2 || projections[1].Expression == nil || projections[1].Expression.Kind != PhysicalExtractExpression { + t.Fatalf("root selection was not lowered to EXTRACT projection: %#v", projections) + } +} diff --git a/internal/dataframe/physical_optimize.go b/internal/dataframe/physical_optimize.go new file mode 100644 index 0000000..8fd64dd --- /dev/null +++ b/internal/dataframe/physical_optimize.go @@ -0,0 +1,337 @@ +package dataframe + +import ( + "fmt" + "sort" +) + +// OptimizePhysicalPlan applies semantics-preserving physical rewrites using +// the conservative structural cost policy. An unshared plan is always +// available as the correctness oracle, and the local policy switch can be used +// to compare the two physical shapes without changing request semantics. +func OptimizePhysicalPlan(plan PhysicalPlan) (PhysicalPlan, error) { + return OptimizePhysicalPlanWithPolicy(plan, DefaultPhysicalOptimizationPolicy()) +} + +// OptimizePhysicalPlanWithPolicy is the explicit form used by tests and +// benchmarking tools. The policy decides only whether an optional rewrite is +// enabled; it never relaxes physical-plan validation. +func OptimizePhysicalPlanWithPolicy(plan PhysicalPlan, policy PhysicalOptimizationPolicy) (PhysicalPlan, error) { + if err := plan.Validate(); err != nil { + return PhysicalPlan{}, fmt.Errorf("validate physical plan: %w", err) + } + out := clonePhysicalPlan(plan) + out.OptimizationPolicy = newPhysicalOptimizationReport(policy) + groups := map[string][]int{} + decompositions := map[int]PhysicalTraversalPrefixDecomposition{} + for i, op := range out.Operations { + if op.Kind != PhysicalSetOp || op.Set == nil || op.Set.SourceSetVariable != "" { + continue + } + decomposition, err := DecomposePhysicalTraversalPrefix(out, *op.Set) + if err != nil { + // Ineligibility is an expected optimizer outcome. The original plan + // remains the execution oracle. + continue + } + decompositions[i] = decomposition + groups[decomposition.PrefixKey] = append(groups[decomposition.PrefixKey], i) + } + groupKeys := make([]string, 0, len(groups)) + for key := range groups { + groupKeys = append(groupKeys, key) + } + sort.Strings(groupKeys) + for _, key := range groupKeys { + indices := groups[key] + if len(indices) < 2 { + continue + } + decision := PhysicalOptimizationDecision{ + Rule: OptimizerRuleTraversalSharing, + CandidateSets: len(indices), + } + // Sharing is useful only when it removes target-type-specific traversals. + types := map[string]bool{} + for _, index := range indices { + t := decompositions[index].Subset.TargetTypeBindKey + if value, ok := out.BindVars[t].(string); ok { + types[value] = true + } + } + if len(types) < 2 { + decision.Reason = "candidate group has fewer than two target resource types" + out.OptimizationPolicy.addDecision(decision) + continue + } + baseline, optimized, savings := estimateTraversalSharingWork(decompositions[indices[0]], len(indices)) + decision.EstimatedBaselineWork = baseline + decision.EstimatedOptimizedWork = optimized + decision.EstimatedSavings = savings + if !policy.Enabled { + decision.Reason = "cost policy disabled" + out.OptimizationPolicy.addDecision(decision) + continue + } + if savings < policy.MinimumSavings { + decision.Reason = fmt.Sprintf("estimated savings %d is below policy minimum %d", savings, policy.MinimumSavings) + out.OptimizationPolicy.addDecision(decision) + continue + } + if err := sharePhysicalSetGroup(&out, indices, types, decompositions); err != nil { + decision.Reason = "rewrite rejected: " + err.Error() + out.OptimizationPolicy.addDecision(decision) + continue + } + decision.Enabled = true + decision.Reason = "estimated prefix work reduction exceeds policy minimum" + out.OptimizationPolicy.addDecision(decision) + } + if err := out.Validate(); err != nil { + return PhysicalPlan{}, fmt.Errorf("validate optimized physical plan: %w", err) + } + return out, nil +} + +func sharePhysicalSetGroup(plan *PhysicalPlan, indices []int, types map[string]bool, decompositions map[int]PhysicalTraversalPrefixDecomposition) error { + first := indices[0] + // The broad set changes its target bind from one type to a type list. Deep + // clone before that change: its first consumer must retain the original + // single target-type bind for the typed subset. + originalOperation := clonePhysicalOperation(plan.Operations[first]) + original := *originalOperation.Set + t := *original.Subplan.Operations[0].Traversal + base := original + baseName := "shared_" + sanitizeColumnName(t.SourceVariable) + "_" + sanitizeColumnName(valueString(plan.BindVars[t.EdgeLabelBindKey])) + "_neighbors" + used := map[string]bool{} + for _, op := range plan.Operations { + if op.Set != nil { + used[op.Set.Variable] = true + } + } + for n := 2; used[baseName]; n++ { + baseName = fmt.Sprintf("%s_%d", baseName, n) + } + typesKey := baseName + "_target_types" + targetTypes := make([]string, 0, len(types)) + for typ := range types { + targetTypes = append(targetTypes, typ) + } + // Deterministic order is part of plan stability. + for i := 0; i < len(targetTypes); i++ { + for j := i + 1; j < len(targetTypes); j++ { + if targetTypes[j] < targetTypes[i] { + targetTypes[i], targetTypes[j] = targetTypes[j], targetTypes[i] + } + } + } + plan.BindVars[typesKey] = targetTypes + t.TargetTypeBindKey = typesKey + base.Subplan.Operations[0].Traversal = &t + base.Subplan.Operations = clonePhysicalOperations(original.Subplan.Operations[:7]) + base.Variable = baseName + base.SourceSetVariable, base.ItemVariable = "", "" + // Prepared values belong to typed consumer sets. The broad shared neighbor + // set must contain raw nodes only; consumers prepare their own projections + // after resource-type filtering. + base.Prepared = nil + base.Subplan.Return = PhysicalExpression{Kind: PhysicalValueExpression, Cardinality: PhysicalObjectCardinality, NullBehavior: PhysicalPreserveNull, Value: &PhysicalValue{Variable: t.TargetVariable}} + // Rebuild operation stream, inserting the broad traversal immediately before + // the first consumer and replacing each consumer with a typed subset. + indexSet := map[int]bool{} + for _, i := range indices { + indexSet[i] = true + } + newOps := make([]PhysicalOperation, 0, len(plan.Operations)+1) + for i, op := range plan.Operations { + if i == first { + newOps = append(newOps, PhysicalOperation{Kind: PhysicalSetOp, Source: plan.Operations[first].Source, Set: &base}) + } + if !indexSet[i] { + newOps = append(newOps, op) + continue + } + set := *op.Set + decomposition, found := decompositions[i] + if !found { + return fmt.Errorf("shared set %q has no validated traversal-prefix decomposition", set.Variable) + } + origTraversal := *set.Subplan.Operations[0].Traversal + item := set.Variable + "_item" + typeKey := origTraversal.TargetTypeBindKey + sub := PhysicalSubplan{Captures: []string{baseName}, Return: PhysicalExpression{Kind: PhysicalValueExpression, Cardinality: PhysicalObjectCardinality, NullBehavior: PhysicalPreserveNull, Value: &PhysicalValue{Variable: item}}} + sub.Operations = append(sub.Operations, PhysicalOperation{Kind: PhysicalFilterOp, Filter: &PhysicalFilter{Predicate: PhysicalPredicate{Operator: "EQUALS", Left: PhysicalValue{Variable: item, Path: []string{"resourceType"}}, Right: &PhysicalValue{BindKey: typeKey}}}}) + for _, child := range decomposition.Subset.ConsumerOperations { + rewritten := rewritePhysicalOperationVariables(child, origTraversal.TargetVariable, item, origTraversal.EdgeVariable, item) + sub.Operations = append(sub.Operations, rewritten) + } + set.SourceSetVariable, set.ItemVariable, set.Subplan = baseName, item, sub + set.Unique, set.SortByKey = true, true + newOps = append(newOps, PhysicalOperation{Kind: PhysicalSetOp, Source: op.Source, Set: &set}) + } + plan.Operations = newOps + plan.SharedTraversalCount += len(indices) - 1 + plan.AppliedRules = appendUniqueRule(plan.AppliedRules, OptimizerRuleTraversalSharing) + return nil +} + +func valueString(v any) string { + if s, ok := v.(string); ok { + return s + } + return "edge" +} +func appendUniqueRule(rules []string, rule string) []string { + for _, r := range rules { + if r == rule { + return rules + } + } + return append(rules, rule) +} +func rewritePhysicalValue(v PhysicalValue, fromTarget, toTarget, fromEdge, toEdge string) PhysicalValue { + if v.Variable == fromTarget { + v.Variable = toTarget + } + if v.Variable == fromEdge { + v.Variable = toEdge + } + return v +} +func rewritePhysicalOperationVariables(op PhysicalOperation, fromTarget, toTarget, fromEdge, toEdge string) PhysicalOperation { + if op.Traversal != nil { + t := *op.Traversal + if t.SourceVariable == fromTarget { + t.SourceVariable = toTarget + } + if t.SourceVariable == fromEdge { + t.SourceVariable = toEdge + } + if t.TargetVariable == fromTarget { + t.TargetVariable = toTarget + } + if t.TargetVariable == fromEdge { + t.TargetVariable = toEdge + } + if t.EdgeVariable == fromTarget { + t.EdgeVariable = toTarget + } + if t.EdgeVariable == fromEdge { + t.EdgeVariable = toEdge + } + op.Traversal = &t + } + if op.Filter != nil { + f := *op.Filter + f.Predicate.Left = rewritePhysicalValue(f.Predicate.Left, fromTarget, toTarget, fromEdge, toEdge) + if f.Predicate.LeftExpression != nil { + e := rewritePhysicalExpressionVariables(*f.Predicate.LeftExpression, fromTarget, toTarget, fromEdge, toEdge) + f.Predicate.LeftExpression = &e + } + if f.Predicate.Right != nil { + v := rewritePhysicalValue(*f.Predicate.Right, fromTarget, toTarget, fromEdge, toEdge) + f.Predicate.Right = &v + } + if f.Expression != nil { + expression := rewritePhysicalPredicateExpressionVariables(*f.Expression, fromTarget, toTarget, fromEdge, toEdge) + f.Expression = &expression + } + op.Filter = &f + } + if op.DerivedLet != nil { + d := *op.DerivedLet + for i := range d.Inputs { + d.Inputs[i] = rewritePhysicalValue(d.Inputs[i], fromTarget, toTarget, fromEdge, toEdge) + } + if d.Expression != nil { + expression := rewritePhysicalExpressionVariables(*d.Expression, fromTarget, toTarget, fromEdge, toEdge) + d.Expression = &expression + } + op.DerivedLet = &d + } + return op +} + +func rewritePhysicalExpressionVariables(expression PhysicalExpression, fromTarget, toTarget, fromEdge, toEdge string) PhysicalExpression { + if expression.Value != nil { + v := rewritePhysicalValue(*expression.Value, fromTarget, toTarget, fromEdge, toEdge) + expression.Value = &v + } + if expression.Extract != nil { + e := *expression.Extract + e.Source = rewritePhysicalValue(e.Source, fromTarget, toTarget, fromEdge, toEdge) + expression.Extract = &e + } + if expression.Aggregate != nil { + a := *expression.Aggregate + a.Source = rewritePhysicalValue(a.Source, fromTarget, toTarget, fromEdge, toEdge) + if a.Value != nil { + v := rewritePhysicalExpressionVariables(*a.Value, fromTarget, toTarget, fromEdge, toEdge) + a.Value = &v + } + if a.Predicate != nil { + predicate := rewritePhysicalPredicateExpressionVariables(*a.Predicate, fromTarget, toTarget, fromEdge, toEdge) + a.Predicate = &predicate + } + expression.Aggregate = &a + } + if expression.Pivot != nil { + pivot := *expression.Pivot + pivot.Source = rewritePhysicalValue(pivot.Source, fromTarget, toTarget, fromEdge, toEdge) + expression.Pivot = &pivot + } + if expression.Slice != nil { + slice := *expression.Slice + slice.Source = rewritePhysicalValue(slice.Source, fromTarget, toTarget, fromEdge, toEdge) + if slice.Predicate != nil { + predicate := rewritePhysicalPredicateExpressionVariables(*slice.Predicate, fromTarget, toTarget, fromEdge, toEdge) + slice.Predicate = &predicate + } + if slice.Sort != nil { + sort := rewritePhysicalExpressionVariables(*slice.Sort, fromTarget, toTarget, fromEdge, toEdge) + slice.Sort = &sort + } + for index := range slice.Projections { + slice.Projections[index].Expression = rewritePhysicalExpressionVariables(slice.Projections[index].Expression, fromTarget, toTarget, fromEdge, toEdge) + } + expression.Slice = &slice + } + if expression.Object != nil { + object := *expression.Object + object.Fields = append([]PhysicalExpressionProjection(nil), object.Fields...) + for index := range object.Fields { + object.Fields[index].Expression = rewritePhysicalExpressionVariables(object.Fields[index].Expression, fromTarget, toTarget, fromEdge, toEdge) + } + expression.Object = &object + } + return expression +} + +func rewritePhysicalPredicateExpressionVariables(predicate PhysicalPredicateExpression, fromTarget, toTarget, fromEdge, toEdge string) PhysicalPredicateExpression { + predicate = clonePhysicalPredicateExpression(predicate) + if predicate.Comparison != nil { + comparison := *predicate.Comparison + comparison.Left = rewritePhysicalValue(comparison.Left, fromTarget, toTarget, fromEdge, toEdge) + if comparison.LeftExpression != nil { + expression := rewritePhysicalExpressionVariables(*comparison.LeftExpression, fromTarget, toTarget, fromEdge, toEdge) + comparison.LeftExpression = &expression + } + if comparison.Right != nil { + right := rewritePhysicalValue(*comparison.Right, fromTarget, toTarget, fromEdge, toEdge) + comparison.Right = &right + } + predicate.Comparison = &comparison + } + for index := range predicate.Children { + predicate.Children[index] = rewritePhysicalPredicateExpressionVariables(predicate.Children[index], fromTarget, toTarget, fromEdge, toEdge) + } + if predicate.Exists != nil { + subplan := clonePhysicalSubplan(*predicate.Exists) + for index := range subplan.Operations { + subplan.Operations[index] = rewritePhysicalOperationVariables(subplan.Operations[index], fromTarget, toTarget, fromEdge, toEdge) + } + subplan.Return = rewritePhysicalExpressionVariables(subplan.Return, fromTarget, toTarget, fromEdge, toEdge) + predicate.Exists = &subplan + } + return predicate +} diff --git a/internal/dataframe/physical_optimize_test.go b/internal/dataframe/physical_optimize_test.go new file mode 100644 index 0000000..290be09 --- /dev/null +++ b/internal/dataframe/physical_optimize_test.go @@ -0,0 +1,254 @@ +package dataframe + +import ( + "strings" + "testing" +) + +func TestOptimizePhysicalPlanSharesEquivalentTypedPrefixes(t *testing.T) { + plan := physicalScopedSiblingPlan(t) + optimized, err := OptimizePhysicalPlan(plan) + if err != nil { + t.Fatalf("OptimizePhysicalPlan() error = %v", err) + } + if optimized.SharedTraversalCount != 1 { + t.Fatalf("shared traversal count = %d, want 1", optimized.SharedTraversalCount) + } + if !containsOptimizerRule(optimized.AppliedRules, OptimizerRuleTraversalSharing) { + t.Fatalf("missing sharing rule: %#v", optimized.AppliedRules) + } + if len(optimized.Operations) != len(plan.Operations)+1 { + t.Fatalf("optimized operation count = %d, want %d", len(optimized.Operations), len(plan.Operations)+1) + } + if err := optimized.Validate(); err != nil { + t.Fatalf("optimized plan invalid: %v", err) + } + var broad, subsets int + for _, op := range optimized.Operations { + if op.Kind != PhysicalSetOp { + continue + } + if op.Set.SourceSetVariable == "" { + broad++ + } else { + subsets++ + } + } + if broad != 1 || subsets != 2 { + t.Fatalf("broad=%d subsets=%d, want 1/2", broad, subsets) + } +} + +func TestOptimizePhysicalPlanReportsStructuralCostDecision(t *testing.T) { + optimized, err := OptimizePhysicalPlanWithPolicy(physicalScopedSiblingPlan(t), PhysicalOptimizationPolicy{Enabled: true, MinimumSavings: 1}) + if err != nil { + t.Fatal(err) + } + decisions := optimized.OptimizationPolicy.Decisions + if len(decisions) != 1 { + t.Fatalf("cost-policy decisions = %#v, want one decision", decisions) + } + decision := decisions[0] + if !decision.Enabled || decision.Rule != OptimizerRuleTraversalSharing { + t.Fatalf("cost-policy decision = %#v, want enabled traversal sharing", decision) + } + if decision.EstimatedBaselineWork <= decision.EstimatedOptimizedWork || decision.EstimatedSavings <= 0 { + t.Fatalf("cost estimate = %#v, want positive savings", decision) + } + if optimized.OptimizationPolicy.Policy == "" || !optimized.OptimizationPolicy.Enabled { + t.Fatalf("missing enabled policy report: %#v", optimized.OptimizationPolicy) + } +} + +func TestOptimizePhysicalPlanCostPolicyCanDisableRewrite(t *testing.T) { + original := physicalScopedSiblingPlan(t) + optimized, err := OptimizePhysicalPlanWithPolicy(original, PhysicalOptimizationPolicy{Enabled: false, MinimumSavings: 1}) + if err != nil { + t.Fatal(err) + } + if optimized.SharedTraversalCount != 0 { + t.Fatalf("disabled policy shared traversal count = %d, want 0", optimized.SharedTraversalCount) + } + if len(optimized.Operations) != len(original.Operations) { + t.Fatalf("disabled policy changed operation count from %d to %d", len(original.Operations), len(optimized.Operations)) + } + if len(optimized.OptimizationPolicy.Decisions) != 1 || optimized.OptimizationPolicy.Decisions[0].Enabled { + t.Fatalf("disabled policy decision = %#v, want explicit rejection", optimized.OptimizationPolicy.Decisions) + } + if optimized.OptimizationPolicy.Decisions[0].Reason != "cost policy disabled" { + t.Fatalf("disabled policy reason = %q", optimized.OptimizationPolicy.Decisions[0].Reason) + } +} + +func TestOptimizePhysicalPlanCostPolicyMinimumSavingsRejectsCandidate(t *testing.T) { + optimized, err := OptimizePhysicalPlanWithPolicy(physicalScopedSiblingPlan(t), PhysicalOptimizationPolicy{Enabled: true, MinimumSavings: 999}) + if err != nil { + t.Fatal(err) + } + if optimized.SharedTraversalCount != 0 { + t.Fatalf("high policy threshold shared traversal count = %d, want 0", optimized.SharedTraversalCount) + } + if len(optimized.OptimizationPolicy.Decisions) != 1 || optimized.OptimizationPolicy.Decisions[0].Enabled { + t.Fatalf("high policy decision = %#v, want rejection", optimized.OptimizationPolicy.Decisions) + } + if optimized.OptimizationPolicy.Decisions[0].EstimatedSavings >= 999 { + t.Fatalf("high policy estimate unexpectedly met threshold: %#v", optimized.OptimizationPolicy.Decisions[0]) + } +} + +func TestEstimatePreparedSelectorWorkRequiresRepeatedConsumer(t *testing.T) { + if baseline, optimized, savings := estimatePreparedSelectorWork(1); baseline != 0 || optimized != 0 || savings != 0 { + t.Fatalf("single selector estimate = %d/%d/%d, want no preparation", baseline, optimized, savings) + } + if baseline, optimized, savings := estimatePreparedSelectorWork(2); baseline <= optimized || savings <= 0 { + t.Fatalf("repeated selector estimate = %d/%d/%d, want positive savings", baseline, optimized, savings) + } +} + +func TestDefaultPhysicalOptimizationPolicyDeveloperSwitch(t *testing.T) { + t.Setenv("LOOM_PHYSICAL_COST_POLICY", "off") + policy := DefaultPhysicalOptimizationPolicy() + if policy.Enabled { + t.Fatalf("disabled environment policy = %#v", policy) + } + t.Setenv("LOOM_PHYSICAL_COST_POLICY", "on") + t.Setenv("LOOM_PHYSICAL_COST_MIN_SAVINGS", "17") + policy = DefaultPhysicalOptimizationPolicy() + if !policy.Enabled || policy.MinimumSavings != 17 { + t.Fatalf("configured environment policy = %#v", policy) + } +} + +func TestOptimizePhysicalPlanRendersOneScopedTraversalForSiblingSets(t *testing.T) { + plan := physicalScopedSiblingPlan(t) + optimized, err := OptimizePhysicalPlan(plan) + if err != nil { + t.Fatal(err) + } + rendered, err := RenderPhysicalPlan(optimized) + if err != nil { + t.Fatal(err) + } + if got := strings.Count(rendered.Query, "INBOUND root @@child_set_"); got != 1 { + t.Fatalf("rendered sibling group used %d root traversals, want 1:\n%s", got, rendered.Query) + } + if got := strings.Count(rendered.Query, "child_set_1_edge.auth_resource_path IN @auth_resource_paths"); got != 1 { + t.Fatalf("shared traversal did not retain its edge auth scope exactly once:\n%s", rendered.Query) + } + if got := strings.Count(rendered.Query, "child_set_1_node.auth_resource_path IN @auth_resource_paths"); got != 1 { + t.Fatalf("shared traversal did not retain its node auth scope exactly once:\n%s", rendered.Query) + } +} + +func TestDecomposePhysicalTraversalPrefixIsAlphaEquivalentAcrossSiblingVariables(t *testing.T) { + plan := physicalScopedSiblingPlan(t) + sets := physicalSets(plan) + if len(sets) != 2 { + t.Fatalf("physical sets = %d, want 2", len(sets)) + } + first, err := DecomposePhysicalTraversalPrefix(plan, *sets[0]) + if err != nil { + t.Fatal(err) + } + second, err := DecomposePhysicalTraversalPrefix(plan, *sets[1]) + if err != nil { + t.Fatal(err) + } + if first.PrefixKey != second.PrefixKey { + t.Fatalf("sibling prefixes did not canonicalize:\nfirst=%s\nsecond=%s", first.PrefixKey, second.PrefixKey) + } + if first.Subset.TargetTypeBindKey == second.Subset.TargetTypeBindKey { + t.Fatalf("fixture did not retain distinct target subsets: %#v %#v", first.Subset, second.Subset) + } +} + +func TestOptimizePhysicalPlanRebindsTypedConsumerFiltersToSharedSubsetItems(t *testing.T) { + plan := physicalScopedSiblingPlanWithFilters(t) + optimized, err := OptimizePhysicalPlan(plan) + if err != nil { + t.Fatal(err) + } + if err := optimized.Validate(); err != nil { + t.Fatalf("optimized plan validation: %v", err) + } + for _, set := range physicalSets(optimized) { + if set.SourceSetVariable == "" { + continue + } + if len(set.Subplan.Operations) != 2 { + t.Fatalf("shared subset %q operations = %#v", set.Variable, set.Subplan.Operations) + } + filter := set.Subplan.Operations[1].Filter + if filter == nil || filter.Expression == nil || filter.Expression.Comparison == nil || filter.Expression.Comparison.LeftExpression == nil || filter.Expression.Comparison.LeftExpression.Extract == nil { + t.Fatalf("shared subset %q lost its typed consumer filter: %#v", set.Variable, set.Subplan.Operations) + } + if got := filter.Expression.Comparison.LeftExpression.Extract.Source.Variable; got != set.ItemVariable { + t.Fatalf("shared subset %q filter source = %q, want item %q", set.Variable, got, set.ItemVariable) + } + } +} + +func TestDecomposePhysicalTraversalPrefixRejectsUnscopedOrSharedSets(t *testing.T) { + plan := physicalScopedSiblingPlan(t) + set := *physicalSets(plan)[0] + set.Subplan.Operations = set.Subplan.Operations[:6] + _, err := DecomposePhysicalTraversalPrefix(plan, set) + assertPrefixRejection(t, err, PhysicalPrefixMissingTraversal) + + set = *physicalSets(plan)[0] + set.SourceSetVariable = "another_set" + _, err = DecomposePhysicalTraversalPrefix(plan, set) + assertPrefixRejection(t, err, PhysicalPrefixSharedSubset) +} + +func assertPrefixRejection(t *testing.T, err error, want PhysicalTraversalPrefixRejectionReason) { + t.Helper() + if err == nil { + t.Fatalf("DecomposePhysicalTraversalPrefix() error = nil, want %s", want) + } + got, ok := err.(*PhysicalTraversalPrefixError) + if !ok || got.Reason != want { + t.Fatalf("prefix error = %#v, want %s", err, want) + } +} + +func physicalScopedSiblingPlan(t *testing.T) PhysicalPlan { + t.Helper() + plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, Project: "project-1", AuthResourcePaths: []string{"/programs/p1"}, + Root: SemanticNode{Alias: "root", ResourceType: "Patient", Children: []SemanticNode{ + {Alias: "condition", ResourceType: "Condition", EdgeLabel: "subject_Patient", Fields: []SemanticField{{Name: "id", FieldRef: "Condition.id", Selector: mustPhysicalSelector(t, "id")}}}, + {Alias: "specimen", ResourceType: "Specimen", EdgeLabel: "subject_Patient", Fields: []SemanticField{{Name: "id", FieldRef: "Specimen.id", Selector: mustPhysicalSelector(t, "id")}}}, + }}, + }) + if err != nil { + t.Fatal(err) + } + return plan +} + +func physicalScopedSiblingPlanWithFilters(t *testing.T) PhysicalPlan { + t.Helper() + plan := physicalScopedSiblingPlan(t) + for _, set := range physicalSets(plan) { + traversal := set.Subplan.Operations[0].Traversal + predicate := PhysicalPredicate{Operator: string(FilterExists), ValueKind: FilterString, + LeftExpression: &PhysicalExpression{Kind: PhysicalExtractExpression, Cardinality: PhysicalArrayCardinality, NullBehavior: PhysicalEmptyOnNull, + Extract: &PhysicalExtract{Source: PhysicalValue{Variable: traversal.TargetVariable, Path: []string{"payload"}}, ResourceType: valueString(plan.BindVars[traversal.TargetTypeBindKey]), Selector: mustPhysicalSelector(t, "id")}}} + set.Subplan.Operations = append(set.Subplan.Operations, PhysicalOperation{Kind: PhysicalFilterOp, Filter: &PhysicalFilter{Expression: &PhysicalPredicateExpression{Kind: PhysicalComparisonPredicate, Comparison: &predicate}}}) + } + if err := plan.Validate(); err != nil { + t.Fatalf("filtered fixture validation: %v", err) + } + return plan +} + +func physicalSets(plan PhysicalPlan) []*PhysicalSet { + sets := make([]*PhysicalSet, 0) + for _, operation := range plan.Operations { + if operation.Kind == PhysicalSetOp && operation.Set != nil { + sets = append(sets, operation.Set) + } + } + return sets +} diff --git a/internal/dataframe/physical_plan.go b/internal/dataframe/physical_plan.go index d61e9c5..f47958b 100644 --- a/internal/dataframe/physical_plan.go +++ b/internal/dataframe/physical_plan.go @@ -4,6 +4,8 @@ import ( "fmt" "regexp" "strings" + + "github.com/calypr/loom/fhirschema" ) // PhysicalPlan is the renderer-independent AQL operation graph produced after @@ -14,6 +16,18 @@ type PhysicalPlan struct { Source PhysicalSource BindVars map[string]any Operations []PhysicalOperation + // AppliedRules records physical rewrites without exposing renderer + // implementation details to callers. + AppliedRules []string + SharedTraversalCount int + // OptimizationPolicy records every optional rewrite decision made by the + // physical optimizer, including conservative rejections. + OptimizationPolicy PhysicalOptimizationReport + // RequiredMatchReuseCount records duplicate required EXISTS predicates + // removed during physical lowering. It is deliberately separate from + // shared traversal count: required predicates remain pre-window + // semi-joins, while optional sets are post-window materializations. + RequiredMatchReuseCount int } // PhysicalSource retains semantic provenance through physical optimization so @@ -34,6 +48,10 @@ const ( PhysicalTraversalOp PhysicalOperationKind = "TRAVERSAL" PhysicalFilterOp PhysicalOperationKind = "FILTER" PhysicalDerivedLetOp PhysicalOperationKind = "DERIVED_LET" + // PhysicalSetOp materializes a correlated, array-valued subplan. It is the + // only operation that can introduce a set variable; selectors, aggregates, + // pivots, and slices consume that variable through typed expressions. + PhysicalSetOp PhysicalOperationKind = "SET" // PhysicalSortOp and PhysicalLimitOp describe the root execution window. // They are intentionally typed so preview ordering and bounds cannot be // smuggled into an AQL string by a caller. @@ -51,6 +69,7 @@ type PhysicalOperation struct { Traversal *PhysicalTraversal Filter *PhysicalFilter DerivedLet *PhysicalDerivedLet + Set *PhysicalSet Sort *PhysicalSort Limit *PhysicalLimit Return *PhysicalReturn @@ -92,22 +111,208 @@ type PhysicalValue struct { BindKey string } +// PhysicalCardinality and PhysicalNullBehavior are deliberately explicit on +// every rich expression. A renderer must not infer array/scalar/null behavior +// from where an expression appears in an AQL template. +type PhysicalCardinality string + +const ( + PhysicalScalarCardinality PhysicalCardinality = "SCALAR" + PhysicalArrayCardinality PhysicalCardinality = "ARRAY" + PhysicalObjectCardinality PhysicalCardinality = "OBJECT" +) + +type PhysicalNullBehavior string + +const ( + PhysicalPreserveNull PhysicalNullBehavior = "PRESERVE_NULL" + PhysicalOmitNulls PhysicalNullBehavior = "OMIT_NULLS" + PhysicalEmptyOnNull PhysicalNullBehavior = "EMPTY_ON_NULL" +) + +type PhysicalExpressionKind string + +const ( + PhysicalValueExpression PhysicalExpressionKind = "VALUE" + PhysicalExtractExpression PhysicalExpressionKind = "EXTRACT" + PhysicalAggregateExpression PhysicalExpressionKind = "AGGREGATE" + PhysicalPivotExpression PhysicalExpressionKind = "PIVOT_MAP" + PhysicalSliceExpression PhysicalExpressionKind = "SLICE" + PhysicalObjectExpression PhysicalExpressionKind = "OBJECT" +) + +// PhysicalExpression is a closed, renderer-independent value tree. It carries +// no AQL source text: selector paths have already been parsed and all literals +// are represented by bind values. +type PhysicalExpression struct { + Kind PhysicalExpressionKind + Cardinality PhysicalCardinality + NullBehavior PhysicalNullBehavior + Value *PhysicalValue + Extract *PhysicalExtract + Aggregate *PhysicalAggregate + Pivot *PhysicalPivotMap + Slice *PhysicalSlice + Object *PhysicalObject +} + +// PhysicalExtract obtains one FHIR selector from a variable or prior set +// element. ResourceType keeps schema validation available after semantic +// lowering; fallbacks preserve the existing FIRST_NON_NULL behavior. +type PhysicalExtract struct { + Source PhysicalValue + ResourceType string + Selector Selector + Fallbacks []Selector + // Distinct preserves the explicit DISTINCT projection mode after semantic + // lowering. It is meaningful only for an array-valued expression. + Distinct bool + // Prepared points at a selector value projected by a prepared child set. + // Source remains the owning set for scope validation and diagnostics. + Prepared *PhysicalPreparedReference +} + +// PhysicalPreparedReference identifies one selector column in a prepared set. +type PhysicalPreparedReference struct { + SetVariable string + Field string +} + +// PhysicalPreparedSet describes selector projections shared by rich +// consumers over one materialized relationship set. Preparation stays +// attached to the correlated set so root row grain cannot change. +type PhysicalPreparedSet struct { + Variable string + SourceSetVariable string + Fields []PhysicalPreparedField +} + +type PhysicalPreparedField struct { + Name string + ResourceType string + Selector Selector +} + +type PhysicalAggregateOperation string + +const ( + PhysicalCountAggregate PhysicalAggregateOperation = "COUNT" + PhysicalCountDistinctAggregate PhysicalAggregateOperation = "COUNT_DISTINCT" + PhysicalExistsAggregate PhysicalAggregateOperation = "EXISTS" + PhysicalDistinctValuesAggregate PhysicalAggregateOperation = "DISTINCT_VALUES" + PhysicalMinAggregate PhysicalAggregateOperation = "MIN" + PhysicalMaxAggregate PhysicalAggregateOperation = "MAX" + PhysicalFirstAggregate PhysicalAggregateOperation = "FIRST" +) + +type PhysicalAggregate struct { + Source PhysicalValue + Operation PhysicalAggregateOperation + Value *PhysicalExpression + Predicate *PhysicalPredicateExpression +} + +type PhysicalPivotMap struct { + Source PhysicalValue + ResourceType string + KeySelector Selector + ValueSelector Selector + ColumnsBindKey string + PreparedKey *PhysicalPreparedReference + PreparedValue *PhysicalPreparedReference +} + +// PhysicalSlice is a bounded, stable, nested projection over a prior set. +// Limit remains a bind variable so callers cannot synthesize query literals. +type PhysicalSlice struct { + Source PhysicalValue + Predicate *PhysicalPredicateExpression + Sort *PhysicalExpression + LimitBindKey string + Projections []PhysicalExpressionProjection +} + +type PhysicalExpressionProjection struct { + Name string + Expression PhysicalExpression +} + +type PhysicalObject struct { + Fields []PhysicalExpressionProjection +} + +// PhysicalSet is a correlated, array-valued subplan. Captures are declared +// explicitly so validation can prevent accidental references to parent or +// future variables. The set variable becomes visible only after its subplan +// has validated successfully. +type PhysicalSet struct { + Variable string + Subplan PhysicalSubplan + Unique bool + // SourceSetVariable is set for a typed subset over an already materialized + // shared traversal. Such a set does not begin with TRAVERSAL; ItemVariable + // is bound by the renderer while iterating SourceSetVariable. + SourceSetVariable string + ItemVariable string + // SortByKey makes the set's node order part of physical semantics. Optional + // relationship materialization must not rely on Arango traversal order. + SortByKey bool + Prepared *PhysicalPreparedSet +} + +type PhysicalSubplan struct { + Captures []string + Operations []PhysicalOperation + Return PhysicalExpression +} + type PhysicalPredicate struct { Operator string Left PhysicalValue - Right *PhysicalValue + // LeftExpression lets a comparison consume a typed selector extraction. + // Exactly one of Left and LeftExpression is present. This keeps user + // filters out of AQL-shaped strings while the scope predicates can retain + // their compact value-only form. + LeftExpression *PhysicalExpression + Right *PhysicalValue + Quantifier ArrayQuantifier + ValueKind FilterValueKind +} + +type PhysicalPredicateKind string + +const ( + PhysicalComparisonPredicate PhysicalPredicateKind = "COMPARISON" + PhysicalAllPredicate PhysicalPredicateKind = "ALL" + PhysicalAnyPredicate PhysicalPredicateKind = "ANY" + PhysicalNotPredicate PhysicalPredicateKind = "NOT" + PhysicalExistsPredicate PhysicalPredicateKind = "EXISTS" +) + +// PhysicalPredicateExpression is the typed predicate tree used by rich +// physical operations. Exists contains a bounded correlated subplan; it is +// not a string-shaped LENGTH(FOR ...) compatibility escape hatch. +type PhysicalPredicateExpression struct { + Kind PhysicalPredicateKind + Comparison *PhysicalPredicate + Children []PhysicalPredicateExpression + Exists *PhysicalSubplan } type PhysicalFilter struct { - Predicate PhysicalPredicate + // Predicate is retained for the frozen navigation plan. New lowering must + // use Expression so compound and existence predicates stay typed. + Predicate PhysicalPredicate + Expression *PhysicalPredicateExpression } // PhysicalDerivedLet names a derived value. Operator is a compiler-owned // symbolic operation (for example UNIQUE or LENGTH), never raw AQL. type PhysicalDerivedLet struct { - Variable string - Operator string - Inputs []PhysicalValue + Variable string + Operator string + Inputs []PhysicalValue + Expression *PhysicalExpression } // PhysicalSort is the deliberately small ordering primitive currently needed @@ -124,8 +329,9 @@ type PhysicalLimit struct { } type PhysicalProjection struct { - Name string - Value PhysicalValue + Name string + Value PhysicalValue + Expression *PhysicalExpression } type PhysicalReturn struct { @@ -167,6 +373,9 @@ func (p PhysicalPlan) Validate() error { if err := requireBind(p.BindVars, operation.RootScan.CollectionBindKey); err != nil { return fmt.Errorf("operation %d: %w", i, err) } + if err := requireCollectionBind(p.BindVars, operation.RootScan.CollectionBindKey); err != nil { + return fmt.Errorf("operation %d: %w", i, err) + } if err := definePhysicalVariable(defined, operation.RootScan.Variable); err != nil { return fmt.Errorf("operation %d: %w", i, err) } @@ -188,6 +397,12 @@ func (p PhysicalPlan) Validate() error { } } } + if traversal.EdgeCollectionBindKey == "" { + return fmt.Errorf("operation %d: traversal edge collection bind key is required", i) + } + if err := requireCollectionBind(p.BindVars, traversal.EdgeCollectionBindKey); err != nil { + return fmt.Errorf("operation %d: %w", i, err) + } if err := definePhysicalVariable(defined, traversal.TargetVariable); err != nil { return fmt.Errorf("operation %d: %w", i, err) } @@ -197,22 +412,30 @@ func (p PhysicalPlan) Validate() error { } } case PhysicalFilterOp: - if err := validatePhysicalPredicate(operation.Filter.Predicate, defined, p.BindVars); err != nil { + if err := validatePhysicalFilter(*operation.Filter, defined, p.BindVars); err != nil { return fmt.Errorf("operation %d: %w", i, err) } case PhysicalDerivedLetOp: derived := operation.DerivedLet - if strings.TrimSpace(derived.Operator) == "" { - return fmt.Errorf("operation %d: derived LET operator is required", i) - } - for _, input := range derived.Inputs { - if err := validatePhysicalValue(input, defined, p.BindVars); err != nil { - return fmt.Errorf("operation %d: %w", i, err) - } + if err := validatePhysicalDerivedLet(*derived, defined, p.BindVars); err != nil { + return fmt.Errorf("operation %d: %w", i, err) } if err := definePhysicalVariable(defined, derived.Variable); err != nil { return fmt.Errorf("operation %d: %w", i, err) } + case PhysicalSetOp: + set := operation.Set + if err := validatePhysicalSet(*set, defined, p.BindVars); err != nil { + return fmt.Errorf("operation %d set %q: %w", i, set.Variable, err) + } + if err := definePhysicalVariable(defined, set.Variable); err != nil { + return fmt.Errorf("operation %d: %w", i, err) + } + if set.Prepared != nil { + if err := definePhysicalVariable(defined, set.Prepared.Variable); err != nil { + return fmt.Errorf("operation %d prepared set: %w", i, err) + } + } case PhysicalSortOp: if err := validatePhysicalValue(operation.Sort.Value, defined, p.BindVars); err != nil { return fmt.Errorf("operation %d: %w", i, err) @@ -233,7 +456,7 @@ func (p PhysicalPlan) Validate() error { return fmt.Errorf("operation %d: return projection name %q is empty or duplicated", i, projection.Name) } seenNames[projection.Name] = true - if err := validatePhysicalValue(projection.Value, defined, p.BindVars); err != nil { + if err := validatePhysicalProjection(projection, defined, p.BindVars); err != nil { return fmt.Errorf("operation %d projection %q: %w", i, projection.Name, err) } } @@ -248,6 +471,65 @@ func (p PhysicalPlan) Validate() error { return nil } +func validatePhysicalSet(set PhysicalSet, parent map[string]bool, bindVars map[string]any) error { + if set.Prepared != nil { + prepared := set.Prepared + if !physicalVariablePattern.MatchString(prepared.Variable) || !physicalVariablePattern.MatchString(prepared.SourceSetVariable) { + return fmt.Errorf("prepared set variables must be safe") + } + if prepared.SourceSetVariable != set.Variable { + return fmt.Errorf("prepared set source %q must equal owning set %q", prepared.SourceSetVariable, set.Variable) + } + if len(prepared.Fields) == 0 { + return fmt.Errorf("prepared set %q requires at least one field", prepared.Variable) + } + seen := map[string]bool{} + for _, field := range prepared.Fields { + if !physicalVariablePattern.MatchString(field.Name) || seen[field.Name] { + return fmt.Errorf("prepared set field %q is unsafe or duplicated", field.Name) + } + seen[field.Name] = true + if strings.TrimSpace(field.ResourceType) == "" || !fhirschema.HasResource(field.ResourceType) { + return fmt.Errorf("prepared set field %q has invalid resource type %q", field.Name, field.ResourceType) + } + if err := validatePhysicalSelector(field.ResourceType, field.Selector); err != nil { + return fmt.Errorf("prepared set field %q selector: %w", field.Name, err) + } + } + } + if set.SourceSetVariable == "" { + return validatePhysicalSubplan(set.Subplan, parent, bindVars) + } + if !physicalVariablePattern.MatchString(set.ItemVariable) { + return fmt.Errorf("shared subset %q has unsafe item variable", set.ItemVariable) + } + if !parent[set.SourceSetVariable] { + return fmt.Errorf("shared subset source %q is out of scope", set.SourceSetVariable) + } + if len(set.Subplan.Captures) != 1 || set.Subplan.Captures[0] != set.SourceSetVariable { + return fmt.Errorf("shared subset %q must capture exactly its source set", set.Variable) + } + defined := map[string]bool{set.SourceSetVariable: true, set.ItemVariable: true} + for index, operation := range set.Subplan.Operations { + if operation.Kind != PhysicalFilterOp && operation.Kind != PhysicalDerivedLetOp { + return fmt.Errorf("shared subset operation %d has unsupported kind %q", index, operation.Kind) + } + if operation.Kind == PhysicalFilterOp { + if err := validatePhysicalFilter(*operation.Filter, defined, bindVars); err != nil { + return err + } + } else { + if err := validatePhysicalDerivedLet(*operation.DerivedLet, defined, bindVars); err != nil { + return err + } + if err := definePhysicalVariable(defined, operation.DerivedLet.Variable); err != nil { + return err + } + } + } + return validatePhysicalExpression(set.Subplan.Return, defined, bindVars) +} + func (operation PhysicalOperation) validatePayload() error { payloads := 0 if operation.RootScan != nil { @@ -262,6 +544,9 @@ func (operation PhysicalOperation) validatePayload() error { if operation.DerivedLet != nil { payloads++ } + if operation.Set != nil { + payloads++ + } if operation.Sort != nil { payloads++ } @@ -278,6 +563,7 @@ func (operation PhysicalOperation) validatePayload() error { (operation.Kind == PhysicalTraversalOp && operation.Traversal != nil) || (operation.Kind == PhysicalFilterOp && operation.Filter != nil) || (operation.Kind == PhysicalDerivedLetOp && operation.DerivedLet != nil) || + (operation.Kind == PhysicalSetOp && operation.Set != nil) || (operation.Kind == PhysicalSortOp && operation.Sort != nil) || (operation.Kind == PhysicalLimitOp && operation.Limit != nil) || (operation.Kind == PhysicalReturnOp && operation.Return != nil) @@ -308,19 +594,556 @@ func requireBind(bindVars map[string]any, key string) error { return nil } +func requireCollectionBind(bindVars map[string]any, key string) error { + value, ok := bindVars[key] + if !ok { + return fmt.Errorf("bind key %q is not defined", key) + } + collection, ok := value.(string) + if !ok || strings.TrimSpace(collection) == "" { + return fmt.Errorf("collection bind key %q must have a non-empty string value", key) + } + return nil +} + func validatePhysicalPredicate(predicate PhysicalPredicate, defined map[string]bool, bindVars map[string]any) error { - if strings.TrimSpace(predicate.Operator) == "" { - return fmt.Errorf("filter operator is required") + operator := strings.ToUpper(strings.TrimSpace(predicate.Operator)) + switch operator { + case "EQUALS", "NOT_EQUALS", "IN", "EXISTS", "MISSING", "CONTAINS_TEXT", "GT", "GTE", "LT", "LTE": + default: + return fmt.Errorf("unknown physical filter operator %q", predicate.Operator) + } + hasLeftValue := predicate.Left.Variable != "" || predicate.Left.BindKey != "" || len(predicate.Left.Path) != 0 + hasLeftExpression := predicate.LeftExpression != nil + if hasLeftValue == hasLeftExpression { + return fmt.Errorf("physical filter predicate requires exactly one left value or expression") } - if err := validatePhysicalValue(predicate.Left, defined, bindVars); err != nil { + if hasLeftExpression { + if err := validatePhysicalExpression(*predicate.LeftExpression, defined, bindVars); err != nil { + return fmt.Errorf("physical filter predicate left expression: %w", err) + } + if predicate.LeftExpression.Cardinality != PhysicalArrayCardinality { + return fmt.Errorf("physical filter predicate left expression must be array-valued") + } + if !predicate.ValueKind.Valid() { + return fmt.Errorf("physical filter predicate value kind %q is invalid", predicate.ValueKind) + } + if predicate.Quantifier != "" && !predicate.Quantifier.Valid() { + return fmt.Errorf("physical filter predicate quantifier %q is invalid", predicate.Quantifier) + } + } else if err := validatePhysicalValue(predicate.Left, defined, bindVars); err != nil { return err } + requiresRight := operator != "EXISTS" && operator != "MISSING" + if requiresRight != (predicate.Right != nil) { + return fmt.Errorf("physical filter operator %s right value presence is invalid", operator) + } if predicate.Right != nil { - return validatePhysicalValue(*predicate.Right, defined, bindVars) + if err := validatePhysicalValue(*predicate.Right, defined, bindVars); err != nil { + return err + } + } + return nil +} + +func validatePhysicalFilter(filter PhysicalFilter, defined map[string]bool, bindVars map[string]any) error { + legacy := strings.TrimSpace(filter.Predicate.Operator) != "" + rich := filter.Expression != nil + if legacy == rich { + return fmt.Errorf("filter requires exactly one legacy predicate or predicate expression") + } + if legacy { + return validatePhysicalPredicate(filter.Predicate, defined, bindVars) + } + return validatePhysicalPredicateExpression(*filter.Expression, defined, bindVars) +} + +func validatePhysicalDerivedLet(derived PhysicalDerivedLet, defined map[string]bool, bindVars map[string]any) error { + legacy := strings.TrimSpace(derived.Operator) != "" || len(derived.Inputs) != 0 + rich := derived.Expression != nil + if legacy == rich { + return fmt.Errorf("derived LET requires exactly one legacy operation or expression") + } + if rich { + return validatePhysicalExpression(*derived.Expression, defined, bindVars) + } + if strings.TrimSpace(derived.Operator) == "" { + return fmt.Errorf("derived LET operator is required") + } + for _, input := range derived.Inputs { + if err := validatePhysicalValue(input, defined, bindVars); err != nil { + return err + } + } + return nil +} + +func validatePhysicalProjection(projection PhysicalProjection, defined map[string]bool, bindVars map[string]any) error { + hasValue := projection.Value.Variable != "" || projection.Value.BindKey != "" || len(projection.Value.Path) != 0 + hasExpression := projection.Expression != nil + if hasValue == hasExpression { + return fmt.Errorf("projection requires exactly one value or expression") + } + if hasExpression { + return validatePhysicalExpression(*projection.Expression, defined, bindVars) + } + return validatePhysicalValue(projection.Value, defined, bindVars) +} + +func validatePhysicalExpression(expression PhysicalExpression, defined map[string]bool, bindVars map[string]any) error { + if err := validatePhysicalExpressionObjectCycles(expression); err != nil { + return err + } + if !expression.Cardinality.valid() { + return fmt.Errorf("expression has invalid cardinality %q", expression.Cardinality) + } + if !expression.NullBehavior.valid() { + return fmt.Errorf("expression has invalid null behavior %q", expression.NullBehavior) + } + payloads := 0 + if expression.Value != nil { + payloads++ + } + if expression.Extract != nil { + payloads++ + } + if expression.Aggregate != nil { + payloads++ + } + if expression.Pivot != nil { + payloads++ + } + if expression.Slice != nil { + payloads++ + } + if expression.Object != nil { + payloads++ + } + if payloads != 1 { + return fmt.Errorf("expression must contain exactly one payload") + } + switch expression.Kind { + case PhysicalValueExpression: + if expression.Value == nil { + return fmt.Errorf("expression payload does not match kind") + } + return validatePhysicalValue(*expression.Value, defined, bindVars) + case PhysicalExtractExpression: + if expression.Extract == nil { + return fmt.Errorf("expression payload does not match kind") + } + return validatePhysicalExtract(*expression.Extract, defined, bindVars) + case PhysicalAggregateExpression: + if expression.Aggregate == nil { + return fmt.Errorf("expression payload does not match kind") + } + return validatePhysicalAggregate(*expression.Aggregate, defined, bindVars) + case PhysicalPivotExpression: + if expression.Pivot == nil { + return fmt.Errorf("expression payload does not match kind") + } + return validatePhysicalPivot(*expression.Pivot, defined, bindVars) + case PhysicalSliceExpression: + if expression.Slice == nil { + return fmt.Errorf("expression payload does not match kind") + } + return validatePhysicalSlice(*expression.Slice, defined, bindVars) + case PhysicalObjectExpression: + if expression.Object == nil { + return fmt.Errorf("expression payload does not match kind") + } + return validatePhysicalObject(*expression.Object, defined, bindVars) + default: + return fmt.Errorf("unknown expression kind %q", expression.Kind) + } +} + +// validatePhysicalExpressionObjectCycles protects the recursive expression +// validator from a malformed in-memory plan containing a cycle of +// PhysicalObject pointers. JSON decoding cannot produce such a cycle, but +// plans are also assembled by compiler stages and tests, where pointers can +// be wired directly. The active/visited split permits shared (DAG) objects +// while rejecting only true recursion. +func validatePhysicalExpressionObjectCycles(expression PhysicalExpression) error { + active := map[*PhysicalObject]bool{} + visited := map[*PhysicalObject]bool{} + var visitExpression func(PhysicalExpression) error + var visitObject func(*PhysicalObject) error + var visitPredicate func(*PhysicalPredicateExpression) error + var visitSubplan func(PhysicalSubplan) error + visitExpression = func(current PhysicalExpression) error { + if current.Object != nil { + if err := visitObject(current.Object); err != nil { + return err + } + } + if current.Aggregate != nil && current.Aggregate.Value != nil { + if err := visitExpression(*current.Aggregate.Value); err != nil { + return err + } + } + if current.Aggregate != nil && current.Aggregate.Predicate != nil { + if err := visitPredicate(current.Aggregate.Predicate); err != nil { + return err + } + } + if current.Slice != nil { + if current.Slice.Predicate != nil { + if err := visitPredicate(current.Slice.Predicate); err != nil { + return err + } + } + if current.Slice.Sort != nil { + if err := visitExpression(*current.Slice.Sort); err != nil { + return err + } + } + for _, projection := range current.Slice.Projections { + if err := visitExpression(projection.Expression); err != nil { + return err + } + } + } + return nil + } + visitPredicate = func(predicate *PhysicalPredicateExpression) error { + if predicate == nil { + return nil + } + if predicate.Comparison != nil && predicate.Comparison.LeftExpression != nil { + if err := visitExpression(*predicate.Comparison.LeftExpression); err != nil { + return err + } + } + for index := range predicate.Children { + if err := visitPredicate(&predicate.Children[index]); err != nil { + return err + } + } + if predicate.Exists != nil { + return visitSubplan(*predicate.Exists) + } + return nil + } + visitSubplan = func(subplan PhysicalSubplan) error { + for _, operation := range subplan.Operations { + switch operation.Kind { + case PhysicalFilterOp: + if operation.Filter != nil && operation.Filter.Expression != nil { + if err := visitPredicate(operation.Filter.Expression); err != nil { + return err + } + } + case PhysicalDerivedLetOp: + if operation.DerivedLet != nil && operation.DerivedLet.Expression != nil { + if err := visitExpression(*operation.DerivedLet.Expression); err != nil { + return err + } + } + case PhysicalSetOp: + if operation.Set != nil { + if err := visitSubplan(operation.Set.Subplan); err != nil { + return err + } + } + } + } + return visitExpression(subplan.Return) + } + visitObject = func(object *PhysicalObject) error { + if active[object] { + return fmt.Errorf("physical object expression contains a recursive cycle") + } + if visited[object] { + return nil + } + active[object] = true + for _, field := range object.Fields { + if err := visitExpression(field.Expression); err != nil { + return err + } + } + delete(active, object) + visited[object] = true + return nil + } + return visitExpression(expression) +} + +func (cardinality PhysicalCardinality) valid() bool { + return cardinality == PhysicalScalarCardinality || cardinality == PhysicalArrayCardinality || cardinality == PhysicalObjectCardinality +} + +func (behavior PhysicalNullBehavior) valid() bool { + return behavior == PhysicalPreserveNull || behavior == PhysicalOmitNulls || behavior == PhysicalEmptyOnNull +} + +func validatePhysicalExtract(extract PhysicalExtract, defined map[string]bool, bindVars map[string]any) error { + if err := validatePhysicalValue(extract.Source, defined, bindVars); err != nil { + return err + } + if strings.TrimSpace(extract.ResourceType) == "" || !fhirschema.HasResource(extract.ResourceType) { + return fmt.Errorf("extract resource type %q is not represented by the active generated FHIR schema", extract.ResourceType) + } + if err := validatePhysicalSelector(extract.ResourceType, extract.Selector); err != nil { + return fmt.Errorf("extract selector: %w", err) + } + for index, fallback := range extract.Fallbacks { + if err := validatePhysicalSelector(extract.ResourceType, fallback); err != nil { + return fmt.Errorf("extract fallback %d: %w", index, err) + } + } + if extract.Prepared != nil { + if err := validatePhysicalPreparedReference(*extract.Prepared, defined); err != nil { + return err + } + if len(extract.Fallbacks) != 0 { + return fmt.Errorf("prepared extract cannot use fallback selectors") + } + } + return nil +} + +func validatePhysicalPreparedReference(reference PhysicalPreparedReference, defined map[string]bool) error { + if !physicalVariablePattern.MatchString(reference.SetVariable) || !defined[reference.SetVariable] { + return fmt.Errorf("prepared set variable %q is out of scope", reference.SetVariable) + } + if !physicalVariablePattern.MatchString(reference.Field) { + return fmt.Errorf("prepared field %q is unsafe", reference.Field) + } + return nil +} + +func validatePhysicalSelector(resourceType string, selector Selector) error { + if len(selector.Steps) == 0 { + return fmt.Errorf("selector is required") + } + if _, _, err := selectorCardinality(resourceType, selector); err != nil { + return err + } + return nil +} + +func validatePhysicalAggregate(aggregate PhysicalAggregate, defined map[string]bool, bindVars map[string]any) error { + if err := validatePhysicalValue(aggregate.Source, defined, bindVars); err != nil { + return err + } + switch aggregate.Operation { + case PhysicalCountAggregate, PhysicalCountDistinctAggregate, PhysicalExistsAggregate, PhysicalDistinctValuesAggregate, PhysicalMinAggregate, PhysicalMaxAggregate, PhysicalFirstAggregate: + default: + return fmt.Errorf("unknown aggregate operation %q", aggregate.Operation) + } + needsValue := aggregate.Operation != PhysicalCountAggregate && aggregate.Operation != PhysicalExistsAggregate + if needsValue != (aggregate.Value != nil) { + return fmt.Errorf("aggregate operation %q value presence is invalid", aggregate.Operation) + } + if aggregate.Value != nil { + if err := validatePhysicalExpression(*aggregate.Value, defined, bindVars); err != nil { + return fmt.Errorf("aggregate value: %w", err) + } + } + if aggregate.Predicate != nil { + if err := validatePhysicalPredicateExpression(*aggregate.Predicate, defined, bindVars); err != nil { + return fmt.Errorf("aggregate predicate: %w", err) + } } return nil } +func validatePhysicalPivot(pivot PhysicalPivotMap, defined map[string]bool, bindVars map[string]any) error { + if err := validatePhysicalValue(pivot.Source, defined, bindVars); err != nil { + return err + } + if strings.TrimSpace(pivot.ResourceType) == "" || !fhirschema.HasResource(pivot.ResourceType) { + return fmt.Errorf("pivot resource type %q is not represented by the active generated FHIR schema", pivot.ResourceType) + } + if err := validatePhysicalSelector(pivot.ResourceType, pivot.KeySelector); err != nil { + return fmt.Errorf("pivot key selector: %w", err) + } + if err := validatePhysicalSelector(pivot.ResourceType, pivot.ValueSelector); err != nil { + return fmt.Errorf("pivot value selector: %w", err) + } + if err := requireBind(bindVars, pivot.ColumnsBindKey); err != nil { + return err + } + columns, ok := bindVars[pivot.ColumnsBindKey].([]string) + if !ok || len(columns) == 0 { + return fmt.Errorf("pivot columns bind %q must be a non-empty []string", pivot.ColumnsBindKey) + } + for _, column := range columns { + if strings.TrimSpace(column) == "" { + return fmt.Errorf("pivot columns bind %q contains an empty column", pivot.ColumnsBindKey) + } + } + if pivot.PreparedKey != nil { + if err := validatePhysicalPreparedReference(*pivot.PreparedKey, defined); err != nil { + return fmt.Errorf("prepared pivot key: %w", err) + } + } + if pivot.PreparedValue != nil { + if err := validatePhysicalPreparedReference(*pivot.PreparedValue, defined); err != nil { + return fmt.Errorf("prepared pivot value: %w", err) + } + } + return nil +} + +func validatePhysicalSlice(slice PhysicalSlice, defined map[string]bool, bindVars map[string]any) error { + if err := validatePhysicalValue(slice.Source, defined, bindVars); err != nil { + return err + } + if slice.Predicate != nil { + if err := validatePhysicalPredicateExpression(*slice.Predicate, defined, bindVars); err != nil { + return fmt.Errorf("slice predicate: %w", err) + } + } + if slice.Sort == nil { + return fmt.Errorf("slice requires a stable sort expression") + } + if err := validatePhysicalExpression(*slice.Sort, defined, bindVars); err != nil { + return fmt.Errorf("slice sort: %w", err) + } + if err := requireBind(bindVars, slice.LimitBindKey); err != nil { + return err + } + limit, ok := bindVars[slice.LimitBindKey].(int) + if !ok || limit <= 0 { + return fmt.Errorf("slice limit bind %q must be a positive int", slice.LimitBindKey) + } + return validatePhysicalExpressionProjections(slice.Projections, defined, bindVars, "slice") +} + +func validatePhysicalObject(object PhysicalObject, defined map[string]bool, bindVars map[string]any) error { + return validatePhysicalExpressionProjections(object.Fields, defined, bindVars, "object") +} + +func validatePhysicalExpressionProjections(projections []PhysicalExpressionProjection, defined map[string]bool, bindVars map[string]any, owner string) error { + if len(projections) == 0 { + return fmt.Errorf("%s requires at least one projection", owner) + } + seen := map[string]bool{} + for _, projection := range projections { + if strings.TrimSpace(projection.Name) == "" || seen[projection.Name] { + return fmt.Errorf("%s projection name %q is empty or duplicated", owner, projection.Name) + } + seen[projection.Name] = true + if err := validatePhysicalExpression(projection.Expression, defined, bindVars); err != nil { + return fmt.Errorf("%s projection %q: %w", owner, projection.Name, err) + } + } + return nil +} + +func validatePhysicalPredicateExpression(predicate PhysicalPredicateExpression, defined map[string]bool, bindVars map[string]any) error { + switch predicate.Kind { + case PhysicalComparisonPredicate: + if predicate.Comparison == nil || len(predicate.Children) != 0 || predicate.Exists != nil { + return fmt.Errorf("comparison predicate requires exactly one comparison") + } + return validatePhysicalPredicate(*predicate.Comparison, defined, bindVars) + case PhysicalAllPredicate, PhysicalAnyPredicate: + if predicate.Comparison != nil || predicate.Exists != nil || len(predicate.Children) == 0 { + return fmt.Errorf("%s predicate requires one or more child predicates", predicate.Kind) + } + for index, child := range predicate.Children { + if err := validatePhysicalPredicateExpression(child, defined, bindVars); err != nil { + return fmt.Errorf("predicate child %d: %w", index, err) + } + } + return nil + case PhysicalNotPredicate: + if predicate.Comparison != nil || predicate.Exists != nil || len(predicate.Children) != 1 { + return fmt.Errorf("NOT predicate requires exactly one child predicate") + } + return validatePhysicalPredicateExpression(predicate.Children[0], defined, bindVars) + case PhysicalExistsPredicate: + if predicate.Comparison != nil || len(predicate.Children) != 0 || predicate.Exists == nil { + return fmt.Errorf("EXISTS predicate requires exactly one subplan") + } + return validatePhysicalSubplan(*predicate.Exists, defined, bindVars) + default: + return fmt.Errorf("unknown predicate kind %q", predicate.Kind) + } +} + +func validatePhysicalSubplan(subplan PhysicalSubplan, parent map[string]bool, bindVars map[string]any) error { + if len(subplan.Captures) == 0 { + return fmt.Errorf("subplan requires at least one explicit capture") + } + defined := make(map[string]bool, len(subplan.Captures)) + for _, capture := range subplan.Captures { + if !parent[capture] { + return fmt.Errorf("subplan capture %q is out of scope", capture) + } + if err := definePhysicalVariable(defined, capture); err != nil { + return fmt.Errorf("subplan capture: %w", err) + } + } + if len(subplan.Operations) == 0 { + return fmt.Errorf("subplan requires at least one operation") + } + for index, operation := range subplan.Operations { + if operation.Kind == PhysicalRootScanOp || operation.Kind == PhysicalReturnOp || operation.Kind == PhysicalSortOp || operation.Kind == PhysicalLimitOp { + return fmt.Errorf("subplan operation %d cannot be %s", index, operation.Kind) + } + if err := operation.validatePayload(); err != nil { + return fmt.Errorf("subplan operation %d (%s): %w", index, operation.Kind, err) + } + switch operation.Kind { + case PhysicalTraversalOp: + traversal := operation.Traversal + if !defined[traversal.SourceVariable] { + return fmt.Errorf("subplan operation %d: traversal source variable %q is out of scope", index, traversal.SourceVariable) + } + if traversal.Direction != PhysicalOutbound && traversal.Direction != PhysicalInbound && traversal.Direction != PhysicalAny { + return fmt.Errorf("subplan operation %d: invalid traversal direction %q", index, traversal.Direction) + } + if traversal.EdgeTargetTypeField != "" && !physicalPathPartPattern.MatchString(traversal.EdgeTargetTypeField) { + return fmt.Errorf("subplan operation %d: unsafe traversal edge type field %q", index, traversal.EdgeTargetTypeField) + } + if err := requireCollectionBind(bindVars, traversal.EdgeCollectionBindKey); err != nil { + return fmt.Errorf("subplan operation %d: %w", index, err) + } + for _, key := range []string{traversal.EdgeLabelBindKey, traversal.TargetTypeBindKey} { + if key != "" { + if err := requireBind(bindVars, key); err != nil { + return fmt.Errorf("subplan operation %d: %w", index, err) + } + } + } + if err := definePhysicalVariable(defined, traversal.TargetVariable); err != nil { + return fmt.Errorf("subplan operation %d: %w", index, err) + } + if traversal.EdgeVariable != "" { + if err := definePhysicalVariable(defined, traversal.EdgeVariable); err != nil { + return fmt.Errorf("subplan operation %d: %w", index, err) + } + } + case PhysicalFilterOp: + if err := validatePhysicalFilter(*operation.Filter, defined, bindVars); err != nil { + return fmt.Errorf("subplan operation %d: %w", index, err) + } + case PhysicalDerivedLetOp: + if err := validatePhysicalDerivedLet(*operation.DerivedLet, defined, bindVars); err != nil { + return fmt.Errorf("subplan operation %d: %w", index, err) + } + if err := definePhysicalVariable(defined, operation.DerivedLet.Variable); err != nil { + return fmt.Errorf("subplan operation %d: %w", index, err) + } + case PhysicalSetOp: + if err := validatePhysicalSet(*operation.Set, defined, bindVars); err != nil { + return fmt.Errorf("subplan operation %d set %q: %w", index, operation.Set.Variable, err) + } + if err := definePhysicalVariable(defined, operation.Set.Variable); err != nil { + return fmt.Errorf("subplan operation %d: %w", index, err) + } + default: + return fmt.Errorf("subplan operation %d has unsupported kind %q", index, operation.Kind) + } + } + return validatePhysicalExpression(subplan.Return, defined, bindVars) +} + func validatePhysicalValue(value PhysicalValue, defined map[string]bool, bindVars map[string]any) error { hasVariable := value.Variable != "" hasBind := value.BindKey != "" diff --git a/internal/dataframe/physical_plan_test.go b/internal/dataframe/physical_plan_test.go index 0a7ffbb..d177b7b 100644 --- a/internal/dataframe/physical_plan_test.go +++ b/internal/dataframe/physical_plan_test.go @@ -98,3 +98,105 @@ func TestPhysicalPlanValidateTaggedOperationAndReturnShape(t *testing.T) { }) } } + +func TestPhysicalPlanValidateRichExpressionContract(t *testing.T) { + patientGender := mustPhysicalSelector(t, "gender") + attachmentTitle := mustPhysicalSelector(t, "content[].attachment.title") + root := PhysicalValue{Variable: "root"} + files := PhysicalValue{Variable: "files"} + file := PhysicalValue{Variable: "file"} + + fileSubplan := PhysicalSubplan{ + Captures: []string{"root"}, + Operations: []PhysicalOperation{{ + Kind: PhysicalTraversalOp, + Traversal: &PhysicalTraversal{ + SourceVariable: "root", TargetVariable: "file", EdgeVariable: "file_edge", + Direction: PhysicalInbound, EdgeCollectionBindKey: "edge_collection", + EdgeLabelBindKey: "file_label", TargetTypeBindKey: "file_type", + }, + }}, + Return: physicalValueExpression(file, PhysicalObjectCardinality), + } + existsSubplan := fileSubplan + existsSubplan.Return = physicalValueExpression(file, PhysicalScalarCardinality) + + plan := PhysicalPlan{ + Version: 2, + BindVars: map[string]any{ + "root_collection": "Patient", "edge_collection": "fhir_edge", + "file_label": "subject_Patient", "file_type": "DocumentReference", + "project": "project-a", "pivot_columns": []string{"BAM", "VCF"}, "slice_limit": 2, + }, + Operations: []PhysicalOperation{ + {Kind: PhysicalRootScanOp, RootScan: &PhysicalRootScan{Variable: "root", CollectionBindKey: "root_collection"}}, + {Kind: PhysicalFilterOp, Filter: &PhysicalFilter{Expression: &PhysicalPredicateExpression{ + Kind: PhysicalAllPredicate, + Children: []PhysicalPredicateExpression{ + {Kind: PhysicalComparisonPredicate, Comparison: &PhysicalPredicate{Operator: "EQUALS", Left: PhysicalValue{Variable: "root", Path: []string{"project"}}, Right: &PhysicalValue{BindKey: "project"}}}, + {Kind: PhysicalExistsPredicate, Exists: &existsSubplan}, + }, + }}}, + {Kind: PhysicalSetOp, Set: &PhysicalSet{Variable: "files", Unique: true, Subplan: fileSubplan}}, + {Kind: PhysicalReturnOp, Return: &PhysicalReturn{Projections: []PhysicalProjection{{ + Name: "row", + Expression: &PhysicalExpression{ + Kind: PhysicalObjectExpression, Cardinality: PhysicalObjectCardinality, NullBehavior: PhysicalPreserveNull, + Object: &PhysicalObject{Fields: []PhysicalExpressionProjection{ + {Name: "gender", Expression: PhysicalExpression{Kind: PhysicalExtractExpression, Cardinality: PhysicalScalarCardinality, NullBehavior: PhysicalPreserveNull, Extract: &PhysicalExtract{Source: root, ResourceType: "Patient", Selector: patientGender}}}, + {Name: "file_count", Expression: PhysicalExpression{Kind: PhysicalAggregateExpression, Cardinality: PhysicalScalarCardinality, NullBehavior: PhysicalEmptyOnNull, Aggregate: &PhysicalAggregate{Source: files, Operation: PhysicalCountAggregate}}}, + {Name: "file_titles", Expression: PhysicalExpression{Kind: PhysicalPivotExpression, Cardinality: PhysicalObjectCardinality, NullBehavior: PhysicalEmptyOnNull, Pivot: &PhysicalPivotMap{Source: files, ResourceType: "DocumentReference", KeySelector: attachmentTitle, ValueSelector: attachmentTitle, ColumnsBindKey: "pivot_columns"}}}, + {Name: "representative_files", Expression: PhysicalExpression{Kind: PhysicalSliceExpression, Cardinality: PhysicalArrayCardinality, NullBehavior: PhysicalEmptyOnNull, Slice: &PhysicalSlice{Source: files, LimitBindKey: "slice_limit", Sort: physicalExpressionPtr(physicalValueExpression(files, PhysicalScalarCardinality)), Projections: []PhysicalExpressionProjection{{Name: "title", Expression: PhysicalExpression{Kind: PhysicalExtractExpression, Cardinality: PhysicalScalarCardinality, NullBehavior: PhysicalPreserveNull, Extract: &PhysicalExtract{Source: files, ResourceType: "DocumentReference", Selector: attachmentTitle}}}}}}}, + }}, + }, + }}}}, + }, + } + if err := plan.Validate(); err != nil { + t.Fatalf("rich physical plan should validate: %v", err) + } +} + +func TestPhysicalPlanValidateRichExpressionRejectsUnsafeScopeAndShape(t *testing.T) { + plan := validPhysicalPlan() + plan.Version = 2 + plan.Operations[3] = PhysicalOperation{Kind: PhysicalSetOp, Set: &PhysicalSet{ + Variable: "files", + Subplan: PhysicalSubplan{ + Captures: []string{"future"}, + Operations: []PhysicalOperation{{Kind: PhysicalDerivedLetOp, DerivedLet: &PhysicalDerivedLet{Variable: "x", Expression: physicalExpressionPtr(physicalValueExpression(PhysicalValue{Variable: "future"}, PhysicalScalarCardinality))}}}, + Return: physicalValueExpression(PhysicalValue{Variable: "x"}, PhysicalScalarCardinality), + }, + }} + if err := plan.Validate(); err == nil || !strings.Contains(err.Error(), "capture \"future\" is out of scope") { + t.Fatalf("Validate() error = %v; want out-of-scope capture", err) + } + + plan = validPhysicalPlan() + plan.Version = 2 + plan.Operations[3] = PhysicalOperation{Kind: PhysicalDerivedLetOp, DerivedLet: &PhysicalDerivedLet{ + Variable: "pivot", + Expression: &PhysicalExpression{Kind: PhysicalPivotExpression, Cardinality: PhysicalObjectCardinality, NullBehavior: PhysicalEmptyOnNull, Pivot: &PhysicalPivotMap{ + Source: PhysicalValue{Variable: "specimen"}, ResourceType: "Specimen", + KeySelector: mustPhysicalSelector(t, "type.coding[].display"), ValueSelector: mustPhysicalSelector(t, "type.coding[].display"), ColumnsBindKey: "edge_label", + }}, + }} + if err := plan.Validate(); err == nil || !strings.Contains(err.Error(), "must be a non-empty []string") { + t.Fatalf("Validate() error = %v; want typed pivot columns", err) + } +} + +func mustPhysicalSelector(t *testing.T, input string) Selector { + t.Helper() + selector, err := ParseSelector(input) + if err != nil { + t.Fatalf("ParseSelector(%q): %v", input, err) + } + return selector +} + +func physicalValueExpression(value PhysicalValue, cardinality PhysicalCardinality) PhysicalExpression { + return PhysicalExpression{Kind: PhysicalValueExpression, Cardinality: cardinality, NullBehavior: PhysicalPreserveNull, Value: &value} +} + +func physicalExpressionPtr(expression PhysicalExpression) *PhysicalExpression { return &expression } diff --git a/internal/dataframe/physical_prefix.go b/internal/dataframe/physical_prefix.go new file mode 100644 index 0000000..3c7aa46 --- /dev/null +++ b/internal/dataframe/physical_prefix.go @@ -0,0 +1,231 @@ +package dataframe + +import ( + "encoding/json" + "fmt" +) + +// PhysicalTraversalPrefix is the canonical, target-type-independent portion +// of one optional generic traversal set. It describes exactly the work that a +// future optimizer may materialize once for compatible siblings; it is not a +// renderer instruction and has no runtime effect by itself. +// +// NodeVariable and EdgeVariable are deliberately canonical names. Local +// variables from the source set live on PhysicalTraversalSubset, which makes +// alpha-equivalent prefixes compare without relying on lowering counters. +type PhysicalTraversalPrefix struct { + SourceVariable string + Direction PhysicalTraversalDirection + EdgeCollectionBindKey string + EdgeLabelBindKey string + EdgeTargetTypeField string + ProjectBindKey string + DatasetGenerationBindKey string + AuthPathsBindKey string + AuthUnrestrictedBindKey string + ScopeAllowedBindKey string + ScopeOperationCount int + NodeVariable string + EdgeVariable string +} + +const ( + physicalTraversalPrefixNodeVariable = "__loom_prefix_node" + physicalTraversalPrefixEdgeVariable = "__loom_prefix_edge" +) + +// PhysicalTraversalSubset contains the target-type specialization and work +// after the mandatory traversal scope. Its local variables are retained so a +// later rewrite can perform explicit alpha-renaming instead of guessing from +// AQL strings. +type PhysicalTraversalSubset struct { + TargetTypeBindKey string + TargetVariable string + EdgeVariable string + ConsumerOperations []PhysicalOperation +} + +// PhysicalTraversalPrefixDecomposition is the only B1 output consumed by a +// future sharing rewrite. PrefixKey is stable across generated local variable +// and target-type bind names, but differs for any scoped physical behavior. +type PhysicalTraversalPrefixDecomposition struct { + Prefix PhysicalTraversalPrefix + Subset PhysicalTraversalSubset + PrefixKey string +} + +type PhysicalTraversalPrefixRejectionReason string + +const ( + PhysicalPrefixNotOptionalSet PhysicalTraversalPrefixRejectionReason = "NOT_OPTIONAL_SET" + PhysicalPrefixSharedSubset PhysicalTraversalPrefixRejectionReason = "ALREADY_SHARED_SUBSET" + PhysicalPrefixInvalidCapture PhysicalTraversalPrefixRejectionReason = "INVALID_PARENT_CAPTURE" + PhysicalPrefixMissingTraversal PhysicalTraversalPrefixRejectionReason = "MISSING_TRAVERSAL" + PhysicalPrefixUnsupportedDirection PhysicalTraversalPrefixRejectionReason = "UNSUPPORTED_DIRECTION" + PhysicalPrefixInvalidRoute PhysicalTraversalPrefixRejectionReason = "INVALID_ROUTE" + PhysicalPrefixInvalidScope PhysicalTraversalPrefixRejectionReason = "INVALID_SCOPE" + PhysicalPrefixInvalidTarget PhysicalTraversalPrefixRejectionReason = "INVALID_TARGET_SUBSET" +) + +// PhysicalTraversalPrefixError makes rejection intentional and inspectable. +// Optimizers must retain this reason in diagnostics rather than treating an +// ineligible set as an accidental non-match. +type PhysicalTraversalPrefixError struct { + Reason PhysicalTraversalPrefixRejectionReason + Detail string +} + +func (e *PhysicalTraversalPrefixError) Error() string { + if e.Detail == "" { + return fmt.Sprintf("physical traversal prefix is not shareable: %s", e.Reason) + } + return fmt.Sprintf("physical traversal prefix is not shareable: %s: %s", e.Reason, e.Detail) +} + +func rejectPhysicalTraversalPrefix(reason PhysicalTraversalPrefixRejectionReason, format string, args ...any) error { + return &PhysicalTraversalPrefixError{Reason: reason, Detail: fmt.Sprintf(format, args...)} +} + +// DecomposePhysicalTraversalPrefix validates and canonically decomposes a +// generic optional traversal set. It does not alter the plan and deliberately +// rejects shared subsets, required EXISTS paths, non-proven directions, and +// sets whose tenant scope is not the exact generic edge/node scope block. +func DecomposePhysicalTraversalPrefix(plan PhysicalPlan, set PhysicalSet) (PhysicalTraversalPrefixDecomposition, error) { + if set.SourceSetVariable != "" { + return PhysicalTraversalPrefixDecomposition{}, rejectPhysicalTraversalPrefix(PhysicalPrefixSharedSubset, "set %q reads %q", set.Variable, set.SourceSetVariable) + } + if set.Variable == "" { + return PhysicalTraversalPrefixDecomposition{}, rejectPhysicalTraversalPrefix(PhysicalPrefixNotOptionalSet, "set variable is empty") + } + if len(set.Subplan.Captures) != 1 { + return PhysicalTraversalPrefixDecomposition{}, rejectPhysicalTraversalPrefix(PhysicalPrefixInvalidCapture, "set %q must have exactly one parent capture", set.Variable) + } + if len(set.Subplan.Operations) < 7 { + return PhysicalTraversalPrefixDecomposition{}, rejectPhysicalTraversalPrefix(PhysicalPrefixMissingTraversal, "set %q requires traversal plus exact generic scope", set.Variable) + } + first := set.Subplan.Operations[0] + if first.Kind != PhysicalTraversalOp || first.Traversal == nil { + return PhysicalTraversalPrefixDecomposition{}, rejectPhysicalTraversalPrefix(PhysicalPrefixMissingTraversal, "set %q first operation is not TRAVERSAL", set.Variable) + } + traversal := *first.Traversal + if traversal.SourceVariable != set.Subplan.Captures[0] { + return PhysicalTraversalPrefixDecomposition{}, rejectPhysicalTraversalPrefix(PhysicalPrefixInvalidCapture, "traversal source %q does not match capture %q", traversal.SourceVariable, set.Subplan.Captures[0]) + } + if traversal.Direction != PhysicalInbound && traversal.Direction != PhysicalOutbound { + return PhysicalTraversalPrefixDecomposition{}, rejectPhysicalTraversalPrefix(PhysicalPrefixUnsupportedDirection, "direction %q", traversal.Direction) + } + if err := validateGenericNavigationTraversal(plan, traversal); err != nil { + return PhysicalTraversalPrefixDecomposition{}, rejectPhysicalTraversalPrefix(PhysicalPrefixInvalidRoute, "%v", err) + } + + // The prefix is exactly TRAVERSAL followed by edge/node project, + // generation, and auth scope. Consumer predicates start only after this + // block, so they cannot accidentally broaden the shared neighbor set. + scope := set.Subplan.Operations[1:7] + scopeVariable, err := validateGenericNavigationScopeBlock(scope, traversal.TargetVariable, traversal.EdgeVariable, traversal.TargetVariable) + if err != nil { + return PhysicalTraversalPrefixDecomposition{}, rejectPhysicalTraversalPrefix(PhysicalPrefixInvalidScope, "%v", err) + } + if scopeVariable == "" { + return PhysicalTraversalPrefixDecomposition{}, rejectPhysicalTraversalPrefix(PhysicalPrefixInvalidScope, "auth scope variable is empty") + } + if traversal.TargetTypeBindKey == "" { + return PhysicalTraversalPrefixDecomposition{}, rejectPhysicalTraversalPrefix(PhysicalPrefixInvalidTarget, "target type bind is empty") + } + if _, ok := plan.BindVars[traversal.TargetTypeBindKey].(string); !ok { + return PhysicalTraversalPrefixDecomposition{}, rejectPhysicalTraversalPrefix(PhysicalPrefixInvalidTarget, "target type bind %q is not a string", traversal.TargetTypeBindKey) + } + + prefix := PhysicalTraversalPrefix{ + SourceVariable: traversal.SourceVariable, + Direction: traversal.Direction, + EdgeCollectionBindKey: traversal.EdgeCollectionBindKey, + EdgeLabelBindKey: traversal.EdgeLabelBindKey, + EdgeTargetTypeField: traversal.EdgeTargetTypeField, + ProjectBindKey: physicalScopeProjectBind, + DatasetGenerationBindKey: physicalScopeDatasetGenerationBind, + AuthPathsBindKey: physicalScopeAuthPathsBind, + AuthUnrestrictedBindKey: physicalScopeAuthPathsUnrestrictedBind, + ScopeAllowedBindKey: physicalScopeAllowedBind, + ScopeOperationCount: len(scope), + NodeVariable: physicalTraversalPrefixNodeVariable, + EdgeVariable: physicalTraversalPrefixEdgeVariable, + } + key, err := physicalTraversalPrefixKey(plan, prefix) + if err != nil { + return PhysicalTraversalPrefixDecomposition{}, err + } + return PhysicalTraversalPrefixDecomposition{ + Prefix: prefix, + Subset: PhysicalTraversalSubset{ + TargetTypeBindKey: traversal.TargetTypeBindKey, + TargetVariable: traversal.TargetVariable, + EdgeVariable: traversal.EdgeVariable, + ConsumerOperations: clonePhysicalOperations(set.Subplan.Operations[7:]), + }, + PrefixKey: key, + }, nil +} + +func physicalTraversalPrefixKey(plan PhysicalPlan, prefix PhysicalTraversalPrefix) (string, error) { + bind := func(key string) (string, error) { + value, found := plan.BindVars[key] + if !found { + return "", rejectPhysicalTraversalPrefix(PhysicalPrefixInvalidScope, "bind %q is missing", key) + } + encoded, err := json.Marshal(value) + if err != nil { + return "", rejectPhysicalTraversalPrefix(PhysicalPrefixInvalidScope, "bind %q cannot be canonically encoded: %v", key, err) + } + return string(encoded), nil + } + collection, err := bind(prefix.EdgeCollectionBindKey) + if err != nil { + return "", err + } + label, err := bind(prefix.EdgeLabelBindKey) + if err != nil { + return "", err + } + project, err := bind(prefix.ProjectBindKey) + if err != nil { + return "", err + } + generation, err := bind(prefix.DatasetGenerationBindKey) + if err != nil { + return "", err + } + paths, err := bind(prefix.AuthPathsBindKey) + if err != nil { + return "", err + } + unrestricted, err := bind(prefix.AuthUnrestrictedBindKey) + if err != nil { + return "", err + } + allowed, err := bind(prefix.ScopeAllowedBindKey) + if err != nil { + return "", err + } + key := struct { + Source, Direction, Collection, Label, TargetField string + Project, Generation, Paths, Unrestricted, Allowed string + ScopeOperationCount int + }{prefix.SourceVariable, string(prefix.Direction), collection, label, prefix.EdgeTargetTypeField, project, generation, paths, unrestricted, allowed, prefix.ScopeOperationCount} + encoded, err := json.Marshal(key) + if err != nil { + return "", fmt.Errorf("encode physical traversal prefix key: %w", err) + } + return string(encoded), nil +} + +func clonePhysicalOperations(operations []PhysicalOperation) []PhysicalOperation { + if len(operations) == 0 { + return nil + } + out := make([]PhysicalOperation, len(operations)) + for index, operation := range operations { + out[index] = clonePhysicalOperation(operation) + } + return out +} diff --git a/internal/dataframe/physical_render.go b/internal/dataframe/physical_render.go index 3112b12..e4460f8 100644 --- a/internal/dataframe/physical_render.go +++ b/internal/dataframe/physical_render.go @@ -2,6 +2,8 @@ package dataframe import ( "fmt" + "sort" + "strconv" "strings" ) @@ -10,18 +12,16 @@ import ( // required "@name" key form for collection bind variables referenced as // "@@name" in Query. // -// This renderer covers the frozen generic navigation subset emitted by -// BuildGenericPhysicalPlan. CompileRequest and the dataframe service use it -// for that subset; richer semantic requests retain the compatibility lowered -// renderer until their typed physical operators are frozen. +// This renderer covers generic physical navigation and rich expression +// operators emitted by BuildGenericPhysicalPlan. Projection names, including +// nested object field names, remain bind-backed and never become AQL source. type RenderedPhysicalPlan struct { Query string BindVars map[string]any } -// RenderPhysicalPlan renders the frozen navigation-only physical-plan subset -// to deterministic AQL. It validates the full plan before rendering and keeps -// data and metadata values out of the generated AQL source. +// RenderPhysicalPlan renders a validated physical plan to deterministic AQL. +// It keeps data and metadata values out of the generated AQL source. func RenderPhysicalPlan(plan PhysicalPlan) (RenderedPhysicalPlan, error) { if err := plan.Validate(); err != nil { return RenderedPhysicalPlan{}, fmt.Errorf("validate physical plan: %w", err) @@ -61,6 +61,13 @@ func RenderPhysicalPlan(plan PhysicalPlan) (RenderedPhysicalPlan, error) { } lines = append(lines, line...) } + for index, operation := range layout.rootPredicates { + line, err := renderer.renderScopeOperation(operation, " ") + if err != nil { + return RenderedPhysicalPlan{}, fmt.Errorf("render root predicate %d (%s): %w", index, operation.Kind, err) + } + lines = append(lines, line...) + } for index, operation := range layout.rootWindow { line, err := renderer.renderRootWindowOperation(operation, " ") if err != nil { @@ -75,6 +82,13 @@ func RenderPhysicalPlan(plan PhysicalPlan) (RenderedPhysicalPlan, error) { } lines = append(lines, line...) } + for index, set := range layout.sets { + line, err := renderer.renderSet(set, index+1) + if err != nil { + return RenderedPhysicalPlan{}, fmt.Errorf("render child set %d: %w", index+1, err) + } + lines = append(lines, line...) + } returnExpression, err := renderer.renderReturn(layout.returnOp) if err != nil { return RenderedPhysicalPlan{}, fmt.Errorf("render RETURN: %w", err) @@ -109,12 +123,19 @@ type physicalPlanRenderer struct { collectionKeys map[string]struct{} setVariables map[string]string reservedVars map[string]struct{} + preparedItem string } func (r *physicalPlanRenderer) renderScopeOperation(operation PhysicalOperation, indent string) ([]string, error) { switch operation.Kind { case PhysicalFilterOp: - expression, err := r.renderPredicate(operation.Filter.Predicate) + var expression string + var err error + if operation.Filter.Expression != nil { + expression, err = r.renderPredicateExpression(*operation.Filter.Expression, indent) + } else { + expression, err = r.renderPredicate(operation.Filter.Predicate) + } if err != nil { return nil, err } @@ -134,11 +155,13 @@ func (r *physicalPlanRenderer) renderScopeOperation(operation PhysicalOperation, // produced by BuildGenericPhysicalPlan. Traversals are retained as sets rather // than emitted as top-level loops so the root scan remains the row grain. type physicalNavigationRenderLayout struct { - root PhysicalRootScan - rootScope []PhysicalOperation - rootWindow []PhysicalOperation - traversals []physicalNavigationTraversal - returnOp PhysicalReturn + root PhysicalRootScan + rootScope []PhysicalOperation + rootPredicates []PhysicalOperation + rootWindow []PhysicalOperation + traversals []physicalNavigationTraversal + sets []PhysicalSet + returnOp PhysicalReturn } type physicalNavigationTraversal struct { @@ -169,6 +192,10 @@ func buildNavigationRenderLayout(plan PhysicalPlan) (physicalNavigationRenderLay } index := 5 + for index < last && plan.Operations[index].Kind == PhysicalFilterOp && plan.Operations[index].Filter.Expression != nil { + layout.rootPredicates = append(layout.rootPredicates, plan.Operations[index]) + index++ + } if index < last && plan.Operations[index].Kind == PhysicalSortOp { if err := validateGenericNavigationRootSort(plan.Operations[index], layout.root.Variable); err != nil { return physicalNavigationRenderLayout{}, fmt.Errorf("root execution window at operation %d: %w", index, err) @@ -187,6 +214,11 @@ func buildNavigationRenderLayout(plan PhysicalPlan) (physicalNavigationRenderLay } for index < last { operation := plan.Operations[index] + if operation.Kind == PhysicalSetOp { + layout.sets = append(layout.sets, *operation.Set) + index++ + continue + } if operation.Kind != PhysicalTraversalOp { return physicalNavigationRenderLayout{}, fmt.Errorf("generic navigation renderer expected TRAVERSAL at operation %d, got %s", index, operation.Kind) } @@ -327,6 +359,9 @@ func sameRenderPhysicalValue(left, right PhysicalValue) bool { func validateNavigationReturnScope(returnOp PhysicalReturn, rootVariable, rootScopeVariable string) error { for _, projection := range returnOp.Projections { + if projection.Expression != nil { + continue + } if projection.Value.BindKey != "" { continue } @@ -370,6 +405,121 @@ func (r *physicalPlanRenderer) renderTraversalSet(block physicalNavigationTraver return lines, nil } +func (r *physicalPlanRenderer) renderSet(set PhysicalSet, index int) ([]string, error) { + if set.SourceSetVariable != "" { + return r.renderSharedSubset(set) + } + if len(set.Subplan.Operations) == 0 { + return nil, fmt.Errorf("set %q has no subplan operations", set.Variable) + } + first := set.Subplan.Operations[0] + if first.Kind != PhysicalTraversalOp || first.Traversal == nil { + return nil, fmt.Errorf("set %q must begin with TRAVERSAL", set.Variable) + } + t := first.Traversal + parentVariable := t.SourceVariable + indent := " " + lines := []string{fmt.Sprintf(" LET %s = (", set.Variable)} + if parentSet, ok := r.setVariables[t.SourceVariable]; ok { + parentVariable = r.newInternalVariable(fmt.Sprintf("parent_set_%d", index)) + lines = append(lines, fmt.Sprintf(" FOR %s IN %s", parentVariable, parentSet)) + indent = " " + } + lines = append(lines, fmt.Sprintf("%sFOR %s, %s IN 1..1 %s %s @@%s", indent, t.TargetVariable, t.EdgeVariable, t.Direction, parentVariable, t.EdgeCollectionBindKey), fmt.Sprintf("%s FILTER %s.label == @%s", indent, t.EdgeVariable, t.EdgeLabelBindKey)) + if t.EdgeTargetTypeField != "" { + lines = append(lines, r.renderTraversalTypeFilters(t, indent)...) + } + for opIndex, operation := range set.Subplan.Operations[1:] { + rendered, err := r.renderScopeOperation(operation, indent+" ") + if err != nil { + return nil, fmt.Errorf("set operation %d: %w", opIndex+1, err) + } + lines = append(lines, rendered...) + } + value, err := r.renderExpression(set.Subplan.Return) + if err != nil { + return nil, err + } + if set.SortByKey { + lines = append(lines, indent+" SORT "+t.TargetVariable+"._key") + } + lines = append(lines, indent+" RETURN "+value, " )") + if set.Unique { + lines[0] = fmt.Sprintf(" LET %s = UNIQUE((", set.Variable) + lines[len(lines)-1] = " ))" + } + r.setVariables[set.Variable] = set.Variable + if set.Prepared != nil { + prepared, err := r.renderPreparedSet(*set.Prepared) + if err != nil { + return nil, err + } + lines = append(lines, prepared...) + r.setVariables[set.Prepared.Variable] = set.Prepared.Variable + } + _ = index + return lines, nil +} + +func (r *physicalPlanRenderer) renderPreparedSet(prepared PhysicalPreparedSet) ([]string, error) { + if r.setVariables[prepared.SourceSetVariable] == "" { + return nil, fmt.Errorf("prepared source set %q has not been rendered", prepared.SourceSetVariable) + } + item := r.newInternalVariable("prepared_item") + lines := []string{fmt.Sprintf(" LET %s = (", prepared.Variable), fmt.Sprintf(" FOR %s IN %s", item, prepared.SourceSetVariable)} + fields := []string{fmt.Sprintf("_key: %s._key", item), fmt.Sprintf("__loom_prepared_node: %s", item)} + for _, field := range prepared.Fields { + values, err := r.renderSelectorArrayFromSource(item+".payload", field.Selector, false) + if err != nil { + return nil, fmt.Errorf("prepared field %q: %w", field.Name, err) + } + fields = append(fields, field.Name+": "+values) + } + lines = append(lines, " RETURN { "+strings.Join(fields, ", ")+" }", " )") + return lines, nil +} + +func (r *physicalPlanRenderer) renderTraversalTypeFilters(t *PhysicalTraversal, indent string) []string { + if t.TargetTypeBindKey == "" || t.EdgeTargetTypeField == "" { + return nil + } + if _, ok := r.bindVars[t.TargetTypeBindKey].([]string); ok { + return []string{ + fmt.Sprintf("%s FILTER POSITION(@%s, %s.%s, true)", indent, t.TargetTypeBindKey, t.EdgeVariable, t.EdgeTargetTypeField), + fmt.Sprintf("%s FILTER POSITION(@%s, %s.resourceType, true)", indent, t.TargetTypeBindKey, t.TargetVariable), + } + } + return []string{fmt.Sprintf("%s FILTER %s.%s == @%s", indent, t.EdgeVariable, t.EdgeTargetTypeField, t.TargetTypeBindKey), fmt.Sprintf("%s FILTER %s.resourceType == @%s", indent, t.TargetVariable, t.TargetTypeBindKey)} +} + +func (r *physicalPlanRenderer) renderSharedSubset(set PhysicalSet) ([]string, error) { + if r.setVariables[set.SourceSetVariable] == "" { + return nil, fmt.Errorf("shared subset source %q has not been rendered", set.SourceSetVariable) + } + lines := []string{fmt.Sprintf(" LET %s = (", set.Variable), fmt.Sprintf(" FOR %s IN %s", set.ItemVariable, set.SourceSetVariable)} + for index, operation := range set.Subplan.Operations { + rendered, err := r.renderScopeOperation(operation, " ") + if err != nil { + return nil, fmt.Errorf("shared subset operation %d: %w", index, err) + } + lines = append(lines, rendered...) + } + value, err := r.renderExpression(set.Subplan.Return) + if err != nil { + return nil, err + } + if set.SortByKey { + lines = append(lines, " SORT "+set.ItemVariable+"._key") + } + lines = append(lines, " RETURN "+value, " )") + if set.Unique { + lines[0] = fmt.Sprintf(" LET %s = UNIQUE((", set.Variable) + lines[len(lines)-1] = " ))" + } + r.setVariables[set.Variable] = set.Variable + return lines, nil +} + func physicalPlanVariableNames(plan PhysicalPlan) map[string]struct{} { variables := map[string]struct{}{} for _, operation := range plan.Operations { @@ -384,6 +534,8 @@ func physicalPlanVariableNames(plan PhysicalPlan) map[string]struct{} { } case PhysicalDerivedLetOp: variables[operation.DerivedLet.Variable] = struct{}{} + case PhysicalSetOp: + variables[operation.Set.Variable] = struct{}{} } } return variables @@ -402,6 +554,9 @@ func (r *physicalPlanRenderer) newInternalVariable(suffix string) string { } func (r *physicalPlanRenderer) renderPredicate(predicate PhysicalPredicate) (string, error) { + if predicate.LeftExpression != nil { + return r.renderSelectorPredicate(predicate) + } if strings.ToUpper(strings.TrimSpace(predicate.Operator)) != "EQUALS" { return "", fmt.Errorf("unsupported physical filter operator %q", predicate.Operator) } @@ -419,6 +574,575 @@ func (r *physicalPlanRenderer) renderPredicate(predicate PhysicalPredicate) (str return left + " == " + right, nil } +func (r *physicalPlanRenderer) renderSelectorPredicate(predicate PhysicalPredicate) (string, error) { + values, err := r.renderExpression(*predicate.LeftExpression) + if err != nil { + return "", err + } + operator := strings.ToUpper(strings.TrimSpace(predicate.Operator)) + if operator == "EXISTS" { + return "LENGTH(" + values + ") > 0", nil + } + if operator == "MISSING" { + return "LENGTH(" + values + ") == 0", nil + } + if predicate.Right == nil { + return "", fmt.Errorf("physical filter operator %q requires a right value", predicate.Operator) + } + right, err := r.renderValue(*predicate.Right) + if err != nil { + return "", err + } + valueVar := r.newInternalVariable("filter_value") + match := "" + switch operator { + case "EQUALS": + match = valueVar + " == " + right + case "NOT_EQUALS": + match = valueVar + " != " + right + case "IN": + match = "POSITION(" + right + ", " + valueVar + ", true)" + case "CONTAINS_TEXT": + match = "CONTAINS(TO_STRING(" + valueVar + "), " + right + ")" + case "GT", "GTE", "LT", "LTE": + left, comparisonRight := valueVar, right + if predicate.ValueKind == FilterDate || predicate.ValueKind == FilterDateTime { + left, comparisonRight = "DATE_TIMESTAMP("+valueVar+")", "DATE_TIMESTAMP("+right+")" + } + operatorText := map[string]string{"GT": ">", "GTE": ">=", "LT": "<", "LTE": "<="}[operator] + match = left + " " + operatorText + " " + comparisonRight + default: + return "", fmt.Errorf("unsupported physical selector filter operator %q", predicate.Operator) + } + matching := "LENGTH(FOR " + valueVar + " IN " + values + " FILTER " + match + " LIMIT 1 RETURN 1)" + quantifier := predicate.Quantifier + if quantifier == "" { + quantifier = QuantifierAny + } + switch quantifier { + case QuantifierAny: + return matching + " > 0", nil + case QuantifierNone: + return matching + " == 0", nil + case QuantifierAll: + return "LENGTH(" + values + ") > 0 AND LENGTH(FOR " + valueVar + " IN " + values + " FILTER NOT (" + match + ") LIMIT 1 RETURN 1) == 0", nil + default: + return "", fmt.Errorf("unsupported physical selector filter quantifier %q", quantifier) + } +} + +func (r *physicalPlanRenderer) renderPredicateExpression(predicate PhysicalPredicateExpression, indent string) (string, error) { + switch predicate.Kind { + case PhysicalComparisonPredicate: + return r.renderPredicate(*predicate.Comparison) + case PhysicalAllPredicate, PhysicalAnyPredicate: + parts := make([]string, 0, len(predicate.Children)) + for _, child := range predicate.Children { + part, err := r.renderPredicateExpression(child, indent) + if err != nil { + return "", err + } + parts = append(parts, "("+part+")") + } + join := " AND " + if predicate.Kind == PhysicalAnyPredicate { + join = " OR " + } + return strings.Join(parts, join), nil + case PhysicalNotPredicate: + child, err := r.renderPredicateExpression(predicate.Children[0], indent) + if err != nil { + return "", err + } + return "NOT (" + child + ")", nil + case PhysicalExistsPredicate: + return r.renderExistsSubplan(*predicate.Exists, indent) + default: + return "", fmt.Errorf("unsupported physical predicate kind %q", predicate.Kind) + } +} + +// renderExistsSubplan serializes a validated correlated subplan. EXISTS is +// always bounded: relationship matching is a semi-join, never a row-expanding +// traversal, so the renderer appends LIMIT 1 immediately before RETURN. +func (r *physicalPlanRenderer) renderExistsSubplan(subplan PhysicalSubplan, indent string) (string, error) { + lines := make([]string, 0, len(subplan.Operations)*3+2) + for index, operation := range subplan.Operations { + switch operation.Kind { + case PhysicalTraversalOp: + traversal := operation.Traversal + lines = append(lines, + fmt.Sprintf("%sFOR %s, %s IN 1..1 %s %s @@%s", indent+" ", traversal.TargetVariable, traversal.EdgeVariable, traversal.Direction, traversal.SourceVariable, traversal.EdgeCollectionBindKey), + fmt.Sprintf("%s FILTER %s.label == @%s", indent+" ", traversal.EdgeVariable, traversal.EdgeLabelBindKey), + fmt.Sprintf("%s FILTER %s.%s == @%s", indent+" ", traversal.EdgeVariable, traversal.EdgeTargetTypeField, traversal.TargetTypeBindKey), + fmt.Sprintf("%s FILTER %s.resourceType == @%s", indent+" ", traversal.TargetVariable, traversal.TargetTypeBindKey), + ) + case PhysicalFilterOp, PhysicalDerivedLetOp: + rendered, err := r.renderScopeOperation(operation, indent+" ") + if err != nil { + return "", fmt.Errorf("subplan operation %d (%s): %w", index, operation.Kind, err) + } + lines = append(lines, rendered...) + default: + return "", fmt.Errorf("subplan operation %d has unsupported render kind %q", index, operation.Kind) + } + } + value, err := r.renderExpression(subplan.Return) + if err != nil { + return "", err + } + lines = append(lines, indent+" LIMIT 1", indent+" RETURN "+value) + return "LENGTH((\n" + strings.Join(lines, "\n") + "\n" + indent + " )) > 0", nil +} + +func (r *physicalPlanRenderer) renderExpression(expression PhysicalExpression) (string, error) { + switch expression.Kind { + case PhysicalValueExpression: + return r.renderValue(*expression.Value) + case PhysicalExtractExpression: + return r.renderExtract(expression) + case PhysicalAggregateExpression: + return r.renderAggregate(expression) + case PhysicalPivotExpression: + return r.renderPivot(expression) + case PhysicalSliceExpression: + return r.renderSlice(expression) + case PhysicalObjectExpression: + return r.renderObject(expression) + default: + return "", fmt.Errorf("physical renderer does not yet support expression kind %q", expression.Kind) + } +} + +// renderObject renders a recursively typed object expression. Sorting a copy +// gives equivalent physical plans stable AQL and bind-key allocation without +// changing the semantic field order held by the plan. +// +// The compact dynamic-key literal is used when every field preserves nulls. +// If any field requests OMIT_NULLS, fields are represented as a temporary +// stream and merged so null-valued fields can be removed without evaluating +// their expression twice. +func (r *physicalPlanRenderer) renderObject(expression PhysicalExpression) (string, error) { + object := expression.Object + if object == nil { + return "", fmt.Errorf("OBJECT expression is missing payload") + } + fields := append([]PhysicalExpressionProjection(nil), object.Fields...) + sort.SliceStable(fields, func(left, right int) bool { + return fields[left].Name < fields[right].Name + }) + + type renderedField struct { + nameKey string + value string + omit bool + } + rendered := make([]renderedField, 0, len(fields)) + for index, field := range fields { + value, err := r.renderExpression(field.Expression) + if err != nil { + return "", fmt.Errorf("object field %q: %w", field.Name, err) + } + nameKey := r.newInternalBindKey("object_field_" + strconv.Itoa(index) + "_name") + r.bindVars[nameKey] = field.Name + rendered = append(rendered, renderedField{ + nameKey: nameKey, + value: value, + omit: field.Expression.NullBehavior == PhysicalOmitNulls, + }) + } + + hasOmittedField := false + for _, field := range rendered { + if field.omit { + hasOmittedField = true + break + } + } + if !hasOmittedField { + parts := make([]string, 0, len(rendered)) + for _, field := range rendered { + parts = append(parts, fmt.Sprintf("[@%s]: %s", field.nameKey, field.value)) + } + return "{ " + strings.Join(parts, ", ") + " }", nil + } + + items := make([]string, 0, len(rendered)) + for _, field := range rendered { + items = append(items, fmt.Sprintf("{ __loom_object_name: @%s, __loom_object_value: %s, __loom_object_omit: %t }", field.nameKey, field.value, field.omit)) + } + return fmt.Sprintf(`MERGE( + FOR __loom_object_field IN [%s] + FILTER __loom_object_field.__loom_object_omit == false OR __loom_object_field.__loom_object_value != null + RETURN { [__loom_object_field.__loom_object_name]: __loom_object_field.__loom_object_value } +)`, strings.Join(items, ", ")), nil +} + +// renderSlice emits a correlated, bounded array projection. Sort and the +// _key tie-break are rendered inside the subquery so representative values +// are deterministic even when traversal order changes. +func (r *physicalPlanRenderer) renderSlice(expression PhysicalExpression) (string, error) { + slice := expression.Slice + if slice == nil { + return "", fmt.Errorf("SLICE expression is missing payload") + } + source, err := r.renderValue(slice.Source) + if err != nil { + return "", err + } + items := source + preparedVariable := slicePreparedVariable(slice) + if preparedVariable != "" { + items = preparedVariable + } + setSource := slice.Source.Variable != "" && r.setVariables[slice.Source.Variable] != "" + if !setSource { + items = "[" + source + "]" + } + item := r.newInternalVariable("slice_item") + lines := []string{"(FOR " + item + " IN " + items} + if slice.Predicate != nil { + if slice.Predicate.Kind != PhysicalComparisonPredicate || slice.Predicate.Comparison == nil { + return "", fmt.Errorf("slice predicate must be a comparison") + } + comparison := *slice.Predicate.Comparison + if comparison.LeftExpression != nil && comparison.LeftExpression.Extract != nil { + left := *comparison.LeftExpression + extract := *left.Extract + extract.Source = PhysicalValue{Variable: item, Path: []string{"payload"}} + left.Extract = &extract + comparison.LeftExpression = &left + } else { + comparison.Left = PhysicalValue{Variable: item} + } + previousPreparedItem := r.preparedItem + r.preparedItem = item + predicate, err := r.renderPredicate(comparison) + r.preparedItem = previousPreparedItem + if err != nil { + return "", err + } + lines = append(lines, " FILTER "+predicate) + } + if slice.Sort == nil { + return "", fmt.Errorf("slice requires sort expression") + } + sortExpression := *slice.Sort + if sortExpression.Kind == PhysicalValueExpression && sortExpression.Value != nil { + value := *sortExpression.Value + value.Variable = item + value.BindKey = "" + sortExpression.Value = &value + } + sortValue, err := r.renderExpression(sortExpression) + if err != nil { + return "", err + } + lines = append(lines, " SORT "+sortValue+" ASC, "+item+"._key ASC") + lines = append(lines, " LIMIT @"+slice.LimitBindKey) + fields := make([]string, 0, len(slice.Projections)) + for index, projection := range slice.Projections { + projectionExpression := projection.Expression + if projectionExpression.Kind == PhysicalExtractExpression && projectionExpression.Extract != nil { + extract := *projectionExpression.Extract + extract.Source = PhysicalValue{Variable: item, Path: []string{"payload"}} + projectionExpression.Extract = &extract + } + previousPreparedItem := r.preparedItem + r.preparedItem = item + value, err := r.renderExpression(projectionExpression) + r.preparedItem = previousPreparedItem + if err != nil { + return "", fmt.Errorf("slice projection %d (%s): %w", index, projection.Name, err) + } + nameKey := r.newInternalBindKey("slice_projection_" + strconv.Itoa(index) + "_name") + r.bindVars[nameKey] = projection.Name + fields = append(fields, "["+"@"+nameKey+"]: "+value) + } + lines = append(lines, " RETURN { "+strings.Join(fields, ", ")+" }") + return strings.Join(lines, "\n") + "\n)", nil +} + +func slicePreparedVariable(slice *PhysicalSlice) string { + if slice == nil { + return "" + } + if slice.Predicate != nil && slice.Predicate.Comparison != nil && slice.Predicate.Comparison.LeftExpression != nil && slice.Predicate.Comparison.LeftExpression.Extract != nil && slice.Predicate.Comparison.LeftExpression.Extract.Prepared != nil { + return slice.Predicate.Comparison.LeftExpression.Extract.Prepared.SetVariable + } + for _, projection := range slice.Projections { + if projection.Expression.Extract != nil && projection.Expression.Extract.Prepared != nil { + return projection.Expression.Extract.Prepared.SetVariable + } + } + return "" +} + +// renderPivot emits a bounded sparse object keyed by the requested catalog +// columns. Values from all matching resources are combined per key and reduced +// deterministically to the first sorted value while keeping selectors and +// column values typed. +func (r *physicalPlanRenderer) renderPivot(expression PhysicalExpression) (string, error) { + pivot := expression.Pivot + if pivot == nil { + return "", fmt.Errorf("PIVOT expression is missing payload") + } + if _, collection := r.collectionKeys[pivot.ColumnsBindKey]; collection { + return "", fmt.Errorf("pivot columns bind %q cannot be a collection bind", pivot.ColumnsBindKey) + } + columns, ok := r.bindVars[pivot.ColumnsBindKey].([]string) + if !ok || len(columns) == 0 { + return "", fmt.Errorf("pivot columns bind %q is not a non-empty []string", pivot.ColumnsBindKey) + } + items, err := r.renderValue(pivot.Source) + if err != nil { + return "", err + } + if pivot.Source.Variable == "" || r.setVariables[pivot.Source.Variable] == "" { + items = "[" + items + "]" + } + if pivot.PreparedKey != nil { + items = pivot.PreparedKey.SetVariable + } + item := r.newInternalVariable("pivot_item") + previousPreparedItem := r.preparedItem + r.preparedItem = item + keyExpr, err := r.renderPreparedOrSelector(item, pivot.PreparedKey, pivot.KeySelector) + if err != nil { + r.preparedItem = previousPreparedItem + return "", err + } + valueExpr, err := r.renderPreparedOrSelector(item, pivot.PreparedValue, pivot.ValueSelector) + r.preparedItem = previousPreparedItem + if err != nil { + return "", err + } + return fmt.Sprintf(`MERGE( + FOR __pair IN ( + FOR %s IN %s + LET __pivot_keys = UNIQUE(%s) + LET __pivot_values = %s + FILTER LENGTH(__pivot_values) > 0 + FOR __pivot_key IN __pivot_keys + FILTER POSITION(@%s, __pivot_key, true) + RETURN { key: __pivot_key, values: __pivot_values } + ) + COLLECT __pivot_key = __pair.key INTO __pivot_group + LET __pivot_flat_values = SORTED_UNIQUE(FLATTEN(__pivot_group[*].__pair.values)) + FILTER LENGTH(__pivot_flat_values) > 0 + RETURN { [__pivot_key]: FIRST(__pivot_flat_values) } +)`, item, items, keyExpr, valueExpr, pivot.ColumnsBindKey), nil +} + +// renderAggregate emits reductions over either a correlated PhysicalSet or a +// singleton root document. The source is kept typed in the IR; this method is +// the only place that decides the AQL collection expression (`set` versus +// `[root]`). +func (r *physicalPlanRenderer) renderAggregate(expression PhysicalExpression) (string, error) { + aggregate := expression.Aggregate + if aggregate == nil { + return "", fmt.Errorf("AGGREGATE expression is missing payload") + } + source, err := r.renderValue(aggregate.Source) + if err != nil { + return "", err + } + items := source + if preparedVariable := aggregatePreparedVariable(aggregate); preparedVariable != "" { + items = preparedVariable + } + if aggregate.Source.Variable == "" || r.setVariables[aggregate.Source.Variable] == "" { + items = "[" + source + "]" + } + perItem := aggregate.Predicate != nil + if perItem { + if aggregate.Predicate.Kind != PhysicalComparisonPredicate || aggregate.Predicate.Comparison == nil { + return "", fmt.Errorf("aggregate predicate must be a comparison") + } + item := r.newInternalVariable("aggregate_item") + comparison := *aggregate.Predicate.Comparison + if comparison.LeftExpression == nil || comparison.LeftExpression.Extract == nil { + return "", fmt.Errorf("aggregate predicate must extract a selector") + } + left := *comparison.LeftExpression + extract := *left.Extract + if extract.Prepared == nil { + extract.Source = PhysicalValue{Variable: item, Path: []string{"payload"}} + } + left.Extract = &extract + comparison.LeftExpression = &left + previousPreparedItem := r.preparedItem + r.preparedItem = item + predicate, err := r.renderPredicate(comparison) + r.preparedItem = previousPreparedItem + if err != nil { + return "", err + } + items = "(FOR " + item + " IN " + items + " FILTER " + predicate + " RETURN " + item + ")" + } + switch aggregate.Operation { + case PhysicalCountAggregate: + return "LENGTH(" + items + ")", nil + case PhysicalExistsAggregate: + if aggregate.Value == nil { + return "LENGTH(" + items + ") > 0", nil + } + values, err := r.renderAggregateValue(*aggregate.Value, items, perItem) + if err != nil { + return "", err + } + return "LENGTH(FOR __value IN FLATTEN(" + values + ") FILTER __value != null LIMIT 1 RETURN 1) > 0", nil + case PhysicalCountDistinctAggregate, PhysicalDistinctValuesAggregate, PhysicalMinAggregate, PhysicalMaxAggregate, PhysicalFirstAggregate: + if aggregate.Value == nil { + return "", fmt.Errorf("aggregate operation %q requires a value expression", aggregate.Operation) + } + values, err := r.renderAggregateValue(*aggregate.Value, items, perItem) + if err != nil { + return "", err + } + flattened := "FLATTEN(" + values + ")" + switch aggregate.Operation { + case PhysicalCountDistinctAggregate: + return "LENGTH(SORTED_UNIQUE(" + flattened + "))", nil + case PhysicalDistinctValuesAggregate: + return "SORTED_UNIQUE(" + flattened + ")", nil + case PhysicalMinAggregate: + return "MIN(" + flattened + ")", nil + case PhysicalMaxAggregate: + return "MAX(" + flattened + ")", nil + case PhysicalFirstAggregate: + return "FIRST(" + flattened + ")", nil + } + } + return "", fmt.Errorf("unsupported aggregate operation %q", aggregate.Operation) +} + +func aggregatePreparedVariable(aggregate *PhysicalAggregate) string { + if aggregate == nil { + return "" + } + if aggregate.Value != nil && aggregate.Value.Extract != nil && aggregate.Value.Extract.Prepared != nil { + return aggregate.Value.Extract.Prepared.SetVariable + } + if aggregate.Predicate != nil && aggregate.Predicate.Comparison != nil && aggregate.Predicate.Comparison.LeftExpression != nil && aggregate.Predicate.Comparison.LeftExpression.Extract != nil && aggregate.Predicate.Comparison.LeftExpression.Extract.Prepared != nil { + return aggregate.Predicate.Comparison.LeftExpression.Extract.Prepared.SetVariable + } + return "" +} + +func (r *physicalPlanRenderer) renderAggregateValue(expression PhysicalExpression, items string, perItem bool) (string, error) { + if !perItem { + if expression.Extract != nil && expression.Extract.Prepared != nil { + return "(FOR __loom_prepared_value IN " + expression.Extract.Prepared.SetVariable + " RETURN __loom_prepared_value." + expression.Extract.Prepared.Field + ")", nil + } + return r.renderExpression(expression) + } + if expression.Kind != PhysicalExtractExpression || expression.Extract == nil { + return "", fmt.Errorf("aggregate predicates require an extract value expression") + } + item := r.newInternalVariable("aggregate_value_item") + clone := expression + extract := *expression.Extract + if extract.Prepared == nil { + extract.Source = PhysicalValue{Variable: item, Path: []string{"payload"}} + } + clone.Extract = &extract + previousPreparedItem := r.preparedItem + r.preparedItem = item + value, err := r.renderExtract(clone) + r.preparedItem = previousPreparedItem + if err != nil { + return "", err + } + return "(FOR " + item + " IN " + items + " RETURN " + value + ")", nil +} + +func (r *physicalPlanRenderer) renderPreparedOrSelector(item string, reference *PhysicalPreparedReference, selector Selector) (string, error) { + if reference != nil { + return item + "." + reference.Field, nil + } + return r.renderSelectorArrayFromSource(item+".payload", selector, false) +} + +func (r *physicalPlanRenderer) renderExtract(expression PhysicalExpression) (string, error) { + extract := expression.Extract + if extract == nil { + return "", fmt.Errorf("EXTRACT expression is missing payload") + } + if extract.Prepared != nil { + value := "" + if r.preparedItem != "" { + value = r.preparedItem + "." + extract.Prepared.Field + } else { + value = "(FOR __loom_prepared_value IN " + extract.Prepared.SetVariable + " RETURN __loom_prepared_value." + extract.Prepared.Field + ")" + } + if expression.Cardinality == PhysicalArrayCardinality { + if extract.Distinct { + return "SORTED_UNIQUE(FLATTEN(" + value + "))", nil + } + return value, nil + } + return "FIRST(FLATTEN(" + value + "))", nil + } + source, err := r.renderValue(extract.Source) + if err != nil { + return "", err + } + arrays := make([]string, 0, 1+len(extract.Fallbacks)) + setSource := extract.Source.Variable != "" && r.setVariables[extract.Source.Variable] != "" + for _, selector := range append([]Selector{extract.Selector}, extract.Fallbacks...) { + array, err := r.renderSelectorArrayFromSource(source, selector, setSource) + if err != nil { + return "", err + } + arrays = append(arrays, array) + } + values := arrays[0] + if len(arrays) > 1 { + values = "FLATTEN([" + strings.Join(arrays, ", ") + "])" + } + if expression.Cardinality == PhysicalArrayCardinality { + if extract.Distinct { + return "SORTED_UNIQUE(" + values + ")", nil + } + return values, nil + } + if !setSource && len(arrays) == 1 && extract.Selector.Filter == nil && selectorHasNoArrays(extract.Selector) { + return compileDirectExpr(source, extract.Selector.Steps), nil + } + return "FIRST(" + values + ")", nil +} + +func (r *physicalPlanRenderer) renderSelectorArrayFromSource(source string, selector Selector, setSource bool) (string, error) { + if len(selector.Steps) == 0 { + return "", fmt.Errorf("selector is required") + } + prefix, last := selector.Steps[:len(selector.Steps)-1], selector.Steps[len(selector.Steps)-1] + lines, current := []string{"FOR __root IN [" + source + "]"}, "__root" + if setSource { + lines, current = []string{"FOR __item IN " + source, " FOR __root IN [__item.payload]"}, "__root" + } + for index, step := range prefix { + next := fmt.Sprintf("__s%d", index) + switch { + case step.Iterate: + lines = append(lines, fmt.Sprintf(" FOR %s IN (%s.%s ? %s.%s : [])", next, current, step.Field, current, step.Field)) + case step.Index != nil: + lines = append(lines, fmt.Sprintf(" LET %s = ((%s.%s ? %s.%s : [])[%d])", next, current, step.Field, current, step.Field, *step.Index), " FILTER "+next+" != null") + default: + lines = append(lines, fmt.Sprintf(" LET %s = %s.%s", next, current, step.Field), " FILTER "+next+" != null") + } + current = next + } + if selector.Filter != nil { + key := r.newInternalBindKey("selector_contains") + r.bindVars[key] = selector.Filter.Needle + lines = append(lines, fmt.Sprintf(" FILTER CONTAINS(%s.%s ? %s.%s : \"\", @%s)", current, selector.Filter.Field, current, selector.Filter.Field, key)) + } + lines = append(lines, " LET __value = "+extractFinalExpr(current, last), " FILTER __value != null", " RETURN __value") + return "(\n " + strings.Join(lines, "\n ") + "\n )", nil +} + func (r *physicalPlanRenderer) renderDerivedLet(derived PhysicalDerivedLet) (string, error) { if strings.ToUpper(strings.TrimSpace(derived.Operator)) != "AUTH_RESOURCE_PATH_ALLOWED" { return "", fmt.Errorf("unsupported physical derived LET operator %q", derived.Operator) @@ -468,7 +1192,13 @@ func (r *physicalPlanRenderer) renderReturn(returnOp PhysicalReturn) (string, er for index, projection := range returnOp.Projections { nameBindKey := r.newInternalBindKey(fmt.Sprintf("projection_%d_name", index)) r.bindVars[nameBindKey] = projection.Name - value, err := r.renderValue(projection.Value) + var value string + var err error + if projection.Expression != nil { + value, err = r.renderExpression(*projection.Expression) + } else { + value, err = r.renderValue(projection.Value) + } if err != nil { return "", err } @@ -506,16 +1236,33 @@ func (r *physicalPlanRenderer) newInternalBindKey(suffix string) string { func collectionBindKeys(plan PhysicalPlan) (map[string]struct{}, error) { keys := map[string]struct{}{} - for index, operation := range plan.Operations { - switch operation.Kind { - case PhysicalRootScanOp: - keys[operation.RootScan.CollectionBindKey] = struct{}{} - case PhysicalTraversalOp: - if operation.Traversal.EdgeCollectionBindKey == "" { - return nil, fmt.Errorf("render operation %d (TRAVERSAL): edge collection bind key is required", index) + var collectOperations func([]PhysicalOperation, string) error + collectOperations = func(operations []PhysicalOperation, owner string) error { + for index, operation := range operations { + switch operation.Kind { + case PhysicalRootScanOp: + keys[operation.RootScan.CollectionBindKey] = struct{}{} + case PhysicalTraversalOp: + if operation.Traversal.EdgeCollectionBindKey == "" { + return fmt.Errorf("%s operation %d (TRAVERSAL): edge collection bind key is required", owner, index) + } + keys[operation.Traversal.EdgeCollectionBindKey] = struct{}{} + case PhysicalFilterOp: + if operation.Filter.Expression != nil { + if err := collectPredicateCollections(*operation.Filter.Expression, collectOperations, owner); err != nil { + return err + } + } + case PhysicalSetOp: + if err := collectOperations(operation.Set.Subplan.Operations, owner+" SET"); err != nil { + return err + } } - keys[operation.Traversal.EdgeCollectionBindKey] = struct{}{} } + return nil + } + if err := collectOperations(plan.Operations, "render"); err != nil { + return nil, err } for key := range keys { value, ok := plan.BindVars[key] @@ -530,6 +1277,18 @@ func collectionBindKeys(plan PhysicalPlan) (map[string]struct{}, error) { return keys, nil } +func collectPredicateCollections(predicate PhysicalPredicateExpression, collectOperations func([]PhysicalOperation, string) error, owner string) error { + if predicate.Exists != nil { + return collectOperations(predicate.Exists.Operations, owner+" EXISTS") + } + for _, child := range predicate.Children { + if err := collectPredicateCollections(child, collectOperations, owner); err != nil { + return err + } + } + return nil +} + func validateRenderablePhysicalPlan(plan PhysicalPlan, collectionKeys map[string]struct{}) error { for index, operation := range plan.Operations { if err := validateRenderableOperation(operation, collectionKeys); err != nil { @@ -565,7 +1324,17 @@ func validateRenderableOperation(operation PhysicalOperation, collectionKeys map return fmt.Errorf("TRAVERSAL requires edge label and target resource type bind keys") } return nil + case PhysicalSetOp: + for index, suboperation := range operation.Set.Subplan.Operations { + if err := validateRenderableOperation(suboperation, collectionKeys); err != nil { + return fmt.Errorf("SET subplan operation %d: %w", index, err) + } + } + return nil case PhysicalFilterOp: + if operation.Filter.Expression != nil { + return validateRenderablePredicateExpression(*operation.Filter.Expression, collectionKeys) + } if strings.ToUpper(strings.TrimSpace(operation.Filter.Predicate.Operator)) != "EQUALS" { return fmt.Errorf("unsupported physical filter operator %q", operation.Filter.Predicate.Operator) } @@ -595,6 +1364,12 @@ func validateRenderableOperation(operation PhysicalOperation, collectionKeys map return nil case PhysicalReturnOp: for _, projection := range operation.Return.Projections { + if projection.Expression != nil { + if projection.Expression.Kind != PhysicalValueExpression && projection.Expression.Kind != PhysicalExtractExpression && projection.Expression.Kind != PhysicalAggregateExpression && projection.Expression.Kind != PhysicalPivotExpression && projection.Expression.Kind != PhysicalSliceExpression && projection.Expression.Kind != PhysicalObjectExpression { + return fmt.Errorf("unsupported physical return expression kind %q", projection.Expression.Kind) + } + continue + } if err := checkValue(projection.Value); err != nil { return err } @@ -605,6 +1380,38 @@ func validateRenderableOperation(operation PhysicalOperation, collectionKeys map } } +func validateRenderablePredicateExpression(predicate PhysicalPredicateExpression, collectionKeys map[string]struct{}) error { + switch predicate.Kind { + case PhysicalExistsPredicate: + if predicate.Exists == nil { + return fmt.Errorf("EXISTS predicate requires a subplan") + } + for index, operation := range predicate.Exists.Operations { + if err := validateRenderableOperation(operation, collectionKeys); err != nil { + return fmt.Errorf("EXISTS subplan operation %d (%s): %w", index, operation.Kind, err) + } + } + if predicate.Exists.Return.Kind != PhysicalValueExpression || predicate.Exists.Return.Value == nil { + return fmt.Errorf("EXISTS subplan return must be a physical value expression") + } + return nil + case PhysicalComparisonPredicate: + if predicate.Comparison == nil { + return fmt.Errorf("comparison predicate requires a comparison") + } + return nil + case PhysicalAllPredicate, PhysicalAnyPredicate, PhysicalNotPredicate: + for _, child := range predicate.Children { + if err := validateRenderablePredicateExpression(child, collectionKeys); err != nil { + return err + } + } + return nil + default: + return fmt.Errorf("unsupported physical predicate kind %q", predicate.Kind) + } +} + func runtimePhysicalBindVars(bindVars map[string]any, collectionKeys map[string]struct{}) map[string]any { out := make(map[string]any, len(bindVars)) for key, value := range bindVars { diff --git a/internal/dataframe/physical_render_test.go b/internal/dataframe/physical_render_test.go index 90ffce6..cb71701 100644 --- a/internal/dataframe/physical_render_test.go +++ b/internal/dataframe/physical_render_test.go @@ -145,6 +145,139 @@ func TestRenderPhysicalPlanIsDeterministicAndCopiesBindVars(t *testing.T) { } } +func TestRenderPhysicalPlanNestedObjectExpression(t *testing.T) { + plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, Project: "project-1", AuthResourcePaths: []string{"/programs/p1"}, + Root: SemanticNode{Alias: "root", ResourceType: "Patient"}, + }) + if err != nil { + t.Fatal(err) + } + gender := mustPhysicalSelector(t, "gender") + value := func(value PhysicalValue) PhysicalExpression { + return PhysicalExpression{Kind: PhysicalValueExpression, Cardinality: PhysicalScalarCardinality, NullBehavior: PhysicalPreserveNull, Value: &value} + } + genderExpression := PhysicalExpression{ + Kind: PhysicalExtractExpression, Cardinality: PhysicalScalarCardinality, NullBehavior: PhysicalPreserveNull, + Extract: &PhysicalExtract{Source: PhysicalValue{Variable: "root", Path: []string{"payload"}}, ResourceType: "Patient", Selector: gender}, + } + inner := PhysicalExpression{ + Kind: PhysicalObjectExpression, Cardinality: PhysicalObjectCardinality, NullBehavior: PhysicalPreserveNull, + Object: &PhysicalObject{Fields: []PhysicalExpressionProjection{ + {Name: "z_key", Expression: value(PhysicalValue{Variable: "root", Path: []string{"_key"}})}, + {Name: "a_gender", Expression: genderExpression}, + }}, + } + outer := PhysicalExpression{ + Kind: PhysicalObjectExpression, Cardinality: PhysicalObjectCardinality, NullBehavior: PhysicalPreserveNull, + Object: &PhysicalObject{Fields: []PhysicalExpressionProjection{ + {Name: "scalar", Expression: genderExpression}, + {Name: "nested", Expression: inner}, + }}, + } + returnOp := plan.Operations[len(plan.Operations)-1].Return + returnOp.Projections = []PhysicalProjection{{Name: "row", Expression: &outer}} + + first, err := RenderPhysicalPlan(plan) + if err != nil { + t.Fatalf("RenderPhysicalPlan() error = %v", err) + } + second, err := RenderPhysicalPlan(plan) + if err != nil { + t.Fatalf("second RenderPhysicalPlan() error = %v", err) + } + if first.Query != second.Query { + t.Fatalf("nested object rendering is not deterministic:\nfirst=%s\nsecond=%s", first.Query, second.Query) + } + for _, want := range []string{ + "RETURN { [@__loom_physical_projection_0_name]: {", + } { + if !strings.Contains(first.Query, want) { + t.Fatalf("nested object query missing %q:\n%s", want, first.Query) + } + } + if got := strings.Count(first.Query, "[@__loom_physical_object_field_"); got != 4 { + t.Fatalf("nested object did not render four bind-backed field names, got %d:\n%s", got, first.Query) + } + fieldNames := map[string]bool{} + for key, value := range first.BindVars { + if strings.HasPrefix(key, "__loom_physical_object_field_") { + if name, ok := value.(string); ok { + fieldNames[name] = true + } + } + } + for _, name := range []string{"nested", "scalar", "a_gender", "z_key"} { + if !fieldNames[name] { + t.Fatalf("object field %q was not bind-backed: %#v", name, first.BindVars) + } + } + foundNestedField := false + for key, value := range first.BindVars { + if strings.HasPrefix(key, "__loom_physical_object_field_") && value == "a_gender" { + foundNestedField = true + break + } + } + if !foundNestedField { + t.Fatalf("nested object field name was not bind-backed: %#v", first.BindVars) + } +} + +func TestRenderPhysicalPlanObjectExpressionOmitsNullFields(t *testing.T) { + plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, Project: "project-1", AuthResourcePaths: []string{"/programs/p1"}, + Root: SemanticNode{Alias: "root", ResourceType: "Patient"}, + }) + if err != nil { + t.Fatal(err) + } + gender := mustPhysicalSelector(t, "gender") + optional := PhysicalExpression{ + Kind: PhysicalExtractExpression, Cardinality: PhysicalScalarCardinality, NullBehavior: PhysicalOmitNulls, + Extract: &PhysicalExtract{Source: PhysicalValue{Variable: "root", Path: []string{"payload"}}, ResourceType: "Patient", Selector: gender}, + } + object := PhysicalExpression{ + Kind: PhysicalObjectExpression, Cardinality: PhysicalObjectCardinality, NullBehavior: PhysicalPreserveNull, + Object: &PhysicalObject{Fields: []PhysicalExpressionProjection{{Name: "optional_gender", Expression: optional}}}, + } + returnOp := plan.Operations[len(plan.Operations)-1].Return + returnOp.Projections = []PhysicalProjection{{Name: "row", Expression: &object}} + rendered, err := RenderPhysicalPlan(plan) + if err != nil { + t.Fatalf("RenderPhysicalPlan() error = %v", err) + } + for _, want := range []string{ + "MERGE(", + "__loom_object_omit: true", + "FILTER __loom_object_field.__loom_object_omit == false OR __loom_object_field.__loom_object_value != null", + } { + if !strings.Contains(rendered.Query, want) { + t.Fatalf("null-omitting object query missing %q:\n%s", want, rendered.Query) + } + } + if got := rendered.BindVars["__loom_physical_object_field_0_name"]; got != "optional_gender" { + t.Fatalf("object field bind = %#v", got) + } +} + +func TestPhysicalPlanValidateRejectsRecursiveObjectExpression(t *testing.T) { + plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, Project: "project-1", AuthResourcePaths: []string{"/programs/p1"}, + Root: SemanticNode{Alias: "root", ResourceType: "Patient"}, + }) + if err != nil { + t.Fatal(err) + } + object := &PhysicalObject{} + cycle := PhysicalExpression{Kind: PhysicalObjectExpression, Cardinality: PhysicalObjectCardinality, NullBehavior: PhysicalPreserveNull, Object: object} + object.Fields = []PhysicalExpressionProjection{{Name: "self", Expression: cycle}} + plan.Operations[len(plan.Operations)-1].Return.Projections = []PhysicalProjection{{Name: "row", Expression: &cycle}} + if err := plan.Validate(); err == nil || !strings.Contains(err.Error(), "recursive cycle") { + t.Fatalf("Validate() error = %v; want recursive object cycle rejection", err) + } +} + func TestRenderPhysicalPlanRejectsUnsupportedOrAmbiguousOperations(t *testing.T) { newPlan := func(t *testing.T) PhysicalPlan { t.Helper() diff --git a/internal/dataframe/physical_required_match.go b/internal/dataframe/physical_required_match.go new file mode 100644 index 0000000..bf4a6af --- /dev/null +++ b/internal/dataframe/physical_required_match.go @@ -0,0 +1,164 @@ +package dataframe + +import ( + "encoding/json" + "fmt" +) + +// appendRequiredTraversalMatchFilters lowers every REQUIRED semantic route to +// a correlated typed EXISTS subplan. The subplan is deliberately separate +// from optional traversal materialization: it is a root semi-join and must run +// before the root sort/window, while optional traversal sets remain post-limit. +func appendRequiredTraversalMatchFilters(physical *PhysicalPlan, root SemanticNode) error { + nextMatch := 0 + seen := map[string]struct{}{} + var walk func(SemanticNode, []SemanticNode) error + walk = func(parent SemanticNode, route []SemanticNode) error { + for _, child := range parent.Children { + next := append(append([]SemanticNode(nil), route...), child) + if child.MatchMode.required() { + // Two required children with the same physical route and typed + // predicates are the same root semi-join even when their aliases + // differ. Deduplicating this exact proof is safe: it does not + // move a predicate across the root execution window or alter any + // optional child materialization. + key, err := requiredSemanticRouteKey(root.ResourceType, next) + if err != nil { + return err + } + if _, duplicate := seen[key]; duplicate { + physical.RequiredMatchReuseCount++ + continue + } + seen[key] = struct{}{} + predicate, err := buildRequiredTraversalExists(physical, nextMatch, root, next) + if err != nil { + return err + } + physical.Operations = append(physical.Operations, PhysicalOperation{ + Kind: PhysicalFilterOp, + Source: PhysicalSource{SemanticNode: child.Alias, ResourceType: child.ResourceType, Relationship: child.EdgeLabel}, + Filter: &PhysicalFilter{Expression: &predicate}, + }) + nextMatch++ + } + if err := walk(child, next); err != nil { + return err + } + } + return nil + } + return walk(root, nil) +} + +// requiredSemanticRouteKey intentionally excludes aliases and selection +// shape. A required route only contributes root membership, so aliases cannot +// distinguish two predicates. JSON gives us a deterministic key for typed +// filters without using AQL text or resource-specific knowledge. +func requiredSemanticRouteKey(rootResourceType string, route []SemanticNode) (string, error) { + type step struct { + ResourceType string + EdgeLabel string + Filters []TypedFilter + } + steps := make([]step, 0, len(route)) + for _, node := range route { + steps = append(steps, step{ResourceType: node.ResourceType, EdgeLabel: node.EdgeLabel, Filters: node.Filters}) + } + encoded, err := json.Marshal(struct { + Root string + Steps []step + }{Root: rootResourceType, Steps: steps}) + if err != nil { + return "", fmt.Errorf("encode required traversal reuse key: %w", err) + } + return string(encoded), nil +} + +func buildRequiredTraversalExists(physical *PhysicalPlan, matchIndex int, root SemanticNode, routeNodes []SemanticNode) (PhysicalPredicateExpression, error) { + if len(routeNodes) == 0 { + return PhysicalPredicateExpression{}, fmt.Errorf("required traversal match %d has no route steps", matchIndex) + } + + subplan := PhysicalSubplan{Captures: []string{"root"}} + parentVariable := "root" + parentType := root.ResourceType + for stepIndex, node := range routeNodes { + route, err := resolveStorageRoute(parentType, node.EdgeLabel, node.ResourceType) + if err != nil { + return PhysicalPredicateExpression{}, fmt.Errorf("required traversal match %d step %d: %w", matchIndex, stepIndex, err) + } + nodeVariable := fmt.Sprintf("required_%d_node_%d", matchIndex, stepIndex) + edgeVariable := fmt.Sprintf("required_%d_edge_%d", matchIndex, stepIndex) + prefix := fmt.Sprintf("required_%d_%d", matchIndex, stepIndex) + labelBind := prefix + "_label" + typeBind := prefix + "_target_type" + edgeCollectionBind := prefix + "_edge_collection" + physical.BindVars[labelBind] = node.EdgeLabel + physical.BindVars[typeBind] = node.ResourceType + physical.BindVars[edgeCollectionBind] = "fhir_edge" + + subplan.Operations = append(subplan.Operations, PhysicalOperation{ + Kind: PhysicalTraversalOp, + Source: PhysicalSource{SemanticNode: node.Alias, ResourceType: node.ResourceType, Relationship: node.EdgeLabel}, + Traversal: &PhysicalTraversal{ + SourceVariable: parentVariable, TargetVariable: nodeVariable, EdgeVariable: edgeVariable, + Direction: route.Direction, EdgeCollectionBindKey: edgeCollectionBind, + EdgeLabelBindKey: labelBind, TargetTypeBindKey: typeBind, + EdgeTargetTypeField: route.targetEdgeTypeField(), + }, + }) + subplan.Operations = appendProjectScope(subplan.Operations, []string{edgeVariable, nodeVariable}, node.EdgeLabel, node) + subplan.Operations = appendDatasetGenerationScope(subplan.Operations, []string{edgeVariable, nodeVariable}, node.EdgeLabel, node) + subplan.Operations = appendAuthScope(subplan.Operations, []PhysicalValue{ + {Variable: edgeVariable, Path: []string{"auth_resource_path"}}, + {Variable: nodeVariable, Path: []string{"auth_resource_path"}}, + }, fmt.Sprintf("required_%d_%d_scope_allowed", matchIndex, stepIndex), node) + for filterIndex, filter := range node.Filters { + if err := ValidateTypedFilterForResource(node.ResourceType, filter); err != nil { + return PhysicalPredicateExpression{}, fmt.Errorf("required traversal match %d step %d filter %d: %w", matchIndex, stepIndex, filterIndex, err) + } + selector, err := ParseSelector(filter.Selector) + if err != nil { + return PhysicalPredicateExpression{}, err + } + predicate := PhysicalPredicate{Operator: string(filter.Operator), Quantifier: filter.Quantifier, ValueKind: filter.FieldKind, + LeftExpression: &PhysicalExpression{Kind: PhysicalExtractExpression, Cardinality: PhysicalArrayCardinality, NullBehavior: PhysicalEmptyOnNull, + Extract: &PhysicalExtract{Source: PhysicalValue{Variable: nodeVariable, Path: []string{"payload"}}, ResourceType: node.ResourceType, Selector: selector}}} + if filter.Operator != FilterExists && filter.Operator != FilterMissing { + if len(filter.Values) == 0 { + return PhysicalPredicateExpression{}, fmt.Errorf("required traversal filter %q has no value", filter.FieldRef) + } + key := fmt.Sprintf("required_%d_%d_filter_%d_value", matchIndex, stepIndex, filterIndex) + if filter.Operator == FilterIn { + values := make([]any, 0, len(filter.Values)) + for _, value := range filter.Values { + literal, err := filterLiteral(value) + if err != nil { + return PhysicalPredicateExpression{}, err + } + values = append(values, literal) + } + physical.BindVars[key] = values + } else { + literal, err := filterLiteral(filter.Values[0]) + if err != nil { + return PhysicalPredicateExpression{}, err + } + physical.BindVars[key] = literal + } + predicate.Right = &PhysicalValue{BindKey: key} + } + subplan.Operations = append(subplan.Operations, PhysicalOperation{Kind: PhysicalFilterOp, Filter: &PhysicalFilter{Expression: &PhysicalPredicateExpression{Kind: PhysicalComparisonPredicate, Comparison: &predicate}}}) + } + parentVariable = nodeVariable + parentType = node.ResourceType + } + resultBind := fmt.Sprintf("required_%d_result", matchIndex) + physical.BindVars[resultBind] = 1 + subplan.Return = PhysicalExpression{ + Kind: PhysicalValueExpression, Cardinality: PhysicalScalarCardinality, NullBehavior: PhysicalPreserveNull, + Value: &PhysicalValue{BindKey: resultBind}, + } + return PhysicalPredicateExpression{Kind: PhysicalExistsPredicate, Exists: &subplan}, nil +} diff --git a/internal/dataframe/physical_required_match_arango_integration_test.go b/internal/dataframe/physical_required_match_arango_integration_test.go new file mode 100644 index 0000000..1bd570f --- /dev/null +++ b/internal/dataframe/physical_required_match_arango_integration_test.go @@ -0,0 +1,48 @@ +package dataframe + +import ( + "context" + "os" + "strings" + "testing" + + arangostore "github.com/calypr/loom/internal/store/arango" +) + +// TestPhysicalRequiredTraversalMatchesExplainAgainstArango keeps the P4 +// execution contract tied to the real parser and optimizer. It is opt-in like +// the other compiler integration tests because it targets a developer-loaded +// META database. It covers both the normal parent-to-child INBOUND route and +// the explicitly proven ResearchSubject -> ResearchStudy OUTBOUND route. +func TestPhysicalRequiredTraversalMatchesExplainAgainstArango(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run compiler/Arango integration") + } + url, database, project := compilerArangoTarget() + for _, test := range []struct { + name string + root string + label string + target string + direction string + }{ + {name: "inbound", root: "Patient", label: "subject_Patient", target: "Specimen", direction: "INBOUND"}, + {name: "proven outbound", root: "ResearchSubject", label: "study", target: "ResearchStudy", direction: "OUTBOUND"}, + } { + t.Run(test.name, func(t *testing.T) { + compiled, err := CompileRequest(Builder{ + Project: project, RootResourceType: test.root, + Traversals: []TraversalStep{{Label: test.label, ToResourceType: test.target, Alias: "required", MatchMode: TraversalMatchRequired}}, + }, 5) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(compiled.Query, "FOR required_0_node_0, required_0_edge_0 IN 1..1 "+test.direction+" root @@required_0_0_edge_collection") { + t.Fatalf("required traversal did not use physical renderer:\n%s", compiled.Query) + } + if _, err := ExplainCompiledQuery(context.Background(), arangostore.ConnectionOptions{URL: url, Database: database}, compiled); err != nil { + t.Fatalf("ExplainCompiledQuery() error = %v\nAQL:\n%s", err, compiled.Query) + } + }) + } +} diff --git a/internal/dataframe/physical_required_match_test.go b/internal/dataframe/physical_required_match_test.go new file mode 100644 index 0000000..18e4768 --- /dev/null +++ b/internal/dataframe/physical_required_match_test.go @@ -0,0 +1,86 @@ +package dataframe + +import ( + "strings" + "testing" +) + +func TestRenderPhysicalPlanRequiredInboundTraversalMatch(t *testing.T) { + plan, err := BuildPhysicalPlan(SemanticPlan{ + Version: 1, Project: "project-1", AuthResourcePaths: []string{"/programs/p1"}, + Root: SemanticNode{Alias: "root", ResourceType: "Patient", Children: []SemanticNode{{ + Alias: "condition", ResourceType: "Condition", EdgeLabel: "subject_Patient", MatchMode: TraversalMatchRequired, + }}}, + }) + if err != nil { + t.Fatal(err) + } + rendered, err := RenderPhysicalPlan(plan) + if err != nil { + t.Fatalf("RenderPhysicalPlan() error = %v", err) + } + for _, want := range []string{ + "FILTER LENGTH((", + "FOR required_0_node_0, required_0_edge_0 IN 1..1 INBOUND root @@required_0_0_edge_collection", + "required_0_edge_0.label == @required_0_0_label", + "required_0_edge_0.from_type == @required_0_0_target_type", + "required_0_node_0.resourceType == @required_0_0_target_type", + "required_0_edge_0.project == @project", + "required_0_node_0.project == @project", + "required_0_edge_0.dataset_generation == @dataset_generation", + "required_0_node_0.dataset_generation == @dataset_generation", + "required_0_edge_0.auth_resource_path IN @auth_resource_paths", + "required_0_node_0.auth_resource_path IN @auth_resource_paths", + "LIMIT 1", + } { + if !strings.Contains(rendered.Query, want) { + t.Fatalf("rendered required match missing %q:\n%s", want, rendered.Query) + } + } + if got := rendered.BindVars["@required_0_0_edge_collection"]; got != "fhir_edge" { + t.Fatalf("required traversal edge collection bind = %#v", got) + } +} + +func TestRenderPhysicalPlanRequiredOutboundResearchStudyMatch(t *testing.T) { + plan, err := BuildPhysicalPlan(SemanticPlan{ + Version: 1, Project: "project-1", + Root: SemanticNode{Alias: "root", ResourceType: "ResearchSubject", Children: []SemanticNode{{ + Alias: "study", ResourceType: "ResearchStudy", EdgeLabel: "study", MatchMode: TraversalMatchRequired, + }}}, + }) + if err != nil { + t.Fatal(err) + } + rendered, err := RenderPhysicalPlan(plan) + if err != nil { + t.Fatalf("RenderPhysicalPlan() error = %v", err) + } + for _, want := range []string{ + "FOR required_0_node_0, required_0_edge_0 IN 1..1 OUTBOUND root @@required_0_0_edge_collection", + "required_0_edge_0.to_type == @required_0_0_target_type", + "required_0_node_0.resourceType == @required_0_0_target_type", + "LIMIT 1", + } { + if !strings.Contains(rendered.Query, want) { + t.Fatalf("rendered outbound required match missing %q:\n%s", want, rendered.Query) + } + } +} + +func TestBuildPhysicalPlanRequiredTraversalWithFilterUsesTypedPredicate(t *testing.T) { + plan, err := BuildPhysicalPlan(SemanticPlan{ + Version: 1, Project: "project-1", + Root: SemanticNode{Alias: "root", ResourceType: "Patient", Children: []SemanticNode{{ + Alias: "condition", ResourceType: "Condition", EdgeLabel: "subject_Patient", MatchMode: TraversalMatchRequired, + Filters: []TypedFilter{{FieldRef: "Condition.id", Selector: "id", FieldKind: FilterString, Operator: FilterExists}}, + }}}, + }) + if err != nil { + t.Fatal(err) + } + rendered, err := RenderPhysicalPlan(plan) + if err != nil || !strings.Contains(rendered.Query, "required_0_0") { + t.Fatalf("required filter did not render physically: err=%v query=%s", err, rendered.Query) + } +} diff --git a/internal/dataframe/physical_scope.go b/internal/dataframe/physical_scope.go index 559529a..1df138b 100644 --- a/internal/dataframe/physical_scope.go +++ b/internal/dataframe/physical_scope.go @@ -82,7 +82,7 @@ func physicalScopeResourceForOperation(operation PhysicalOperation) (physicalSco func physicalScopeWindowEnd(operations []PhysicalOperation, start int) int { for index := start; index < len(operations); index++ { switch operations[index].Kind { - case PhysicalRootScanOp, PhysicalTraversalOp, PhysicalReturnOp: + case PhysicalRootScanOp, PhysicalTraversalOp, PhysicalSetOp, PhysicalReturnOp: return index } } diff --git a/internal/dataframe/pivots.go b/internal/dataframe/pivots.go index 38cb96a..84daf88 100644 --- a/internal/dataframe/pivots.go +++ b/internal/dataframe/pivots.go @@ -4,8 +4,8 @@ import ( "context" "fmt" + "github.com/calypr/loom/fhirschema" "github.com/calypr/loom/internal/catalog" - "github.com/calypr/loom/internal/fhirschema" ) func (s *Service) expandPivotColumns(ctx context.Context, builder Builder) (Builder, error) { diff --git a/internal/dataframe/planner.go b/internal/dataframe/planner.go deleted file mode 100644 index 9c05161..0000000 --- a/internal/dataframe/planner.go +++ /dev/null @@ -1,256 +0,0 @@ -package dataframe - -import ( - "fmt" - "strings" - - "github.com/calypr/loom/internal/authscope" -) - -type PlanHint struct { - Mode string - Profile string - NamedSetCount int - ClassifiedFileSummaries bool - StudyLookup bool - // RowIdentity is copied from the semantic plan so the physical renderer, - // compiler explain output, and downstream exporters agree on what one row - // represents. It is not an optimizer hint despite living here temporarily - // during the Builder-to-physical-plan migration. - RowIdentity *RowIdentity - // AppliedRules records stable optimizer rule identifiers that changed the - // physical shape. It is carried into CompiledQuery for explain, golden, and - // performance comparisons. - AppliedRules []string -} - -type logicalRequest struct { - Project string - DatasetGeneration string - AuthResourcePaths []string - AuthScopeMode authscope.ReadScopeMode - Root logicalNode -} - -type logicalNode struct { - ResourceType string - Alias string - Label string - MatchMode TraversalMatchMode - Fields []FieldSelect - Filters []TypedFilter - Pivots []PivotSelect - Aggregates []AggregateSelect - Slices []RepresentativeSlice - Children []logicalNode -} - -type loweringContext struct { - request logicalRequest - builder Builder - setsByName map[string]struct{} - modes map[string]string - genericSetsBySignature map[string]string - genericFilterSetsBySig map[string]string - genericAliasesBySetName map[string]string - genericTraversalShareCount int -} - -func buildLogicalRequest(builder Builder) logicalRequest { - return logicalRequest{ - Project: builder.Project, - DatasetGeneration: normalizeDatasetGeneration(builder.DatasetGeneration), - AuthResourcePaths: cloneStrings(builder.AuthResourcePaths), - AuthScopeMode: builder.AuthScopeMode, - Root: logicalNode{ - ResourceType: builder.RootResourceType, - Alias: "root", - Fields: append([]FieldSelect(nil), builder.Fields...), - Filters: append([]TypedFilter(nil), builder.Filters...), - Pivots: append([]PivotSelect(nil), builder.Pivots...), - Aggregates: append([]AggregateSelect(nil), builder.Aggregates...), - Slices: append([]RepresentativeSlice(nil), builder.Slices...), - Children: logicalNodesFromTraversal(builder.Traversals), - }, - } -} - -func logicalNodesFromTraversal(in []TraversalStep) []logicalNode { - if len(in) == 0 { - return []logicalNode{} - } - out := make([]logicalNode, 0, len(in)) - for _, step := range in { - out = append(out, logicalNode{ - ResourceType: step.ToResourceType, - Alias: step.Alias, - Label: step.Label, - MatchMode: step.MatchMode, - Fields: append([]FieldSelect(nil), step.Fields...), - Filters: append([]TypedFilter(nil), step.Filters...), - Pivots: append([]PivotSelect(nil), step.Pivots...), - Aggregates: append([]AggregateSelect(nil), step.Aggregates...), - Slices: append([]RepresentativeSlice(nil), step.Slices...), - Children: logicalNodesFromTraversal(step.Traversals), - }) - } - return out -} - -func lowerGraphQLBuilder(builder Builder) (Builder, error) { - return lowerGenericGraphQLBuilder(builder, buildLogicalRequest(builder)) -} - -func requestHasTypedFilters(node logicalNode) bool { - if len(node.Filters) > 0 { - return true - } - for _, child := range node.Children { - if requestHasTypedFilters(child) { - return true - } - } - return false -} - -func requestHasRequiredTraversalMatch(node logicalNode) bool { - for _, child := range node.Children { - if child.MatchMode.required() || requestHasRequiredTraversalMatch(child) { - return true - } - } - return false -} - -// Lower converts the public dataframe request into a validated physical-plan -// builder. It is the compiler boundary used by conformance tooling and by the -// service layer; callers should not construct named sets directly. -func Lower(builder Builder) (Builder, error) { - semantic, err := BuildSemanticPlan(builder) - if err != nil { - return Builder{}, err - } - return lowerSemanticBuilder(builder, semantic) -} - -// lowerSemanticBuilder performs the representation-specific half of Lower -// after its caller has already built the semantic request. Keeping that seam -// explicit lets CompileRequest, the service path, and compiler explain all -// choose the typed physical renderer without parsing selectors twice. -func lowerSemanticBuilder(builder Builder, semantic SemanticPlan) (Builder, error) { - planned, err := lowerGraphQLBuilder(builder) - if err != nil { - return Builder{}, err - } - planned.RowGrain = semantic.RowIdentity.Grain - if planned.PlanHint == nil { - return Builder{}, fmt.Errorf("compiler lowering produced no physical plan hint") - } - planned.PlanHint.RowIdentity = cloneRowIdentity(semantic.RowIdentity) - return planned, nil -} - -func unsupportedLoweringError(msg string) error { - return fmt.Errorf("unsupported dataframe query shape: %s", msg) -} - -// lowerNodeSelections implements the canonical selection contract for every -// FHIR root and traversal. AUTO on a repeated relationship is deterministic -// FIRST; callers that need arrays must request ALL or DISTINCT explicitly. -func (ctx *loweringContext) lowerNodeSelections(node logicalNode, sourceSet string) { - for _, field := range node.Fields { - selectExpr := field.Select - fallbacks := append([]string(nil), field.FallbackSelects...) - operation := DerivedOpUnique - switch normalizeValueMode(field.ValueMode) { - case "FIRST": - operation = DerivedOpFirstNonNull - case "ALL": - operation = DerivedOpAll - case "DISTINCT": - operation = DerivedOpUnique - case "AUTO": - operation = DerivedOpFirstNonNull - } - ctx.builder.DerivedFields = append(ctx.builder.DerivedFields, DerivedField{ - Name: sanitizeColumnName(node.Alias + "__" + field.Name), - Source: sourceSet, - Operation: operation, - Select: selectExpr, - FallbackSelects: fallbacks, - }) - } - for _, pivot := range node.Pivots { - keySelect := pivot.ColumnSelect - valueSelect := pivot.ValueSelect - ctx.builder.DerivedFields = append(ctx.builder.DerivedFields, DerivedField{ - Name: sanitizeColumnName(node.Alias + "__" + pivot.Name), - Source: sourceSet, - Operation: DerivedOpPivot, - PivotFamily: pivot.PivotFamily, - PivotKeySelect: keySelect, - PivotValueSelect: valueSelect, - PivotColumns: cloneStrings(pivot.Columns), - }) - } - for _, agg := range node.Aggregates { - field := DerivedField{ - Name: sanitizeColumnName(node.Alias + "__" + agg.Name), - Source: sourceSet, - Select: agg.Select, - PredicatePath: agg.PredicatePath, - PredicateEquals: agg.PredicateEquals, - } - switch strings.ToUpper(strings.TrimSpace(agg.Operation)) { - case "COUNT": - if strings.TrimSpace(field.PredicatePath) != "" || strings.TrimSpace(field.Predicate) != "" { - field.Operation = DerivedOpCountWhere - } else { - field.Operation = DerivedOpCount - } - case "COUNT_DISTINCT": - field.Operation = DerivedOpCountDistinct - case "EXISTS": - field.Operation = DerivedOpAny - case "DISTINCT_VALUES": - field.Operation = DerivedOpUnique - case "MIN": - field.Operation = DerivedOpMin - case "MAX": - field.Operation = DerivedOpMax - default: - continue - } - ctx.builder.DerivedFields = append(ctx.builder.DerivedFields, field) - } - for _, slice := range node.Slices { - projected := RepresentativeSlice{ - Name: sanitizeColumnName(node.Alias + "__" + slice.Name), - SourceSet: sourceSet, - PredicatePath: slice.PredicatePath, - PredicateEquals: slice.PredicateEquals, - Limit: slice.Limit, - Fields: append([]FieldSelect(nil), slice.Fields...), - } - ctx.builder.RepresentativeSlices = append(ctx.builder.RepresentativeSlices, projected) - } -} - -func normalizeValueMode(mode string) string { - switch strings.ToUpper(strings.TrimSpace(mode)) { - case "FIRST", "ALL", "DISTINCT": - return strings.ToUpper(strings.TrimSpace(mode)) - default: - return "AUTO" - } -} - -func (ctx *loweringContext) ensureSet(set NamedSet, mode string) string { - if _, ok := ctx.setsByName[set.Name]; ok { - return set.Name - } - ctx.builder.Sets = append(ctx.builder.Sets, set) - ctx.setsByName[set.Name] = struct{}{} - ctx.modes[set.Name] = mode - return set.Name -} diff --git a/internal/dataframe/profile.go b/internal/dataframe/profile.go new file mode 100644 index 0000000..ebec6a5 --- /dev/null +++ b/internal/dataframe/profile.go @@ -0,0 +1,23 @@ +package dataframe + +import ( + "context" + + arangostore "github.com/calypr/loom/internal/store/arango" +) + +// ProfileCompiledQuery runs Arango's opt-in PROFILE operation for a compiled +// request. It is intentionally separate from normal dataframe execution so a +// frontend request never pays profiling overhead. +func ProfileCompiledQuery(ctx context.Context, opts arangostore.ConnectionOptions, compiled CompiledQuery, profileLevel int) (arangostore.ProfileResult, error) { + client, err := arangostore.Open(ctx, opts.URL, opts.Database) + if err != nil { + return arangostore.ProfileResult{}, err + } + defer client.Close(ctx) + return client.Profile(ctx, arangostore.ProfileRequest{ + Query: compiled.Query, + BindVars: compiled.BindVars, + Options: arangostore.ProfileOptions{Profile: profileLevel}, + }) +} diff --git a/internal/dataframe/relationship_match.go b/internal/dataframe/relationship_match.go index 2c791d2..2af286d 100644 --- a/internal/dataframe/relationship_match.go +++ b/internal/dataframe/relationship_match.go @@ -2,9 +2,6 @@ package dataframe import ( "fmt" - "strings" - - "github.com/calypr/loom/internal/fhirschema" ) // TraversalMatchMode controls whether a relationship contributes values to a @@ -33,100 +30,3 @@ func (m TraversalMatchMode) Validate() error { func (m TraversalMatchMode) required() bool { return m == TraversalMatchRequired } - -// RequiredTraversalMatch is the lowered representation of one existential -// relationship route. It is compiler-owned, not a GraphQL input: Lower builds -// it from TraversalStep.MatchMode and Compile renders it before root sorting -// and limiting. Every step in Steps must match for the root row to survive. -type RequiredTraversalMatch struct { - Steps []TraversalMatchStep -} - -// TraversalMatchStep retains only the information necessary to evaluate a -// relationship existence predicate. Alias and selection shape do not affect -// the semi-join, while typed filters do. -type TraversalMatchStep struct { - Alias string - Label string - ToResourceType string - Filters []TypedFilter -} - -func requiredTraversalMatches(root logicalNode) ([]RequiredTraversalMatch, error) { - matches := make([]RequiredTraversalMatch, 0) - var walk func(parent logicalNode, route []TraversalMatchStep) error - walk = func(parent logicalNode, route []TraversalMatchStep) error { - for _, child := range parent.Children { - if err := child.MatchMode.Validate(); err != nil { - return fmt.Errorf("traversal %s -> %s (%s): %w", parent.ResourceType, child.ResourceType, child.Label, err) - } - if _, err := resolveStorageRoute(parent.ResourceType, child.Label, child.ResourceType); err != nil { - return fmt.Errorf("traversal %s -> %s (%s): %w", parent.ResourceType, child.ResourceType, child.Label, err) - } - - next := appendTraversalMatchStep(route, TraversalMatchStep{ - Alias: child.Alias, - Label: child.Label, - ToResourceType: child.ResourceType, - Filters: append([]TypedFilter(nil), child.Filters...), - }) - if child.MatchMode.required() { - matches = append(matches, RequiredTraversalMatch{Steps: cloneTraversalMatchSteps(next)}) - } - if err := walk(child, next); err != nil { - return err - } - } - return nil - } - if err := walk(root, nil); err != nil { - return nil, err - } - return matches, nil -} - -func validateRequiredTraversalMatches(rootResourceType string, matches []RequiredTraversalMatch) error { - for matchIndex, match := range matches { - if len(match.Steps) == 0 { - return fmt.Errorf("required traversal match %d has no route steps", matchIndex) - } - fromResourceType := rootResourceType - for stepIndex, step := range match.Steps { - if strings.TrimSpace(step.Label) == "" { - return fmt.Errorf("required traversal match %d step %d has no edge label", matchIndex, stepIndex) - } - if !fhirschema.HasResource(step.ToResourceType) { - return fmt.Errorf("required traversal match %d step %d target resource type %q is not represented by the active generated FHIR schema", matchIndex, stepIndex, step.ToResourceType) - } - if _, err := resolveStorageRoute(fromResourceType, step.Label, step.ToResourceType); err != nil { - return fmt.Errorf("required traversal match %d step %d %s -> %s (%s): %w", matchIndex, stepIndex, fromResourceType, step.ToResourceType, step.Label, err) - } - for _, filter := range step.Filters { - if err := ValidateTypedFilterForResource(step.ToResourceType, filter); err != nil { - return fmt.Errorf("required traversal match %d step %d filter %q: %w", matchIndex, stepIndex, filter.FieldRef, err) - } - } - fromResourceType = step.ToResourceType - } - } - return nil -} - -func appendTraversalMatchStep(route []TraversalMatchStep, step TraversalMatchStep) []TraversalMatchStep { - next := make([]TraversalMatchStep, len(route), len(route)+1) - copy(next, route) - next = append(next, step) - return next -} - -func cloneTraversalMatchSteps(in []TraversalMatchStep) []TraversalMatchStep { - if len(in) == 0 { - return nil - } - out := make([]TraversalMatchStep, len(in)) - for i, step := range in { - out[i] = step - out[i].Filters = append([]TypedFilter(nil), step.Filters...) - } - return out -} diff --git a/internal/dataframe/relationship_match_compile.go b/internal/dataframe/relationship_match_compile.go deleted file mode 100644 index a6b4057..0000000 --- a/internal/dataframe/relationship_match_compile.go +++ /dev/null @@ -1,67 +0,0 @@ -package dataframe - -import ( - "fmt" - "strings" -) - -// compileRequiredTraversalMatch emits a bounded root-correlated existence -// subquery. Each step is rechecked against the compiler-owned stored-edge -// route contract, so a manually assembled lowered Builder cannot turn an -// unproven schema-valid forward FHIR reference into an incorrect semi-join. -func (c *compiler) compileRequiredTraversalMatch(rootVar string, matchIndex int, match RequiredTraversalMatch) (string, error) { - if len(match.Steps) == 0 { - return "", fmt.Errorf("required traversal match %d has no route steps", matchIndex) - } - - lines := make([]string, 0, len(match.Steps)*6+2) - parentVar := rootVar - parentResourceType := c.builder.RootResourceType - for stepIndex, step := range match.Steps { - route, err := resolveStorageRoute(parentResourceType, step.Label, step.ToResourceType) - if err != nil { - return "", fmt.Errorf("compile required traversal match %d step %d: %w", matchIndex, stepIndex, err) - } - nodeVar := fmt.Sprintf("__match_%d_%d", matchIndex, stepIndex) - edgeVar := fmt.Sprintf("__match_edge_%d_%d", matchIndex, stepIndex) - labelBind := c.newBind(fmt.Sprintf("match_%d_%d_label", matchIndex, stepIndex), step.Label) - toBind := c.newBind(fmt.Sprintf("match_%d_%d_to", matchIndex, stepIndex), step.ToResourceType) - edgeTypeField := route.targetEdgeTypeField() - if edgeTypeField == "" { - return "", fmt.Errorf("compile required traversal match %d step %d: %w: route direction %q has no fhir_edge target type field", matchIndex, stepIndex, ErrUnsupportedStorageRoute, route.Direction) - } - edgeTypeBind := c.newBind(fmt.Sprintf("match_%d_%d_edge_target_type", matchIndex, stepIndex), step.ToResourceType) - lines = append(lines, fmt.Sprintf("FOR %s, %s IN 1..1 %s %s fhir_edge", nodeVar, edgeVar, route.Direction, parentVar)) - lines = append(lines, fmt.Sprintf(" FILTER %s.project == @project", edgeVar)) - lines = append(lines, fmt.Sprintf(" FILTER %s.project == @project", nodeVar)) - lines = append(lines, fmt.Sprintf(" FILTER %s.%s == @%s", edgeVar, datasetGenerationField, datasetGenerationBindKey)) - lines = append(lines, fmt.Sprintf(" FILTER %s.%s == @%s", nodeVar, datasetGenerationField, datasetGenerationBindKey)) - lines = append(lines, fmt.Sprintf(" FILTER @auth_resource_paths_unrestricted == true OR (%s.auth_resource_path IN @auth_resource_paths AND %s.auth_resource_path IN @auth_resource_paths)", edgeVar, nodeVar)) - lines = append(lines, fmt.Sprintf(" FILTER %s.label == @%s", edgeVar, labelBind)) - lines = append(lines, fmt.Sprintf(" FILTER %s.%s == @%s", edgeVar, edgeTypeField, edgeTypeBind)) - lines = append(lines, fmt.Sprintf(" FILTER %s.resourceType == @%s", nodeVar, toBind)) - filters, err := c.compileTypedFilters(nodeVar+".payload", step.Filters) - if err != nil { - return "", fmt.Errorf("compile required traversal match %d step %d filters: %w", matchIndex, stepIndex, err) - } - if filters != "true" { - lines = append(lines, " FILTER ("+filters+")") - } - parentVar = nodeVar - parentResourceType = step.ToResourceType - } - lines = append(lines, " LIMIT 1", " RETURN 1") - return "LENGTH(\n " + strings.Join(lines, "\n ") + "\n ) > 0", nil -} - -func (c *compiler) compileRequiredTraversalMatches(rootVar string, matches []RequiredTraversalMatch) ([]string, error) { - filters := make([]string, 0, len(matches)) - for matchIndex, match := range matches { - expr, err := c.compileRequiredTraversalMatch(rootVar, matchIndex, match) - if err != nil { - return nil, err - } - filters = append(filters, expr) - } - return filters, nil -} diff --git a/internal/dataframe/relationship_match_test.go b/internal/dataframe/relationship_match_test.go deleted file mode 100644 index 6b72f32..0000000 --- a/internal/dataframe/relationship_match_test.go +++ /dev/null @@ -1,214 +0,0 @@ -package dataframe - -import ( - "strings" - "testing" -) - -func TestOptionalTraversalMatchPreservesRootMembershipAndPostLimitMaterialization(t *testing.T) { - compiled, err := CompileRequest(Builder{ - Project: "P1", - RootResourceType: "Specimen", - Traversals: []TraversalStep{{ - Label: "subject_Specimen", - ToResourceType: "DocumentReference", - Alias: "file", - }}, - }, 5) - if err != nil { - t.Fatal(err) - } - if strings.Contains(compiled.Query, "__match_") || containsOptimizerRule(compiled.OptimizationRules, OptimizerRuleRelationshipSemiJoin) { - t.Fatalf("optional traversal unexpectedly changed root membership:\n%s\nrules=%#v", compiled.Query, compiled.OptimizationRules) - } - if !strings.Contains(compiled.Query, "FOR root IN @@root_collection") { - t.Fatalf("navigation-only generic request did not use the typed physical renderer:\n%s", compiled.Query) - } - if got, want := strings.Index(compiled.Query, "LIMIT @limit"), strings.Index(compiled.Query, "LET __loom_physical_set_1"); got < 0 || want < 0 || got > want { - t.Fatalf("optional traversal should materialize after the root execution window:\n%s", compiled.Query) - } -} - -func TestRequiredDirectTraversalCompilesTypedChildFilterAsRootSemiJoin(t *testing.T) { - melanoma := "melanoma" - builder := Builder{ - Project: "P1", - RootResourceType: "Patient", - Traversals: []TraversalStep{{ - Label: "subject_Patient", - ToResourceType: "Condition", - Alias: "diagnosis", - MatchMode: TraversalMatchRequired, - Filters: []TypedFilter{{ - FieldRef: "Condition.id", - Selector: "id", - FieldKind: FilterString, - Operator: FilterEquals, - Values: []FilterValue{{Kind: FilterString, String: &melanoma}}, - }}, - }}, - } - semantic, err := BuildSemanticPlan(builder) - if err != nil { - t.Fatal(err) - } - if len(semantic.Root.Children) != 1 || semantic.Root.Children[0].MatchMode != TraversalMatchRequired { - t.Fatalf("semantic required match mode was not preserved: %#v", semantic.Root.Children) - } - planned, err := Lower(builder) - if err != nil { - t.Fatal(err) - } - if len(planned.RequiredTraversalMatches) != 1 || len(planned.RequiredTraversalMatches[0].Steps) != 1 { - t.Fatalf("lowered required matches = %#v", planned.RequiredTraversalMatches) - } - compiled, err := Compile(planned, 5) - if err != nil { - t.Fatal(err) - } - if compiled.PlanProfile != "generic_fhir_graph" { - t.Fatalf("required match must use generic lowerer, got %q", compiled.PlanProfile) - } - if !containsOptimizerRule(compiled.OptimizationRules, OptimizerRuleRelationshipSemiJoin) { - t.Fatalf("missing semi-join provenance: %#v", compiled.OptimizationRules) - } - for _, want := range []string{ - "FOR __match_0_0, __match_edge_0_0 IN 1..1 INBOUND root fhir_edge", - "__match_edge_0_0.project == @project", - "__match_edge_0_0.auth_resource_path IN @auth_resource_paths", - "__match_0_0.auth_resource_path IN @auth_resource_paths", - "__match_0_0.resourceType == @__match_0_0_to_", - "__match_0_0.payload", - "LIMIT 1", - } { - if !strings.Contains(compiled.Query, want) { - t.Fatalf("required semi-join missing %q:\n%s", want, compiled.Query) - } - } - assertBindVarValue(t, compiled.BindVars, "subject_Patient") - assertBindVarValue(t, compiled.BindVars, "Condition") - assertBindVarValue(t, compiled.BindVars, melanoma) - assertRootMatchPrecedesLimit(t, compiled.Query) -} - -func TestRequiredNestedTraversalCompilesOneBoundedRoute(t *testing.T) { - fileID := "melanoma-report" - compiled, err := CompileRequest(Builder{ - Project: "P1", - RootResourceType: "Patient", - Traversals: []TraversalStep{{ - Label: "subject_Patient", - ToResourceType: "Specimen", - Alias: "specimen", - Traversals: []TraversalStep{{ - Label: "subject_Specimen", - ToResourceType: "DocumentReference", - Alias: "file", - MatchMode: TraversalMatchRequired, - Filters: []TypedFilter{{ - FieldRef: "DocumentReference.id", - Selector: "id", - FieldKind: FilterString, - Operator: FilterEquals, - Values: []FilterValue{{Kind: FilterString, String: &fileID}}, - }}, - }}, - }}, - }, 5) - if err != nil { - t.Fatal(err) - } - first := "FOR __match_0_0, __match_edge_0_0 IN 1..1 INBOUND root fhir_edge" - second := "FOR __match_0_1, __match_edge_0_1 IN 1..1 INBOUND __match_0_0 fhir_edge" - if !strings.Contains(compiled.Query, first) || !strings.Contains(compiled.Query, second) { - t.Fatalf("required nested route was not compiled as one correlated semi-join:\n%s", compiled.Query) - } - if strings.Index(compiled.Query, first) > strings.Index(compiled.Query, second) { - t.Fatalf("nested route order is reversed:\n%s", compiled.Query) - } - assertBindVarValue(t, compiled.BindVars, "subject_Specimen") - assertBindVarValue(t, compiled.BindVars, "DocumentReference") - assertBindVarValue(t, compiled.BindVars, fileID) - assertRootMatchPrecedesLimit(t, compiled.Query) -} - -func TestRequiredTraversalRejectsUnsafeOrUnknownRoute(t *testing.T) { - tests := []struct { - name string - step TraversalStep - want string - }{ - { - name: "unknown route", - step: TraversalStep{Label: "not_a_generated_route", ToResourceType: "Condition", Alias: "diagnosis", MatchMode: TraversalMatchRequired}, - want: "not represented by the active generated FHIR schema", - }, - { - name: "unsafe route label", - step: TraversalStep{Label: "subject_Patient RETURN SLEEP(1)", ToResourceType: "Condition", Alias: "diagnosis", MatchMode: TraversalMatchRequired}, - want: "not represented by the active generated FHIR schema", - }, - { - name: "unknown match mode", - step: TraversalStep{Label: "subject_Patient", ToResourceType: "Condition", Alias: "diagnosis", MatchMode: TraversalMatchMode("MUST_MATCH")}, - want: "unsupported traversal match mode", - }, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - _, err := CompileRequest(Builder{Project: "P1", RootResourceType: "Patient", Traversals: []TraversalStep{test.step}}, 1) - if err == nil || !strings.Contains(err.Error(), test.want) { - t.Fatalf("CompileRequest() error = %v, want %q", err, test.want) - } - }) - } - t.Run("manual lowered unsafe route", func(t *testing.T) { - _, err := Compile(Builder{ - Project: "P1", - RootResourceType: "Patient", - PlanHint: &PlanHint{Mode: "lowered", Profile: "test"}, - RequiredTraversalMatches: []RequiredTraversalMatch{{ - Steps: []TraversalMatchStep{{Label: "subject_Patient RETURN SLEEP(1)", ToResourceType: "Condition"}}, - }}, - }, 1) - if err == nil || !strings.Contains(err.Error(), "not represented by the active generated FHIR schema") { - t.Fatalf("Compile() error = %v", err) - } - }) -} - -func TestNavigationOnlyPhysicalPlanRejectsRequiredRelationshipMatch(t *testing.T) { - _, err := BuildGenericPhysicalPlan(SemanticPlan{ - Version: 1, - Project: "P1", - Root: SemanticNode{ - Alias: "root", ResourceType: "Patient", - Children: []SemanticNode{{ - Alias: "diagnosis", ResourceType: "Condition", EdgeLabel: "subject_Patient", MatchMode: TraversalMatchRequired, - }}, - }, - }) - if err == nil || !strings.Contains(err.Error(), "requires a relationship match") { - t.Fatalf("BuildGenericPhysicalPlan() error = %v", err) - } -} - -func assertRootMatchPrecedesLimit(t *testing.T, query string) { - t.Helper() - match := strings.Index(query, "FOR __match_0_0") - sort := strings.Index(query, "SORT root._key") - limit := strings.Index(query, "LIMIT @limit") - if match < 0 || sort < 0 || limit < 0 || match > sort || match > limit || sort > limit { - t.Fatalf("required match must be a root predicate before SORT/LIMIT:\n%s", query) - } -} - -func assertBindVarValue(t *testing.T, bindVars map[string]any, want any) { - t.Helper() - for _, got := range bindVars { - if got == want { - return - } - } - t.Fatalf("bind variables do not contain %#v: %#v", want, bindVars) -} diff --git a/internal/dataframe/selection_semantics.go b/internal/dataframe/selection_semantics.go index f70239b..fd45caf 100644 --- a/internal/dataframe/selection_semantics.go +++ b/internal/dataframe/selection_semantics.go @@ -5,7 +5,7 @@ import ( "sort" "strings" - "github.com/calypr/loom/internal/fhirschema" + "github.com/calypr/loom/fhirschema" ) // SelectionSemanticSpec is the compiler-ready meaning of one field selection. diff --git a/internal/dataframe/selector_render.go b/internal/dataframe/selector_render.go new file mode 100644 index 0000000..19ef64d --- /dev/null +++ b/internal/dataframe/selector_render.go @@ -0,0 +1,40 @@ +package dataframe + +import ( + "fmt" +) + +// selectorHasNoArrays and the helpers below are shared by the physical +// renderer and typed-filter compiler. They deliberately render only validated +// Selector values and do not know anything about storage-plan representation. +func selectorHasNoArrays(sel Selector) bool { + for _, step := range sel.Steps { + if step.Iterate || step.Index != nil { + return false + } + } + return true +} + +func compileDirectExpr(rootVar string, steps []SelectorStep) string { + cur := rootVar + for _, step := range steps { + if step.Index != nil { + cur = fmt.Sprintf("((%s.%s ? %s.%s : [])[%d])", cur, step.Field, cur, step.Field, *step.Index) + continue + } + cur = fmt.Sprintf("%s.%s", cur, step.Field) + } + return cur +} + +func extractFinalExpr(cur string, step SelectorStep) string { + switch { + case step.Iterate: + return fmt.Sprintf("(%s.%s ? %s.%s : [])", cur, step.Field, cur, step.Field) + case step.Index != nil: + return fmt.Sprintf("((%s.%s ? %s.%s : [])[%d])", cur, step.Field, cur, step.Field, *step.Index) + default: + return fmt.Sprintf("%s.%s", cur, step.Field) + } +} diff --git a/internal/dataframe/selectors.go b/internal/dataframe/selectors.go index e5928de..0c70f68 100644 --- a/internal/dataframe/selectors.go +++ b/internal/dataframe/selectors.go @@ -5,7 +5,7 @@ import ( "fmt" "strings" - "github.com/calypr/loom/internal/fhirschema" + "github.com/calypr/loom/fhirschema" ) type Selector = fhirschema.Selector diff --git a/internal/dataframe/semantic_plan.go b/internal/dataframe/semantic_plan.go index 1084cd8..98f1125 100644 --- a/internal/dataframe/semantic_plan.go +++ b/internal/dataframe/semantic_plan.go @@ -4,8 +4,8 @@ import ( "fmt" "strings" + "github.com/calypr/loom/fhirschema" "github.com/calypr/loom/internal/authscope" - "github.com/calypr/loom/internal/fhirschema" ) // SemanticPlan is the validated, backend-independent meaning of a dataframe @@ -236,8 +236,8 @@ func semanticNodeFromBuilder(alias, resourceType, edgeLabel string, matchMode Tr } seenAggregates[aggregate.Name] = struct{}{} operation := strings.ToUpper(strings.TrimSpace(aggregate.Operation)) - if _, err := normalizeAggregateFunction(operation); err != nil { - return SemanticNode{}, fmt.Errorf("aggregate %q: %w", aggregate.Name, err) + if !isKnownAggregateOperation(operation) { + return SemanticNode{}, fmt.Errorf("aggregate %q uses unsupported operation %q", aggregate.Name, aggregate.Operation) } if !isKnownValueMode(aggregate.ValueMode) { return SemanticNode{}, fmt.Errorf("aggregate %q uses unsupported value mode %q", aggregate.Name, aggregate.ValueMode) @@ -370,6 +370,15 @@ func aggregateOperationRequiresSelector(operation string) bool { } } +func isKnownAggregateOperation(operation string) bool { + switch strings.ToUpper(strings.TrimSpace(operation)) { + case "COUNT", "COUNT_DISTINCT", "EXISTS", "DISTINCT_VALUES", "MIN", "MAX": + return true + default: + return false + } +} + // Explain returns a compact stable summary suitable for diagnostics and tests. // It intentionally does not expose physical AQL decisions. func (p SemanticPlan) Explain() SemanticPlanExplanation { diff --git a/internal/dataframe/semantic_validation.go b/internal/dataframe/semantic_validation.go index 424e8c2..f57ad9a 100644 --- a/internal/dataframe/semantic_validation.go +++ b/internal/dataframe/semantic_validation.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/calypr/loom/internal/fhirschema" + "github.com/calypr/loom/fhirschema" ) // MaxSemanticTraversalDepth is the maximum number of relationship edges below diff --git a/internal/dataframe/service.go b/internal/dataframe/service.go index f5398b5..cd567fa 100644 --- a/internal/dataframe/service.go +++ b/internal/dataframe/service.go @@ -3,6 +3,7 @@ package dataframe import ( "context" "fmt" + "time" "github.com/calypr/loom/internal/authscope" "github.com/calypr/loom/internal/catalog" @@ -58,30 +59,43 @@ func NewService(cfg ServiceConfig) *Service { } func (s *Service) Run(ctx context.Context, req RunRequest) (*Result, error) { - compiled, err := s.compileRunRequest(ctx, req) + started := time.Now() + compiled, diagnostics, err := s.compileRunRequestWithDiagnostics(ctx, req) if err != nil { return nil, err } - return s.runQuery(ctx, compiled) + result, err := s.runQuery(ctx, compiled) + if err != nil { + return nil, err + } + diagnostics.ArangoQuery = result.Diagnostics.ArangoQuery + diagnostics.RowMaterialization = result.Diagnostics.RowMaterialization + diagnostics.ResultAssembly = result.Diagnostics.ResultAssembly + diagnostics.Total = time.Since(started) + result.Diagnostics = diagnostics + return result, nil } -func (s *Service) compileRunRequest(ctx context.Context, req RunRequest) (CompiledQuery, error) { +func (s *Service) compileRunRequestWithDiagnostics(ctx context.Context, req RunRequest) (CompiledQuery, QueryDiagnostics, error) { + prepareStarted := time.Now() spec, err := s.prepareSpec(ctx, req.Builder) if err != nil { - return CompiledQuery{}, err + return CompiledQuery{}, QueryDiagnostics{}, err } + diagnostics := QueryDiagnostics{RequestPreparation: time.Since(prepareStarted)} limit := req.Limit if limit <= 0 { limit = defaultRowLimit } - // Keep the validated logical request through the compiler boundary. Calling - // Compile on a pre-lowered Builder would force every service execution down - // the legacy string renderer and bypass the typed physical-plan path. + // Keep the validated logical request through the physical compiler boundary. + compileStarted := time.Now() compiled, err := CompileRequest(spec, limit) if err != nil { - return CompiledQuery{}, err + return CompiledQuery{}, QueryDiagnostics{}, err } - return compiled, nil + diagnostics.Compilation = time.Since(compileStarted) + diagnostics.Plan = compiled.PlanDiagnostics + return compiled, diagnostics, nil } func (s *Service) prepareSpec(ctx context.Context, builder Builder) (Builder, error) { diff --git a/internal/dataframe/shaping.go b/internal/dataframe/shaping.go deleted file mode 100644 index d56b5c7..0000000 --- a/internal/dataframe/shaping.go +++ /dev/null @@ -1,200 +0,0 @@ -package dataframe - -import ( - "fmt" - "strings" -) - -// AggregateFunction identifies a stable, backend-independent reduction. -type AggregateFunction string - -const ( - AggregateCount AggregateFunction = "count" - AggregateCountDistinct AggregateFunction = "count_distinct" - AggregateExists AggregateFunction = "exists" - AggregateDistinctValues AggregateFunction = "distinct_values" - AggregateMin AggregateFunction = "min" - AggregateMax AggregateFunction = "max" -) - -func (f AggregateFunction) Validate() error { - switch f { - case AggregateCount, AggregateCountDistinct, AggregateExists, - AggregateDistinctValues, AggregateMin, AggregateMax: - return nil - case "": - return fmt.Errorf("aggregate function is required") - default: - return fmt.Errorf("unsupported aggregate function %q", f) - } -} - -// NullPolicy defines how missing or null input values participate in shaping. -type NullPolicy string - -const ( - NullIgnore NullPolicy = "ignore" - NullInclude NullPolicy = "include" - NullReject NullPolicy = "reject" -) - -func (p NullPolicy) Validate() error { - switch p { - case NullIgnore, NullInclude, NullReject: - return nil - case "": - return fmt.Errorf("null policy is required") - default: - return fmt.Errorf("unsupported null policy %q", p) - } -} - -// AggregateConfig describes an aggregate without binding it to AQL syntax. -// Input is an opaque semantic expression identifier owned by the future IR. -type AggregateConfig struct { - Function AggregateFunction - Input string - NullPolicy NullPolicy -} - -func (c AggregateConfig) Validate() error { - if err := c.Function.Validate(); err != nil { - return err - } - if err := c.NullPolicy.Validate(); err != nil { - return err - } - if c.Function != AggregateCount && strings.TrimSpace(c.Input) == "" { - return fmt.Errorf("aggregate %s requires an input", c.Function) - } - return nil -} - -// DuplicatePolicy defines how multiple values for the same pivot key are -// handled. First and last require deterministic ordering from the caller. -type DuplicatePolicy string - -const ( - DuplicateReject DuplicatePolicy = "reject" - DuplicateFirst DuplicatePolicy = "first" - DuplicateLast DuplicatePolicy = "last" - DuplicateArray DuplicatePolicy = "array" - DuplicateDistinctArray DuplicatePolicy = "distinct_array" -) - -func (p DuplicatePolicy) Validate() error { - switch p { - case DuplicateReject, DuplicateFirst, DuplicateLast, DuplicateArray, - DuplicateDistinctArray: - return nil - case "": - return fmt.Errorf("duplicate policy is required") - default: - return fmt.Errorf("unsupported duplicate policy %q", p) - } -} - -// PivotCardinalityPolicy controls which pivot columns may be materialized. -// Discovery is always bounded; an unbounded discovery policy is intentionally -// absent from this contract. -type PivotCardinalityPolicy string - -const ( - PivotRequestedColumns PivotCardinalityPolicy = "requested_columns" - PivotBoundedDiscovery PivotCardinalityPolicy = "bounded_discovery" -) - -func (p PivotCardinalityPolicy) Validate() error { - switch p { - case PivotRequestedColumns, PivotBoundedDiscovery: - return nil - case "": - return fmt.Errorf("pivot cardinality policy is required") - default: - return fmt.Errorf("unsupported pivot cardinality policy %q", p) - } -} - -// SparsePivotPolicy defines the value emitted when a requested pivot key has -// no matching input. -type SparsePivotPolicy string - -const ( - SparsePivotNull SparsePivotPolicy = "null" - SparsePivotOmit SparsePivotPolicy = "omit" -) - -func (p SparsePivotPolicy) Validate() error { - switch p { - case SparsePivotNull, SparsePivotOmit: - return nil - case "": - return fmt.Errorf("sparse pivot policy is required") - default: - return fmt.Errorf("unsupported sparse pivot policy %q", p) - } -} - -// PivotConfig describes pivot semantics independently of physical lowering. -// Key and Value are opaque semantic expression identifiers owned by the IR. -type PivotConfig struct { - Key string - Value string - DuplicatePolicy DuplicatePolicy - NullPolicy NullPolicy - CardinalityPolicy PivotCardinalityPolicy - SparsePolicy SparsePivotPolicy - RequestedColumns []string - MaxColumns int -} - -func (c PivotConfig) Validate() error { - if strings.TrimSpace(c.Key) == "" { - return fmt.Errorf("pivot key is required") - } - if strings.TrimSpace(c.Value) == "" { - return fmt.Errorf("pivot value is required") - } - if err := c.DuplicatePolicy.Validate(); err != nil { - return err - } - if err := c.NullPolicy.Validate(); err != nil { - return err - } - if err := c.CardinalityPolicy.Validate(); err != nil { - return err - } - if err := c.SparsePolicy.Validate(); err != nil { - return err - } - - seen := make(map[string]struct{}, len(c.RequestedColumns)) - for index, column := range c.RequestedColumns { - column = strings.TrimSpace(column) - if column == "" { - return fmt.Errorf("requested pivot column %d is empty", index) - } - if _, exists := seen[column]; exists { - return fmt.Errorf("requested pivot column %q is duplicated", column) - } - seen[column] = struct{}{} - } - - switch c.CardinalityPolicy { - case PivotRequestedColumns: - if len(c.RequestedColumns) == 0 { - return fmt.Errorf("requested-columns pivot requires at least one column") - } - if c.MaxColumns < 0 { - return fmt.Errorf("pivot max columns cannot be negative") - } - if c.MaxColumns > 0 && len(c.RequestedColumns) > c.MaxColumns { - return fmt.Errorf("requested pivot columns %d exceed maximum %d", len(c.RequestedColumns), c.MaxColumns) - } - case PivotBoundedDiscovery: - if c.MaxColumns <= 0 { - return fmt.Errorf("bounded pivot discovery requires a positive maximum") - } - } - return nil -} diff --git a/internal/dataframe/shaping_plan.go b/internal/dataframe/shaping_plan.go deleted file mode 100644 index d69c69f..0000000 --- a/internal/dataframe/shaping_plan.go +++ /dev/null @@ -1,202 +0,0 @@ -package dataframe - -import ( - "fmt" - "sort" - "strings" - - "github.com/calypr/loom/internal/fhirschema" -) - -// ShapingDefaults makes policies absent from the legacy Builder contract -// explicit at the boundary to the semantic compiler. -type ShapingDefaults struct { - NullPolicy NullPolicy - PivotDuplicatePolicy DuplicatePolicy - SparsePivotPolicy SparsePivotPolicy - MaxDiscoveredPivotCols int -} - -func (d ShapingDefaults) Validate() error { - if err := d.NullPolicy.Validate(); err != nil { - return err - } - if err := d.PivotDuplicatePolicy.Validate(); err != nil { - return err - } - if err := d.SparsePivotPolicy.Validate(); err != nil { - return err - } - if d.MaxDiscoveredPivotCols <= 0 { - return fmt.Errorf("maximum discovered pivot columns must be positive") - } - return nil -} - -// ShapingSource records the semantic node and, for non-root nodes, the -// generated FHIR relationship that supplies aggregate or pivot values. -type ShapingSource struct { - ParentAlias string - TargetAlias string - ResourceType string - Relationship *fhirschema.CompilerTraversal -} - -type AggregateSemanticSpec struct { - Alias string - Source ShapingSource - Config AggregateConfig - Selector *Selector - Predicate *Selector - PredicateEquals string -} - -type PivotSemanticSpec struct { - Alias string - Source ShapingSource - Config PivotConfig - ColumnSelector Selector - ValueSelector Selector - Family string -} - -type ShapingPlan struct { - Aggregates []AggregateSemanticSpec - Pivots []PivotSemanticSpec -} - -// NormalizeShapingPlan validates shaping requests and returns deterministic, -// alias-sorted specs. It contains no AQL expressions or physical-plan choices. -func NormalizeShapingPlan(plan SemanticPlan, defaults ShapingDefaults) (ShapingPlan, error) { - if err := defaults.Validate(); err != nil { - return ShapingPlan{}, fmt.Errorf("shaping defaults: %w", err) - } - out := ShapingPlan{ - Aggregates: make([]AggregateSemanticSpec, 0), - Pivots: make([]PivotSemanticSpec, 0), - } - aliases := map[string]struct{}{} - var walk func(SemanticNode, string, string) error - walk = func(node SemanticNode, parentAlias, parentType string) error { - if strings.TrimSpace(node.Alias) == "" { - return fmt.Errorf("semantic node for %s has no alias", node.ResourceType) - } - if _, exists := aliases[node.Alias]; exists { - return fmt.Errorf("semantic node alias %q is duplicated", node.Alias) - } - aliases[node.Alias] = struct{}{} - source := ShapingSource{ParentAlias: parentAlias, TargetAlias: node.Alias, ResourceType: node.ResourceType} - if parentAlias != "" { - relationship, found, err := fhirschema.ResolveCompilerTraversal(parentType, node.EdgeLabel, node.ResourceType) - if err != nil { - return fmt.Errorf("relationship %s -[%s]-> %s: %w", parentType, node.EdgeLabel, node.ResourceType, err) - } - if !found { - return fmt.Errorf("unknown relationship %s -[%s]-> %s", parentType, node.EdgeLabel, node.ResourceType) - } - source.Relationship = &relationship - } - - for index, aggregate := range node.Aggregates { - spec, err := normalizeAggregateSpec(node.Alias, index, source, aggregate, defaults.NullPolicy) - if err != nil { - return err - } - out.Aggregates = append(out.Aggregates, spec) - } - for index, pivot := range node.Pivots { - spec, err := normalizePivotSpec(node.Alias, index, source, pivot, defaults) - if err != nil { - return err - } - out.Pivots = append(out.Pivots, spec) - } - for _, child := range node.Children { - if err := walk(child, node.Alias, node.ResourceType); err != nil { - return err - } - } - return nil - } - if err := walk(plan.Root, "", ""); err != nil { - return ShapingPlan{}, err - } - sort.Slice(out.Aggregates, func(i, j int) bool { return out.Aggregates[i].Alias < out.Aggregates[j].Alias }) - sort.Slice(out.Pivots, func(i, j int) bool { return out.Pivots[i].Alias < out.Pivots[j].Alias }) - return out, nil -} - -func normalizeAggregateSpec(nodeAlias string, index int, source ShapingSource, in SemanticAggregate, nulls NullPolicy) (AggregateSemanticSpec, error) { - name := stableShapeName(in.Name, "aggregate", index) - function, err := normalizeAggregateFunction(in.Operation) - if err != nil { - return AggregateSemanticSpec{}, fmt.Errorf("aggregate %q: %w", name, err) - } - input := "" - if in.Selector != nil { - input = in.Selector.CanonicalPath() - } else if in.Predicate != nil { - input = in.Predicate.CanonicalPath() - } else if function == AggregateExists { - input = "node:" + source.TargetAlias - } - config := AggregateConfig{Function: function, Input: input, NullPolicy: nulls} - if err := config.Validate(); err != nil { - return AggregateSemanticSpec{}, fmt.Errorf("aggregate %q: %w", name, err) - } - return AggregateSemanticSpec{ - Alias: nodeAlias + "." + name, Source: source, Config: config, - Selector: in.Selector, Predicate: in.Predicate, PredicateEquals: in.PredicateEquals, - }, nil -} - -func normalizePivotSpec(nodeAlias string, index int, source ShapingSource, in SemanticPivot, defaults ShapingDefaults) (PivotSemanticSpec, error) { - name := stableShapeName(in.Name, "pivot", index) - columns := cloneStrings(in.Columns) - cardinality := PivotRequestedColumns - maxColumns := len(columns) - if len(columns) == 0 { - cardinality = PivotBoundedDiscovery - maxColumns = defaults.MaxDiscoveredPivotCols - } - config := PivotConfig{ - Key: in.ColumnSelector.CanonicalPath(), Value: in.ValueSelector.CanonicalPath(), - DuplicatePolicy: defaults.PivotDuplicatePolicy, NullPolicy: defaults.NullPolicy, - CardinalityPolicy: cardinality, SparsePolicy: defaults.SparsePivotPolicy, - RequestedColumns: columns, MaxColumns: maxColumns, - } - if err := config.Validate(); err != nil { - return PivotSemanticSpec{}, fmt.Errorf("pivot %q: %w", name, err) - } - return PivotSemanticSpec{ - Alias: nodeAlias + "." + name, Source: source, Config: config, - ColumnSelector: in.ColumnSelector, ValueSelector: in.ValueSelector, Family: in.Family, - }, nil -} - -func normalizeAggregateFunction(operation string) (AggregateFunction, error) { - switch strings.ToUpper(strings.TrimSpace(operation)) { - case "COUNT": - return AggregateCount, nil - case "COUNT_DISTINCT": - return AggregateCountDistinct, nil - case "EXISTS": - return AggregateExists, nil - case "DISTINCT_VALUES": - return AggregateDistinctValues, nil - case "MIN": - return AggregateMin, nil - case "MAX": - return AggregateMax, nil - default: - return "", fmt.Errorf("unsupported operation %q", operation) - } -} - -func stableShapeName(name, kind string, index int) string { - name = strings.TrimSpace(name) - if name != "" { - return name - } - return fmt.Sprintf("%s_%d", kind, index+1) -} diff --git a/internal/dataframe/shaping_plan_test.go b/internal/dataframe/shaping_plan_test.go deleted file mode 100644 index a20a3e6..0000000 --- a/internal/dataframe/shaping_plan_test.go +++ /dev/null @@ -1,74 +0,0 @@ -package dataframe - -import "testing" - -func TestNormalizeShapingPlanDeterministicSpecs(t *testing.T) { - selector, _ := ParseSelector("code.coding[].code") - value, _ := ParseSelector("valueQuantity.value") - plan := SemanticPlan{Root: SemanticNode{ - Alias: "root", ResourceType: "Observation", - Aggregates: []SemanticAggregate{ - {Name: "values", Operation: "DISTINCT_VALUES", Selector: &value}, - {Name: "", Operation: "COUNT"}, - }, - Pivots: []SemanticPivot{{ - Name: "labs", ColumnSelector: selector, ValueSelector: value, - Columns: []string{"weight", "height"}, Family: "observation", - }}, - }} - got, err := NormalizeShapingPlan(plan, testShapingDefaults()) - if err != nil { - t.Fatalf("NormalizeShapingPlan: %v", err) - } - if len(got.Aggregates) != 2 || got.Aggregates[0].Alias != "root.aggregate_2" || got.Aggregates[1].Alias != "root.values" { - t.Fatalf("unexpected deterministic aggregates: %#v", got.Aggregates) - } - if len(got.Pivots) != 1 || got.Pivots[0].Alias != "root.labs" { - t.Fatalf("unexpected pivots: %#v", got.Pivots) - } - if got.Pivots[0].Config.CardinalityPolicy != PivotRequestedColumns || got.Pivots[0].Config.MaxColumns != 2 { - t.Fatalf("unexpected pivot cardinality: %#v", got.Pivots[0].Config) - } -} - -func TestNormalizeShapingPlanUsesBoundedDiscovery(t *testing.T) { - key, _ := ParseSelector("code") - value, _ := ParseSelector("value") - plan := SemanticPlan{Root: SemanticNode{Alias: "root", ResourceType: "Observation", Pivots: []SemanticPivot{{ColumnSelector: key, ValueSelector: value}}}} - got, err := NormalizeShapingPlan(plan, testShapingDefaults()) - if err != nil { - t.Fatalf("NormalizeShapingPlan: %v", err) - } - if got.Pivots[0].Config.CardinalityPolicy != PivotBoundedDiscovery || got.Pivots[0].Config.MaxColumns != 64 { - t.Fatalf("unexpected discovery policy: %#v", got.Pivots[0].Config) - } -} - -func TestNormalizeShapingPlanRejectsBadRequests(t *testing.T) { - validDefaults := testShapingDefaults() - tests := []struct { - name string - plan SemanticPlan - defs ShapingDefaults - }{ - {"invalid defaults", SemanticPlan{Root: SemanticNode{Alias: "root", ResourceType: "Patient"}}, ShapingDefaults{}}, - {"missing node alias", SemanticPlan{Root: SemanticNode{ResourceType: "Patient"}}, validDefaults}, - {"duplicate node alias", SemanticPlan{Root: SemanticNode{Alias: "root", ResourceType: "Patient", Children: []SemanticNode{{Alias: "root", ResourceType: "Specimen", EdgeLabel: "subject"}}}}, validDefaults}, - {"unknown relationship", SemanticPlan{Root: SemanticNode{Alias: "root", ResourceType: "Patient", Children: []SemanticNode{{Alias: "child", ResourceType: "Specimen", EdgeLabel: "not-a-real-edge"}}}}, validDefaults}, - {"unsupported aggregate", SemanticPlan{Root: SemanticNode{Alias: "root", ResourceType: "Patient", Aggregates: []SemanticAggregate{{Operation: "MEDIAN"}}}}, validDefaults}, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - if _, err := NormalizeShapingPlan(test.plan, test.defs); err == nil { - t.Fatal("invalid shaping request unexpectedly succeeded") - } - }) - } -} - -func testShapingDefaults() ShapingDefaults { - return ShapingDefaults{ - NullPolicy: NullIgnore, PivotDuplicatePolicy: DuplicateDistinctArray, - SparsePivotPolicy: SparsePivotNull, MaxDiscoveredPivotCols: 64, - } -} diff --git a/internal/dataframe/shaping_test.go b/internal/dataframe/shaping_test.go deleted file mode 100644 index 9282781..0000000 --- a/internal/dataframe/shaping_test.go +++ /dev/null @@ -1,98 +0,0 @@ -package dataframe - -import "testing" - -func TestAggregateConfigValidate(t *testing.T) { - valid := []AggregateConfig{ - {Function: AggregateCount, NullPolicy: NullIgnore}, - {Function: AggregateCountDistinct, Input: "patient.id", NullPolicy: NullIgnore}, - {Function: AggregateExists, Input: "condition.id", NullPolicy: NullReject}, - {Function: AggregateDistinctValues, Input: "code", NullPolicy: NullInclude}, - {Function: AggregateMin, Input: "date", NullPolicy: NullIgnore}, - {Function: AggregateMax, Input: "date", NullPolicy: NullIgnore}, - } - for _, config := range valid { - if err := config.Validate(); err != nil { - t.Errorf("Validate(%#v): %v", config, err) - } - } - - invalid := []AggregateConfig{ - {}, - {Function: AggregateMin, NullPolicy: NullIgnore}, - {Function: AggregateCount, NullPolicy: "sometimes"}, - {Function: "median", Input: "value", NullPolicy: NullIgnore}, - } - for _, config := range invalid { - if err := config.Validate(); err == nil { - t.Errorf("invalid aggregate %#v unexpectedly succeeded", config) - } - } -} - -func TestPivotConfigRequestedColumns(t *testing.T) { - config := PivotConfig{ - Key: "observation.code", - Value: "observation.value", - DuplicatePolicy: DuplicateDistinctArray, - NullPolicy: NullIgnore, - CardinalityPolicy: PivotRequestedColumns, - SparsePolicy: SparsePivotNull, - RequestedColumns: []string{"height", "weight"}, - MaxColumns: 2, - } - if err := config.Validate(); err != nil { - t.Fatalf("valid requested-columns pivot: %v", err) - } - - config.RequestedColumns = nil - if err := config.Validate(); err == nil { - t.Fatal("requested-columns pivot without columns unexpectedly succeeded") - } -} - -func TestPivotConfigBoundedDiscovery(t *testing.T) { - config := PivotConfig{ - Key: "observation.code", - Value: "observation.value", - DuplicatePolicy: DuplicateReject, - NullPolicy: NullReject, - CardinalityPolicy: PivotBoundedDiscovery, - SparsePolicy: SparsePivotOmit, - MaxColumns: 100, - } - if err := config.Validate(); err != nil { - t.Fatalf("valid bounded-discovery pivot: %v", err) - } - - config.MaxColumns = 0 - if err := config.Validate(); err == nil { - t.Fatal("unbounded pivot discovery unexpectedly succeeded") - } -} - -func TestPivotConfigRejectsInvalidShape(t *testing.T) { - base := PivotConfig{ - Key: "code", - Value: "value", - DuplicatePolicy: DuplicateFirst, - NullPolicy: NullIgnore, - CardinalityPolicy: PivotRequestedColumns, - SparsePolicy: SparsePivotNull, - RequestedColumns: []string{"a"}, - } - tests := []PivotConfig{ - func() PivotConfig { c := base; c.Key = ""; return c }(), - func() PivotConfig { c := base; c.Value = " "; return c }(), - func() PivotConfig { c := base; c.DuplicatePolicy = "merge"; return c }(), - func() PivotConfig { c := base; c.SparsePolicy = "zero"; return c }(), - func() PivotConfig { c := base; c.RequestedColumns = []string{"a", "a"}; return c }(), - func() PivotConfig { c := base; c.RequestedColumns = []string{" "}; return c }(), - func() PivotConfig { c := base; c.MaxColumns = 1; c.RequestedColumns = []string{"a", "b"}; return c }(), - } - for _, config := range tests { - if err := config.Validate(); err == nil { - t.Errorf("invalid pivot %#v unexpectedly succeeded", config) - } - } -} diff --git a/internal/dataframe/storage_route.go b/internal/dataframe/storage_route.go index a6678fd..bccafcf 100644 --- a/internal/dataframe/storage_route.go +++ b/internal/dataframe/storage_route.go @@ -5,7 +5,7 @@ import ( "fmt" "strings" - "github.com/calypr/loom/internal/fhirschema" + "github.com/calypr/loom/fhirschema" ) // ErrUnsupportedStorageRoute identifies a FHIR relationship that is known to @@ -135,67 +135,3 @@ func formatRegexMatchHints(hints []string) string { } return strings.Join(quoted, ", ") } - -// validateGenericLoweredStorageRoutes closes the pre-lowered Builder path. -// Generic lowering itself emits these sets, but persisted or conformance -// callers can invoke Compile directly. The generic profile contains only a -// root-to-child chain of TRAVERSE sets, so source resource types can be -// derived without trusting caller-provided physical direction. -func validateGenericLoweredStorageRoutes(builder Builder) error { - if builder.PlanHint == nil || builder.PlanHint.Profile != "generic_fhir_graph" { - return nil - } - _, err := resolveGenericLoweredStorageRoutes(builder) - return err -} - -// resolveGenericLoweredStorageRoutes derives the immutable stored-edge route -// for every generic TRAVERSE set. Compile uses the result to emit the edge -// type discriminator in addition to the target node resourceType guard; this -// avoids trusting a persisted lowered Builder's requested direction. -func resolveGenericLoweredStorageRoutes(builder Builder) (map[string]storageRoute, error) { - if builder.PlanHint == nil || builder.PlanHint.Profile != "generic_fhir_graph" { - return nil, nil - } - - setResourceTypes := make(map[string]string, len(builder.Sets)) - routes := make(map[string]storageRoute, len(builder.Sets)) - for _, set := range builder.Sets { - switch strings.ToUpper(strings.TrimSpace(set.Kind)) { - case SetKindTraverse: - fromType := builder.RootResourceType - source := strings.TrimSpace(set.Source) - if source != "" && source != "root" { - var found bool - fromType, found = setResourceTypes[source] - if !found { - return nil, fmt.Errorf("set %q: %w: source set %q does not establish a generated resource type", set.Name, ErrUnsupportedStorageRoute, set.Source) - } - } - route, err := resolveStorageRoute(fromType, set.Label, set.ToResourceType) - if err != nil { - return nil, fmt.Errorf("set %q: %w", set.Name, err) - } - direction := strings.ToUpper(strings.TrimSpace(set.Direction)) - if direction != "" && direction != string(route.Direction) { - return nil, fmt.Errorf("set %q: %w: generic route direction must be %s, got %q", set.Name, ErrUnsupportedStorageRoute, route.Direction, set.Direction) - } - setResourceTypes[set.Name] = set.ToResourceType - routes[set.Name] = route - case SetKindFilter: - source := strings.TrimSpace(set.Source) - fromType, found := setResourceTypes[source] - if source == "root" { - fromType, found = builder.RootResourceType, true - } - if !found { - return nil, fmt.Errorf("set %q: %w: source set %q does not establish a generated resource type", set.Name, ErrUnsupportedStorageRoute, set.Source) - } - if targetType := strings.TrimSpace(set.MatchResourceType); targetType != "" { - fromType = targetType - } - setResourceTypes[set.Name] = fromType - } - } - return routes, nil -} diff --git a/internal/dataframe/storage_route_test.go b/internal/dataframe/storage_route_test.go deleted file mode 100644 index cf0342d..0000000 --- a/internal/dataframe/storage_route_test.go +++ /dev/null @@ -1,274 +0,0 @@ -package dataframe - -import ( - "errors" - "strings" - "testing" -) - -func TestResolveStorageRouteAcceptsGeneratedBuilderOrientation(t *testing.T) { - route, err := resolveStorageRoute("Patient", "subject_Patient", "Condition") - if err != nil { - t.Fatalf("resolveStorageRoute(Patient -> Condition): %v", err) - } - if route.Direction != PhysicalInbound { - t.Fatalf("route direction = %q, want %q", route.Direction, PhysicalInbound) - } - if route.targetEdgeTypeField() != "from_type" { - t.Fatalf("inbound target edge type field = %q, want from_type", route.targetEdgeTypeField()) - } - - planned, err := lowerGenericGraphQLBuilder(Builder{}, buildLogicalRequest(Builder{ - Project: "P1", - RootResourceType: "Patient", - Traversals: []TraversalStep{{ - Alias: "diagnosis", Label: "subject_Patient", ToResourceType: "Condition", - }}, - })) - if err != nil { - t.Fatalf("lowerGenericGraphQLBuilder: %v", err) - } - if len(planned.Sets) != 1 || planned.Sets[0].Direction != string(PhysicalInbound) { - t.Fatalf("generic sets = %#v, want one INBOUND stored route", planned.Sets) - } - compiled, err := Compile(planned, 5) - if err != nil { - t.Fatalf("Compile(generic builder): %v", err) - } - for _, required := range []string{ - "1..1 INBOUND root fhir_edge", - "__edge.project == @project", - "__node.project == @project", - "__edge.dataset_generation == @dataset_generation", - "__node.dataset_generation == @dataset_generation", - "auth_resource_path IN @auth_resource_paths", - "__edge.from_type == @", - "__node.resourceType == @", - } { - if !strings.Contains(compiled.Query, required) { - t.Fatalf("generic query does not retain %q:\n%s", required, compiled.Query) - } - } -} - -func TestGenericLoweredOutboundTraversalScopesLegacyRenderer(t *testing.T) { - compiled, err := Compile(Builder{ - Project: "P1", - DatasetGeneration: "generation-1", - AuthResourcePaths: []string{"/programs/p1"}, - RootResourceType: "ResearchSubject", - PlanHint: &PlanHint{Mode: "lowered", Profile: "generic_fhir_graph"}, - Fields: []FieldSelect{{Name: "id", Select: "id"}}, - Sets: []NamedSet{{ - Name: "study", Kind: SetKindTraverse, Label: "study", ToResourceType: "ResearchStudy", Direction: "OUTBOUND", - }}, - }, 5) - if err != nil { - t.Fatalf("Compile(generic outbound lowered builder): %v", err) - } - for _, required := range []string{ - "1..1 OUTBOUND root fhir_edge", - "__edge.project == @project", - "__node.project == @project", - "__edge.dataset_generation == @dataset_generation", - "__node.dataset_generation == @dataset_generation", - "__edge.to_type == @", - "__node.resourceType == @", - } { - if !strings.Contains(compiled.Query, required) { - t.Fatalf("legacy outbound traversal is missing %q:\n%s", required, compiled.Query) - } - } - assertBindVarValue(t, compiled.BindVars, "ResearchStudy") -} - -func TestGenericLoweredRequiredOutboundTraversalScopesTargetNode(t *testing.T) { - compiled, err := Compile(Builder{ - Project: "P1", - DatasetGeneration: "generation-1", - AuthResourcePaths: []string{"/programs/p1"}, - RootResourceType: "ResearchSubject", - PlanHint: &PlanHint{Mode: "lowered", Profile: "generic_fhir_graph"}, - RequiredTraversalMatches: []RequiredTraversalMatch{{ - Steps: []TraversalMatchStep{{Label: "study", ToResourceType: "ResearchStudy"}}, - }}, - }, 5) - if err != nil { - t.Fatalf("Compile(generic required outbound lowered builder): %v", err) - } - for _, required := range []string{ - "FOR __match_0_0, __match_edge_0_0 IN 1..1 OUTBOUND root fhir_edge", - "__match_edge_0_0.project == @project", - "__match_0_0.project == @project", - "__match_edge_0_0.dataset_generation == @dataset_generation", - "__match_0_0.dataset_generation == @dataset_generation", - "__match_edge_0_0.to_type == @", - "__match_0_0.resourceType == @", - } { - if !strings.Contains(compiled.Query, required) { - t.Fatalf("required outbound traversal is missing %q:\n%s", required, compiled.Query) - } - } - assertBindVarValue(t, compiled.BindVars, "ResearchStudy") -} - -func TestStorageRouteAcceptsProvenOutboundResearchSubjectStudy(t *testing.T) { - route, err := resolveStorageRoute("ResearchSubject", "study", "ResearchStudy") - if err != nil { - t.Fatalf("resolveStorageRoute(ResearchSubject -> ResearchStudy): %v", err) - } - if route.Direction != PhysicalOutbound { - t.Fatalf("route direction = %q, want %q", route.Direction, PhysicalOutbound) - } - if route.targetEdgeTypeField() != "to_type" { - t.Fatalf("outbound target edge type field = %q, want to_type", route.targetEdgeTypeField()) - } - - request := Builder{ - Project: "P1", - DatasetGeneration: "generation-1", - AuthResourcePaths: []string{"/programs/p1"}, - RootResourceType: "ResearchSubject", - Traversals: []TraversalStep{{ - Alias: "study", Label: "study", ToResourceType: "ResearchStudy", - }}, - } - compiled, err := CompileRequest(request, 5) - if err != nil { - t.Fatalf("CompileRequest(ResearchSubject -> ResearchStudy): %v", err) - } - for _, required := range []string{ - "1..1 OUTBOUND root @@traversal_1_edge_collection", - "edge_1.project == @project", - "node_1.project == @project", - "edge_1.dataset_generation == @dataset_generation", - "node_1.dataset_generation == @dataset_generation", - "auth_resource_path IN @auth_resource_paths", - "edge_1.label == @traversal_1_label", - "edge_1.to_type == @traversal_1_target_type", - "node_1.resourceType == @traversal_1_target_type", - } { - if !strings.Contains(compiled.Query, required) { - t.Fatalf("outbound query does not retain %q:\n%s", required, compiled.Query) - } - } - - explanation, err := ExplainCompilerRequest(request, 5) - if err != nil { - t.Fatalf("ExplainCompilerRequest(ResearchSubject -> ResearchStudy): %v", err) - } - if !explanation.GenericPhysicalPlan.Available || explanation.GenericPhysicalPlan.Plan == nil { - t.Fatalf("outbound generic physical plan = %#v", explanation.GenericPhysicalPlan) - } - var traversal *PhysicalTraversal - for _, operation := range explanation.GenericPhysicalPlan.Plan.Operations { - if operation.Kind == PhysicalTraversalOp { - traversal = operation.Traversal - break - } - } - if traversal == nil || traversal.Direction != PhysicalOutbound { - t.Fatalf("explained outbound traversal = %#v, want OUTBOUND", traversal) - } -} - -func TestStorageRouteRejectsGeneratedForwardFHIRReference(t *testing.T) { - _, err := resolveStorageRoute("Condition", "subject_Patient", "Patient") - if !errors.Is(err, ErrUnsupportedStorageRoute) { - t.Fatalf("resolveStorageRoute(Condition -> Patient) error = %v, want ErrUnsupportedStorageRoute", err) - } - - _, err = CompileRequest(Builder{ - Project: "P1", - RootResourceType: "Condition", - Traversals: []TraversalStep{{ - Alias: "patient", Label: "subject_Patient", ToResourceType: "Patient", - }}, - }, 5) - if !errors.Is(err, ErrUnsupportedStorageRoute) { - t.Fatalf("CompileRequest(forward route) error = %v, want ErrUnsupportedStorageRoute", err) - } -} - -func TestStorageRouteAppliesToNestedRequiredMatches(t *testing.T) { - _, err := Lower(Builder{ - Project: "P1", - RootResourceType: "Patient", - Traversals: []TraversalStep{{ - Alias: "specimen", Label: "subject_Patient", ToResourceType: "Specimen", - Traversals: []TraversalStep{{ - Alias: "patient", Label: "subject_Patient", ToResourceType: "Patient", MatchMode: TraversalMatchRequired, - }}, - }}, - }) - if !errors.Is(err, ErrUnsupportedStorageRoute) { - t.Fatalf("Lower(nested required forward route) error = %v, want ErrUnsupportedStorageRoute", err) - } -} - -func TestStorageRouteAppliesToGenericPhysicalPlansAndPreLoweredBuilders(t *testing.T) { - semantic, err := BuildSemanticPlan(Builder{ - Project: "P1", - RootResourceType: "Patient", - Traversals: []TraversalStep{{ - Alias: "diagnosis", Label: "subject_Patient", ToResourceType: "Condition", - }}, - }) - if err != nil { - t.Fatalf("BuildSemanticPlan(builder route): %v", err) - } - physical, err := BuildGenericPhysicalPlan(semantic) - if err != nil { - t.Fatalf("BuildGenericPhysicalPlan: %v", err) - } - var traversal *PhysicalTraversal - for _, operation := range physical.Operations { - if operation.Kind == PhysicalTraversalOp { - traversal = operation.Traversal - break - } - } - if traversal == nil || traversal.Direction != PhysicalInbound { - t.Fatalf("physical traversal = %#v, want INBOUND", traversal) - } - - _, err = Compile(Builder{ - Project: "P1", - RootResourceType: "Patient", - PlanHint: &PlanHint{Mode: "lowered", Profile: "generic_fhir_graph"}, - Sets: []NamedSet{{ - Name: "diagnosis", Kind: SetKindTraverse, Label: "subject_Patient", ToResourceType: "Condition", Direction: "OUTBOUND", - }}, - }, 1) - if !errors.Is(err, ErrUnsupportedStorageRoute) { - t.Fatalf("Compile(pre-lowered wrong direction) error = %v, want ErrUnsupportedStorageRoute", err) - } - - _, err = Compile(Builder{ - Project: "P1", - RootResourceType: "ResearchSubject", - PlanHint: &PlanHint{Mode: "lowered", Profile: "generic_fhir_graph"}, - Sets: []NamedSet{{ - Name: "study", Kind: SetKindTraverse, Label: "study", ToResourceType: "ResearchStudy", Direction: "INBOUND", - }}, - }, 1) - if !errors.Is(err, ErrUnsupportedStorageRoute) { - t.Fatalf("Compile(pre-lowered outbound route with INBOUND direction) error = %v, want ErrUnsupportedStorageRoute", err) - } -} - -func TestGenericStorageRoutePropagatesTypeThroughFilterSet(t *testing.T) { - _, err := Compile(Builder{ - Project: "P1", - RootResourceType: "Patient", - PlanHint: &PlanHint{Mode: "lowered", Profile: "generic_fhir_graph"}, - Sets: []NamedSet{ - {Name: "specimen", Kind: SetKindTraverse, Label: "subject_Patient", ToResourceType: "Specimen", Direction: "INBOUND"}, - {Name: "filtered_specimen", Kind: SetKindFilter, Source: "specimen", MatchResourceType: "Specimen"}, - {Name: "file", Kind: SetKindTraverse, Source: "filtered_specimen", Label: "subject_Specimen", ToResourceType: "DocumentReference", Direction: "INBOUND"}, - }, - }, 1) - if err != nil { - t.Fatalf("Compile(generic route through FILTER set): %v", err) - } -} diff --git a/internal/dataframe/validation.go b/internal/dataframe/validation.go index 61f3062..f6406c8 100644 --- a/internal/dataframe/validation.go +++ b/internal/dataframe/validation.go @@ -5,8 +5,8 @@ import ( "fmt" "strings" + "github.com/calypr/loom/fhirschema" "github.com/calypr/loom/internal/catalog" - "github.com/calypr/loom/internal/fhirschema" ) func (s *Service) validateBuilder(ctx context.Context, builder Builder) error { diff --git a/internal/dataframe/value_mode_test.go b/internal/dataframe/value_mode_test.go deleted file mode 100644 index a52b790..0000000 --- a/internal/dataframe/value_mode_test.go +++ /dev/null @@ -1,82 +0,0 @@ -package dataframe - -import ( - "strings" - "testing" -) - -func TestRootValueModesCompileToDistinctShapes(t *testing.T) { - for mode, want := range map[string]string{ - "FIRST": "FIRST(", - "ALL": "FOR __root", - "DISTINCT": "UNIQUE(", - } { - t.Run(mode, func(t *testing.T) { - compiled, err := CompileRequest(Builder{ - Project: "P1", - RootResourceType: "Patient", - Fields: []FieldSelect{{ - Name: "identifier", Select: "identifier[].value", ValueMode: mode, - }}, - }, 1) - if err != nil { - t.Fatal(err) - } - if !strings.Contains(compiled.Query, want) { - t.Fatalf("%s query missing %q:\n%s", mode, want, compiled.Query) - } - }) - } -} - -func TestGenericTraversalValueModesLowerToPhysicalOperations(t *testing.T) { - for mode, wantOperation := range map[string]string{ - "FIRST": DerivedOpFirstNonNull, - "ALL": DerivedOpAll, - "DISTINCT": DerivedOpUnique, - "AUTO": DerivedOpFirstNonNull, - } { - t.Run(mode, func(t *testing.T) { - planned, err := lowerGenericGraphQLBuilder(Builder{}, buildLogicalRequest(Builder{ - Project: "P1", RootResourceType: "Patient", - Traversals: []TraversalStep{{ - Label: "subject_Patient", ToResourceType: "Condition", Alias: "condition", - Fields: []FieldSelect{{Name: "code", Select: "code.coding[].display", ValueMode: mode}}, - }}, - })) - if err != nil { - t.Fatal(err) - } - if len(planned.DerivedFields) != 1 || planned.DerivedFields[0].Operation != wantOperation { - t.Fatalf("%s derived fields = %#v, want %s", mode, planned.DerivedFields, wantOperation) - } - }) - } -} - -func TestGenericFirstLikeTraversalSelectionSortsSourceSetByStableKey(t *testing.T) { - for _, mode := range []string{"FIRST", "AUTO"} { - t.Run(mode, func(t *testing.T) { - planned, err := Lower(Builder{ - Project: "P1", RootResourceType: "Specimen", - Traversals: []TraversalStep{{ - Label: "subject_Specimen", ToResourceType: "DocumentReference", Alias: "file", - Fields: []FieldSelect{{Name: "title", Select: "content[].attachment.title", ValueMode: mode}}, - }}, - }) - if err != nil { - t.Fatal(err) - } - if len(planned.Sets) != 1 || planned.Sets[0].SortField != "_key" { - t.Fatalf("%s traversal did not request a stable source order: %#v", mode, planned.Sets) - } - compiled, err := Compile(planned, 1) - if err != nil { - t.Fatal(err) - } - if !strings.Contains(compiled.Query, "SORT __item._key") { - t.Fatalf("%s traversal query does not sort its source set:\n%s", mode, compiled.Query) - } - }) - } -} diff --git a/internal/dataframebuilder/guided_discovery.go b/internal/dataframebuilder/guided_discovery.go deleted file mode 100644 index e8bd77e..0000000 --- a/internal/dataframebuilder/guided_discovery.go +++ /dev/null @@ -1,79 +0,0 @@ -package dataframebuilder - -import ( - "context" - "fmt" - "strings" - - "github.com/calypr/loom/internal/authscope" - "github.com/calypr/loom/internal/catalog" - "github.com/calypr/loom/internal/discovery" -) - -// GuidedDiscoveryRequest describes the small project/scope input needed to -// power the product's first questions. It intentionally has no FHIR paths, -// root choice, or AQL fragments: those are derived from the scoped catalog and -// generated FHIR metadata. -type GuidedDiscoveryRequest struct { - Project string - AuthResourcePaths []string -} - -// DiscoverGuided returns a safe, schema-backed capability snapshot for the -// guided dataframe flow. It composes the existing project- and -// auth-scope-aware catalog queries, then removes their implementation details -// behind opaque IDs in internal/discovery. It is not a public transport API -// yet; GraphQL/HTTP exposure remains deliberately unwired while generation -// selection is an internal service dependency. -func (s *Service) DiscoverGuided(ctx context.Context, req GuidedDiscoveryRequest) (discovery.Snapshot, error) { - project := strings.TrimSpace(req.Project) - if project == "" { - return discovery.Snapshot{}, fmt.Errorf("project is required") - } - - principal, _ := authscope.PrincipalFromContext(ctx) - if err := authorizeProject(principal, project, s.scopeResolver != nil); err != nil { - return discovery.Snapshot{}, err - } - generation, err := s.resolveActiveGeneration(ctx, project) - if err != nil { - return discovery.Snapshot{}, err - } - scope, err := s.resolveReadScopeForGeneration(ctx, principal, project, generation, req.AuthResourcePaths) - if err != nil { - return discovery.Snapshot{}, err - } - - fields, err := s.discoverFields(ctx, catalog.PopulatedFieldOptions{ - ConnectionOptions: s.connOpts, - Project: project, - DatasetGeneration: generation, - AuthResourcePathsUnrestricted: catalog.ExplicitAuthResourcePathsUnrestricted(scope.Unrestricted()), - AuthResourcePaths: cloneStrings(scope.AuthResourcePaths), - // An empty resource type is the existing catalog reader's all-types - // query. Discovery filters the result back through generated FHIR - // metadata before anything leaves this service. - ResourceType: "", - PivotOnly: false, - }) - if err != nil { - return discovery.Snapshot{}, err - } - relationships, err := s.discoverReferences(ctx, catalog.PopulatedReferenceOptions{ - ConnectionOptions: s.connOpts, - Project: project, - DatasetGeneration: generation, - AuthResourcePathsUnrestricted: catalog.ExplicitAuthResourcePathsUnrestricted(scope.Unrestricted()), - AuthResourcePaths: cloneStrings(scope.AuthResourcePaths), - Mode: catalog.TraversalModeStorage, - }) - if err != nil { - return discovery.Snapshot{}, err - } - - return discovery.BuildSnapshot(discovery.CatalogFacts{ - Project: project, - Fields: fields, - Relationships: relationships, - }) -} diff --git a/internal/dataframebuilder/guided_discovery_test.go b/internal/dataframebuilder/guided_discovery_test.go deleted file mode 100644 index d852fb4..0000000 --- a/internal/dataframebuilder/guided_discovery_test.go +++ /dev/null @@ -1,76 +0,0 @@ -package dataframebuilder - -import ( - "context" - "testing" - - "github.com/calypr/loom/internal/authscope" - "github.com/calypr/loom/internal/catalog" -) - -func TestServiceDiscoverGuidedUsesResolvedScopeAndExistingCatalogQueries(t *testing.T) { - var gotFieldOptions catalog.PopulatedFieldOptions - var gotReferenceOptions catalog.PopulatedReferenceOptions - service := NewService(Config{ - DiscoverFields: func(_ context.Context, options catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { - gotFieldOptions = options - return []catalog.PopulatedField{ - {Project: options.Project, ResourceType: "Patient", Path: "gender", Kind: "scalar", DocCount: 3, DistinctValues: []string{"female", "male"}}, - }, nil - }, - DiscoverReferences: func(_ context.Context, options catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { - gotReferenceOptions = options - return []catalog.PopulatedReference{ - {FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 3}, - }, nil - }, - }) - ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{ - Subject: "user-1", - Projects: []string{"project-a"}, - AuthResourcePaths: []string{"scope-a", "scope-b"}, - }) - - snapshot, err := service.DiscoverGuided(ctx, GuidedDiscoveryRequest{Project: " project-a "}) - if err != nil { - t.Fatalf("DiscoverGuided() error = %v", err) - } - if gotFieldOptions.Project != "project-a" || gotFieldOptions.ResourceType != "" || gotFieldOptions.PivotOnly { - t.Fatalf("field options = %+v, want all scoped catalog fields", gotFieldOptions) - } - if len(gotFieldOptions.AuthResourcePaths) != 2 || gotFieldOptions.AuthResourcePaths[0] != "scope-a" || gotFieldOptions.AuthResourcePaths[1] != "scope-b" { - t.Fatalf("field auth scope = %#v", gotFieldOptions.AuthResourcePaths) - } - if gotReferenceOptions.Project != "project-a" || gotReferenceOptions.Mode != catalog.TraversalModeStorage || gotReferenceOptions.FromType != "" || gotReferenceOptions.NodeType != "" { - t.Fatalf("reference options = %+v, want all scoped storage relationships", gotReferenceOptions) - } - if err := snapshot.Validate(); err != nil { - t.Fatalf("snapshot validation = %v", err) - } - if snapshot.Dataset.Project != "project-a" || len(snapshot.Columns) != 1 || len(snapshot.Relationships.Entries) != 1 || len(snapshot.Filters) != 1 { - t.Fatalf("guided snapshot = %+v", snapshot) - } -} - -func TestServiceDiscoverGuidedRejectsUnauthorizedProjectAndScope(t *testing.T) { - service := NewService(Config{ - DiscoverFields: func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { - return nil, nil - }, - DiscoverReferences: func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { - return nil, nil - }, - }) - ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{ - Subject: "user-1", - Projects: []string{"project-a"}, - AuthResourcePaths: []string{"scope-a"}, - }) - - if _, err := service.DiscoverGuided(ctx, GuidedDiscoveryRequest{Project: "project-b"}); err == nil { - t.Fatal("expected unauthorized project error") - } - if _, err := service.DiscoverGuided(ctx, GuidedDiscoveryRequest{Project: "project-a", AuthResourcePaths: []string{"scope-b"}}); err == nil { - t.Fatal("expected unauthorized auth scope error") - } -} diff --git a/internal/dataframebuilder/recipe.go b/internal/dataframebuilder/recipe.go deleted file mode 100644 index 0266861..0000000 --- a/internal/dataframebuilder/recipe.go +++ /dev/null @@ -1,146 +0,0 @@ -package dataframebuilder - -import ( - "context" - "fmt" - "strings" - - "github.com/calypr/loom/internal/authscope" - "github.com/calypr/loom/internal/catalog" - "github.com/calypr/loom/internal/dataframe" - "github.com/calypr/loom/internal/discovery" - "github.com/calypr/loom/internal/recipe" - "github.com/calypr/loom/internal/recipecompiler" -) - -// RecipeRequest is the scoped, internal invocation envelope for a product -// recipe. Recipe itself deliberately contains no authorization paths: they are -// resolved from the calling principal at execution time instead of becoming -// durable recipe data. -// -// Column and filter values in Recipe are opaque capability IDs. This request -// accepts neither FHIR selectors nor graph labels. -type RecipeRequest struct { - Recipe recipe.Recipe - AuthResourcePaths []string -} - -// RecipeRunRequest adds a bounded dataframe-service limit to RecipeRequest. -// A non-positive limit retains dataframe.Service's existing default behavior. -// Destination delivery is intentionally outside this type: RunRecipe evaluates -// rows for callers such as a preview, but does not create files or write to -// Elasticsearch. -type RecipeRunRequest struct { - Recipe recipe.Recipe - AuthResourcePaths []string - Limit int -} - -// PrepareRecipe resolves a product recipe against fresh catalog facts for the -// caller's current project and authorization scope. It never caches facts or -// treats an opaque capability ID as a FHIR path. The returned Builder carries -// the resolved scope so its subsequent dataframe execution uses the exact same -// scope that supplied the capabilities. -// -// The current recipe compiler supports root-only selections and filters. It -// receives all currently scoped catalog fields because recipe IDs are opaque; -// narrowing the catalog read based on an untrusted recipe ID would both leak -// implementation details and make stale IDs ambiguous. -func (s *Service) PrepareRecipe(ctx context.Context, req RecipeRequest) (recipecompiler.Plan, error) { - normalized, err := req.Recipe.Normalize() - if err != nil { - return recipecompiler.Plan{}, err - } - - project := strings.TrimSpace(normalized.Project) - if project == "" { - // Normalize currently guarantees this condition, but keep the service - // boundary closed if the recipe contract changes in the future. - return recipecompiler.Plan{}, fmt.Errorf("project is required") - } - - principal, _ := authscope.PrincipalFromContext(ctx) - if err := authorizeProject(principal, project, s.scopeResolver != nil); err != nil { - return recipecompiler.Plan{}, err - } - generation, err := s.resolveActiveGeneration(ctx, project) - if err != nil { - return recipecompiler.Plan{}, err - } - scope, err := s.resolveReadScopeForGeneration(ctx, principal, project, generation, req.AuthResourcePaths) - if err != nil { - return recipecompiler.Plan{}, err - } - - fields, err := s.discoverFields(ctx, catalog.PopulatedFieldOptions{ - ConnectionOptions: s.connOpts, - Project: project, - DatasetGeneration: generation, - AuthResourcePathsUnrestricted: catalog.ExplicitAuthResourcePathsUnrestricted(scope.Unrestricted()), - AuthResourcePaths: cloneStrings(scope.AuthResourcePaths), - // Empty ResourceType is the existing catalog reader's all-types query. - // recipecompiler resolves the chosen opaque IDs against this one fresh, - // scope-constrained fact set. - ResourceType: "", - PivotOnly: false, - }) - if err != nil { - return recipecompiler.Plan{}, err - } - - plan, err := recipecompiler.Build(normalized, discovery.CatalogFacts{ - Project: project, - Fields: fields, - }) - if err != nil { - return recipecompiler.Plan{}, err - } - - // recipecompiler intentionally does not own authorization. Copy rather - // than aliasing the resolver's result so callers cannot mutate a prepared - // plan by retaining the request or resolver-owned slice. - if len(scope.AuthResourcePaths) == 0 { - plan.Builder.AuthResourcePaths = nil - } else { - plan.Builder.AuthResourcePaths = append([]string(nil), scope.AuthResourcePaths...) - } - plan.Builder.DatasetGeneration = generation - plan.Builder.AuthScopeMode = scope.Mode - return plan, nil -} - -// RunRecipe prepares fresh authorized facts and evaluates the resulting -// root-only dataframe plan through dataframe.Service. It is an execution -// primitive for preview-like callers; Recipe.Destination is validated as -// product intent but no export or Elasticsearch delivery occurs here. -func (s *Service) RunRecipe(ctx context.Context, req RecipeRunRequest) (*dataframe.Result, error) { - plan, err := s.PrepareRecipe(ctx, RecipeRequest{ - Recipe: req.Recipe, - AuthResourcePaths: req.AuthResourcePaths, - }) - if err != nil { - return nil, err - } - return s.dataframes.Run(ctx, dataframe.RunRequest{ - Builder: plan.Builder, - Limit: req.Limit, - }) -} - -// StreamRecipe prepares fresh authorized facts and forwards rows through the -// dataframe row-stream. As with RunRecipe, this does not implement any recipe -// destination sink; NDJSON, CSV, and Elasticsearch remain consumers to add on -// top of this shared stream. -func (s *Service) StreamRecipe(ctx context.Context, req RecipeRunRequest, visit func(map[string]any) error) (dataframe.StreamResult, error) { - plan, err := s.PrepareRecipe(ctx, RecipeRequest{ - Recipe: req.Recipe, - AuthResourcePaths: req.AuthResourcePaths, - }) - if err != nil { - return dataframe.StreamResult{}, err - } - return s.dataframes.Stream(ctx, dataframe.RunRequest{ - Builder: plan.Builder, - Limit: req.Limit, - }, visit) -} diff --git a/internal/dataframebuilder/recipe_test.go b/internal/dataframebuilder/recipe_test.go deleted file mode 100644 index 73f53ff..0000000 --- a/internal/dataframebuilder/recipe_test.go +++ /dev/null @@ -1,308 +0,0 @@ -package dataframebuilder - -import ( - "context" - "errors" - "reflect" - "testing" - - "github.com/calypr/loom/internal/authscope" - "github.com/calypr/loom/internal/catalog" - "github.com/calypr/loom/internal/dataframe" - "github.com/calypr/loom/internal/discovery" - "github.com/calypr/loom/internal/recipe" - "github.com/calypr/loom/internal/recipecompiler" -) - -func TestServicePrepareRecipeUsesFreshScopedCatalogFacts(t *testing.T) { - facts := recipeServiceFacts() - genderID := recipeServiceCapabilityID(t, facts, "Patient", "gender") - requestedPaths := []string{"scope-b"} - var fieldOptions []catalog.PopulatedFieldOptions - service := NewService(Config{ - DiscoverFields: func(_ context.Context, options catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { - fieldOptions = append(fieldOptions, options) - return append([]catalog.PopulatedField(nil), facts.Fields...), nil - }, - }) - ctx := recipeServiceContext() - - plan, err := service.PrepareRecipe(ctx, RecipeRequest{ - Recipe: recipePreview(genderID), - AuthResourcePaths: requestedPaths, - }) - if err != nil { - t.Fatalf("PrepareRecipe() error = %v", err) - } - if len(fieldOptions) != 1 { - t.Fatalf("discover fields calls = %d, want 1", len(fieldOptions)) - } - if got := fieldOptions[0]; got.Project != "project-a" || got.ResourceType != "" || got.PivotOnly { - t.Fatalf("catalog options = %+v, want normalized all-types non-pivot read", got) - } - if got, want := fieldOptions[0].AuthResourcePaths, []string{"scope-b"}; !reflect.DeepEqual(got, want) { - t.Fatalf("catalog scope = %#v, want %#v", got, want) - } - if plan.Recipe.Project != "project-a" || plan.Builder.Project != "project-a" { - t.Fatalf("normalized project = recipe %q builder %q", plan.Recipe.Project, plan.Builder.Project) - } - if plan.Builder.RootResourceType != "Patient" || plan.Builder.RowGrain != dataframe.RowGrainPatient { - t.Fatalf("root-only recipe builder = %+v", plan.Builder) - } - if got, want := plan.Builder.AuthResourcePaths, []string{"scope-b"}; !reflect.DeepEqual(got, want) { - t.Fatalf("prepared builder scope = %#v, want %#v", got, want) - } - if len(plan.Builder.Fields) != 1 || plan.Builder.Fields[0].FieldRef != genderID || plan.Builder.Fields[0].Select != "gender" { - t.Fatalf("opaque root field did not resolve through fresh facts: %#v", plan.Builder.Fields) - } - - // Neither the request nor a resolver-owned result can mutate the prepared - // builder's authorization scope after preparation. - requestedPaths[0] = "changed-after-prepare" - if got := plan.Builder.AuthResourcePaths[0]; got != "scope-b" { - t.Fatalf("prepared builder aliases request auth scope: %q", got) - } -} - -func TestServiceRunAndStreamRecipeUsePreparedScopeWithoutDatabase(t *testing.T) { - facts := recipeServiceFacts() - genderID := recipeServiceCapabilityID(t, facts, "Patient", "gender") - var prepareOptions []catalog.PopulatedFieldOptions - var dataframeOptions []catalog.PopulatedFieldOptions - var executionScopes [][]string - - dataframes := dataframe.NewService(dataframe.ServiceConfig{ - DiscoverFields: func(_ context.Context, options catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { - dataframeOptions = append(dataframeOptions, options) - if options.PivotOnly { - return []catalog.PopulatedField{}, nil - } - return []catalog.PopulatedField{facts.Fields[0]}, nil // Patient.gender - }, - ExecuteRows: func(_ context.Context, _ dataframe.ExecuteQueryOptions, _ string, bindVars map[string]any, visit func(map[string]any) error) error { - paths, ok := bindVars["auth_resource_paths"].([]string) - if !ok { - t.Fatalf("auth_resource_paths bind type = %T, want []string", bindVars["auth_resource_paths"]) - } - executionScopes = append(executionScopes, append([]string(nil), paths...)) - return visit(map[string]any{"_key": "patient-1", "gender": "female"}) - }, - }) - service := NewService(Config{ - DiscoverFields: func(_ context.Context, options catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { - prepareOptions = append(prepareOptions, options) - return append([]catalog.PopulatedField(nil), facts.Fields...), nil - }, - Dataframes: dataframes, - }) - ctx := recipeServiceContext() - req := RecipeRunRequest{ - Recipe: recipePreview(genderID), - AuthResourcePaths: []string{"scope-b"}, - Limit: 7, - } - - result, err := service.RunRecipe(ctx, req) - if err != nil { - t.Fatalf("RunRecipe() error = %v", err) - } - if result.RowCount != 1 || len(result.Rows) != 1 || result.Rows[0]["gender"] != "female" { - t.Fatalf("RunRecipe result = %#v", result) - } - - streamedRows := 0 - streamed, err := service.StreamRecipe(ctx, req, func(row map[string]any) error { - streamedRows++ - if row["_key"] != "patient-1" || row["gender"] != "female" { - t.Fatalf("streamed row = %#v", row) - } - return nil - }) - if err != nil { - t.Fatalf("StreamRecipe() error = %v", err) - } - if streamed.RowCount != 1 || streamedRows != 1 { - t.Fatalf("StreamRecipe counts = result %d visitor %d", streamed.RowCount, streamedRows) - } - - if len(prepareOptions) != 2 { - t.Fatalf("fresh recipe catalog reads = %d, want one per run", len(prepareOptions)) - } - for _, options := range prepareOptions { - if options.ResourceType != "" || options.PivotOnly || !reflect.DeepEqual(options.AuthResourcePaths, []string{"scope-b"}) { - t.Fatalf("recipe catalog options = %+v", options) - } - } - if len(dataframeOptions) != 6 { // validation fields/pivots plus pivot expansion for Run and Stream - t.Fatalf("dataframe catalog reads = %d, want 6", len(dataframeOptions)) - } - for _, options := range dataframeOptions { - if options.ResourceType != "Patient" || !reflect.DeepEqual(options.AuthResourcePaths, []string{"scope-b"}) { - t.Fatalf("dataframe catalog options = %+v", options) - } - } - if got, want := executionScopes, [][]string{{"scope-b"}, {"scope-b"}}; !reflect.DeepEqual(got, want) { - t.Fatalf("query execution scopes = %#v, want %#v", got, want) - } -} - -func TestServicePrepareRecipeRejectsStaleRelatedAndRawCapabilities(t *testing.T) { - facts := recipeServiceFacts() - genderID := recipeServiceCapabilityID(t, facts, "Patient", "gender") - birthDateID := recipeServiceCapabilityID(t, facts, "Patient", "birthDate") - observationID := recipeServiceCapabilityID(t, facts, "Observation", "valueInteger") - - tests := []struct { - name string - fields []catalog.PopulatedField - recipe recipe.Recipe - want error - }{ - { - name: "stale opaque capability", - fields: []catalog.PopulatedField{facts.Fields[1]}, // Patient.birthDate, no longer gender - recipe: recipePreview(genderID), - want: recipecompiler.ErrColumnCapabilityUnavailable, - }, - { - name: "related root capability", - fields: facts.Fields, - recipe: recipePreview(genderID, observationID), - want: recipecompiler.ErrRelatedResource, - }, - { - name: "raw FHIR path is not a capability", - fields: facts.Fields, - recipe: recipePreview("gender"), - want: recipecompiler.ErrColumnCapabilityUnavailable, - }, - { - name: "unknown opaque-looking capability", - fields: facts.Fields, - recipe: recipePreview("col_0000000000000000000000000000000000000000000000000000000000000000"), - want: recipecompiler.ErrColumnCapabilityUnavailable, - }, - { - name: "fresh root capability remains accepted", - fields: facts.Fields, - recipe: recipePreview(birthDateID), - want: nil, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - service := NewService(Config{ - DiscoverFields: func(_ context.Context, _ catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { - return append([]catalog.PopulatedField(nil), test.fields...), nil - }, - }) - plan, err := service.PrepareRecipe(recipeServiceContext(), RecipeRequest{Recipe: test.recipe}) - if test.want == nil { - if err != nil { - t.Fatalf("PrepareRecipe() error = %v", err) - } - if len(plan.Builder.Fields) != 1 || plan.Builder.Fields[0].Select != "birthDate" { - t.Fatalf("fresh opaque root plan = %+v", plan.Builder) - } - return - } - if !errors.Is(err, test.want) { - t.Fatalf("PrepareRecipe() error = %v, want %v", err, test.want) - } - if len(plan.Builder.Fields) != 0 || len(plan.Builder.Filters) != 0 { - t.Fatalf("failed capability resolution returned builder = %+v", plan.Builder) - } - }) - } -} - -func TestServicePrepareRecipeRejectsUnauthorizedScopeBeforeCatalogRead(t *testing.T) { - facts := recipeServiceFacts() - genderID := recipeServiceCapabilityID(t, facts, "Patient", "gender") - called := false - service := NewService(Config{ - DiscoverFields: func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { - called = true - return facts.Fields, nil - }, - }) - ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{ - Projects: []string{"project-a"}, - AuthResourcePaths: []string{"scope-a"}, - }) - - _, err := service.PrepareRecipe(ctx, RecipeRequest{ - Recipe: recipePreview(genderID), - AuthResourcePaths: []string{"scope-b"}, - }) - if err == nil { - t.Fatal("expected unauthorized scope error") - } - if called { - t.Fatal("catalog read occurred before scope authorization") - } -} - -func recipeServiceFacts() discovery.CatalogFacts { - return discovery.CatalogFacts{ - Project: "project-a", - Fields: []catalog.PopulatedField{ - {Project: "project-a", ResourceType: "Patient", Path: "gender", Kind: "scalar", DocCount: 3, DistinctValues: []string{"female", "male"}}, - {Project: "project-a", ResourceType: "Patient", Path: "birthDate", Kind: "scalar", DocCount: 3, DistinctValues: []string{"1970-01-01", "2000-12-31"}}, - {Project: "project-a", ResourceType: "Observation", Path: "valueInteger", Kind: "scalar", DocCount: 2, DistinctValues: []string{"12", "13"}}, - }, - } -} - -func recipeServiceCapabilityID(t *testing.T, facts discovery.CatalogFacts, resourceType string, canonicalPath string) string { - t.Helper() - snapshot, err := discovery.BuildSnapshot(facts) - if err != nil { - t.Fatalf("BuildSnapshot() error = %v", err) - } - resolver, err := discovery.NewCapabilityResolver(facts) - if err != nil { - t.Fatalf("NewCapabilityResolver() error = %v", err) - } - for _, column := range snapshot.Columns { - resolved, err := resolver.ResolveColumn(column.ID) - if err != nil { - t.Fatalf("ResolveColumn(%q) error = %v", column.ID, err) - } - if resolved.ResourceType == resourceType && resolved.CanonicalPath == canonicalPath { - return string(column.ID) - } - } - t.Fatalf("no opaque capability for %s.%s", resourceType, canonicalPath) - return "" -} - -func recipePreview(columnIDs ...string) recipe.Recipe { - columns := make([]recipe.ColumnSelection, 0, len(columnIDs)) - for index, id := range columnIDs { - name := "column" - if index == 0 { - name = "gender" - } - columns = append(columns, recipe.ColumnSelection{ID: id, OutputName: name}) - } - return recipe.Recipe{ - Version: recipe.VersionV1, - Template: recipe.TemplatePatientCohort, - TemplateVersion: 1, - Project: " project-a ", - GenerationPolicy: recipe.GenerationLatest, - Grain: recipe.GrainPatient, - Columns: columns, - Destination: recipe.Destination{Type: recipe.DestinationPreview}, - } -} - -func recipeServiceContext() context.Context { - return authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{ - Subject: "recipe-user", - Projects: []string{"project-a"}, - AuthResourcePaths: []string{"scope-a", "scope-b"}, - }) -} diff --git a/internal/dataframeexport/doc.go b/internal/dataframeexport/doc.go deleted file mode 100644 index 089c8b8..0000000 --- a/internal/dataframeexport/doc.go +++ /dev/null @@ -1,16 +0,0 @@ -// Package dataframeexport connects validated dataframe execution to the -// row-only export encoders. -// -// It deliberately owns neither dataframe compilation nor artifact storage, -// jobs, delivery transports, or destination-specific behavior. A RowStream -// calls its Runner for every invocation. With a *dataframe.Service, the -// RunRequest is therefore catalog- and authorization-validated as part of -// each execution; this package neither caches that validation nor collects -// result rows. -// -// Inferred CSV columns require two executions: one to discover the column -// union and one to write rows. Those executions must observe the same logical -// dataframe and ordering, which requires an externally stable dataset -// generation or snapshot. Loom does not provide that generation/snapshot -// contract yet. Supplying explicit CSV columns uses exactly one execution. -package dataframeexport diff --git a/internal/dataframeexport/stream.go b/internal/dataframeexport/stream.go deleted file mode 100644 index 41ccfdc..0000000 --- a/internal/dataframeexport/stream.go +++ /dev/null @@ -1,65 +0,0 @@ -package dataframeexport - -import ( - "context" - "errors" - "fmt" - "io" - - "github.com/calypr/loom/internal/dataframe" - "github.com/calypr/loom/internal/export" -) - -var errRunnerRequired = errors.New("dataframe stream runner is required") - -// Runner is the narrow dataframe execution boundary needed for export. It is -// satisfied by *dataframe.Service. Keeping it small lets callers retain the -// dataframe service's existing validation, authorization, and streaming -// behavior without coupling export code to service construction. -type Runner interface { - Stream(context.Context, dataframe.RunRequest, func(map[string]any) error) (dataframe.StreamResult, error) -} - -// NewRowStream creates an export.RowStream backed by runner for request. The -// request is passed unchanged to every invocation, and no rows are buffered or -// copied by this adapter. A dataframe.Service validates the request when each -// stream invocation begins. -// -// The returned stream preserves a runner error and a row-visitor error without -// wrapping either. It also checks cancellation before invoking the runner and -// after a successful invocation. This matters because inferred CSV executes -// the stream twice; callers need an externally stable dataset generation or -// snapshot for that mode, which Loom does not provide yet. -func NewRowStream(runner Runner, request dataframe.RunRequest) (export.RowStream, error) { - if runner == nil { - return nil, errRunnerRequired - } - - return func(ctx context.Context, visit export.RowVisitor) error { - if visit == nil { - return fmt.Errorf("export row visitor is required") - } - if err := ctx.Err(); err != nil { - return err - } - - _, err := runner.Stream(ctx, request, visit) - if err != nil { - return err - } - return ctx.Err() - }, nil -} - -// EncodeCSV writes CSV rows from request using the existing export encoder. -// Explicit options.Columns executes the dataframe request once. Omitting -// columns executes it twice (discovery, then writing), so it is safe only when -// an external caller guarantees a stable dataset generation or snapshot; Loom -// does not provide that contract yet. -func EncodeCSV(ctx context.Context, dst io.Writer, options export.CSVOptions, runner Runner, request dataframe.RunRequest) (export.Result, error) { - stream, err := NewRowStream(runner, request) - if err != nil { - return export.Result{}, err - } - return export.EncodeCSV(ctx, dst, options, stream) -} diff --git a/internal/dataframeexport/stream_test.go b/internal/dataframeexport/stream_test.go deleted file mode 100644 index 114ac3c..0000000 --- a/internal/dataframeexport/stream_test.go +++ /dev/null @@ -1,176 +0,0 @@ -package dataframeexport - -import ( - "bytes" - "context" - "errors" - "reflect" - "testing" - - "github.com/calypr/loom/internal/dataframe" - "github.com/calypr/loom/internal/export" -) - -func TestNewRowStreamForwardsRowsAndRequest(t *testing.T) { - request := dataframe.RunRequest{ - Builder: dataframe.Builder{Project: "project-a", RootResourceType: "Patient"}, - Limit: 9, - } - runner := &fakeRunner{rows: []map[string]any{ - {"patient_id": "p1", "status": "active"}, - {"patient_id": "p2", "status": "inactive"}, - }} - stream, err := NewRowStream(runner, request) - if err != nil { - t.Fatalf("NewRowStream() error = %v", err) - } - - var got []map[string]any - err = stream(context.Background(), func(row map[string]any) error { - got = append(got, row) - return nil - }) - if err != nil { - t.Fatalf("RowStream() error = %v", err) - } - if !reflect.DeepEqual(got, runner.rows) { - t.Fatalf("forwarded rows = %#v, want %#v", got, runner.rows) - } - if runner.calls != 1 { - t.Fatalf("runner calls = %d, want 1", runner.calls) - } - if !reflect.DeepEqual(runner.requests, []dataframe.RunRequest{request}) { - t.Fatalf("runner requests = %#v, want %#v", runner.requests, []dataframe.RunRequest{request}) - } -} - -func TestNewRowStreamPreservesRunnerAndVisitorErrors(t *testing.T) { - t.Run("runner", func(t *testing.T) { - runnerErr := errors.New("runner stopped") - stream, err := NewRowStream(&fakeRunner{err: runnerErr}, dataframe.RunRequest{}) - if err != nil { - t.Fatalf("NewRowStream() error = %v", err) - } - if err := stream(context.Background(), func(map[string]any) error { return nil }); !errors.Is(err, runnerErr) { - t.Fatalf("RowStream() error = %v, want runner error", err) - } - }) - - t.Run("visitor", func(t *testing.T) { - visitorErr := errors.New("stop after first row") - stream, err := NewRowStream(&fakeRunner{rows: []map[string]any{{"id": "one"}}}, dataframe.RunRequest{}) - if err != nil { - t.Fatalf("NewRowStream() error = %v", err) - } - if err := stream(context.Background(), func(map[string]any) error { return visitorErr }); !errors.Is(err, visitorErr) { - t.Fatalf("RowStream() error = %v, want visitor error", err) - } - }) -} - -func TestNewRowStreamPreservesCanceledContextWithoutCallingRunner(t *testing.T) { - runner := &fakeRunner{rows: []map[string]any{{"id": "one"}}} - stream, err := NewRowStream(runner, dataframe.RunRequest{}) - if err != nil { - t.Fatalf("NewRowStream() error = %v", err) - } - ctx, cancel := context.WithCancel(context.Background()) - cancel() - - err = stream(ctx, func(map[string]any) error { return nil }) - if !errors.Is(err, context.Canceled) { - t.Fatalf("RowStream() error = %v, want context.Canceled", err) - } - if runner.calls != 0 { - t.Fatalf("runner calls = %d, want 0 after cancellation", runner.calls) - } -} - -func TestEncodeCSVWithExplicitColumnsRunsOneDataframeStream(t *testing.T) { - request := dataframe.RunRequest{Builder: dataframe.Builder{Project: "project-a"}, Limit: 2} - runner := &fakeRunner{rows: []map[string]any{ - {"patient_id": "p1", "status": "active"}, - {"patient_id": "p2", "status": "inactive"}, - }} - var output bytes.Buffer - - result, err := EncodeCSV(context.Background(), &output, export.CSVOptions{Columns: []string{"patient_id", "status"}}, runner, request) - if err != nil { - t.Fatalf("EncodeCSV() error = %v", err) - } - if runner.calls != 1 { - t.Fatalf("runner calls = %d, want one explicit-schema pass", runner.calls) - } - if result.Rows != 2 { - t.Fatalf("rows = %d, want 2", result.Rows) - } - if got, want := output.String(), "patient_id,status\np1,active\np2,inactive\n"; got != want { - t.Fatalf("CSV = %q, want %q", got, want) - } - if !reflect.DeepEqual(runner.requests, []dataframe.RunRequest{request}) { - t.Fatalf("runner requests = %#v, want one original request", runner.requests) - } -} - -func TestEncodeCSVWithInferredColumnsReplaysDataframeStream(t *testing.T) { - request := dataframe.RunRequest{Builder: dataframe.Builder{Project: "project-a"}, Limit: 2} - runner := &fakeRunner{rows: []map[string]any{ - {"patient_id": "p1", "status": "active"}, - {"patient_id": "p2", "status": "inactive"}, - }} - var output bytes.Buffer - - result, err := EncodeCSV(context.Background(), &output, export.CSVOptions{}, runner, request) - if err != nil { - t.Fatalf("EncodeCSV() error = %v", err) - } - if runner.calls != 2 { - t.Fatalf("runner calls = %d, want discovery and writing passes", runner.calls) - } - if result.Rows != 2 { - t.Fatalf("rows = %d, want 2 from the writing pass", result.Rows) - } - if got, want := output.String(), "patient_id,status\np1,active\np2,inactive\n"; got != want { - t.Fatalf("CSV = %q, want %q", got, want) - } - wantRequests := []dataframe.RunRequest{request, request} - if !reflect.DeepEqual(runner.requests, wantRequests) { - t.Fatalf("runner requests = %#v, want %#v", runner.requests, wantRequests) - } -} - -func TestNewRowStreamRejectsNilRunner(t *testing.T) { - stream, err := NewRowStream(nil, dataframe.RunRequest{}) - if err == nil { - t.Fatal("NewRowStream() error = nil, want runner-required error") - } - if stream != nil { - t.Fatalf("NewRowStream() stream = %v, want nil", stream) - } -} - -type fakeRunner struct { - rows []map[string]any - err error - calls int - requests []dataframe.RunRequest -} - -func (r *fakeRunner) Stream(ctx context.Context, request dataframe.RunRequest, visit func(map[string]any) error) (dataframe.StreamResult, error) { - r.calls++ - r.requests = append(r.requests, request) - var count int - for _, row := range r.rows { - if err := ctx.Err(); err != nil { - return dataframe.StreamResult{RowCount: count}, err - } - if err := visit(row); err != nil { - return dataframe.StreamResult{RowCount: count}, err - } - count++ - } - if r.err != nil { - return dataframe.StreamResult{RowCount: count}, r.err - } - return dataframe.StreamResult{RowCount: count}, nil -} diff --git a/internal/dataset/active.go b/internal/dataset/active.go index 7694b70..252653f 100644 --- a/internal/dataset/active.go +++ b/internal/dataset/active.go @@ -26,7 +26,7 @@ func ActiveGenerationFor(manifest Manifest) (ActiveGeneration, error) { } // Validate checks only the reference's key representation. Read adapters must -// call ResolveActive against their persisted manifest set to verify readiness. +// verify readiness against their persisted manifest record. func (a ActiveGeneration) Validate() error { if err := a.Dataset.Validate(); err != nil { return fmt.Errorf("%w: %w", ErrInvalidActiveGeneration, err) @@ -34,37 +34,6 @@ func (a ActiveGeneration) Validate() error { return nil } -// ResolveActive returns the single READY manifest named by active. It rejects -// missing, duplicate, failed, loading, and superseded matches, which prevents -// a caller from silently reading a different generation. -func ResolveActive(active ActiveGeneration, manifests []Manifest) (Manifest, error) { - if err := active.Validate(); err != nil { - return Manifest{}, err - } - - var matched *Manifest - for index, manifest := range manifests { - if !manifest.Dataset.Equal(active.Dataset) { - continue - } - if err := manifest.Validate(); err != nil { - return Manifest{}, fmt.Errorf("%w: matching manifest at index %d: %w", ErrInvalidActiveGeneration, index, err) - } - if matched != nil { - return Manifest{}, fmt.Errorf("%w: multiple manifests match %s/%s", ErrInvalidActiveGeneration, active.Dataset.Project, active.Dataset.Generation) - } - copy := manifest.Clone() - matched = © - } - if matched == nil { - return Manifest{}, fmt.Errorf("%w: %s/%s was not found", ErrInvalidActiveGeneration, active.Dataset.Project, active.Dataset.Generation) - } - if matched.State != ManifestStateReady { - return Manifest{}, fmt.Errorf("%w: %s/%s is %s", ErrGenerationNotReady, active.Dataset.Project, active.Dataset.Generation, matched.State) - } - return matched.Clone(), nil -} - // ActivationPlan is a persistence-neutral description of an active-generation // switch. A storage adapter must atomically persist Active and, when Previous // is non-nil, supersede that previous manifest in its own transaction. diff --git a/internal/dataset/active_test.go b/internal/dataset/active_test.go index a2126a7..71d8a72 100644 --- a/internal/dataset/active_test.go +++ b/internal/dataset/active_test.go @@ -1,7 +1,6 @@ package dataset import ( - "bytes" "encoding/json" "errors" "testing" @@ -10,18 +9,9 @@ import ( func TestActiveGenerationResolutionAndActivationPlan(t *testing.T) { previous := readyManifest(t, "project-a", "generation-old") candidate := readyManifest(t, "project-a", "generation-new") - active, err := ActiveGenerationFor(candidate) - if err != nil { + if _, err := ActiveGenerationFor(candidate); err != nil { t.Fatalf("ActiveGenerationFor(candidate): %v", err) } - resolved, err := ResolveActive(active, []Manifest{previous, candidate}) - if err != nil { - t.Fatalf("ResolveActive: %v", err) - } - if !resolved.Dataset.Equal(candidate.Dataset) { - t.Fatalf("ResolveActive dataset = %#v, want %#v", resolved.Dataset, candidate.Dataset) - } - plan, err := PlanActivation(&previous, candidate) if err != nil { t.Fatalf("PlanActivation: %v", err) @@ -68,72 +58,3 @@ func TestActiveGenerationResolutionAndActivationPlan(t *testing.T) { t.Fatalf("PlanActivation(FAILED candidate) error = %v, want ErrGenerationNotReady", err) } } - -func TestResolveActiveRejectsMissingDuplicateAndNonReadyManifests(t *testing.T) { - ready := readyManifest(t, "project-a", "generation-ready") - active, err := ActiveGenerationFor(ready) - if err != nil { - t.Fatal(err) - } - if _, err := ResolveActive(active, nil); !errors.Is(err, ErrInvalidActiveGeneration) { - t.Fatalf("ResolveActive(missing) error = %v, want ErrInvalidActiveGeneration", err) - } - if _, err := ResolveActive(active, []Manifest{ready, ready.Clone()}); !errors.Is(err, ErrInvalidActiveGeneration) { - t.Fatalf("ResolveActive(duplicate) error = %v, want ErrInvalidActiveGeneration", err) - } - - failed := failedManifest(t, "project-a", "generation-ready") - if _, err := ResolveActive(active, []Manifest{failed}); !errors.Is(err, ErrGenerationNotReady) { - t.Fatalf("ResolveActive(FAILED matching generation) error = %v, want ErrGenerationNotReady", err) - } - if _, err := ActiveGenerationFor(failed); !errors.Is(err, ErrGenerationNotReady) { - t.Fatalf("ActiveGenerationFor(FAILED) error = %v, want ErrGenerationNotReady", err) - } -} - -func TestReadBindingPinsReadyGenerationAndScope(t *testing.T) { - ready := readyManifest(t, "project-a", "generation-ready") - active, err := ActiveGenerationFor(ready) - if err != nil { - t.Fatal(err) - } - scope, err := RestrictedAuthScopeFingerprint([]string{"project-a-scope"}) - if err != nil { - t.Fatal(err) - } - binding, err := BindActive(active, ready, scope) - if err != nil { - t.Fatalf("BindActive: %v", err) - } - if !binding.Dataset().Equal(ready.Dataset) || !binding.AuthScopeFingerprint().Equal(scope) { - t.Fatalf("binding = %#v, want generation/scope from ready manifest", binding) - } - - encoded, err := json.Marshal(binding) - if err != nil { - t.Fatalf("json.Marshal(ReadBinding): %v", err) - } - if bytes.Contains(encoded, []byte("project-a-scope")) { - t.Fatalf("ReadBinding exposed raw scope path: %s", encoded) - } - var decoded ReadBinding - if err := json.Unmarshal(encoded, &decoded); err != nil { - t.Fatalf("json.Unmarshal(ReadBinding): %v", err) - } - if !decoded.Dataset().Equal(binding.Dataset()) || decoded.AnalysisVersion() != binding.AnalysisVersion() || !decoded.AuthScopeFingerprint().Equal(binding.AuthScopeFingerprint()) { - t.Fatalf("ReadBinding did not round trip\ngot: %#v\nwant: %#v", decoded, binding) - } - - loading := transitionManifest(t, fixtureManifest(t, "project-a", "generation-loading"), ManifestStateLoading) - loadingActive := ActiveGeneration{Dataset: loading.Dataset} - if _, err := BindActive(loadingActive, loading, scope); !errors.Is(err, ErrGenerationNotReady) { - t.Fatalf("BindActive(LOADING) error = %v, want ErrGenerationNotReady", err) - } - other := readyManifest(t, "project-a", "generation-other") - if _, err := BindActive(active, other, scope); !errors.Is(err, ErrInvalidActiveGeneration) { - t.Fatalf("BindActive(mismatch) error = %v, want ErrInvalidActiveGeneration", err) - } - if _, err := BindActive(active, ready, AuthScopeFingerprint{}); !errors.Is(err, ErrInvalidAuthScopeFingerprint) { - t.Fatalf("BindActive(invalid scope) error = %v, want ErrInvalidAuthScopeFingerprint", err) - } -} diff --git a/internal/datasetstore/collections.go b/internal/dataset/arango/collections.go similarity index 98% rename from internal/datasetstore/collections.go rename to internal/dataset/arango/collections.go index 349fa4c..d2edf1c 100644 --- a/internal/datasetstore/collections.go +++ b/internal/dataset/arango/collections.go @@ -1,4 +1,4 @@ -package datasetstore +package arango import arangostore "github.com/calypr/loom/internal/store/arango" diff --git a/internal/datasetstore/doc.go b/internal/dataset/arango/doc.go similarity index 69% rename from internal/datasetstore/doc.go rename to internal/dataset/arango/doc.go index ad151f0..bc117aa 100644 --- a/internal/datasetstore/doc.go +++ b/internal/dataset/arango/doc.go @@ -1,12 +1,12 @@ -// Package datasetstore persists the immutable dataset generation lifecycle in +// Package arango persists the immutable dataset generation lifecycle in // ArangoDB. // // The adapter deliberately owns only manifests and the selected active // generation. It does not load FHIR resources, build a catalog, resolve // authorization, execute dataframes, or expose a public API. In particular it -// never stores raw authorization paths, tokens, subjects, claims, or a -// dataset.AuthScopeFingerprint: authorization scope is a per-read concern, -// not persistent generation metadata. +// never stores raw authorization paths, tokens, subjects, or claims: +// authorization scope is a per-read concern, not persistent generation +// metadata. // // A manifest record and its project's active-generation record live in one // physical collection, distinguished by an internal record type. ArangoDB AQL @@ -14,4 +14,4 @@ // lifecycle records together lets Activate use one UPDATE statement to // supersede the old READY manifest and select the new one atomically on a // single-server deployment. -package datasetstore +package arango diff --git a/internal/datasetstore/store.go b/internal/dataset/arango/store.go similarity index 99% rename from internal/datasetstore/store.go rename to internal/dataset/arango/store.go index 2f2f9ea..0199c83 100644 --- a/internal/datasetstore/store.go +++ b/internal/dataset/arango/store.go @@ -1,4 +1,4 @@ -package datasetstore +package arango import ( "context" diff --git a/internal/datasetstore/store_test.go b/internal/dataset/arango/store_test.go similarity index 99% rename from internal/datasetstore/store_test.go rename to internal/dataset/arango/store_test.go index 393ef9d..ac9a4f4 100644 --- a/internal/datasetstore/store_test.go +++ b/internal/dataset/arango/store_test.go @@ -1,4 +1,4 @@ -package datasetstore +package arango import ( "context" diff --git a/internal/dataset/binding.go b/internal/dataset/binding.go deleted file mode 100644 index 6f96c0d..0000000 --- a/internal/dataset/binding.go +++ /dev/null @@ -1,112 +0,0 @@ -package dataset - -import ( - "encoding/json" - "fmt" -) - -// ReadBinding is the immutable identity envelope that a future analysis, -// discovery, dataframe, cache, or export adapter can carry after it has -// resolved a READY active generation. It does not itself query data or prove a -// persistence transaction occurred. -type ReadBinding struct { - dataset DatasetRef - analysisVersion AnalysisVersion - authScopeFingerprint AuthScopeFingerprint -} - -// BindActive constructs a generation-pinned, authorization-scoped read value. -// The supplied manifest must be the READY manifest named by active. The empty -// AnalysisVersion placeholder remains valid, but consumers that require an -// analysis snapshot must require binding.AnalysisVersion().IsSet(). -func BindActive(active ActiveGeneration, manifest Manifest, scope AuthScopeFingerprint) (ReadBinding, error) { - if err := active.Validate(); err != nil { - return ReadBinding{}, err - } - if err := manifest.Validate(); err != nil { - return ReadBinding{}, err - } - if !active.Dataset.Equal(manifest.Dataset) { - return ReadBinding{}, fmt.Errorf("%w: active generation does not match manifest", ErrInvalidActiveGeneration) - } - if manifest.State != ManifestStateReady { - return ReadBinding{}, fmt.Errorf("%w: %s/%s is %s", ErrGenerationNotReady, manifest.Dataset.Project, manifest.Dataset.Generation, manifest.State) - } - if err := scope.Validate(); err != nil { - return ReadBinding{}, err - } - binding := ReadBinding{ - dataset: manifest.Dataset, - analysisVersion: manifest.AnalysisVersion, - authScopeFingerprint: scope, - } - if err := binding.Validate(); err != nil { - return ReadBinding{}, err - } - return binding, nil -} - -// Dataset returns the immutable generation selected for this binding. -func (b ReadBinding) Dataset() DatasetRef { return b.dataset } - -// AnalysisVersion returns the opaque attached analysis version, or the empty -// C1 placeholder when the generation has no finalized analysis snapshot yet. -func (b ReadBinding) AnalysisVersion() AnalysisVersion { return b.analysisVersion } - -// AuthScopeFingerprint returns the authorization-scope cache key without -// exposing raw authorization paths. -func (b ReadBinding) AuthScopeFingerprint() AuthScopeFingerprint { - return b.authScopeFingerprint -} - -// Validate checks a serialized binding's fields. It cannot prove that its -// DatasetRef is active without resolving it through the manifest store. -func (b ReadBinding) Validate() error { - if err := b.dataset.Validate(); err != nil { - return fmt.Errorf("%w: dataset: %w", ErrInvalidActiveGeneration, err) - } - if err := b.analysisVersion.Validate(); err != nil { - return fmt.Errorf("%w: analysisVersion: %w", ErrInvalidActiveGeneration, err) - } - if err := b.authScopeFingerprint.Validate(); err != nil { - return fmt.Errorf("%w: authScopeFingerprint: %w", ErrInvalidActiveGeneration, err) - } - return nil -} - -func (b ReadBinding) MarshalJSON() ([]byte, error) { - if err := b.Validate(); err != nil { - return nil, err - } - return json.Marshal(readBindingWire{ - Dataset: b.dataset, - AnalysisVersion: b.analysisVersion, - AuthScopeFingerprint: b.authScopeFingerprint, - }) -} - -func (b *ReadBinding) UnmarshalJSON(data []byte) error { - if b == nil { - return fmt.Errorf("%w: cannot unmarshal into nil ReadBinding", ErrInvalidActiveGeneration) - } - var decoded readBindingWire - if err := decodeStrictJSON(data, &decoded); err != nil { - return fmt.Errorf("%w: decode JSON: %v", ErrInvalidActiveGeneration, err) - } - binding := ReadBinding{ - dataset: decoded.Dataset, - analysisVersion: decoded.AnalysisVersion, - authScopeFingerprint: decoded.AuthScopeFingerprint, - } - if err := binding.Validate(); err != nil { - return err - } - *b = binding - return nil -} - -type readBindingWire struct { - Dataset DatasetRef `json:"dataset"` - AnalysisVersion AnalysisVersion `json:"analysisVersion"` - AuthScopeFingerprint AuthScopeFingerprint `json:"authScopeFingerprint"` -} diff --git a/internal/dataset/schema.go b/internal/dataset/schema.go index c3ee763..59bcb03 100644 --- a/internal/dataset/schema.go +++ b/internal/dataset/schema.go @@ -9,12 +9,12 @@ import ( "strings" "unicode/utf8" - "github.com/calypr/loom/internal/schemaidentity" + "github.com/calypr/loom/internal/graphschema" ) // SchemaIdentitySnapshot is the serializable, immutable schema metadata // attached to a dataset generation. It is copied from the active Loom binary's -// schemaidentity.Identity when a generation is created. +// graphschema.Identity when a generation is created. // // FHIRVersion is deliberately empty when the configured graph schema does not // explicitly declare one. This package never infers a FHIR version from a URL, @@ -26,10 +26,10 @@ type SchemaIdentitySnapshot struct { generatedResourceTypes []string } -// SnapshotSchemaIdentity copies an immutable schemaidentity.Identity into the +// SnapshotSchemaIdentity copies an immutable graphschema.Identity into the // public dataset lifecycle value. The resulting snapshot has no reference to // the source identity's backing data. -func SnapshotSchemaIdentity(identity schemaidentity.Identity) (SchemaIdentitySnapshot, error) { +func SnapshotSchemaIdentity(identity graphschema.Identity) (SchemaIdentitySnapshot, error) { return NewSchemaIdentitySnapshot( identity.SchemaID(), identity.FHIRVersion(), @@ -56,7 +56,7 @@ func NewSchemaIdentitySnapshot(schemaID, fhirVersion, schemaSHA256 string, gener return snapshot, nil } -// SchemaID returns the exact graph-schema $id copied from schemaidentity, or +// SchemaID returns the exact graph-schema $id copied from graphschema, or // an empty string when the source schema does not declare one. func (s SchemaIdentitySnapshot) SchemaID() string { return s.schemaID } @@ -141,7 +141,7 @@ func validateOptionalSchemaMetadata(field, value string) error { } func utf8ValidNonControl(value string) bool { - // Schema metadata must retain the exact text that schemaidentity observed; + // Schema metadata must retain the exact text that graphschema observed; // unlike a project key it is not whitespace-normalized here. for _, r := range value { if r < 0x20 || r == 0x7f { diff --git a/internal/dataset/schema_test.go b/internal/dataset/schema_test.go index 8dfb791..42aa547 100644 --- a/internal/dataset/schema_test.go +++ b/internal/dataset/schema_test.go @@ -7,13 +7,13 @@ import ( "reflect" "testing" - "github.com/calypr/loom/internal/schemaidentity" + "github.com/calypr/loom/internal/graphschema" ) func TestSnapshotSchemaIdentityPreservesSourceAndCopies(t *testing.T) { - identity, err := schemaidentity.Load(filepath.Join("..", "..", "schemas", "graph-fhir.json")) + identity, err := graphschema.Load(filepath.Join("..", "..", "schemas", "graph-fhir.json")) if err != nil { - t.Fatalf("schemaidentity.Load: %v", err) + t.Fatalf("graphschema.Load: %v", err) } snapshot, err := SnapshotSchemaIdentity(identity) if err != nil { diff --git a/internal/dataset/scope.go b/internal/dataset/scope.go deleted file mode 100644 index b9cdc04..0000000 --- a/internal/dataset/scope.go +++ /dev/null @@ -1,164 +0,0 @@ -package dataset - -import ( - "crypto/sha256" - "encoding/hex" - "encoding/json" - "fmt" - "sort" - "strings" -) - -const ( - authScopeFingerprintVersion = "loom-auth-scope-v1" - fingerprintAlgorithmSHA256 = "sha256" -) - -// AuthScopeMode distinguishes an unscoped caller from a caller with a scoped -// authorization result. In particular, a restricted caller with zero allowed -// paths must not share a cache key with an unrestricted caller. -type AuthScopeMode string - -const ( - AuthScopeUnrestricted AuthScopeMode = "unrestricted" - AuthScopeRestricted AuthScopeMode = "restricted" -) - -// AuthScopeFingerprint is a stable, serializable representation of an -// effective authorization scope. It intentionally retains no raw paths, token, -// subject, or claims. Callers must construct it from the already-authorized, -// canonical effective scope returned by the authorization layer. -type AuthScopeFingerprint struct { - mode AuthScopeMode - algorithm string - digest string -} - -// UnrestrictedAuthScopeFingerprint returns the canonical fingerprint for an -// authorization layer that is explicitly unrestricted. -func UnrestrictedAuthScopeFingerprint() AuthScopeFingerprint { - return AuthScopeFingerprint{ - mode: AuthScopeUnrestricted, - algorithm: fingerprintAlgorithmSHA256, - digest: fingerprintDigest(AuthScopeUnrestricted, nil), - } -} - -// RestrictedAuthScopeFingerprint returns a fingerprint for one effective, -// restricted scope. Input paths must already be canonical authorization-path -// identifiers. Ordering does not matter; duplicate or noncanonical values are -// rejected so two integrations cannot silently hash different representations -// of the same scope. -func RestrictedAuthScopeFingerprint(paths []string) (AuthScopeFingerprint, error) { - canonicalPaths, err := canonicalScopePaths(paths) - if err != nil { - return AuthScopeFingerprint{}, err - } - return AuthScopeFingerprint{ - mode: AuthScopeRestricted, - algorithm: fingerprintAlgorithmSHA256, - digest: fingerprintDigest(AuthScopeRestricted, canonicalPaths), - }, nil -} - -// Mode returns whether the fingerprint represents an unrestricted or -// restricted authorization result. -func (f AuthScopeFingerprint) Mode() AuthScopeMode { return f.mode } - -// Algorithm returns the digest algorithm used for this fingerprint. -func (f AuthScopeFingerprint) Algorithm() string { return f.algorithm } - -// Digest returns the lower-case hexadecimal digest. It never exposes raw -// authorization paths. -func (f AuthScopeFingerprint) Digest() string { return f.digest } - -// Equal reports exact cache-key equality. -func (f AuthScopeFingerprint) Equal(other AuthScopeFingerprint) bool { - return f.mode == other.mode && f.algorithm == other.algorithm && f.digest == other.digest -} - -// Validate checks a persisted fingerprint. It cannot recompute a digest -// without the intentionally omitted raw scope paths. -func (f AuthScopeFingerprint) Validate() error { - if f.mode != AuthScopeUnrestricted && f.mode != AuthScopeRestricted { - return fmt.Errorf("%w: mode must be unrestricted or restricted", ErrInvalidAuthScopeFingerprint) - } - if f.algorithm != fingerprintAlgorithmSHA256 { - return fmt.Errorf("%w: algorithm must be %q", ErrInvalidAuthScopeFingerprint, fingerprintAlgorithmSHA256) - } - if len(f.digest) != sha256.Size*2 || strings.ToLower(f.digest) != f.digest { - return fmt.Errorf("%w: digest must be a lower-case SHA-256 hexadecimal value", ErrInvalidAuthScopeFingerprint) - } - if _, err := hex.DecodeString(f.digest); err != nil { - return fmt.Errorf("%w: digest is not hexadecimal: %v", ErrInvalidAuthScopeFingerprint, err) - } - return nil -} - -func canonicalScopePaths(paths []string) ([]string, error) { - canonical := append([]string(nil), paths...) - if len(canonical) > maxScopePaths { - return nil, fmt.Errorf("%w: scope has more than %d paths", ErrInvalidAuthScopeFingerprint, maxScopePaths) - } - for index, path := range canonical { - if err := validateOpaqueIdentifier(fmt.Sprintf("scope path at index %d", index), path, false); err != nil { - return nil, fmt.Errorf("%w: %v", ErrInvalidAuthScopeFingerprint, err) - } - } - sort.Strings(canonical) - for index := 1; index < len(canonical); index++ { - if canonical[index] == canonical[index-1] { - return nil, fmt.Errorf("%w: duplicate scope path", ErrInvalidAuthScopeFingerprint) - } - } - return canonical, nil -} - -func fingerprintDigest(mode AuthScopeMode, canonicalPaths []string) string { - hash := sha256.New() - _, _ = hash.Write([]byte(authScopeFingerprintVersion)) - _, _ = hash.Write([]byte{0}) - _, _ = hash.Write([]byte(mode)) - for _, path := range canonicalPaths { - _, _ = hash.Write([]byte{0}) - _, _ = hash.Write([]byte(path)) - } - return hex.EncodeToString(hash.Sum(nil)) -} - -func (f AuthScopeFingerprint) MarshalJSON() ([]byte, error) { - if err := f.Validate(); err != nil { - return nil, err - } - return json.Marshal(authScopeFingerprintWire{ - Mode: f.mode, - Algorithm: f.algorithm, - Digest: f.digest, - }) -} - -func (f *AuthScopeFingerprint) UnmarshalJSON(data []byte) error { - if f == nil { - return fmt.Errorf("%w: cannot unmarshal into nil AuthScopeFingerprint", ErrInvalidAuthScopeFingerprint) - } - var decoded authScopeFingerprintWire - if err := decodeStrictJSON(data, &decoded); err != nil { - return fmt.Errorf("%w: decode JSON: %v", ErrInvalidAuthScopeFingerprint, err) - } - value := AuthScopeFingerprint{ - mode: decoded.Mode, - algorithm: decoded.Algorithm, - digest: decoded.Digest, - } - if err := value.Validate(); err != nil { - return err - } - *f = value - return nil -} - -type authScopeFingerprintWire struct { - Mode AuthScopeMode `json:"mode"` - Algorithm string `json:"algorithm"` - Digest string `json:"digest"` -} diff --git a/internal/dataset/scope_test.go b/internal/dataset/scope_test.go deleted file mode 100644 index 1afd3de..0000000 --- a/internal/dataset/scope_test.go +++ /dev/null @@ -1,78 +0,0 @@ -package dataset - -import ( - "bytes" - "encoding/json" - "errors" - "testing" -) - -func TestAuthScopeFingerprintCanonicalizesWithoutRetainingPaths(t *testing.T) { - paths := []string{"project-beta", "project-alpha"} - first, err := RestrictedAuthScopeFingerprint(paths) - if err != nil { - t.Fatalf("RestrictedAuthScopeFingerprint: %v", err) - } - second, err := RestrictedAuthScopeFingerprint([]string{"project-alpha", "project-beta"}) - if err != nil { - t.Fatalf("RestrictedAuthScopeFingerprint reordered: %v", err) - } - if !first.Equal(second) { - t.Fatalf("reordered scopes differ\nfirst: %#v\nsecond: %#v", first, second) - } - paths[0] = "mutated-after-construction" - if !first.Equal(second) { - t.Fatal("fingerprint changed after source slice mutation") - } - - emptyRestricted, err := RestrictedAuthScopeFingerprint(nil) - if err != nil { - t.Fatalf("RestrictedAuthScopeFingerprint(empty): %v", err) - } - unrestricted := UnrestrictedAuthScopeFingerprint() - if emptyRestricted.Equal(unrestricted) { - t.Fatal("restricted empty scope collided with unrestricted scope") - } - if got, want := emptyRestricted.Mode(), AuthScopeRestricted; got != want { - t.Fatalf("empty restricted mode = %q, want %q", got, want) - } - - encoded, err := json.Marshal(first) - if err != nil { - t.Fatalf("json.Marshal(AuthScopeFingerprint): %v", err) - } - if bytes.Contains(encoded, []byte("project-alpha")) || bytes.Contains(encoded, []byte("project-beta")) { - t.Fatalf("scope fingerprint JSON exposed raw paths: %s", encoded) - } - var decoded AuthScopeFingerprint - if err := json.Unmarshal(encoded, &decoded); err != nil { - t.Fatalf("json.Unmarshal(AuthScopeFingerprint): %v", err) - } - if !decoded.Equal(first) { - t.Fatalf("scope fingerprint did not round trip\ngot: %#v\nwant: %#v", decoded, first) - } -} - -func TestAuthScopeFingerprintRejectsAmbiguousOrInvalidValues(t *testing.T) { - for _, paths := range [][]string{ - {"project-a", "project-a"}, - {" project-a"}, - {""}, - {"project-a\nproject-b"}, - } { - if _, err := RestrictedAuthScopeFingerprint(paths); !errors.Is(err, ErrInvalidAuthScopeFingerprint) { - t.Errorf("RestrictedAuthScopeFingerprint(%#v) error = %v, want ErrInvalidAuthScopeFingerprint", paths, err) - } - } - - for _, raw := range []string{ - `{"mode":"restricted","algorithm":"md5","digest":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}`, - `{"mode":"restricted","algorithm":"sha256","digest":"not-a-digest"}`, - `{"mode":"restricted","algorithm":"sha256","digest":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","unknown":true}`, - } { - var fingerprint AuthScopeFingerprint - if err := json.Unmarshal([]byte(raw), &fingerprint); !errors.Is(err, ErrInvalidAuthScopeFingerprint) { - t.Errorf("json.Unmarshal(%s) error = %v, want ErrInvalidAuthScopeFingerprint", raw, err) - } - } -} diff --git a/internal/dataset/validation.go b/internal/dataset/validation.go index 7bb4559..7b7f30b 100644 --- a/internal/dataset/validation.go +++ b/internal/dataset/validation.go @@ -14,7 +14,6 @@ import ( const ( maxOpaqueIdentifierBytes = 512 maxResourceTypes = 4096 - maxScopePaths = 4096 ) var ( @@ -24,8 +23,6 @@ var ( ErrInvalidSchemaIdentity = errors.New("invalid schema identity") // ErrInvalidAnalysisVersion reports a malformed analysis-version value. ErrInvalidAnalysisVersion = errors.New("invalid analysis version") - // ErrInvalidAuthScopeFingerprint reports a malformed scope fingerprint. - ErrInvalidAuthScopeFingerprint = errors.New("invalid authorization scope fingerprint") // ErrInvalidManifest reports a manifest whose immutable values or state are // not valid for this lifecycle contract. ErrInvalidManifest = errors.New("invalid dataset manifest") diff --git a/internal/discovery/build.go b/internal/discovery/build.go deleted file mode 100644 index ed89a41..0000000 --- a/internal/discovery/build.go +++ /dev/null @@ -1,640 +0,0 @@ -package discovery - -import ( - "crypto/sha256" - "encoding/hex" - "fmt" - "sort" - "strings" - "unicode" - "unicode/utf8" - - "github.com/calypr/loom/internal/catalog" - "github.com/calypr/loom/internal/fhirschema" -) - -// GeneratedRootSummaries returns every concrete root supported by the active -// generated FHIR schema. No root is marked available because this function -// deliberately has no dataset or catalog dependency. -func GeneratedRootSummaries() []RootResourceSummary { - resourceTypes := fhirschema.ResourceTypes() - roots := make([]RootResourceSummary, 0, len(resourceTypes)) - for _, resourceType := range resourceTypes { - roots = append(roots, RootResourceSummary{ - ResourceType: resourceType, - Supported: true, - SupportReason: RootSupportNotObservedInCatalog, - }) - } - return roots -} - -// BuildSnapshot converts already-authorized catalog facts into a deterministic -// guided-discovery response. It intentionally ignores catalog fields and -// relationships that are not representable by the active generated schema; -// exposing them would let the frontend offer a choice that the compiler cannot -// prove safe. -func BuildSnapshot(facts CatalogFacts) (Snapshot, error) { - evidence, err := collectEvidence(facts) - if err != nil { - return Snapshot{}, err - } - return snapshotFromEvidence(evidence) -} - -// discoveryEvidence is the common schema/catalog-normalized source for both -// the JSON-safe Snapshot and the non-JSON capability resolver. Keeping this -// private prevents raw catalog paths and graph labels from becoming a product -// transport contract. -type discoveryEvidence struct { - project string - roots []RootResourceSummary - rootIndexes map[string]int - columns map[ColumnID]*columnAggregate - relationships map[RelationshipID]*relationshipAggregate -} - -func collectEvidence(facts CatalogFacts) (discoveryEvidence, error) { - project := strings.TrimSpace(facts.Project) - if project == "" { - return discoveryEvidence{}, fmt.Errorf("catalog facts require a project") - } - roots := GeneratedRootSummaries() - rootIndexes := rootIndexes(roots) - columns, err := aggregateColumns(project, facts.Fields, rootIndexes) - if err != nil { - return discoveryEvidence{}, err - } - relationships, err := aggregateRelationships(facts.Relationships, rootIndexes) - if err != nil { - return discoveryEvidence{}, err - } - return discoveryEvidence{ - project: project, - roots: roots, - rootIndexes: rootIndexes, - columns: columns, - relationships: relationships, - }, nil -} - -func snapshotFromEvidence(evidence discoveryEvidence) (Snapshot, error) { - snapshot := Snapshot{ - Dataset: DatasetSummary{ - Project: evidence.project, - Roots: append([]RootResourceSummary(nil), evidence.roots...), - }, - Relationships: RelationshipInventory{Entries: []Relationship{}}, - Columns: []CandidateColumn{}, - Filters: []GuidedFilterSuggestion{}, - } - columns := materializeColumns(evidence.columns) - snapshot.Columns = columns - for _, column := range columns { - root := &snapshot.Dataset.Roots[evidence.rootIndexes[column.ResourceType]] - markRootAvailable(root) - root.CandidateColumnCount++ - } - - relationships := materializeRelationships(evidence.relationships) - snapshot.Relationships.Entries = relationships - for _, relationship := range relationships { - from := &snapshot.Dataset.Roots[evidence.rootIndexes[relationship.FromResourceType]] - to := &snapshot.Dataset.Roots[evidence.rootIndexes[relationship.ToResourceType]] - markRootAvailable(from) - markRootAvailable(to) - from.RelationshipCount++ - } - - snapshot.Filters = materializeFilterSuggestions(columns) - if err := snapshot.Validate(); err != nil { - return Snapshot{}, fmt.Errorf("build discovery snapshot: %w", err) - } - return snapshot, nil -} - -func markRootAvailable(root *RootResourceSummary) { - root.Available = true - root.SupportReason = RootSupportObservedInCatalog -} - -type columnSpec struct { - resourceType string - canonical string - selector fhirschema.FieldSelectorSpec - hasSelector bool - valueKind ValueKind - repeated bool - canSelect bool - canFilter bool - canPivot bool -} - -type columnAggregate struct { - columnSpec - populatedDocumentCount int64 - values map[string]struct{} - valuesTruncated bool - pivots map[string]*pivotAggregate -} - -// pivotSpec is schema-validated metadata derived from a populated catalog -// field. It remains private until a caller resolves an opaque ColumnID. -type pivotSpec struct { - family string - columnSelector fhirschema.FieldSelectorSpec - valueSelector fhirschema.FieldSelectorSpec -} - -type pivotAggregate struct { - spec pivotSpec - columns map[string]struct{} - truncated bool -} - -func aggregateColumns(project string, fields []catalog.PopulatedField, roots map[string]int) (map[ColumnID]*columnAggregate, error) { - aggregates := make(map[ColumnID]*columnAggregate) - for _, field := range fields { - resourceType := strings.TrimSpace(field.ResourceType) - if resourceType == "" || strings.TrimSpace(field.Path) == "" { - return nil, fmt.Errorf("catalog field requires resource type and path") - } - if field.DocCount < 0 || field.SampleCount < 0 { - return nil, fmt.Errorf("catalog field has a negative population count") - } - if strings.TrimSpace(field.Project) != project { - return nil, fmt.Errorf("catalog field project does not match requested project") - } - if _, ok := roots[resourceType]; !ok { - // The checked-in generated schema is the authoritative compiler - // boundary. A stale or wider catalog must not widen this response. - continue - } - - canonical := fhirschema.CanonicalizePath(field.Path) - if canonical == "" { - return nil, fmt.Errorf("catalog field path has no canonical form") - } - pivot, pivotAvailable := observedPivotSpec(resourceType, canonical, field) - spec, ok := classifyColumn(resourceType, canonical, pivotAvailable) - if !ok { - // Object, extension, and unrepresented paths remain intentionally - // hidden until the generated schema can describe their lowering. - continue - } - id := opaqueColumnID(resourceType, canonical) - aggregate, ok := aggregates[id] - if !ok { - aggregate = &columnAggregate{ - columnSpec: spec, - values: make(map[string]struct{}), - pivots: make(map[string]*pivotAggregate), - } - aggregates[id] = aggregate - } - if pivotAvailable { - aggregate.canPivot = true - aggregate.addPivot(pivot, field.PivotColumns, field.DistinctTruncated) - } - aggregate.populatedDocumentCount += field.DocCount - aggregate.valuesTruncated = aggregate.valuesTruncated || field.DistinctTruncated - for _, value := range field.DistinctValues { - value = strings.TrimSpace(value) - if value != "" { - aggregate.values[value] = struct{}{} - } - } - } - return aggregates, nil -} - -func (aggregate *columnAggregate) addPivot(spec pivotSpec, columns []string, truncated bool) { - key := pivotSpecKey(spec) - pivot, ok := aggregate.pivots[key] - if !ok { - pivot = &pivotAggregate{ - spec: spec, - columns: make(map[string]struct{}), - } - aggregate.pivots[key] = pivot - } - pivot.truncated = pivot.truncated || truncated - for _, column := range columns { - column = strings.TrimSpace(column) - if column != "" { - pivot.columns[column] = struct{}{} - } - } -} - -func classifyColumn(resourceType, canonical string, pivotAvailable bool) (columnSpec, bool) { - if metadata, ok := fhirschema.ResolveTerminalScalarMetadata(resourceType, canonical); ok { - if valueKind, ok := valueKindFromPrimitive(metadata.Primitive); ok { - field, found := fhirschema.LookupField(resourceType, canonical) - if !found { - return columnSpec{}, false - } - return columnSpec{ - resourceType: resourceType, - canonical: canonical, - selector: fhirschema.SelectorFromField(field), - hasSelector: true, - valueKind: valueKind, - repeated: metadata.Repeated, - canSelect: true, - canFilter: true, - canPivot: pivotAvailable, - }, true - } - } - - // The catalog knows whether a populated object was observed as a pivot - // candidate, but generated schema metadata still decides whether that pivot - // has a supported compiler family. The opaque ID resolves back to the - // catalog-owned selectors only after the user makes a choice. - if pivotAvailable { - return columnSpec{ - resourceType: resourceType, - canonical: canonical, - valueKind: ValueKindComposite, - canPivot: true, - }, true - } - return columnSpec{}, false -} - -func observedPivotSpec(resourceType, canonical string, field catalog.PopulatedField) (pivotSpec, bool) { - if !field.PivotCandidate { - return pivotSpec{}, false - } - columnExpression := strings.TrimSpace(field.PivotColumnSelect) - valueExpression := strings.TrimSpace(field.PivotValueSelect) - var columnSelector, valueSelector fhirschema.FieldSelectorSpec - if columnExpression == "" && valueExpression == "" { - defaultSpec, ok := fhirschema.DefaultPivotSpec(resourceType, canonical, "") - if !ok { - return pivotSpec{}, false - } - columnSelector = defaultSpec.ColumnSelector - valueSelector = defaultSpec.ValueSelector - } else { - if columnExpression == "" || valueExpression == "" { - return pivotSpec{}, false - } - var ok bool - columnSelector, ok = selectorSpecFromExpression(columnExpression) - if !ok { - return pivotSpec{}, false - } - valueSelector, ok = selectorSpecFromExpression(valueExpression) - if !ok { - return pivotSpec{}, false - } - } - pivot, err := fhirschema.ValidatePivotSelectors(resourceType, columnSelector, valueSelector) - if err != nil || pivot.CatalogRootPath != canonical { - return pivotSpec{}, false - } - if family := strings.TrimSpace(field.PivotFamily); family != "" && family != pivot.Family { - return pivotSpec{}, false - } - return pivotSpec{ - family: pivot.Family, - columnSelector: pivot.ColumnSelector, - valueSelector: pivot.ValueSelector, - }, true -} - -func selectorSpecFromExpression(expression string) (fhirschema.FieldSelectorSpec, bool) { - selector, err := fhirschema.ParseSelector(expression) - if err != nil || len(selector.Steps) == 0 { - return fhirschema.FieldSelectorSpec{}, false - } - parts := make([]string, 0, len(selector.Steps)) - for _, step := range selector.Steps { - parts = append(parts, selectorStepExpression(step)) - } - spec := fhirschema.FieldSelectorSpec{ValuePath: parts[len(parts)-1]} - if len(parts) > 1 { - spec.SourcePath = strings.Join(parts[:len(parts)-1], ".") - } - if selector.Filter != nil { - spec.Where = &fhirschema.FieldPredicateSpec{ - Path: selector.Filter.Field, - Op: fhirschema.PredicateContains, - Value: selector.Filter.Needle, - } - } - return spec, true -} - -func selectorStepExpression(step fhirschema.SelectorStep) string { - if step.Iterate { - return step.Field + "[]" - } - if step.Index != nil { - return fmt.Sprintf("%s[%d]", step.Field, *step.Index) - } - return step.Field -} - -func pivotSpecKey(spec pivotSpec) string { - return strings.Join([]string{ - spec.family, - fhirschema.SelectorExpression(spec.columnSelector), - fhirschema.SelectorExpression(spec.valueSelector), - }, "\x00") -} - -func valueKindFromPrimitive(primitive fhirschema.PrimitiveKind) (ValueKind, bool) { - switch primitive { - case fhirschema.PrimitiveString: - return ValueKindString, true - case fhirschema.PrimitiveBoolean: - return ValueKindBoolean, true - case fhirschema.PrimitiveInteger: - return ValueKindInteger, true - case fhirschema.PrimitiveDecimal: - return ValueKindDecimal, true - case fhirschema.PrimitiveDate: - return ValueKindDate, true - case fhirschema.PrimitiveDateTime: - return ValueKindDateTime, true - default: - return "", false - } -} - -func materializeColumns(aggregates map[ColumnID]*columnAggregate) []CandidateColumn { - columns := make([]CandidateColumn, 0, len(aggregates)) - for id, aggregate := range aggregates { - values, truncated := normalizedValues(aggregate.values, aggregate.valuesTruncated) - columns = append(columns, CandidateColumn{ - ID: id, - ResourceType: aggregate.resourceType, - Label: humanizePath(aggregate.canonical), - ValueKind: aggregate.valueKind, - Repeated: aggregate.repeated, - CanSelect: aggregate.canSelect, - CanFilter: aggregate.canFilter, - CanPivot: aggregate.canPivot, - PopulatedDocumentCount: aggregate.populatedDocumentCount, - SuggestedValues: values, - ValuesTruncated: truncated, - }) - } - sort.Slice(columns, func(i, j int) bool { - if columns[i].ResourceType != columns[j].ResourceType { - return columns[i].ResourceType < columns[j].ResourceType - } - if columns[i].Label != columns[j].Label { - return columns[i].Label < columns[j].Label - } - return columns[i].ID < columns[j].ID - }) - return columns -} - -type relationshipAggregate struct { - fromType string - label string - toType string - multiple RelationshipMultiplicity - traversal fhirschema.CompilerTraversal - edgeCount int64 -} - -func aggregateRelationships(references []catalog.PopulatedReference, roots map[string]int) (map[RelationshipID]*relationshipAggregate, error) { - aggregates := make(map[RelationshipID]*relationshipAggregate) - for _, reference := range references { - fromType := strings.TrimSpace(reference.FromType) - label := strings.TrimSpace(reference.Label) - toType := strings.TrimSpace(reference.ToType) - if fromType == "" || label == "" || toType == "" { - return nil, fmt.Errorf("catalog relationship requires source, label, and target") - } - if reference.EdgeCount < 0 { - return nil, fmt.Errorf("catalog relationship has a negative edge count") - } - if _, ok := roots[fromType]; !ok { - continue - } - if _, ok := roots[toType]; !ok { - continue - } - traversal, found, err := fhirschema.ResolveCompilerTraversal(fromType, label, toType) - if err != nil { - return nil, fmt.Errorf("active generated schema has unsafe traversal metadata") - } - if !found { - continue - } - - id := opaqueRelationshipID(fromType, label, toType) - multiplicity := RelationshipOne - if traversal.Multiplicity == fhirschema.TraversalMany { - multiplicity = RelationshipMany - } - aggregate, ok := aggregates[id] - if !ok { - aggregate = &relationshipAggregate{ - fromType: fromType, - label: label, - toType: toType, - multiple: multiplicity, - traversal: traversal, - } - aggregates[id] = aggregate - } - // DiscoverPopulatedReferences already aggregates each route. If a - // caller accidentally supplies it more than once, max preserves an - // idempotent normalized snapshot instead of double-counting a route. - if reference.EdgeCount > aggregate.edgeCount { - aggregate.edgeCount = reference.EdgeCount - } - } - - return aggregates, nil -} - -func materializeRelationships(aggregates map[RelationshipID]*relationshipAggregate) []Relationship { - relationships := make([]Relationship, 0, len(aggregates)) - for id, aggregate := range aggregates { - relationships = append(relationships, Relationship{ - ID: id, - FromResourceType: aggregate.fromType, - ToResourceType: aggregate.toType, - Label: humanizeRelationshipLabel(aggregate.label, aggregate.toType), - Multiplicity: aggregate.multiple, - ObservedEdgeCount: aggregate.edgeCount, - }) - } - sort.Slice(relationships, func(i, j int) bool { - if relationships[i].FromResourceType != relationships[j].FromResourceType { - return relationships[i].FromResourceType < relationships[j].FromResourceType - } - if relationships[i].ToResourceType != relationships[j].ToResourceType { - return relationships[i].ToResourceType < relationships[j].ToResourceType - } - if relationships[i].Label != relationships[j].Label { - return relationships[i].Label < relationships[j].Label - } - return relationships[i].ID < relationships[j].ID - }) - return relationships -} - -func materializeFilterSuggestions(columns []CandidateColumn) []GuidedFilterSuggestion { - filters := make([]GuidedFilterSuggestion, 0, len(columns)) - for _, column := range columns { - if !column.CanFilter { - continue - } - filters = append(filters, GuidedFilterSuggestion{ - ID: opaqueFilterSuggestionID(column.ID), - ColumnID: column.ID, - ResourceType: column.ResourceType, - Label: column.Label, - ValueKind: column.ValueKind, - Repeated: column.Repeated, - Operators: filterOperators(column.ValueKind), - Quantifiers: filterQuantifiers(column.Repeated), - SuggestedValues: append([]string(nil), column.SuggestedValues...), - ValuesTruncated: column.ValuesTruncated, - }) - } - sort.Slice(filters, func(i, j int) bool { - if filters[i].ResourceType != filters[j].ResourceType { - return filters[i].ResourceType < filters[j].ResourceType - } - if filters[i].Label != filters[j].Label { - return filters[i].Label < filters[j].Label - } - return filters[i].ID < filters[j].ID - }) - return filters -} - -func filterOperators(kind ValueKind) []FilterOperator { - operators := []FilterOperator{ - FilterEquals, - FilterNotEquals, - FilterIn, - FilterExists, - FilterMissing, - } - switch kind { - case ValueKindString: - operators = append(operators, FilterContains) - case ValueKindInteger, ValueKindDecimal, ValueKindDate, ValueKindDateTime: - operators = append(operators, FilterGreaterThan, FilterGreaterEq, FilterLessThan, FilterLessEq) - } - return operators -} - -func filterQuantifiers(repeated bool) []FilterQuantifier { - if !repeated { - return []FilterQuantifier{} - } - return []FilterQuantifier{FilterAny, FilterAll, FilterNone} -} - -func normalizedValues(values map[string]struct{}, alreadyTruncated bool) ([]string, bool) { - if len(values) == 0 { - return []string{}, alreadyTruncated - } - out := make([]string, 0, len(values)) - for value := range values { - out = append(out, value) - } - sort.Strings(out) - if len(out) > maxSuggestedValues { - return append([]string(nil), out[:maxSuggestedValues]...), true - } - return out, alreadyTruncated -} - -func rootIndexes(roots []RootResourceSummary) map[string]int { - indexes := make(map[string]int, len(roots)) - for i, root := range roots { - indexes[root.ResourceType] = i - } - return indexes -} - -func opaqueColumnID(resourceType, canonical string) ColumnID { - return ColumnID("col_" + stableHash("column", resourceType, canonical)) -} - -func opaqueRelationshipID(fromType, label, toType string) RelationshipID { - return RelationshipID("rel_" + stableHash("relationship", fromType, label, toType)) -} - -func opaqueFilterSuggestionID(columnID ColumnID) FilterSuggestionID { - return FilterSuggestionID("flt_" + stableHash("filter", string(columnID))) -} - -func stableHash(parts ...string) string { - hash := sha256.New() - for _, part := range parts { - _, _ = hash.Write([]byte(part)) - _, _ = hash.Write([]byte{0}) - } - return hex.EncodeToString(hash.Sum(nil)) -} - -func humanizePath(canonical string) string { - segments := strings.Split(canonical, ".") - words := make([]string, 0, len(segments)) - for _, segment := range segments { - segment = strings.TrimSuffix(segment, "[]") - if label := humanizeIdentifier(segment); label != "" { - words = append(words, label) - } - } - return strings.Join(words, " ") -} - -func humanizeRelationshipLabel(label, toType string) string { - label = strings.TrimSuffix(label, "_"+toType) - parts := strings.Split(label, "_") - if len(parts) > 1 && fhirschema.HasResource(parts[len(parts)-1]) { - label = strings.Join(parts[:len(parts)-1], "_") - } - return humanizeIdentifier(label) -} - -func humanizeIdentifier(value string) string { - value = strings.TrimSpace(value) - if value == "" { - return "" - } - var words []string - var word []rune - flush := func() { - if len(word) == 0 { - return - } - words = append(words, strings.ToLower(string(word))) - word = word[:0] - } - for _, r := range value { - if r == '_' || r == '-' || r == '.' || unicode.IsSpace(r) { - flush() - continue - } - if len(word) > 0 && unicode.IsUpper(r) && unicode.IsLower(word[len(word)-1]) { - flush() - } - word = append(word, r) - } - flush() - for i, word := range words { - if word == "" { - continue - } - first, size := utf8.DecodeRuneInString(word) - words[i] = string(unicode.ToUpper(first)) + word[size:] - } - return strings.Join(words, " ") -} diff --git a/internal/discovery/discovery_test.go b/internal/discovery/discovery_test.go deleted file mode 100644 index 033ef5c..0000000 --- a/internal/discovery/discovery_test.go +++ /dev/null @@ -1,253 +0,0 @@ -package discovery - -import ( - "encoding/json" - "reflect" - "slices" - "strings" - "testing" - - "github.com/calypr/loom/internal/catalog" - "github.com/calypr/loom/internal/fhirschema" -) - -func TestGeneratedRootSummariesFollowActiveGeneratedSchema(t *testing.T) { - got := GeneratedRootSummaries() - want := fhirschema.ResourceTypes() - if len(got) != len(want) { - t.Fatalf("GeneratedRootSummaries() length = %d, want %d", len(got), len(want)) - } - for index, resourceType := range want { - root := got[index] - if root.ResourceType != resourceType { - t.Errorf("root %d resourceType = %q, want %q", index, root.ResourceType, resourceType) - } - if !root.Supported || root.Available || root.SupportReason != RootSupportNotObservedInCatalog { - t.Errorf("root %q = %+v, want generated-only supported root", resourceType, root) - } - if root.CandidateColumnCount != 0 || root.RelationshipCount != 0 { - t.Errorf("root %q carries catalog counts without catalog facts: %+v", resourceType, root) - } - } -} - -func TestBuildSnapshotBuildsOpaqueCatalogAndSchemaBackedContract(t *testing.T) { - facts := CatalogFacts{ - Project: "project-a", - Fields: []catalog.PopulatedField{ - { - Project: "project-a", ResourceType: "Patient", Path: "gender", Kind: "scalar", - DocCount: 4, SampleCount: 2, DistinctValues: []string{"male", "female", "female"}, - }, - { - Project: "project-a", AuthResourcePath: "restricted", ResourceType: "Patient", Path: "gender", Kind: "scalar", - DocCount: 2, SampleCount: 2, DistinctValues: []string{"unknown", "female"}, DistinctTruncated: true, - }, - { - Project: "project-a", ResourceType: "Patient", Path: "birthDate", Kind: "scalar", - DocCount: 5, SampleCount: 2, DistinctValues: []string{"1990-01-01", "2000-02-02"}, - }, - { - Project: "project-a", ResourceType: "Patient", Path: "name[].family", Kind: "scalar", - DocCount: 4, SampleCount: 2, DistinctValues: []string{"Ng", "Smith"}, - }, - { - Project: "project-a", ResourceType: "Observation", Path: "code", Kind: "codeable_concept", - DocCount: 4, SampleCount: 1, DistinctValues: []string{"Hemoglobin"}, PivotCandidate: true, - }, - { - Project: "project-a", ResourceType: "Observation", Path: "valueInteger", Kind: "scalar", - DocCount: 4, SampleCount: 2, DistinctValues: []string{"12", "13"}, - }, - // Unsupported schema paths and resource types must never reach the - // guided response merely because they appear in an old catalog. - {Project: "project-a", ResourceType: "Patient", Path: "notRepresented", Kind: "scalar", DocCount: 1}, - {Project: "project-a", ResourceType: "Encounter", Path: "status", Kind: "scalar", DocCount: 1}, - }, - Relationships: []catalog.PopulatedReference{ - {FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 7}, - // Duplicate source facts normalize idempotently rather than making - // the discovery result depend on caller pagination/retries. - {FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 2}, - {FromType: "Patient", Label: "not_a_generated_route", ToType: "Specimen", EdgeCount: 99}, - {FromType: "Encounter", Label: "subject_Patient", ToType: "Patient", EdgeCount: 3}, - }, - } - - snapshot, err := BuildSnapshot(facts) - if err != nil { - t.Fatalf("BuildSnapshot() error = %v", err) - } - if err := snapshot.Validate(); err != nil { - t.Fatalf("snapshot.Validate() error = %v", err) - } - - patient := findRoot(t, snapshot.Dataset.Roots, "Patient") - if !patient.Supported || !patient.Available || patient.SupportReason != RootSupportObservedInCatalog || patient.CandidateColumnCount != 3 || patient.RelationshipCount != 1 { - t.Errorf("Patient summary = %+v, want observed supported root with 3 columns and 1 route", patient) - } - observation := findRoot(t, snapshot.Dataset.Roots, "Observation") - if !observation.Available || observation.CandidateColumnCount != 2 || observation.RelationshipCount != 0 { - t.Errorf("Observation summary = %+v, want 2 candidate columns", observation) - } - specimen := findRoot(t, snapshot.Dataset.Roots, "Specimen") - if !specimen.Available || specimen.SupportReason != RootSupportObservedInCatalog || specimen.CandidateColumnCount != 0 { - t.Errorf("Specimen summary = %+v, want availability through incoming route", specimen) - } - diagnosticReport := findRoot(t, snapshot.Dataset.Roots, "DiagnosticReport") - if !diagnosticReport.Supported || diagnosticReport.Available || diagnosticReport.SupportReason != RootSupportNotObservedInCatalog { - t.Errorf("DiagnosticReport summary = %+v, want supported but not observed", diagnosticReport) - } - - if len(snapshot.Relationships.Entries) != 1 { - t.Fatalf("relationship count = %d, want 1: %+v", len(snapshot.Relationships.Entries), snapshot.Relationships.Entries) - } - relationship := snapshot.Relationships.Entries[0] - if relationship.FromResourceType != "Patient" || relationship.ToResourceType != "Specimen" || relationship.Label != "Subject" || relationship.ObservedEdgeCount != 7 { - t.Errorf("relationship = %+v, want normalized Patient Subject Specimen route", relationship) - } - if strings.Contains(string(relationship.ID), "subject_Patient") { - t.Errorf("relationship ID leaked underlying graph label: %q", relationship.ID) - } - - gender := findColumn(t, snapshot.Columns, "Patient", "Gender") - if gender.ValueKind != ValueKindString || !gender.CanSelect || !gender.CanFilter || gender.CanPivot || gender.Repeated || gender.PopulatedDocumentCount != 6 { - t.Errorf("gender column = %+v", gender) - } - if !reflect.DeepEqual(gender.SuggestedValues, []string{"female", "male", "unknown"}) || !gender.ValuesTruncated { - t.Errorf("gender values = %#v truncated=%t", gender.SuggestedValues, gender.ValuesTruncated) - } - if strings.Contains(string(gender.ID), "gender") { - t.Errorf("column ID leaked canonical field path: %q", gender.ID) - } - - pivot := findColumn(t, snapshot.Columns, "Observation", "Code") - if pivot.ValueKind != ValueKindComposite || pivot.CanSelect || pivot.CanFilter || !pivot.CanPivot || pivot.Repeated { - t.Errorf("Observation code pivot candidate = %+v", pivot) - } - - repeated := findFilter(t, snapshot.Filters, "Patient", "Name Family") - if !repeated.Repeated || !reflect.DeepEqual(repeated.Quantifiers, []FilterQuantifier{FilterAny, FilterAll, FilterNone}) { - t.Errorf("repeated filter = %+v", repeated) - } - date := findFilter(t, snapshot.Filters, "Patient", "Birth Date") - if !slices.Contains(date.Operators, FilterGreaterEq) || !slices.Contains(date.Operators, FilterLessEq) { - t.Errorf("date filter lacks ordered operations: %+v", date.Operators) - } - if got, want := len(snapshot.Filters), 4; got != want { - t.Errorf("filter count = %d, want %d", got, want) - } - - encoded, err := json.Marshal(snapshot) - if err != nil { - t.Fatalf("marshal snapshot: %v", err) - } - for _, forbidden := range []string{"name[].family", "subject_Patient", "auth_resource_path", "selector", "fieldRef"} { - if strings.Contains(string(encoded), forbidden) { - t.Errorf("snapshot JSON leaked internal catalog/query detail %q: %s", forbidden, encoded) - } - } -} - -func TestBuildSnapshotIsDeterministicAcrossCatalogFactOrder(t *testing.T) { - facts := CatalogFacts{ - Project: "project-a", - Fields: []catalog.PopulatedField{ - {Project: "project-a", ResourceType: "Patient", Path: "gender", Kind: "scalar", DocCount: 3, DistinctValues: []string{"male", "female"}}, - {Project: "project-a", ResourceType: "Patient", Path: "birthDate", Kind: "scalar", DocCount: 3, DistinctValues: []string{"2000-01-01"}}, - }, - Relationships: []catalog.PopulatedReference{ - {FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 4}, - }, - } - first, err := BuildSnapshot(facts) - if err != nil { - t.Fatalf("first BuildSnapshot() error = %v", err) - } - facts.Fields = append([]catalog.PopulatedField(nil), facts.Fields...) - facts.Relationships = append([]catalog.PopulatedReference(nil), facts.Relationships...) - slices.Reverse(facts.Fields) - slices.Reverse(facts.Relationships) - second, err := BuildSnapshot(facts) - if err != nil { - t.Fatalf("second BuildSnapshot() error = %v", err) - } - if !reflect.DeepEqual(first, second) { - t.Errorf("BuildSnapshot() changed with input order\nfirst: %#v\nsecond: %#v", first, second) - } -} - -func TestBuildSnapshotBoundsSuggestedValuesAndRejectsWrongScope(t *testing.T) { - values := make([]string, 0, maxSuggestedValues+5) - for index := 0; index < maxSuggestedValues+5; index++ { - values = append(values, string(rune('a'+index/10))+string(rune('0'+index%10))) - } - snapshot, err := BuildSnapshot(CatalogFacts{ - Project: "project-a", - Fields: []catalog.PopulatedField{{ - Project: "project-a", ResourceType: "Patient", Path: "gender", Kind: "scalar", DocCount: 55, DistinctValues: values, - }}, - }) - if err != nil { - t.Fatalf("BuildSnapshot() error = %v", err) - } - column := findColumn(t, snapshot.Columns, "Patient", "Gender") - if len(column.SuggestedValues) != maxSuggestedValues || !column.ValuesTruncated { - t.Errorf("bounded values = %d truncated=%t, want %d/true", len(column.SuggestedValues), column.ValuesTruncated, maxSuggestedValues) - } - - _, err = BuildSnapshot(CatalogFacts{ - Project: "project-a", - Fields: []catalog.PopulatedField{{Project: "other-project", ResourceType: "Patient", Path: "gender", Kind: "scalar"}}, - }) - if err == nil || !strings.Contains(err.Error(), "project") { - t.Errorf("scope-mismatched catalog field error = %v, want project error", err) - } -} - -func TestSnapshotValidateRejectsNonOpaqueColumnIdentifier(t *testing.T) { - snapshot, err := BuildSnapshot(CatalogFacts{ - Project: "project-a", - Fields: []catalog.PopulatedField{{Project: "project-a", ResourceType: "Patient", Path: "gender", Kind: "scalar", DocCount: 1}}, - }) - if err != nil { - t.Fatalf("BuildSnapshot() error = %v", err) - } - snapshot.Columns[0].ID = "Patient.gender" - if err := snapshot.Validate(); err == nil || !strings.Contains(err.Error(), "opaque") { - t.Errorf("Validate() error = %v, want opaque ID failure", err) - } -} - -func findRoot(t *testing.T, roots []RootResourceSummary, resourceType string) RootResourceSummary { - t.Helper() - for _, root := range roots { - if root.ResourceType == resourceType { - return root - } - } - t.Fatalf("root %q not found", resourceType) - return RootResourceSummary{} -} - -func findColumn(t *testing.T, columns []CandidateColumn, resourceType, label string) CandidateColumn { - t.Helper() - for _, column := range columns { - if column.ResourceType == resourceType && column.Label == label { - return column - } - } - t.Fatalf("column %s/%s not found in %+v", resourceType, label, columns) - return CandidateColumn{} -} - -func findFilter(t *testing.T, filters []GuidedFilterSuggestion, resourceType, label string) GuidedFilterSuggestion { - t.Helper() - for _, filter := range filters { - if filter.ResourceType == resourceType && filter.Label == label { - return filter - } - } - t.Fatalf("filter %s/%s not found in %+v", resourceType, label, filters) - return GuidedFilterSuggestion{} -} diff --git a/internal/discovery/resolution.go b/internal/discovery/resolution.go deleted file mode 100644 index 2e0c193..0000000 --- a/internal/discovery/resolution.go +++ /dev/null @@ -1,169 +0,0 @@ -package discovery - -import ( - "errors" - "sort" - - "github.com/calypr/loom/internal/fhirschema" -) - -// ErrColumnUnavailable is returned for both unknown and stale column IDs. The -// error intentionally does not disclose whether an identifier was once valid -// in another project, authorization scope, or catalog state. -var ErrColumnUnavailable = errors.New("discovery column capability is unavailable in current catalog facts") - -// ErrRelationshipUnavailable is returned for both unknown and stale route -// IDs, without disclosing graph labels outside the current scoped facts. -var ErrRelationshipUnavailable = errors.New("discovery relationship capability is unavailable in current catalog facts") - -// CapabilityResolver resolves opaque Snapshot identifiers against one fresh, -// already-authorized CatalogFacts value. It is intentionally in-memory only: -// the caller owns catalog reads, authorization, and any future dataset identity -// integration. -type CapabilityResolver struct { - evidence discoveryEvidence -} - -// NewCapabilityResolver builds a resolver from one current project/scope's -// catalog facts. It applies exactly the same generated-schema and catalog -// normalization as BuildSnapshot. -func NewCapabilityResolver(facts CatalogFacts) (*CapabilityResolver, error) { - evidence, err := collectEvidence(facts) - if err != nil { - return nil, err - } - return &CapabilityResolver{evidence: evidence}, nil -} - -// ResolvedColumn contains compiler-adjacent facts that must never be used as -// transport data. All fields are excluded from JSON to prevent canonical FHIR -// paths or selectors from escaping the opaque Snapshot boundary. -type ResolvedColumn struct { - ID ColumnID `json:"-"` - ResourceType string `json:"-"` - CanonicalPath string `json:"-"` - Selector *fhirschema.FieldSelectorSpec `json:"-"` - ValueKind ValueKind `json:"-"` - Repeated bool `json:"-"` - CanSelect bool `json:"-"` - CanFilter bool `json:"-"` - CanPivot bool `json:"-"` - FilterOperators []FilterOperator `json:"-"` - FilterQuantifiers []FilterQuantifier `json:"-"` - PopulatedDocumentCount int64 `json:"-"` - SuggestedValues []string `json:"-"` - ValuesTruncated bool `json:"-"` - Pivot *ResolvedPivot `json:"-"` -} - -// ResolvedPivot is a schema-validated, catalog-observed pivot family. Its -// selector fields remain internal and are omitted from JSON even when a caller -// accidentally marshals a resolved capability. -type ResolvedPivot struct { - Family string `json:"-"` - ColumnSelector fhirschema.FieldSelectorSpec `json:"-"` - ValueSelector fhirschema.FieldSelectorSpec `json:"-"` - Columns []string `json:"-"` - ColumnsTruncated bool `json:"-"` -} - -// ResolvedRelationship contains the raw generated graph route required by a -// later mapper. Snapshot intentionally exposes only an opaque ID and a human -// label, while this record is kept entirely out of JSON. -type ResolvedRelationship struct { - ID RelationshipID `json:"-"` - FromResourceType string `json:"-"` - EdgeLabel string `json:"-"` - ToResourceType string `json:"-"` - Multiplicity RelationshipMultiplicity `json:"-"` - ObservedEdgeCount int64 `json:"-"` - Traversal fhirschema.CompilerTraversal `json:"-"` -} - -// ResolveColumn resolves a ColumnID only when it is still present in the fresh -// schema-supported catalog evidence used to construct this resolver. -func (resolver *CapabilityResolver) ResolveColumn(id ColumnID) (ResolvedColumn, error) { - if resolver == nil { - return ResolvedColumn{}, ErrColumnUnavailable - } - aggregate, ok := resolver.evidence.columns[id] - if !ok { - return ResolvedColumn{}, ErrColumnUnavailable - } - values, truncated := normalizedValues(aggregate.values, aggregate.valuesTruncated) - resolved := ResolvedColumn{ - ID: id, - ResourceType: aggregate.resourceType, - CanonicalPath: aggregate.canonical, - ValueKind: aggregate.valueKind, - Repeated: aggregate.repeated, - CanSelect: aggregate.canSelect, - CanFilter: aggregate.canFilter, - CanPivot: aggregate.canPivot, - PopulatedDocumentCount: aggregate.populatedDocumentCount, - SuggestedValues: values, - ValuesTruncated: truncated, - } - if aggregate.hasSelector { - selector := cloneSelectorSpec(aggregate.selector) - resolved.Selector = &selector - } - if aggregate.canFilter { - resolved.FilterOperators = append([]FilterOperator(nil), filterOperators(aggregate.valueKind)...) - resolved.FilterQuantifiers = append([]FilterQuantifier(nil), filterQuantifiers(aggregate.repeated)...) - } - if pivot := resolvedPivot(aggregate); pivot != nil { - resolved.Pivot = pivot - } - return resolved, nil -} - -// ResolveRelationship resolves a RelationshipID only when its route remains -// populated and represented by the active generated FHIR graph schema. -func (resolver *CapabilityResolver) ResolveRelationship(id RelationshipID) (ResolvedRelationship, error) { - if resolver == nil { - return ResolvedRelationship{}, ErrRelationshipUnavailable - } - aggregate, ok := resolver.evidence.relationships[id] - if !ok { - return ResolvedRelationship{}, ErrRelationshipUnavailable - } - return ResolvedRelationship{ - ID: id, - FromResourceType: aggregate.fromType, - EdgeLabel: aggregate.label, - ToResourceType: aggregate.toType, - Multiplicity: aggregate.multiple, - ObservedEdgeCount: aggregate.edgeCount, - Traversal: aggregate.traversal, - }, nil -} - -func resolvedPivot(aggregate *columnAggregate) *ResolvedPivot { - if len(aggregate.pivots) == 0 { - return nil - } - keys := make([]string, 0, len(aggregate.pivots)) - for key := range aggregate.pivots { - keys = append(keys, key) - } - sort.Strings(keys) - pivot := aggregate.pivots[keys[0]] - columns, truncated := normalizedValues(pivot.columns, pivot.truncated) - return &ResolvedPivot{ - Family: pivot.spec.family, - ColumnSelector: cloneSelectorSpec(pivot.spec.columnSelector), - ValueSelector: cloneSelectorSpec(pivot.spec.valueSelector), - Columns: columns, - ColumnsTruncated: truncated, - } -} - -func cloneSelectorSpec(spec fhirschema.FieldSelectorSpec) fhirschema.FieldSelectorSpec { - cloned := spec - if spec.Where != nil { - where := *spec.Where - cloned.Where = &where - } - return cloned -} diff --git a/internal/discovery/resolution_test.go b/internal/discovery/resolution_test.go deleted file mode 100644 index d39117c..0000000 --- a/internal/discovery/resolution_test.go +++ /dev/null @@ -1,201 +0,0 @@ -package discovery - -import ( - "encoding/json" - "errors" - "strings" - "testing" - - "github.com/calypr/loom/internal/catalog" - "github.com/calypr/loom/internal/fhirschema" -) - -func TestCapabilityResolverResolvesEverySnapshotIDFromSameFacts(t *testing.T) { - facts := resolutionFacts() - snapshot, err := BuildSnapshot(facts) - if err != nil { - t.Fatalf("BuildSnapshot() error = %v", err) - } - resolver, err := NewCapabilityResolver(facts) - if err != nil { - t.Fatalf("NewCapabilityResolver() error = %v", err) - } - - for _, candidate := range snapshot.Columns { - resolved, err := resolver.ResolveColumn(candidate.ID) - if err != nil { - t.Fatalf("ResolveColumn(%q) error = %v", candidate.ID, err) - } - if resolved.ID != candidate.ID || resolved.ResourceType != candidate.ResourceType || resolved.ValueKind != candidate.ValueKind || resolved.Repeated != candidate.Repeated || resolved.CanSelect != candidate.CanSelect || resolved.CanFilter != candidate.CanFilter || resolved.CanPivot != candidate.CanPivot { - t.Errorf("column resolution for %q does not match snapshot candidate\nresolved: %+v\ncandidate: %+v", candidate.ID, resolved, candidate) - } - } - for _, relationship := range snapshot.Relationships.Entries { - resolved, err := resolver.ResolveRelationship(relationship.ID) - if err != nil { - t.Fatalf("ResolveRelationship(%q) error = %v", relationship.ID, err) - } - if resolved.ID != relationship.ID || resolved.FromResourceType != relationship.FromResourceType || resolved.ToResourceType != relationship.ToResourceType || resolved.Multiplicity != relationship.Multiplicity || resolved.ObservedEdgeCount != relationship.ObservedEdgeCount { - t.Errorf("relationship resolution for %q does not match snapshot relationship\nresolved: %+v\nrelationship: %+v", relationship.ID, resolved, relationship) - } - if resolved.EdgeLabel != "subject_Patient" || resolved.Traversal.FromType != "Patient" || resolved.Traversal.ToType != "Specimen" { - t.Errorf("relationship resolution lost generated route metadata: %+v", resolved) - } - } - - gender := findColumn(t, snapshot.Columns, "Patient", "Gender") - resolvedGender, err := resolver.ResolveColumn(gender.ID) - if err != nil { - t.Fatalf("ResolveColumn(gender) error = %v", err) - } - if resolvedGender.CanonicalPath != "gender" || resolvedGender.Selector == nil || fhirschema.SelectorExpression(*resolvedGender.Selector) != "gender" { - t.Errorf("gender resolution selector = %+v path=%q", resolvedGender.Selector, resolvedGender.CanonicalPath) - } - if !containsFilterOperator(resolvedGender.FilterOperators, FilterContains) || len(resolvedGender.FilterQuantifiers) != 0 { - t.Errorf("gender resolution filter metadata = operators=%v quantifiers=%v", resolvedGender.FilterOperators, resolvedGender.FilterQuantifiers) - } - - code := findColumn(t, snapshot.Columns, "Observation", "Code") - resolvedCode, err := resolver.ResolveColumn(code.ID) - if err != nil { - t.Fatalf("ResolveColumn(code) error = %v", err) - } - if resolvedCode.Selector != nil || resolvedCode.Pivot == nil { - t.Fatalf("code resolution = %+v, want pivot-only capability", resolvedCode) - } - if resolvedCode.Pivot.Family != fhirschema.PivotFamilyObservationCodeValue || - fhirschema.SelectorExpression(resolvedCode.Pivot.ColumnSelector) != "code.coding[].display" || - fhirschema.SelectorExpression(resolvedCode.Pivot.ValueSelector) != "valueInteger" || - !equalStrings(resolvedCode.Pivot.Columns, []string{"Hemoglobin"}) { - t.Errorf("code pivot metadata = %+v", resolvedCode.Pivot) - } - - resolvedRelationship, err := resolver.ResolveRelationship(snapshot.Relationships.Entries[0].ID) - if err != nil { - t.Fatalf("ResolveRelationship() before JSON check: %v", err) - } - for _, value := range []any{resolvedGender, resolvedCode, resolvedRelationship} { - encoded, err := json.Marshal(value) - if err != nil { - t.Fatalf("marshal resolved capability: %v", err) - } - if string(encoded) != "{}" { - t.Errorf("resolved capability unexpectedly has JSON surface: %s", encoded) - } - } -} - -func TestCapabilityResolverRejectsUnknownStaleAndCrossProjectFacts(t *testing.T) { - facts := resolutionFacts() - snapshot, err := BuildSnapshot(facts) - if err != nil { - t.Fatalf("BuildSnapshot() error = %v", err) - } - gender := findColumn(t, snapshot.Columns, "Patient", "Gender") - relationshipID := snapshot.Relationships.Entries[0].ID - - freshFacts := CatalogFacts{ - Project: "project-a", - Fields: []catalog.PopulatedField{{ - Project: "project-a", ResourceType: "Patient", Path: "birthDate", Kind: "scalar", DocCount: 1, - }}, - } - resolver, err := NewCapabilityResolver(freshFacts) - if err != nil { - t.Fatalf("NewCapabilityResolver(fresh) error = %v", err) - } - if _, err := resolver.ResolveColumn(gender.ID); !errors.Is(err, ErrColumnUnavailable) { - t.Errorf("stale column error = %v, want ErrColumnUnavailable", err) - } - if _, err := resolver.ResolveRelationship(relationshipID); !errors.Is(err, ErrRelationshipUnavailable) { - t.Errorf("stale relationship error = %v, want ErrRelationshipUnavailable", err) - } - unknownColumn := ColumnID("col_" + strings.Repeat("0", 64)) - unknownRelationship := RelationshipID("rel_" + strings.Repeat("0", 64)) - if _, err := resolver.ResolveColumn(unknownColumn); !errors.Is(err, ErrColumnUnavailable) { - t.Errorf("unknown column error = %v, want ErrColumnUnavailable", err) - } - if _, err := resolver.ResolveRelationship(unknownRelationship); !errors.Is(err, ErrRelationshipUnavailable) { - t.Errorf("unknown relationship error = %v, want ErrRelationshipUnavailable", err) - } - - _, err = NewCapabilityResolver(CatalogFacts{ - Project: "project-a", - Fields: []catalog.PopulatedField{{ - Project: "other-project", ResourceType: "Patient", Path: "gender", Kind: "scalar", DocCount: 1, - }}, - }) - if err == nil || !strings.Contains(err.Error(), "project") { - t.Errorf("cross-project facts error = %v, want project mismatch", err) - } -} - -func TestInvalidCatalogPivotDoesNotBecomeResolvableCapability(t *testing.T) { - facts := CatalogFacts{ - Project: "project-a", - Fields: []catalog.PopulatedField{{ - Project: "project-a", - ResourceType: "Observation", - Path: "code", - Kind: "codeable_concept", - DocCount: 1, - PivotCandidate: true, - PivotColumnSelect: "code.coding[].display", - PivotValueSelect: "notARepresentedValue", - PivotColumns: []string{"Hemoglobin"}, - }}, - } - snapshot, err := BuildSnapshot(facts) - if err != nil { - t.Fatalf("BuildSnapshot() error = %v", err) - } - for _, column := range snapshot.Columns { - if column.ResourceType == "Observation" && column.Label == "Code" { - t.Errorf("unsupported observed pivot leaked into Snapshot: %+v", column) - } - } - resolver, err := NewCapabilityResolver(facts) - if err != nil { - t.Fatalf("NewCapabilityResolver() error = %v", err) - } - if _, err := resolver.ResolveColumn(opaqueColumnID("Observation", "code")); !errors.Is(err, ErrColumnUnavailable) { - t.Errorf("unsupported pivot resolution error = %v, want ErrColumnUnavailable", err) - } -} - -func resolutionFacts() CatalogFacts { - return CatalogFacts{ - Project: "project-a", - Fields: []catalog.PopulatedField{ - { - Project: "project-a", ResourceType: "Patient", Path: "gender", Kind: "scalar", DocCount: 3, - DistinctValues: []string{"female", "male"}, - }, - { - Project: "project-a", - ResourceType: "Observation", - Path: "code", - Kind: "codeable_concept", - DocCount: 3, - DistinctValues: []string{"Hemoglobin"}, - PivotCandidate: true, - PivotFamily: fhirschema.PivotFamilyObservationCodeValue, - PivotColumnSelect: "code.coding[].display", - PivotValueSelect: "valueInteger", - PivotColumns: []string{"Hemoglobin"}, - }, - }, - Relationships: []catalog.PopulatedReference{ - {FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 3}, - }, - } -} - -func containsFilterOperator(operators []FilterOperator, want FilterOperator) bool { - for _, operator := range operators { - if operator == want { - return true - } - } - return false -} diff --git a/internal/discovery/types.go b/internal/discovery/types.go deleted file mode 100644 index e2f379c..0000000 --- a/internal/discovery/types.go +++ /dev/null @@ -1,186 +0,0 @@ -// Package discovery defines the internal, catalog-backed vocabulary used to -// build a guided dataframe experience. It deliberately exposes opaque column -// and relationship identifiers instead of FHIR selectors or graph labels. -// -// The package has no transport or database dependency. A caller first obtains -// scoped facts from internal/catalog, then passes those facts to BuildSnapshot. -// A later command handler must resolve every opaque identifier against a fresh, -// authorized snapshot before it asks the dataframe compiler to lower a query. -package discovery - -import "github.com/calypr/loom/internal/catalog" - -const maxSuggestedValues = 50 - -// CatalogFacts is a server-internal adapter input. Fields and Relationships -// must already have been read for one authorized project/scope using the -// existing catalog readers. It is intentionally not a transport request: it -// carries catalog facts, including implementation-level field paths, only long -// enough for BuildSnapshot to turn them into opaque user-facing identifiers. -// This package deliberately does not create a dataset, generation, or scope -// identity model; an owning identity layer can correlate this scoped snapshot -// later without changing the discovery vocabulary. -type CatalogFacts struct { - Project string - Fields []catalog.PopulatedField - Relationships []catalog.PopulatedReference -} - -// Snapshot is the bounded discovery response that a guided frontend may use. -// It contains no FHIR field paths, selectors, AQL fragments, collection names, -// authorization paths, or graph edge labels. -type Snapshot struct { - Dataset DatasetSummary `json:"dataset"` - Relationships RelationshipInventory `json:"relationships"` - Columns []CandidateColumn `json:"columns"` - Filters []GuidedFilterSuggestion `json:"filters"` -} - -// DatasetSummary describes the generated-schema root resources and their -// availability in the supplied catalog facts. Roots remain present even when -// unavailable so a caller can distinguish "not loaded in this scope" from -// "not represented by this Loom build". A user-facing chooser should normally -// offer only roots whose Available flag is true. -type DatasetSummary struct { - Project string `json:"project"` - Roots []RootResourceSummary `json:"roots"` -} - -// RootResourceSummary is derived from the active generated FHIR schema and -// then annotated from catalog facts. The counts describe discoverable compiler -// inputs, not a total number of FHIR documents. -type RootResourceSummary struct { - ResourceType string `json:"resourceType"` - Supported bool `json:"supported"` - Available bool `json:"available"` - SupportReason RootSupportReason `json:"supportReason"` - CandidateColumnCount int `json:"candidateColumnCount"` - RelationshipCount int `json:"relationshipCount"` -} - -// RootSupportReason is intentionally small and stable. It describes only the -// generated-schema/catalog evidence available to this package; it is not a -// dataset generation, load job, or persistence state. -type RootSupportReason string - -const ( - RootSupportObservedInCatalog RootSupportReason = "OBSERVED_IN_CATALOG" - RootSupportNotObservedInCatalog RootSupportReason = "NOT_OBSERVED_IN_CATALOG" -) - -// RelationshipID is an opaque, deterministic identifier. It is stable for a -// generated-schema route while the active graph schema remains the same. -type RelationshipID string - -// RelationshipInventory contains only populated routes that are represented -// by the active generated FHIR graph schema. Its entries are suitable for a -// guided "include related …" chooser, but do not imply a physical AQL -// direction. -type RelationshipInventory struct { - Entries []Relationship `json:"entries"` -} - -// RelationshipMultiplicity is the schema-declared target cardinality. It is a -// semantic fact, not an estimate of rows or an AQL traversal direction. -type RelationshipMultiplicity string - -const ( - RelationshipOne RelationshipMultiplicity = "ONE" - RelationshipMany RelationshipMultiplicity = "MANY" -) - -// Relationship is a populated, compiler-safe route between concrete generated -// FHIR resource roots. Label is presentation text; the underlying graph label -// remains internal and is recoverable only by resolving ID against facts. -type Relationship struct { - ID RelationshipID `json:"id"` - FromResourceType string `json:"fromResourceType"` - ToResourceType string `json:"toResourceType"` - Label string `json:"label"` - Multiplicity RelationshipMultiplicity `json:"multiplicity"` - ObservedEdgeCount int64 `json:"observedEdgeCount"` -} - -// ColumnID is an opaque, deterministic identifier for a catalog field. It is -// deliberately not a field path or a dataframe FieldRef. -type ColumnID string - -// ValueKind is the safe scalar shape known from generated FHIR metadata. A -// COMPOSITE candidate represents a catalog pivot root and is not directly -// filterable or selectable until a later compiler adapter resolves it. -type ValueKind string - -const ( - ValueKindString ValueKind = "STRING" - ValueKindBoolean ValueKind = "BOOLEAN" - ValueKindInteger ValueKind = "INTEGER" - ValueKindDecimal ValueKind = "DECIMAL" - ValueKindDate ValueKind = "DATE" - ValueKindDateTime ValueKind = "DATE_TIME" - ValueKindComposite ValueKind = "COMPOSITE" -) - -// CandidateColumn is a safe frontend-facing field choice. Capability flags -// make composite pivot roots explicit instead of pretending every observed -// catalog object can be lowered as a scalar dataframe column. -type CandidateColumn struct { - ID ColumnID `json:"id"` - ResourceType string `json:"resourceType"` - Label string `json:"label"` - ValueKind ValueKind `json:"valueKind"` - Repeated bool `json:"repeated"` - CanSelect bool `json:"canSelect"` - CanFilter bool `json:"canFilter"` - CanPivot bool `json:"canPivot"` - PopulatedDocumentCount int64 `json:"populatedDocumentCount"` - SuggestedValues []string `json:"suggestedValues"` - ValuesTruncated bool `json:"valuesTruncated"` -} - -// FilterSuggestionID is an opaque, deterministic identifier for the guided -// filter affordance associated with a scalar CandidateColumn. -type FilterSuggestionID string - -// FilterOperator is intentionally a closed product vocabulary. A later -// compiler adapter maps these tokens to dataframe.TypedFilter only after it -// resolves ColumnID against the current authorized catalog facts. -type FilterOperator string - -const ( - FilterEquals FilterOperator = "EQUALS" - FilterNotEquals FilterOperator = "NOT_EQUALS" - FilterIn FilterOperator = "IN" - FilterExists FilterOperator = "EXISTS" - FilterMissing FilterOperator = "MISSING" - FilterContains FilterOperator = "CONTAINS_TEXT" - FilterGreaterThan FilterOperator = "GT" - FilterGreaterEq FilterOperator = "GTE" - FilterLessThan FilterOperator = "LT" - FilterLessEq FilterOperator = "LTE" -) - -// FilterQuantifier controls how a repeated scalar field is evaluated. Scalar -// candidates have no quantifier options. -type FilterQuantifier string - -const ( - FilterAny FilterQuantifier = "ANY" - FilterAll FilterQuantifier = "ALL" - FilterNone FilterQuantifier = "NONE" -) - -// GuidedFilterSuggestion is the complete field/operator/value vocabulary for -// a guided filter sentence such as "Gender is female." Values are examples -// observed by the catalog, not an exhaustive terminology list. -type GuidedFilterSuggestion struct { - ID FilterSuggestionID `json:"id"` - ColumnID ColumnID `json:"columnId"` - ResourceType string `json:"resourceType"` - Label string `json:"label"` - ValueKind ValueKind `json:"valueKind"` - Repeated bool `json:"repeated"` - Operators []FilterOperator `json:"operators"` - Quantifiers []FilterQuantifier `json:"quantifiers"` - SuggestedValues []string `json:"suggestedValues"` - ValuesTruncated bool `json:"valuesTruncated"` -} diff --git a/internal/discovery/validation.go b/internal/discovery/validation.go deleted file mode 100644 index bb9e732..0000000 --- a/internal/discovery/validation.go +++ /dev/null @@ -1,326 +0,0 @@ -package discovery - -import ( - "encoding/hex" - "fmt" - "strings" - - "github.com/calypr/loom/internal/fhirschema" -) - -// Validate proves that a Snapshot remains a normalized, compiler-safe product -// contract. It is useful at the boundary where a later command handler accepts -// IDs chosen from a prior discovery response. -func (snapshot Snapshot) Validate() error { - if strings.TrimSpace(snapshot.Dataset.Project) == "" { - return fmt.Errorf("dataset project is required") - } - roots, err := validateRoots(snapshot.Dataset.Roots) - if err != nil { - return err - } - - columnCounts := make(map[string]int, len(roots)) - columns, err := validateColumns(snapshot.Columns, roots, columnCounts) - if err != nil { - return err - } - relationshipCounts := make(map[string]int, len(roots)) - if err := validateRelationships(snapshot.Relationships.Entries, roots, relationshipCounts); err != nil { - return err - } - if err := validateFilters(snapshot.Filters, columns); err != nil { - return err - } - - for _, root := range snapshot.Dataset.Roots { - if root.CandidateColumnCount != columnCounts[root.ResourceType] { - return fmt.Errorf("root candidate column count does not match columns") - } - if root.RelationshipCount != relationshipCounts[root.ResourceType] { - return fmt.Errorf("root relationship count does not match relationships") - } - if root.Available != (root.CandidateColumnCount > 0 || root.RelationshipCount > 0 || hasIncomingRelationship(snapshot.Relationships.Entries, root.ResourceType)) { - return fmt.Errorf("root availability does not match supplied catalog facts") - } - } - return nil -} - -func validateRoots(roots []RootResourceSummary) (map[string]RootResourceSummary, error) { - expected := fhirschema.ResourceTypes() - if len(roots) != len(expected) { - return nil, fmt.Errorf("dataset roots do not match active generated schema") - } - byType := make(map[string]RootResourceSummary, len(roots)) - for i, root := range roots { - if root.ResourceType != expected[i] { - return nil, fmt.Errorf("dataset roots are not the sorted active generated schema roots") - } - if !root.Supported { - return nil, fmt.Errorf("generated schema root must be marked supported") - } - if !root.SupportReason.Valid() { - return nil, fmt.Errorf("root support reason is invalid") - } - if root.Available && root.SupportReason != RootSupportObservedInCatalog { - return nil, fmt.Errorf("available root must have observed catalog support reason") - } - if !root.Available && root.SupportReason != RootSupportNotObservedInCatalog { - return nil, fmt.Errorf("unavailable root must have not observed support reason") - } - if root.CandidateColumnCount < 0 || root.RelationshipCount < 0 { - return nil, fmt.Errorf("root counts must not be negative") - } - byType[root.ResourceType] = root - } - return byType, nil -} - -func validateColumns(columns []CandidateColumn, roots map[string]RootResourceSummary, counts map[string]int) (map[ColumnID]CandidateColumn, error) { - byID := make(map[ColumnID]CandidateColumn, len(columns)) - var previous CandidateColumn - for index, column := range columns { - if !validOpaqueID(string(column.ID), "col_") { - return nil, fmt.Errorf("candidate column ID is not a valid opaque identifier") - } - if _, ok := roots[column.ResourceType]; !ok { - return nil, fmt.Errorf("candidate column resource type is not an active generated root") - } - if strings.TrimSpace(column.Label) == "" { - return nil, fmt.Errorf("candidate column label is required") - } - if !column.ValueKind.Valid() { - return nil, fmt.Errorf("candidate column has an unsupported value kind") - } - if column.PopulatedDocumentCount < 0 { - return nil, fmt.Errorf("candidate column population count must not be negative") - } - if err := validateColumnCapabilities(column); err != nil { - return nil, err - } - if err := validateSuggestedValues(column.SuggestedValues); err != nil { - return nil, err - } - if _, exists := byID[column.ID]; exists { - return nil, fmt.Errorf("candidate column IDs must be unique") - } - if index > 0 && compareColumns(previous, column) >= 0 { - return nil, fmt.Errorf("candidate columns are not sorted deterministically") - } - previous = column - byID[column.ID] = column - counts[column.ResourceType]++ - } - return byID, nil -} - -func validateColumnCapabilities(column CandidateColumn) error { - switch column.ValueKind { - case ValueKindComposite: - if column.Repeated || column.CanSelect || column.CanFilter || !column.CanPivot { - return fmt.Errorf("composite candidate must be pivot-only") - } - default: - if !column.CanSelect || !column.CanFilter { - return fmt.Errorf("scalar candidate must support selection and filtering") - } - } - return nil -} - -func validateRelationships(relationships []Relationship, roots map[string]RootResourceSummary, counts map[string]int) error { - seen := make(map[RelationshipID]struct{}, len(relationships)) - var previous Relationship - for index, relationship := range relationships { - if !validOpaqueID(string(relationship.ID), "rel_") { - return fmt.Errorf("relationship ID is not a valid opaque identifier") - } - if _, ok := roots[relationship.FromResourceType]; !ok { - return fmt.Errorf("relationship source is not an active generated root") - } - if _, ok := roots[relationship.ToResourceType]; !ok { - return fmt.Errorf("relationship target is not an active generated root") - } - if strings.TrimSpace(relationship.Label) == "" { - return fmt.Errorf("relationship label is required") - } - if !relationship.Multiplicity.Valid() { - return fmt.Errorf("relationship has unsupported multiplicity") - } - if relationship.ObservedEdgeCount < 0 { - return fmt.Errorf("relationship edge count must not be negative") - } - if _, exists := seen[relationship.ID]; exists { - return fmt.Errorf("relationship IDs must be unique") - } - if index > 0 && compareRelationships(previous, relationship) >= 0 { - return fmt.Errorf("relationships are not sorted deterministically") - } - previous = relationship - seen[relationship.ID] = struct{}{} - counts[relationship.FromResourceType]++ - } - return nil -} - -func validateFilters(filters []GuidedFilterSuggestion, columns map[ColumnID]CandidateColumn) error { - seen := make(map[FilterSuggestionID]struct{}, len(filters)) - var previous GuidedFilterSuggestion - filterableColumns := 0 - for _, column := range columns { - if column.CanFilter { - filterableColumns++ - } - } - if len(filters) != filterableColumns { - return fmt.Errorf("guided filters must cover every filterable candidate exactly once") - } - for index, filter := range filters { - if !validOpaqueID(string(filter.ID), "flt_") { - return fmt.Errorf("guided filter ID is not a valid opaque identifier") - } - column, ok := columns[filter.ColumnID] - if !ok || !column.CanFilter { - return fmt.Errorf("guided filter does not resolve to a filterable candidate") - } - if filter.ID != opaqueFilterSuggestionID(filter.ColumnID) || - filter.ResourceType != column.ResourceType || - filter.Label != column.Label || - filter.ValueKind != column.ValueKind || - filter.Repeated != column.Repeated || - !equalFilterOperators(filter.Operators, filterOperators(column.ValueKind)) || - !equalFilterQuantifiers(filter.Quantifiers, filterQuantifiers(column.Repeated)) || - !equalStrings(filter.SuggestedValues, column.SuggestedValues) || - filter.ValuesTruncated != column.ValuesTruncated { - return fmt.Errorf("guided filter does not match its candidate") - } - if _, exists := seen[filter.ID]; exists { - return fmt.Errorf("guided filter IDs must be unique") - } - if index > 0 && compareFilters(previous, filter) >= 0 { - return fmt.Errorf("guided filters are not sorted deterministically") - } - previous = filter - seen[filter.ID] = struct{}{} - } - return nil -} - -func hasIncomingRelationship(relationships []Relationship, resourceType string) bool { - for _, relationship := range relationships { - if relationship.ToResourceType == resourceType { - return true - } - } - return false -} - -func validOpaqueID(value, prefix string) bool { - if !strings.HasPrefix(value, prefix) || len(value) != len(prefix)+64 { - return false - } - _, err := hex.DecodeString(strings.TrimPrefix(value, prefix)) - return err == nil -} - -func validateSuggestedValues(values []string) error { - if len(values) > maxSuggestedValues { - return fmt.Errorf("suggested values exceed the bounded limit") - } - for index, value := range values { - if strings.TrimSpace(value) == "" { - return fmt.Errorf("suggested values must not be empty") - } - if index > 0 && values[index-1] >= value { - return fmt.Errorf("suggested values are not sorted and unique") - } - } - return nil -} - -func compareColumns(left, right CandidateColumn) int { - if left.ResourceType != right.ResourceType { - return strings.Compare(left.ResourceType, right.ResourceType) - } - if left.Label != right.Label { - return strings.Compare(left.Label, right.Label) - } - return strings.Compare(string(left.ID), string(right.ID)) -} - -func compareRelationships(left, right Relationship) int { - if left.FromResourceType != right.FromResourceType { - return strings.Compare(left.FromResourceType, right.FromResourceType) - } - if left.ToResourceType != right.ToResourceType { - return strings.Compare(left.ToResourceType, right.ToResourceType) - } - if left.Label != right.Label { - return strings.Compare(left.Label, right.Label) - } - return strings.Compare(string(left.ID), string(right.ID)) -} - -func compareFilters(left, right GuidedFilterSuggestion) int { - if left.ResourceType != right.ResourceType { - return strings.Compare(left.ResourceType, right.ResourceType) - } - if left.Label != right.Label { - return strings.Compare(left.Label, right.Label) - } - return strings.Compare(string(left.ID), string(right.ID)) -} - -func equalStrings(left, right []string) bool { - if len(left) != len(right) { - return false - } - for index := range left { - if left[index] != right[index] { - return false - } - } - return true -} - -func equalFilterOperators(left, right []FilterOperator) bool { - if len(left) != len(right) { - return false - } - for index := range left { - if left[index] != right[index] { - return false - } - } - return true -} - -func equalFilterQuantifiers(left, right []FilterQuantifier) bool { - if len(left) != len(right) { - return false - } - for index := range left { - if left[index] != right[index] { - return false - } - } - return true -} - -func (kind ValueKind) Valid() bool { - switch kind { - case ValueKindString, ValueKindBoolean, ValueKindInteger, ValueKindDecimal, ValueKindDate, ValueKindDateTime, ValueKindComposite: - return true - default: - return false - } -} - -func (multiplicity RelationshipMultiplicity) Valid() bool { - return multiplicity == RelationshipOne || multiplicity == RelationshipMany -} - -func (reason RootSupportReason) Valid() bool { - return reason == RootSupportObservedInCatalog || reason == RootSupportNotObservedInCatalog -} diff --git a/internal/export/encode.go b/internal/export/encode.go deleted file mode 100644 index eb0622c..0000000 --- a/internal/export/encode.go +++ /dev/null @@ -1,369 +0,0 @@ -// Package export serializes flat dataframe rows to portable export formats. -// -// It deliberately owns only row encoding. Query execution, artifact storage, -// delivery transports, and job management stay outside this package so every -// destination can consume the same flat-row contract. -package export - -import ( - "context" - "encoding/csv" - "encoding/json" - "fmt" - "io" - "math" - "reflect" - "sort" - "strconv" -) - -// RowVisitor receives one flat dataframe row. Returning an error asks the -// producer to stop iteration. -type RowVisitor func(map[string]any) error - -// RowStream emits rows without materializing the dataframe in this package. -// -// A stream must respect an error returned by RowVisitor. EncodeCSV calls a -// stream once when CSVOptions.Columns is supplied and twice otherwise: once -// to discover the deterministic column union and once to write records. For -// that mode, callers must provide a replayable stream that returns the same -// logical rows in the same order for each invocation (for example, re-running -// a stable compiled query). -type RowStream func(context.Context, RowVisitor) error - -// Result describes encoder progress. On success it describes the complete -// export. If an encoder returns an error, Rows and Bytes describe only the -// progress observed before that error. Columns is always in output order. -type Result struct { - Rows int64 - Bytes int64 - Columns []string -} - -// CSVOptions controls CSV schema selection. A non-empty Columns slice is the -// exact header and field order to write. Rows containing a column outside the -// configured schema are rejected rather than silently discarded. With no -// columns, EncodeCSV discovers the union of all row keys and sorts it -// lexicographically. -type CSVOptions struct { - Columns []string -} - -// ValueError reports a value that cannot be represented as a flat dataframe -// scalar. Maps, slices, structs, pointers, and non-finite numbers are -// intentionally rejected instead of being stringified or nested in output. -type ValueError struct { - Row int64 - Column string - ValueType string - Reason string -} - -func (e *ValueError) Error() string { - if e.Reason != "" { - return fmt.Sprintf("row %d column %q has unsupported value of type %s: %s", e.Row, e.Column, e.ValueType, e.Reason) - } - return fmt.Sprintf("row %d column %q has unsupported nested value of type %s; export rows must contain scalar values", e.Row, e.Column, e.ValueType) -} - -// ColumnError reports an invalid CSV schema or a row field that cannot be -// represented by that schema. Row is zero for a configured-header error. -type ColumnError struct { - Row int64 - Column string - Reason string -} - -func (e *ColumnError) Error() string { - if e.Row == 0 { - return fmt.Sprintf("CSV column %q %s", e.Column, e.Reason) - } - return fmt.Sprintf("row %d column %q %s", e.Row, e.Column, e.Reason) -} - -// EncodeNDJSON writes one JSON object and exactly one trailing newline for -// every row in stream. It retains at most one encoded row plus the observed -// column set, never the complete dataframe. -func EncodeNDJSON(ctx context.Context, dst io.Writer, stream RowStream) (Result, error) { - if dst == nil { - return Result{}, fmt.Errorf("NDJSON destination writer is required") - } - - writer := &countingWriter{dst: dst} - columns := make(map[string]struct{}) - var result Result - err := visitRows(ctx, stream, func(row map[string]any) error { - rowNumber := result.Rows + 1 - keys, err := validateRow(row, rowNumber) - if err != nil { - return err - } - for _, key := range keys { - columns[key] = struct{}{} - } - - encoded, err := marshalRow(row) - if err != nil { - return fmt.Errorf("row %d: encode NDJSON: %w", rowNumber, err) - } - encoded = append(encoded, '\n') - if _, err := writeAll(writer, encoded); err != nil { - return fmt.Errorf("row %d: write NDJSON: %w", rowNumber, err) - } - result.Rows++ - return nil - }) - result.Bytes = writer.n - result.Columns = sortedColumns(columns) - if err != nil { - return result, err - } - return result, nil -} - -// EncodeCSV writes a CSV header followed by one record for each row. It uses -// encoding/csv for RFC 4180-compatible escaping. When Columns is omitted the -// source is scanned once to discover a sorted column union, then replayed to -// encode rows; this keeps memory proportional to the number of columns rather -// than the number of rows. -func EncodeCSV(ctx context.Context, dst io.Writer, options CSVOptions, stream RowStream) (Result, error) { - if dst == nil { - return Result{}, fmt.Errorf("CSV destination writer is required") - } - - columns, allowed, err := configuredColumns(options.Columns) - if err != nil { - return Result{}, err - } - if len(columns) == 0 { - columns, err = discoverColumns(ctx, stream) - if err != nil { - return Result{}, err - } - allowed = make(map[string]struct{}, len(columns)) - for _, column := range columns { - allowed[column] = struct{}{} - } - } - - writer := &countingWriter{dst: dst} - csvWriter := csv.NewWriter(writer) - if len(columns) > 0 { - if err := csvWriter.Write(columns); err != nil { - return Result{Columns: cloneStrings(columns)}, fmt.Errorf("write CSV header: %w", err) - } - } - - result := Result{Columns: cloneStrings(columns)} - streamErr := visitRows(ctx, stream, func(row map[string]any) error { - rowNumber := result.Rows + 1 - keys, err := validateRow(row, rowNumber) - if err != nil { - return err - } - for _, key := range keys { - if _, ok := allowed[key]; !ok { - return &ColumnError{Row: rowNumber, Column: key, Reason: "is not present in the CSV schema"} - } - } - - record := make([]string, len(columns)) - for i, column := range columns { - record[i] = scalarString(row[column]) - } - if err := csvWriter.Write(record); err != nil { - return fmt.Errorf("row %d: write CSV: %w", rowNumber, err) - } - result.Rows++ - return nil - }) - csvWriter.Flush() - result.Bytes = writer.n - if streamErr != nil { - return result, streamErr - } - if err := csvWriter.Error(); err != nil { - return result, fmt.Errorf("write CSV: %w", err) - } - return result, nil -} - -func visitRows(ctx context.Context, stream RowStream, visit RowVisitor) error { - if stream == nil { - return fmt.Errorf("export row stream is required") - } - if err := ctx.Err(); err != nil { - return err - } - if err := stream(ctx, func(row map[string]any) error { - if err := ctx.Err(); err != nil { - return err - } - return visit(row) - }); err != nil { - return fmt.Errorf("stream export rows: %w", err) - } - return ctx.Err() -} - -func configuredColumns(columns []string) ([]string, map[string]struct{}, error) { - if len(columns) == 0 { - return nil, nil, nil - } - out := cloneStrings(columns) - seen := make(map[string]struct{}, len(out)) - for _, column := range out { - if column == "" { - return nil, nil, &ColumnError{Column: column, Reason: "must not be empty"} - } - if _, ok := seen[column]; ok { - return nil, nil, &ColumnError{Column: column, Reason: "is duplicated"} - } - seen[column] = struct{}{} - } - return out, seen, nil -} - -func discoverColumns(ctx context.Context, stream RowStream) ([]string, error) { - columns := make(map[string]struct{}) - var rows int64 - err := visitRows(ctx, stream, func(row map[string]any) error { - rows++ - keys, err := validateRow(row, rows) - if err != nil { - return err - } - for _, key := range keys { - columns[key] = struct{}{} - } - return nil - }) - if err != nil { - return nil, err - } - return sortedColumns(columns), nil -} - -func validateRow(row map[string]any, rowNumber int64) ([]string, error) { - keys := make([]string, 0, len(row)) - for key := range row { - keys = append(keys, key) - } - sort.Strings(keys) - for _, key := range keys { - if key == "" { - return nil, &ColumnError{Row: rowNumber, Column: key, Reason: "must not be empty"} - } - if err := validateScalar(row[key], rowNumber, key); err != nil { - return nil, err - } - } - return keys, nil -} - -func validateScalar(value any, rowNumber int64, column string) error { - if value == nil { - return nil - } - valueType := reflect.TypeOf(value).String() - if _, ok := value.(json.Marshaler); ok { - return &ValueError{Row: rowNumber, Column: column, ValueType: valueType, Reason: "custom JSON marshalers are not supported for flat export values"} - } - valueOf := reflect.ValueOf(value) - switch valueOf.Kind() { - case reflect.Bool, reflect.String, - reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, - reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - if number, ok := value.(json.Number); ok { - if _, err := json.Marshal(number); err != nil { - return &ValueError{Row: rowNumber, Column: column, ValueType: valueType, Reason: "invalid JSON number"} - } - } - return nil - case reflect.Float32, reflect.Float64: - floatValue := valueOf.Float() - if math.IsNaN(floatValue) || math.IsInf(floatValue, 0) { - return &ValueError{Row: rowNumber, Column: column, ValueType: valueType, Reason: "non-finite numbers are not valid JSON"} - } - return nil - default: - return &ValueError{Row: rowNumber, Column: column, ValueType: valueType} - } -} - -func marshalRow(row map[string]any) ([]byte, error) { - if row == nil { - return []byte("{}"), nil - } - return json.Marshal(row) -} - -func scalarString(value any) string { - if value == nil { - return "" - } - valueOf := reflect.ValueOf(value) - switch valueOf.Kind() { - case reflect.String: - return valueOf.String() - case reflect.Bool: - return strconv.FormatBool(valueOf.Bool()) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return strconv.FormatInt(valueOf.Int(), 10) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return strconv.FormatUint(valueOf.Uint(), 10) - case reflect.Float32, reflect.Float64: - return strconv.FormatFloat(valueOf.Float(), 'g', -1, valueOf.Type().Bits()) - default: - return "" - } -} - -func sortedColumns(columns map[string]struct{}) []string { - if len(columns) == 0 { - return []string{} - } - out := make([]string, 0, len(columns)) - for column := range columns { - out = append(out, column) - } - sort.Strings(out) - return out -} - -func cloneStrings(values []string) []string { - if len(values) == 0 { - return []string{} - } - return append([]string(nil), values...) -} - -type countingWriter struct { - dst io.Writer - n int64 -} - -func (w *countingWriter) Write(p []byte) (int, error) { - n, err := w.dst.Write(p) - w.n += int64(n) - if err == nil && n != len(p) { - return n, io.ErrShortWrite - } - return n, err -} - -func writeAll(dst io.Writer, data []byte) (int64, error) { - var written int64 - for len(data) > 0 { - n, err := dst.Write(data) - written += int64(n) - data = data[n:] - if err != nil { - return written, err - } - if n == 0 { - return written, io.ErrShortWrite - } - } - return written, nil -} diff --git a/internal/export/encode_test.go b/internal/export/encode_test.go deleted file mode 100644 index 009fd37..0000000 --- a/internal/export/encode_test.go +++ /dev/null @@ -1,215 +0,0 @@ -package export - -import ( - "bytes" - "context" - "encoding/csv" - "encoding/json" - "errors" - "reflect" - "strings" - "testing" -) - -func TestEncodeNDJSONWritesOneDeterministicObjectPerLine(t *testing.T) { - rows := staticRows( - map[string]any{"zeta": 2, "alpha": "first"}, - map[string]any{"alpha": "second", "nullable": nil}, - ) - - var output bytes.Buffer - result, err := EncodeNDJSON(context.Background(), &output, rows) - if err != nil { - t.Fatalf("EncodeNDJSON() error = %v", err) - } - const want = "{\"alpha\":\"first\",\"zeta\":2}\n{\"alpha\":\"second\",\"nullable\":null}\n" - if got := output.String(); got != want { - t.Fatalf("NDJSON = %q, want %q", got, want) - } - if result.Rows != 2 { - t.Fatalf("Rows = %d, want 2", result.Rows) - } - if result.Bytes != int64(len(want)) { - t.Fatalf("Bytes = %d, want %d", result.Bytes, len(want)) - } - if wantColumns := []string{"alpha", "nullable", "zeta"}; !reflect.DeepEqual(result.Columns, wantColumns) { - t.Fatalf("Columns = %#v, want %#v", result.Columns, wantColumns) - } - - for _, line := range strings.Split(strings.TrimSuffix(output.String(), "\n"), "\n") { - var row map[string]any - if err := json.Unmarshal([]byte(line), &row); err != nil { - t.Fatalf("NDJSON line %q is not an object: %v", line, err) - } - } -} - -func TestEncodeCSVDiscoversSortedColumnUnionWithoutMaterializingRows(t *testing.T) { - var passes int - rows := func(ctx context.Context, visit RowVisitor) error { - passes++ - for _, row := range []map[string]any{ - {"zeta": "z", "alpha": "a"}, - {"middle": 2, "alpha": "again"}, - } { - if err := visit(row); err != nil { - return err - } - } - return nil - } - - var output bytes.Buffer - result, err := EncodeCSV(context.Background(), &output, CSVOptions{}, rows) - if err != nil { - t.Fatalf("EncodeCSV() error = %v", err) - } - const want = "alpha,middle,zeta\na,,z\nagain,2,\n" - if got := output.String(); got != want { - t.Fatalf("CSV = %q, want %q", got, want) - } - if passes != 2 { - t.Fatalf("stream passes = %d, want 2 for inferred columns", passes) - } - if result.Rows != 2 { - t.Fatalf("Rows = %d, want 2", result.Rows) - } - if wantColumns := []string{"alpha", "middle", "zeta"}; !reflect.DeepEqual(result.Columns, wantColumns) { - t.Fatalf("Columns = %#v, want %#v", result.Columns, wantColumns) - } -} - -func TestEncodeCSVUsesConfiguredOrderAndStandardEscaping(t *testing.T) { - rows := staticRows(map[string]any{ - "plain": "value", - "quoted": "say \"hello\"", - "comma": "left,right", - "newline": "first\nsecond", - }) - - var output bytes.Buffer - result, err := EncodeCSV(context.Background(), &output, CSVOptions{Columns: []string{"newline", "comma", "quoted", "plain"}}, rows) - if err != nil { - t.Fatalf("EncodeCSV() error = %v", err) - } - if wantColumns := []string{"newline", "comma", "quoted", "plain"}; !reflect.DeepEqual(result.Columns, wantColumns) { - t.Fatalf("Columns = %#v, want %#v", result.Columns, wantColumns) - } - - parsed, err := csv.NewReader(strings.NewReader(output.String())).ReadAll() - if err != nil { - t.Fatalf("parse CSV: %v", err) - } - want := [][]string{ - {"newline", "comma", "quoted", "plain"}, - {"first\nsecond", "left,right", "say \"hello\"", "value"}, - } - if !reflect.DeepEqual(parsed, want) { - t.Fatalf("parsed CSV = %#v, want %#v; raw=%q", parsed, want, output.String()) - } -} - -func TestEncodeEmptyInput(t *testing.T) { - empty := staticRows() - - var ndjson bytes.Buffer - ndjsonResult, err := EncodeNDJSON(context.Background(), &ndjson, empty) - if err != nil { - t.Fatalf("EncodeNDJSON() error = %v", err) - } - if ndjson.String() != "" || ndjsonResult.Rows != 0 || len(ndjsonResult.Columns) != 0 { - t.Fatalf("empty NDJSON = %q, result=%#v", ndjson.String(), ndjsonResult) - } - - var inferredCSV bytes.Buffer - inferredResult, err := EncodeCSV(context.Background(), &inferredCSV, CSVOptions{}, empty) - if err != nil { - t.Fatalf("EncodeCSV inferred() error = %v", err) - } - if inferredCSV.String() != "" || inferredResult.Rows != 0 || len(inferredResult.Columns) != 0 { - t.Fatalf("empty inferred CSV = %q, result=%#v", inferredCSV.String(), inferredResult) - } - - var configuredCSV bytes.Buffer - configuredResult, err := EncodeCSV(context.Background(), &configuredCSV, CSVOptions{Columns: []string{"patient_id", "status"}}, empty) - if err != nil { - t.Fatalf("EncodeCSV configured() error = %v", err) - } - if got, want := configuredCSV.String(), "patient_id,status\n"; got != want { - t.Fatalf("configured empty CSV = %q, want %q", got, want) - } - if configuredResult.Rows != 0 { - t.Fatalf("configured empty Rows = %d, want 0", configuredResult.Rows) - } -} - -func TestEncodeRejectsNestedValuesWithRowAndColumn(t *testing.T) { - tests := []struct { - name string - run func(*bytes.Buffer) error - }{ - { - name: "ndjson", - run: func(output *bytes.Buffer) error { - _, err := EncodeNDJSON(context.Background(), output, staticRows(map[string]any{"nested": map[string]any{"no": "thanks"}})) - return err - }, - }, - { - name: "csv", - run: func(output *bytes.Buffer) error { - _, err := EncodeCSV(context.Background(), output, CSVOptions{}, staticRows(map[string]any{"nested": []string{"no", "thanks"}})) - return err - }, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - var output bytes.Buffer - err := test.run(&output) - if err == nil { - t.Fatal("expected an error") - } - var valueErr *ValueError - if !errors.As(err, &valueErr) { - t.Fatalf("error = %T %v, want ValueError", err, err) - } - if valueErr.Row != 1 || valueErr.Column != "nested" { - t.Fatalf("ValueError = %#v, want row 1/nested", valueErr) - } - if !strings.Contains(err.Error(), "unsupported nested value") { - t.Fatalf("error = %q, want clear nested-value explanation", err) - } - }) - } -} - -func TestEncodeCSVRejectsColumnsThatWouldBeDropped(t *testing.T) { - var output bytes.Buffer - _, err := EncodeCSV(context.Background(), &output, CSVOptions{Columns: []string{"included"}}, staticRows(map[string]any{"included": "yes", "extra": "no"})) - if err == nil { - t.Fatal("expected an error") - } - var columnErr *ColumnError - if !errors.As(err, &columnErr) { - t.Fatalf("error = %T %v, want ColumnError", err, err) - } - if columnErr.Row != 1 || columnErr.Column != "extra" { - t.Fatalf("ColumnError = %#v, want row 1 extra", columnErr) - } -} - -func staticRows(rows ...map[string]any) RowStream { - return func(ctx context.Context, visit RowVisitor) error { - for _, row := range rows { - if err := ctx.Err(); err != nil { - return err - } - if err := visit(row); err != nil { - return err - } - } - return nil - } -} diff --git a/internal/fhir/extract.go b/internal/fhir/extract.go deleted file mode 100644 index 78926bb..0000000 --- a/internal/fhir/extract.go +++ /dev/null @@ -1,80173 +0,0 @@ -// Code generated by cmd/generate/main.go. DO NOT EDIT. -package fhir - -import ( - "bytes" - "crypto/sha1" - "encoding/hex" - "encoding/json" - "fmt" - "github.com/bytedance/sonic" - "github.com/google/uuid" - "hash" - "strconv" - "strings" - "sync" -) - -// EdgeDocument represents an edge in ArangoDB. -type EdgeDocument struct { - Key string `json:"_key"` - From string `json:"_from"` - To string `json:"_to"` - Label string `json:"label"` - Project string `json:"project"` - FromType string `json:"from_type"` - ToType string `json:"to_type"` -} - -// Result of validation and edge extraction. -type Result struct { - ObjectID string - ResourceType string - Vertex any - Edges []json.RawMessage -} - -// Global namespace UUID constant computed from "calypr-public.ohsu.edu" -var namespaceUUID = uuid.NewMD5(uuid.NameSpaceDNS, []byte("calypr-public.ohsu.edu")) - -var sha1Pool = sync.Pool{ - New: func() any { - return sha1.New() - }, -} - -var bufferPool = sync.Pool{ - New: func() any { - return &bytes.Buffer{} - }, -} - -func fastUUIDSHA1(space uuid.UUID, data []byte) string { - h := sha1Pool.Get().(hash.Hash) - h.Reset() - h.Write(space[:]) - h.Write(data) - var hashBytes [20]byte - h.Sum(hashBytes[:0]) - sha1Pool.Put(h) - - // format uuid v5: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - // version 5 (SHA-1) - hashBytes[6] = (hashBytes[6] & 0x0f) | 0x50 - hashBytes[8] = (hashBytes[8] & 0x3f) | 0x80 - - var buf [36]byte - hex.Encode(buf[0:8], hashBytes[0:4]) - buf[8] = '-' - hex.Encode(buf[9:13], hashBytes[4:6]) - buf[13] = '-' - hex.Encode(buf[14:18], hashBytes[6:8]) - buf[18] = '-' - hex.Encode(buf[19:23], hashBytes[8:10]) - buf[23] = '-' - hex.Encode(buf[24:36], hashBytes[10:16]) - - return string(buf[:]) -} - -func getEdgeUUID(a, b, c string) string { - buf := bufferPool.Get().(*bytes.Buffer) - buf.Reset() - buf.WriteString(a) - buf.WriteByte('-') - buf.WriteString(b) - buf.WriteByte('-') - buf.WriteString(c) - uuidStr := fastUUIDSHA1(namespaceUUID, buf.Bytes()) - bufferPool.Put(buf) - return uuidStr -} - -func collectionID(resourceType, id string) string { - return sanitizeKey(resourceType) + "/" + sanitizeKey(id) -} - -func sanitizeKey(value string) string { - value = strings.TrimSpace(value) - if value == "" { - return "_" - } - needsSanitization := false - for i := 0; i < len(value); i++ { - r := value[i] - if (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || - r == '_' || r == '-' || r == ':' || r == '.' || r == '@' || r == '(' || r == ')' || - r == '+' || r == ',' || r == '=' || r == ';' || r == '$' || r == '!' || r == '*' || - r == '\'' || r == '%' { - // clean character - } else { - needsSanitization = true - break - } - } - if !needsSanitization { - return value - } - - var sb strings.Builder - sb.Grow(len(value)) - for _, r := range value { - if (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || - r == '_' || r == '-' || r == ':' || r == '.' || r == '@' || r == '(' || r == ')' || - r == '+' || r == ',' || r == '=' || r == ';' || r == '$' || r == '!' || r == '*' || - r == '\'' || r == '%' { - sb.WriteRune(r) - } else { - sb.WriteRune('_') - } - } - return sb.String() -} - -func splitFHIRReference(ref string) (string, string, bool) { - firstSlash := strings.IndexByte(ref, '/') - if firstSlash <= 0 || firstSlash == len(ref)-1 { - return "", "", false - } - targetType := ref[:firstSlash] - targetID := ref[firstSlash+1:] - if secondSlash := strings.IndexByte(targetID, '/'); secondSlash != -1 { - targetID = targetID[:secondSlash] - } - if targetID == "" { - return "", "", false - } - return targetType, targetID, true -} - -func targetTypeFromLabel(label string) string { - parts := strings.Split(label, "_") - if len(parts) == 0 { - return "" - } - return parts[len(parts)-1] -} - -func buildEdgeRawJSON(key, from, to, label, projectJSON, fromType, toType string) json.RawMessage { - var buf bytes.Buffer - buf.Grow(256) - buf.WriteString("{\"_key\":\"") - buf.WriteString(key) - buf.WriteString("\",\"_from\":\"") - buf.WriteString(from) - buf.WriteString("\",\"_to\":\"") - buf.WriteString(to) - buf.WriteString("\",\"label\":\"") - buf.WriteString(label) - buf.WriteString("\",\"project\":") - buf.WriteString(projectJSON) - buf.WriteString(",\"from_type\":\"") - buf.WriteString(fromType) - buf.WriteString("\",\"to_type\":\"") - buf.WriteString(toType) - buf.WriteString("\"}") - return json.RawMessage(buf.Bytes()) -} - -// ExtractEdges extracts graph links from Address. -func (x *Address) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Address" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from Age. -func (x *Age) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Age" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from Annotation. -func (x *Annotation) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Annotation" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.AuthorReference != nil { - if x.AuthorReference.Reference != nil { - refVal := *x.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "authorReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "authorReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - if x.AuthorReference != nil { - if x.AuthorReference.Reference != nil { - refVal := *x.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "authorReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "authorReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - if x.AuthorReference != nil { - if x.AuthorReference.Reference != nil { - refVal := *x.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "authorReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "authorReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - if x.AuthorReference != nil { - if x.AuthorReference.Reference != nil { - refVal := *x.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "authorReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "authorReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from Attachment. -func (x *Attachment) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Attachment" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from Availability. -func (x *Availability) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Availability" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from AvailabilityAvailableTime. -func (x *AvailabilityAvailableTime) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "AvailabilityAvailableTime" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from AvailabilityNotAvailableTime. -func (x *AvailabilityNotAvailableTime) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "AvailabilityNotAvailableTime" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from BodyStructure. -func (x *BodyStructure) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "BodyStructure" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Patient != nil { - if x.Patient.Reference != nil { - refVal := *x.Patient.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("patient", targetID), - "patient", - projectJSON, - sourceType, - "patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "body_structure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("structure", id), - "body_structure", - projectJSON, - sourceType, - "structure", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from BodyStructureIncludedStructure. -func (x *BodyStructureIncludedStructure) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "BodyStructureIncludedStructure" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from BodyStructureIncludedStructureBodyLandmarkOrientation. -func (x *BodyStructureIncludedStructureBodyLandmarkOrientation) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "BodyStructureIncludedStructureBodyLandmarkOrientation" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark. -func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "device_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "device_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "device_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "device_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "device_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "device_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "device_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "device_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "device_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "device_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "device_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "device_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "device_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "device_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "device_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "device_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "device_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "device_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "device_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "device_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "device_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "device_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "device_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from CodeableConcept. -func (x *CodeableConcept) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "CodeableConcept" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from CodeableReference. -func (x *CodeableReference) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "CodeableReference" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from Coding. -func (x *Coding) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Coding" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from Condition. -func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Condition" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "subject_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "subject_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("condition", id), - "condition", - projectJSON, - sourceType, - "condition", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "subject_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "subject_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("condition", id), - "condition", - projectJSON, - sourceType, - "condition", - )) - } - } - } - } - } - if x.Evidence != nil { - for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { - if item_3_x_Evidence.Reference != nil { - if item_3_x_Evidence.Reference.Reference != nil { - refVal := *item_3_x_Evidence.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "evidence_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "evidence_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Evidence != nil { - for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { - if item_3_x_Evidence.Reference != nil { - if item_3_x_Evidence.Reference.Reference != nil { - refVal := *item_3_x_Evidence.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "evidence_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "evidence_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Evidence != nil { - for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { - if item_3_x_Evidence.Reference != nil { - if item_3_x_Evidence.Reference.Reference != nil { - refVal := *item_3_x_Evidence.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "evidence_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "evidence_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Evidence != nil { - for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { - if item_3_x_Evidence.Reference != nil { - if item_3_x_Evidence.Reference.Reference != nil { - refVal := *item_3_x_Evidence.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "evidence_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "evidence_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Evidence != nil { - for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { - if item_3_x_Evidence.Reference != nil { - if item_3_x_Evidence.Reference.Reference != nil { - refVal := *item_3_x_Evidence.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "evidence_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "evidence_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Evidence != nil { - for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { - if item_3_x_Evidence.Reference != nil { - if item_3_x_Evidence.Reference.Reference != nil { - refVal := *item_3_x_Evidence.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "evidence_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "evidence_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Evidence != nil { - for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { - if item_3_x_Evidence.Reference != nil { - if item_3_x_Evidence.Reference.Reference != nil { - refVal := *item_3_x_Evidence.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "evidence_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "evidence_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Evidence != nil { - for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { - if item_3_x_Evidence.Reference != nil { - if item_3_x_Evidence.Reference.Reference != nil { - refVal := *item_3_x_Evidence.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "evidence_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "evidence_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Evidence != nil { - for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { - if item_3_x_Evidence.Reference != nil { - if item_3_x_Evidence.Reference.Reference != nil { - refVal := *item_3_x_Evidence.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "evidence_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "evidence_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Evidence != nil { - for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { - if item_3_x_Evidence.Reference != nil { - if item_3_x_Evidence.Reference.Reference != nil { - refVal := *item_3_x_Evidence.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "evidence_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "evidence_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Evidence != nil { - for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { - if item_3_x_Evidence.Reference != nil { - if item_3_x_Evidence.Reference.Reference != nil { - refVal := *item_3_x_Evidence.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "evidence_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "evidence_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Evidence != nil { - for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { - if item_3_x_Evidence.Reference != nil { - if item_3_x_Evidence.Reference.Reference != nil { - refVal := *item_3_x_Evidence.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "evidence_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "evidence_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Evidence != nil { - for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { - if item_3_x_Evidence.Reference != nil { - if item_3_x_Evidence.Reference.Reference != nil { - refVal := *item_3_x_Evidence.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "evidence_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "evidence_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Evidence != nil { - for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { - if item_3_x_Evidence.Reference != nil { - if item_3_x_Evidence.Reference.Reference != nil { - refVal := *item_3_x_Evidence.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "evidence_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "evidence_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Evidence != nil { - for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { - if item_3_x_Evidence.Reference != nil { - if item_3_x_Evidence.Reference.Reference != nil { - refVal := *item_3_x_Evidence.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "evidence_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "evidence_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Evidence != nil { - for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { - if item_3_x_Evidence.Reference != nil { - if item_3_x_Evidence.Reference.Reference != nil { - refVal := *item_3_x_Evidence.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "evidence_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "evidence_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Evidence != nil { - for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { - if item_3_x_Evidence.Reference != nil { - if item_3_x_Evidence.Reference.Reference != nil { - refVal := *item_3_x_Evidence.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "evidence_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "evidence_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Evidence != nil { - for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { - if item_3_x_Evidence.Reference != nil { - if item_3_x_Evidence.Reference.Reference != nil { - refVal := *item_3_x_Evidence.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "evidence_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "evidence_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Evidence != nil { - for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { - if item_3_x_Evidence.Reference != nil { - if item_3_x_Evidence.Reference.Reference != nil { - refVal := *item_3_x_Evidence.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "evidence_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "evidence_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Evidence != nil { - for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { - if item_3_x_Evidence.Reference != nil { - if item_3_x_Evidence.Reference.Reference != nil { - refVal := *item_3_x_Evidence.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "evidence_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "evidence_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Evidence != nil { - for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { - if item_3_x_Evidence.Reference != nil { - if item_3_x_Evidence.Reference.Reference != nil { - refVal := *item_3_x_Evidence.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "evidence_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "evidence_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Evidence != nil { - for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { - if item_3_x_Evidence.Reference != nil { - if item_3_x_Evidence.Reference.Reference != nil { - refVal := *item_3_x_Evidence.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "evidence_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "evidence_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Evidence != nil { - for _, item_3_x_Evidence := range x.Evidence { - if item_3_x_Evidence != nil { - if item_3_x_Evidence.Reference != nil { - if item_3_x_Evidence.Reference.Reference != nil { - refVal := *item_3_x_Evidence.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "evidence_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "evidence_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "note_authorReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "note_authorReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "note_authorReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "note_authorReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Participant != nil { - for _, item_3_x_Participant := range x.Participant { - if item_3_x_Participant != nil { - if item_3_x_Participant.Actor != nil { - if item_3_x_Participant.Actor.Reference != nil { - refVal := *item_3_x_Participant.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "participant_actor_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "participant_actor_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "condition_participant") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("participant", id), - "condition_participant", - projectJSON, - sourceType, - "participant", - )) - } - } - } - } - } - } - } - } - if x.Participant != nil { - for _, item_3_x_Participant := range x.Participant { - if item_3_x_Participant != nil { - if item_3_x_Participant.Actor != nil { - if item_3_x_Participant.Actor.Reference != nil { - refVal := *item_3_x_Participant.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "participant_actor_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "participant_actor_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "condition_participant") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("participant", id), - "condition_participant", - projectJSON, - sourceType, - "participant", - )) - } - } - } - } - } - } - } - } - if x.Participant != nil { - for _, item_3_x_Participant := range x.Participant { - if item_3_x_Participant != nil { - if item_3_x_Participant.Actor != nil { - if item_3_x_Participant.Actor.Reference != nil { - refVal := *item_3_x_Participant.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "participant_actor_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "participant_actor_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "condition_participant") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("participant", id), - "condition_participant", - projectJSON, - sourceType, - "participant", - )) - } - } - } - } - } - } - } - } - if x.Participant != nil { - for _, item_3_x_Participant := range x.Participant { - if item_3_x_Participant != nil { - if item_3_x_Participant.Actor != nil { - if item_3_x_Participant.Actor.Reference != nil { - refVal := *item_3_x_Participant.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "participant_actor_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "participant_actor_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "condition_participant") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("participant", id), - "condition_participant", - projectJSON, - sourceType, - "participant", - )) - } - } - } - } - } - } - } - } - if x.Stage != nil { - for _, item_4_x_Stage := range x.Stage { - if item_4_x_Stage != nil { - if item_4_x_Stage.Assessment != nil { - for _, item_2_item_4_x_Stage_Assessment := range item_4_x_Stage.Assessment { - if item_2_item_4_x_Stage_Assessment != nil { - if item_2_item_4_x_Stage_Assessment.Reference != nil { - refVal := *item_2_item_4_x_Stage_Assessment.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "stage_assessment_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "stage_assessment_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "assessment_condition_stage") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("stage", id), - "assessment_condition_stage", - projectJSON, - sourceType, - "stage", - )) - } - } - } - } - } - } - } - } - } - } - if x.Stage != nil { - for _, item_4_x_Stage := range x.Stage { - if item_4_x_Stage != nil { - if item_4_x_Stage.Assessment != nil { - for _, item_2_item_4_x_Stage_Assessment := range item_4_x_Stage.Assessment { - if item_2_item_4_x_Stage_Assessment != nil { - if item_2_item_4_x_Stage_Assessment.Reference != nil { - refVal := *item_2_item_4_x_Stage_Assessment.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "stage_assessment_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "stage_assessment_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "assessment_condition_stage") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("stage", id), - "assessment_condition_stage", - projectJSON, - sourceType, - "stage", - )) - } - } - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from ConditionParticipant. -func (x *ConditionParticipant) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ConditionParticipant" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Actor != nil { - if x.Actor.Reference != nil { - refVal := *x.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "actor_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "actor_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "condition_participant") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("participant", id), - "condition_participant", - projectJSON, - sourceType, - "participant", - )) - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - refVal := *x.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "actor_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "actor_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "condition_participant") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("participant", id), - "condition_participant", - projectJSON, - sourceType, - "participant", - )) - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - refVal := *x.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "actor_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "actor_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "condition_participant") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("participant", id), - "condition_participant", - projectJSON, - sourceType, - "participant", - )) - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - refVal := *x.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "actor_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "actor_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "condition_participant") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("participant", id), - "condition_participant", - projectJSON, - sourceType, - "participant", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from ConditionStage. -func (x *ConditionStage) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ConditionStage" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Assessment != nil { - for _, item_2_x_Assessment := range x.Assessment { - if item_2_x_Assessment != nil { - if item_2_x_Assessment.Reference != nil { - refVal := *item_2_x_Assessment.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "assessment_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "assessment_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "assessment_condition_stage") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("stage", id), - "assessment_condition_stage", - projectJSON, - sourceType, - "stage", - )) - } - } - } - } - } - } - } - if x.Assessment != nil { - for _, item_2_x_Assessment := range x.Assessment { - if item_2_x_Assessment != nil { - if item_2_x_Assessment.Reference != nil { - refVal := *item_2_x_Assessment.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "assessment_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "assessment_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "assessment_condition_stage") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("stage", id), - "assessment_condition_stage", - projectJSON, - sourceType, - "stage", - )) - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from ContactDetail. -func (x *ContactDetail) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ContactDetail" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from ContactPoint. -func (x *ContactPoint) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ContactPoint" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from Count. -func (x *Count) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Count" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from DataRequirement. -func (x *DataRequirement) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "DataRequirement" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.SubjectReference != nil { - if x.SubjectReference.Reference != nil { - refVal := *x.SubjectReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "subjectReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("subjectReference", targetID), - "subjectReference", - projectJSON, - sourceType, - "subjectReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "data_requirement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("requirement", id), - "data_requirement", - projectJSON, - sourceType, - "requirement", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from DataRequirementCodeFilter. -func (x *DataRequirementCodeFilter) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "DataRequirementCodeFilter" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from DataRequirementDateFilter. -func (x *DataRequirementDateFilter) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "DataRequirementDateFilter" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from DataRequirementSort. -func (x *DataRequirementSort) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "DataRequirementSort" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from DataRequirementValueFilter. -func (x *DataRequirementValueFilter) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "DataRequirementValueFilter" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from DiagnosticReport. -func (x *DiagnosticReport) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "DiagnosticReport" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "basedOn_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_diagnostic_report") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("report", id), - "basedOn_diagnostic_report", - projectJSON, - sourceType, - "report", - )) - } - } - } - } - } - } - } - if x.Performer != nil { - for _, item_2_x_Performer := range x.Performer { - if item_2_x_Performer != nil { - if item_2_x_Performer.Reference != nil { - refVal := *item_2_x_Performer.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "performer_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "performer_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "performer_diagnostic_report") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("report", id), - "performer_diagnostic_report", - projectJSON, - sourceType, - "report", - )) - } - } - } - } - } - } - } - if x.Performer != nil { - for _, item_2_x_Performer := range x.Performer { - if item_2_x_Performer != nil { - if item_2_x_Performer.Reference != nil { - refVal := *item_2_x_Performer.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "performer_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "performer_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "performer_diagnostic_report") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("report", id), - "performer_diagnostic_report", - projectJSON, - sourceType, - "report", - )) - } - } - } - } - } - } - } - if x.Performer != nil { - for _, item_2_x_Performer := range x.Performer { - if item_2_x_Performer != nil { - if item_2_x_Performer.Reference != nil { - refVal := *item_2_x_Performer.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "performer_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "performer_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "performer_diagnostic_report") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("report", id), - "performer_diagnostic_report", - projectJSON, - sourceType, - "report", - )) - } - } - } - } - } - } - } - if x.Result != nil { - for _, item_2_x_Result := range x.Result { - if item_2_x_Result != nil { - if item_2_x_Result.Reference != nil { - refVal := *item_2_x_Result.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "result") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("result", targetID), - "result", - projectJSON, - sourceType, - "result", - )) - } - backrefKey := getEdgeUUID(id, targetID, "result_diagnostic_report") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("report", id), - "result_diagnostic_report", - projectJSON, - sourceType, - "report", - )) - } - } - } - } - } - } - } - if x.ResultsInterpreter != nil { - for _, item_2_x_ResultsInterpreter := range x.ResultsInterpreter { - if item_2_x_ResultsInterpreter != nil { - if item_2_x_ResultsInterpreter.Reference != nil { - refVal := *item_2_x_ResultsInterpreter.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "resultsInterpreter_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "resultsInterpreter_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "resultsInterpreter_diagnostic_report") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("report", id), - "resultsInterpreter_diagnostic_report", - projectJSON, - sourceType, - "report", - )) - } - } - } - } - } - } - } - if x.ResultsInterpreter != nil { - for _, item_2_x_ResultsInterpreter := range x.ResultsInterpreter { - if item_2_x_ResultsInterpreter != nil { - if item_2_x_ResultsInterpreter.Reference != nil { - refVal := *item_2_x_ResultsInterpreter.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "resultsInterpreter_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "resultsInterpreter_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "resultsInterpreter_diagnostic_report") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("report", id), - "resultsInterpreter_diagnostic_report", - projectJSON, - sourceType, - "report", - )) - } - } - } - } - } - } - } - if x.ResultsInterpreter != nil { - for _, item_2_x_ResultsInterpreter := range x.ResultsInterpreter { - if item_2_x_ResultsInterpreter != nil { - if item_2_x_ResultsInterpreter.Reference != nil { - refVal := *item_2_x_ResultsInterpreter.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "resultsInterpreter_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "resultsInterpreter_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "resultsInterpreter_diagnostic_report") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("report", id), - "resultsInterpreter_diagnostic_report", - projectJSON, - sourceType, - "report", - )) - } - } - } - } - } - } - } - if x.Specimen != nil { - for _, item_2_x_Specimen := range x.Specimen { - if item_2_x_Specimen != nil { - if item_2_x_Specimen.Reference != nil { - refVal := *item_2_x_Specimen.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("specimen", targetID), - "specimen", - projectJSON, - sourceType, - "specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "specimen_diagnostic_report") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("report", id), - "specimen_diagnostic_report", - projectJSON, - sourceType, - "report", - )) - } - } - } - } - } - } - } - if x.Study != nil { - for _, item_2_x_Study := range x.Study { - if item_2_x_Study != nil { - if item_2_x_Study.Reference != nil { - refVal := *item_2_x_Study.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "study_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "study_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "study_diagnostic_report") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("report", id), - "study_diagnostic_report", - projectJSON, - sourceType, - "report", - )) - } - } - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "subject_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "subject_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "subject_diagnostic_report") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("report", id), - "subject_diagnostic_report", - projectJSON, - sourceType, - "report", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "subject_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "subject_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "subject_diagnostic_report") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("report", id), - "subject_diagnostic_report", - projectJSON, - sourceType, - "report", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "subject_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "subject_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "subject_diagnostic_report") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("report", id), - "subject_diagnostic_report", - projectJSON, - sourceType, - "report", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "subject_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "subject_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "subject_diagnostic_report") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("report", id), - "subject_diagnostic_report", - projectJSON, - sourceType, - "report", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "subject_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "subject_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "subject_diagnostic_report") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("report", id), - "subject_diagnostic_report", - projectJSON, - sourceType, - "report", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "subject_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "subject_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "subject_diagnostic_report") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("report", id), - "subject_diagnostic_report", - projectJSON, - sourceType, - "report", - )) - } - } - } - } - } - if x.Media != nil { - for _, item_3_x_Media := range x.Media { - if item_3_x_Media != nil { - if item_3_x_Media.Link != nil { - if item_3_x_Media.Link.Reference != nil { - refVal := *item_3_x_Media.Link.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "media_link") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("link", targetID), - "media_link", - projectJSON, - sourceType, - "link", - )) - } - backrefKey := getEdgeUUID(id, targetID, "diagnostic_report_media") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("media", id), - "diagnostic_report_media", - projectJSON, - sourceType, - "media", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "note_authorReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "note_authorReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "note_authorReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "note_authorReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_3_x_SupportingInfo := range x.SupportingInfo { - if item_3_x_SupportingInfo != nil { - if item_3_x_SupportingInfo.Reference != nil { - if item_3_x_SupportingInfo.Reference.Reference != nil { - refVal := *item_3_x_SupportingInfo.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "supportingInfo_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "diagnostic_report_supporting_info") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("info", id), - "diagnostic_report_supporting_info", - projectJSON, - sourceType, - "info", - )) - } - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_3_x_SupportingInfo := range x.SupportingInfo { - if item_3_x_SupportingInfo != nil { - if item_3_x_SupportingInfo.Reference != nil { - if item_3_x_SupportingInfo.Reference.Reference != nil { - refVal := *item_3_x_SupportingInfo.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "supportingInfo_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "diagnostic_report_supporting_info") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("info", id), - "diagnostic_report_supporting_info", - projectJSON, - sourceType, - "info", - )) - } - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_3_x_SupportingInfo := range x.SupportingInfo { - if item_3_x_SupportingInfo != nil { - if item_3_x_SupportingInfo.Reference != nil { - if item_3_x_SupportingInfo.Reference.Reference != nil { - refVal := *item_3_x_SupportingInfo.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "supportingInfo_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "diagnostic_report_supporting_info") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("info", id), - "diagnostic_report_supporting_info", - projectJSON, - sourceType, - "info", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from DiagnosticReportMedia. -func (x *DiagnosticReportMedia) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "DiagnosticReportMedia" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Link != nil { - if x.Link.Reference != nil { - refVal := *x.Link.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "link") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("link", targetID), - "link", - projectJSON, - sourceType, - "link", - )) - } - backrefKey := getEdgeUUID(id, targetID, "diagnostic_report_media") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("media", id), - "diagnostic_report_media", - projectJSON, - sourceType, - "media", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from DiagnosticReportSupportingInfo. -func (x *DiagnosticReportSupportingInfo) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "DiagnosticReportSupportingInfo" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "diagnostic_report_supporting_info") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("info", id), - "diagnostic_report_supporting_info", - projectJSON, - sourceType, - "info", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "diagnostic_report_supporting_info") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("info", id), - "diagnostic_report_supporting_info", - projectJSON, - sourceType, - "info", - )) - } - } - } - } - } - if x.Reference != nil { - if x.Reference.Reference != nil { - refVal := *x.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "diagnostic_report_supporting_info") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("info", id), - "diagnostic_report_supporting_info", - projectJSON, - sourceType, - "info", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from Directory. -func (x *Directory) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Directory" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Child != nil { - for _, item_2_x_Child := range x.Child { - if item_2_x_Child != nil { - if item_2_x_Child.Reference != nil { - refVal := *item_2_x_Child.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Directory" { - forwardKey := getEdgeUUID(targetID, id, "child_Directory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Directory", targetID), - "child_Directory", - projectJSON, - sourceType, - "Directory", - )) - } - } - } - } - } - } - } - if x.Child != nil { - for _, item_2_x_Child := range x.Child { - if item_2_x_Child != nil { - if item_2_x_Child.Reference != nil { - refVal := *item_2_x_Child.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "child_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "child_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from Distance. -func (x *Distance) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Distance" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from DocumentReference. -func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "DocumentReference" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Author != nil { - for _, item_2_x_Author := range x.Author { - if item_2_x_Author != nil { - if item_2_x_Author.Reference != nil { - refVal := *item_2_x_Author.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "author_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "author_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "author_document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "author_document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - if x.Author != nil { - for _, item_2_x_Author := range x.Author { - if item_2_x_Author != nil { - if item_2_x_Author.Reference != nil { - refVal := *item_2_x_Author.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "author_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "author_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "author_document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "author_document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - if x.Author != nil { - for _, item_2_x_Author := range x.Author { - if item_2_x_Author != nil { - if item_2_x_Author.Reference != nil { - refVal := *item_2_x_Author.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "author_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "author_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "author_document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "author_document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - if x.Author != nil { - for _, item_2_x_Author := range x.Author { - if item_2_x_Author != nil { - if item_2_x_Author.Reference != nil { - refVal := *item_2_x_Author.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "author_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "author_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "author_document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "author_document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "basedOn_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "basedOn_document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - if x.Custodian != nil { - if x.Custodian.Reference != nil { - refVal := *x.Custodian.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "custodian") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("custodian", targetID), - "custodian", - projectJSON, - sourceType, - "custodian", - )) - } - backrefKey := getEdgeUUID(id, targetID, "custodian_document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "custodian_document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "subject_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "subject_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "subject_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "subject_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "subject_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "subject_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "subject_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "subject_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "subject_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "subject_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "subject_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "subject_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "subject_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "subject_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "subject_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "subject_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "subject_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "subject_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "subject_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "subject_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "subject_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "subject_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "subject_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "subject_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "subject_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "subject_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "subject_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "subject_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "subject_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "subject_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "subject_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "subject_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "subject_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "subject_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "subject_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "subject_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "subject_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "subject_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "subject_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "subject_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "subject_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "subject_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "subject_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "subject_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "subject_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "subject_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "document_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - if x.Attester != nil { - for _, item_3_x_Attester := range x.Attester { - if item_3_x_Attester != nil { - if item_3_x_Attester.Party != nil { - if item_3_x_Attester.Party.Reference != nil { - refVal := *item_3_x_Attester.Party.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "attester_party_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "attester_party_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference_attester") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("attester", id), - "document_reference_attester", - projectJSON, - sourceType, - "attester", - )) - } - } - } - } - } - } - } - } - if x.Attester != nil { - for _, item_3_x_Attester := range x.Attester { - if item_3_x_Attester != nil { - if item_3_x_Attester.Party != nil { - if item_3_x_Attester.Party.Reference != nil { - refVal := *item_3_x_Attester.Party.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "attester_party_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "attester_party_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference_attester") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("attester", id), - "document_reference_attester", - projectJSON, - sourceType, - "attester", - )) - } - } - } - } - } - } - } - } - if x.Attester != nil { - for _, item_3_x_Attester := range x.Attester { - if item_3_x_Attester != nil { - if item_3_x_Attester.Party != nil { - if item_3_x_Attester.Party.Reference != nil { - refVal := *item_3_x_Attester.Party.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "attester_party_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "attester_party_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference_attester") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("attester", id), - "document_reference_attester", - projectJSON, - sourceType, - "attester", - )) - } - } - } - } - } - } - } - } - if x.Attester != nil { - for _, item_3_x_Attester := range x.Attester { - if item_3_x_Attester != nil { - if item_3_x_Attester.Party != nil { - if item_3_x_Attester.Party.Reference != nil { - refVal := *item_3_x_Attester.Party.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "attester_party_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "attester_party_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference_attester") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("attester", id), - "document_reference_attester", - projectJSON, - sourceType, - "attester", - )) - } - } - } - } - } - } - } - } - if x.BodySite != nil { - for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { - if item_3_x_BodySite.Reference != nil { - if item_3_x_BodySite.Reference.Reference != nil { - refVal := *item_3_x_BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "bodySite_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.BodySite != nil { - for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { - if item_3_x_BodySite.Reference != nil { - if item_3_x_BodySite.Reference.Reference != nil { - refVal := *item_3_x_BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "bodySite_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.BodySite != nil { - for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { - if item_3_x_BodySite.Reference != nil { - if item_3_x_BodySite.Reference.Reference != nil { - refVal := *item_3_x_BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "bodySite_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.BodySite != nil { - for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { - if item_3_x_BodySite.Reference != nil { - if item_3_x_BodySite.Reference.Reference != nil { - refVal := *item_3_x_BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "bodySite_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.BodySite != nil { - for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { - if item_3_x_BodySite.Reference != nil { - if item_3_x_BodySite.Reference.Reference != nil { - refVal := *item_3_x_BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "bodySite_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.BodySite != nil { - for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { - if item_3_x_BodySite.Reference != nil { - if item_3_x_BodySite.Reference.Reference != nil { - refVal := *item_3_x_BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "bodySite_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.BodySite != nil { - for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { - if item_3_x_BodySite.Reference != nil { - if item_3_x_BodySite.Reference.Reference != nil { - refVal := *item_3_x_BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "bodySite_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.BodySite != nil { - for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { - if item_3_x_BodySite.Reference != nil { - if item_3_x_BodySite.Reference.Reference != nil { - refVal := *item_3_x_BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "bodySite_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.BodySite != nil { - for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { - if item_3_x_BodySite.Reference != nil { - if item_3_x_BodySite.Reference.Reference != nil { - refVal := *item_3_x_BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "bodySite_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.BodySite != nil { - for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { - if item_3_x_BodySite.Reference != nil { - if item_3_x_BodySite.Reference.Reference != nil { - refVal := *item_3_x_BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "bodySite_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.BodySite != nil { - for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { - if item_3_x_BodySite.Reference != nil { - if item_3_x_BodySite.Reference.Reference != nil { - refVal := *item_3_x_BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "bodySite_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.BodySite != nil { - for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { - if item_3_x_BodySite.Reference != nil { - if item_3_x_BodySite.Reference.Reference != nil { - refVal := *item_3_x_BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "bodySite_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.BodySite != nil { - for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { - if item_3_x_BodySite.Reference != nil { - if item_3_x_BodySite.Reference.Reference != nil { - refVal := *item_3_x_BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "bodySite_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.BodySite != nil { - for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { - if item_3_x_BodySite.Reference != nil { - if item_3_x_BodySite.Reference.Reference != nil { - refVal := *item_3_x_BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "bodySite_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.BodySite != nil { - for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { - if item_3_x_BodySite.Reference != nil { - if item_3_x_BodySite.Reference.Reference != nil { - refVal := *item_3_x_BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "bodySite_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.BodySite != nil { - for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { - if item_3_x_BodySite.Reference != nil { - if item_3_x_BodySite.Reference.Reference != nil { - refVal := *item_3_x_BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "bodySite_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.BodySite != nil { - for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { - if item_3_x_BodySite.Reference != nil { - if item_3_x_BodySite.Reference.Reference != nil { - refVal := *item_3_x_BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "bodySite_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.BodySite != nil { - for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { - if item_3_x_BodySite.Reference != nil { - if item_3_x_BodySite.Reference.Reference != nil { - refVal := *item_3_x_BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "bodySite_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.BodySite != nil { - for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { - if item_3_x_BodySite.Reference != nil { - if item_3_x_BodySite.Reference.Reference != nil { - refVal := *item_3_x_BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "bodySite_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.BodySite != nil { - for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { - if item_3_x_BodySite.Reference != nil { - if item_3_x_BodySite.Reference.Reference != nil { - refVal := *item_3_x_BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "bodySite_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.BodySite != nil { - for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { - if item_3_x_BodySite.Reference != nil { - if item_3_x_BodySite.Reference.Reference != nil { - refVal := *item_3_x_BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "bodySite_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.BodySite != nil { - for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { - if item_3_x_BodySite.Reference != nil { - if item_3_x_BodySite.Reference.Reference != nil { - refVal := *item_3_x_BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "bodySite_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.BodySite != nil { - for _, item_3_x_BodySite := range x.BodySite { - if item_3_x_BodySite != nil { - if item_3_x_BodySite.Reference != nil { - if item_3_x_BodySite.Reference.Reference != nil { - refVal := *item_3_x_BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "bodySite_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Event != nil { - for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { - if item_3_x_Event.Reference != nil { - if item_3_x_Event.Reference.Reference != nil { - refVal := *item_3_x_Event.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "event_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "event_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Event != nil { - for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { - if item_3_x_Event.Reference != nil { - if item_3_x_Event.Reference.Reference != nil { - refVal := *item_3_x_Event.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "event_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "event_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Event != nil { - for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { - if item_3_x_Event.Reference != nil { - if item_3_x_Event.Reference.Reference != nil { - refVal := *item_3_x_Event.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "event_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "event_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Event != nil { - for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { - if item_3_x_Event.Reference != nil { - if item_3_x_Event.Reference.Reference != nil { - refVal := *item_3_x_Event.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "event_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "event_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Event != nil { - for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { - if item_3_x_Event.Reference != nil { - if item_3_x_Event.Reference.Reference != nil { - refVal := *item_3_x_Event.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "event_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "event_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Event != nil { - for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { - if item_3_x_Event.Reference != nil { - if item_3_x_Event.Reference.Reference != nil { - refVal := *item_3_x_Event.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "event_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "event_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Event != nil { - for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { - if item_3_x_Event.Reference != nil { - if item_3_x_Event.Reference.Reference != nil { - refVal := *item_3_x_Event.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "event_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "event_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Event != nil { - for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { - if item_3_x_Event.Reference != nil { - if item_3_x_Event.Reference.Reference != nil { - refVal := *item_3_x_Event.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "event_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "event_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Event != nil { - for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { - if item_3_x_Event.Reference != nil { - if item_3_x_Event.Reference.Reference != nil { - refVal := *item_3_x_Event.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "event_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "event_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Event != nil { - for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { - if item_3_x_Event.Reference != nil { - if item_3_x_Event.Reference.Reference != nil { - refVal := *item_3_x_Event.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "event_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "event_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Event != nil { - for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { - if item_3_x_Event.Reference != nil { - if item_3_x_Event.Reference.Reference != nil { - refVal := *item_3_x_Event.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "event_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "event_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Event != nil { - for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { - if item_3_x_Event.Reference != nil { - if item_3_x_Event.Reference.Reference != nil { - refVal := *item_3_x_Event.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "event_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "event_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Event != nil { - for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { - if item_3_x_Event.Reference != nil { - if item_3_x_Event.Reference.Reference != nil { - refVal := *item_3_x_Event.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "event_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "event_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Event != nil { - for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { - if item_3_x_Event.Reference != nil { - if item_3_x_Event.Reference.Reference != nil { - refVal := *item_3_x_Event.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "event_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "event_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Event != nil { - for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { - if item_3_x_Event.Reference != nil { - if item_3_x_Event.Reference.Reference != nil { - refVal := *item_3_x_Event.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "event_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "event_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Event != nil { - for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { - if item_3_x_Event.Reference != nil { - if item_3_x_Event.Reference.Reference != nil { - refVal := *item_3_x_Event.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "event_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "event_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Event != nil { - for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { - if item_3_x_Event.Reference != nil { - if item_3_x_Event.Reference.Reference != nil { - refVal := *item_3_x_Event.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "event_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "event_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Event != nil { - for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { - if item_3_x_Event.Reference != nil { - if item_3_x_Event.Reference.Reference != nil { - refVal := *item_3_x_Event.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "event_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "event_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Event != nil { - for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { - if item_3_x_Event.Reference != nil { - if item_3_x_Event.Reference.Reference != nil { - refVal := *item_3_x_Event.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "event_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "event_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Event != nil { - for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { - if item_3_x_Event.Reference != nil { - if item_3_x_Event.Reference.Reference != nil { - refVal := *item_3_x_Event.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "event_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "event_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Event != nil { - for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { - if item_3_x_Event.Reference != nil { - if item_3_x_Event.Reference.Reference != nil { - refVal := *item_3_x_Event.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "event_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "event_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Event != nil { - for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { - if item_3_x_Event.Reference != nil { - if item_3_x_Event.Reference.Reference != nil { - refVal := *item_3_x_Event.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "event_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "event_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Event != nil { - for _, item_3_x_Event := range x.Event { - if item_3_x_Event != nil { - if item_3_x_Event.Reference != nil { - if item_3_x_Event.Reference.Reference != nil { - refVal := *item_3_x_Event.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "event_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "event_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RelatesTo != nil { - for _, item_3_x_RelatesTo := range x.RelatesTo { - if item_3_x_RelatesTo != nil { - if item_3_x_RelatesTo.Target != nil { - if item_3_x_RelatesTo.Target.Reference != nil { - refVal := *item_3_x_RelatesTo.Target.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "relatesTo_target") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("target", targetID), - "relatesTo_target", - projectJSON, - sourceType, - "target", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference_relates_to") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("to", id), - "document_reference_relates_to", - projectJSON, - sourceType, - "to", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from DocumentReferenceAttester. -func (x *DocumentReferenceAttester) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "DocumentReferenceAttester" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Party != nil { - if x.Party.Reference != nil { - refVal := *x.Party.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "party_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "party_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference_attester") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("attester", id), - "document_reference_attester", - projectJSON, - sourceType, - "attester", - )) - } - } - } - } - } - if x.Party != nil { - if x.Party.Reference != nil { - refVal := *x.Party.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "party_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "party_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference_attester") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("attester", id), - "document_reference_attester", - projectJSON, - sourceType, - "attester", - )) - } - } - } - } - } - if x.Party != nil { - if x.Party.Reference != nil { - refVal := *x.Party.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "party_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "party_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference_attester") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("attester", id), - "document_reference_attester", - projectJSON, - sourceType, - "attester", - )) - } - } - } - } - } - if x.Party != nil { - if x.Party.Reference != nil { - refVal := *x.Party.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "party_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "party_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference_attester") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("attester", id), - "document_reference_attester", - projectJSON, - sourceType, - "attester", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from DocumentReferenceContent. -func (x *DocumentReferenceContent) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "DocumentReferenceContent" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from DocumentReferenceContentProfile. -func (x *DocumentReferenceContentProfile) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "DocumentReferenceContentProfile" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from DocumentReferenceRelatesTo. -func (x *DocumentReferenceRelatesTo) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "DocumentReferenceRelatesTo" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Target != nil { - if x.Target.Reference != nil { - refVal := *x.Target.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "target") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("target", targetID), - "target", - projectJSON, - sourceType, - "target", - )) - } - backrefKey := getEdgeUUID(id, targetID, "document_reference_relates_to") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("to", id), - "document_reference_relates_to", - projectJSON, - sourceType, - "to", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from Dosage. -func (x *Dosage) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Dosage" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from DosageDoseAndRate. -func (x *DosageDoseAndRate) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "DosageDoseAndRate" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from Duration. -func (x *Duration) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Duration" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from Expression. -func (x *Expression) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Expression" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from ExtendedContactDetail. -func (x *ExtendedContactDetail) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ExtendedContactDetail" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Organization != nil { - if x.Organization.Reference != nil { - refVal := *x.Organization.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("organization", targetID), - "organization", - projectJSON, - sourceType, - "organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extended_contact_detail") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("detail", id), - "extended_contact_detail", - projectJSON, - sourceType, - "detail", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from Extension. -func (x *Extension) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Extension" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "valueReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extension") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("extension", id), - "extension", - projectJSON, - sourceType, - "extension", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "valueReference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extension") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("extension", id), - "extension", - projectJSON, - sourceType, - "extension", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "valueReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extension") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("extension", id), - "extension", - projectJSON, - sourceType, - "extension", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "valueReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extension") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("extension", id), - "extension", - projectJSON, - sourceType, - "extension", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "valueReference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extension") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("extension", id), - "extension", - projectJSON, - sourceType, - "extension", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "valueReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extension") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("extension", id), - "extension", - projectJSON, - sourceType, - "extension", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "valueReference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extension") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("extension", id), - "extension", - projectJSON, - sourceType, - "extension", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "valueReference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extension") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("extension", id), - "extension", - projectJSON, - sourceType, - "extension", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "valueReference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extension") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("extension", id), - "extension", - projectJSON, - sourceType, - "extension", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "valueReference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extension") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("extension", id), - "extension", - projectJSON, - sourceType, - "extension", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "valueReference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extension") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("extension", id), - "extension", - projectJSON, - sourceType, - "extension", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "valueReference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extension") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("extension", id), - "extension", - projectJSON, - sourceType, - "extension", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "valueReference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extension") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("extension", id), - "extension", - projectJSON, - sourceType, - "extension", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "valueReference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extension") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("extension", id), - "extension", - projectJSON, - sourceType, - "extension", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "valueReference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extension") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("extension", id), - "extension", - projectJSON, - sourceType, - "extension", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "valueReference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extension") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("extension", id), - "extension", - projectJSON, - sourceType, - "extension", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "valueReference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extension") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("extension", id), - "extension", - projectJSON, - sourceType, - "extension", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "valueReference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extension") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("extension", id), - "extension", - projectJSON, - sourceType, - "extension", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "valueReference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extension") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("extension", id), - "extension", - projectJSON, - sourceType, - "extension", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "valueReference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extension") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("extension", id), - "extension", - projectJSON, - sourceType, - "extension", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "valueReference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extension") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("extension", id), - "extension", - projectJSON, - sourceType, - "extension", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "valueReference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extension") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("extension", id), - "extension", - projectJSON, - sourceType, - "extension", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "valueReference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extension") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("extension", id), - "extension", - projectJSON, - sourceType, - "extension", - )) - } - } - } - } - } - if x.ValueAnnotation != nil { - if x.ValueAnnotation.AuthorReference != nil { - if x.ValueAnnotation.AuthorReference.Reference != nil { - refVal := *x.ValueAnnotation.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "valueAnnotation_authorReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - if x.ValueAnnotation != nil { - if x.ValueAnnotation.AuthorReference != nil { - if x.ValueAnnotation.AuthorReference.Reference != nil { - refVal := *x.ValueAnnotation.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "valueAnnotation_authorReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - if x.ValueAnnotation != nil { - if x.ValueAnnotation.AuthorReference != nil { - if x.ValueAnnotation.AuthorReference.Reference != nil { - refVal := *x.ValueAnnotation.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "valueAnnotation_authorReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - if x.ValueAnnotation != nil { - if x.ValueAnnotation.AuthorReference != nil { - if x.ValueAnnotation.AuthorReference.Reference != nil { - refVal := *x.ValueAnnotation.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "valueAnnotation_authorReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "valueCodeableReference_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "valueCodeableReference_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "valueCodeableReference_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "valueCodeableReference_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "valueCodeableReference_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "valueCodeableReference_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "valueCodeableReference_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "valueCodeableReference_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "valueCodeableReference_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "valueCodeableReference_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "valueCodeableReference_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "valueCodeableReference_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "valueCodeableReference_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "valueCodeableReference_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "valueCodeableReference_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "valueCodeableReference_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "valueCodeableReference_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "valueCodeableReference_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "valueCodeableReference_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "valueCodeableReference_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "valueCodeableReference_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "valueCodeableReference_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "valueCodeableReference_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueDataRequirement != nil { - if x.ValueDataRequirement.SubjectReference != nil { - if x.ValueDataRequirement.SubjectReference.Reference != nil { - refVal := *x.ValueDataRequirement.SubjectReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "valueDataRequirement_subjectReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("subjectReference", targetID), - "valueDataRequirement_subjectReference", - projectJSON, - sourceType, - "subjectReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "data_requirement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("requirement", id), - "data_requirement", - projectJSON, - sourceType, - "requirement", - )) - } - } - } - } - } - } - if x.ValueExtendedContactDetail != nil { - if x.ValueExtendedContactDetail.Organization != nil { - if x.ValueExtendedContactDetail.Organization.Reference != nil { - refVal := *x.ValueExtendedContactDetail.Organization.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueExtendedContactDetail_organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("organization", targetID), - "valueExtendedContactDetail_organization", - projectJSON, - sourceType, - "organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extended_contact_detail") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("detail", id), - "extended_contact_detail", - projectJSON, - sourceType, - "detail", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "valueRelatedArtifact_resourceReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "valueRelatedArtifact_resourceReference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "valueRelatedArtifact_resourceReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "valueRelatedArtifact_resourceReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "valueRelatedArtifact_resourceReference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "valueRelatedArtifact_resourceReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "valueRelatedArtifact_resourceReference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "valueRelatedArtifact_resourceReference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "valueRelatedArtifact_resourceReference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "valueRelatedArtifact_resourceReference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "valueRelatedArtifact_resourceReference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "valueRelatedArtifact_resourceReference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "valueRelatedArtifact_resourceReference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "valueRelatedArtifact_resourceReference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "valueRelatedArtifact_resourceReference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "valueRelatedArtifact_resourceReference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "valueRelatedArtifact_resourceReference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "valueRelatedArtifact_resourceReference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "valueRelatedArtifact_resourceReference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "valueRelatedArtifact_resourceReference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "valueRelatedArtifact_resourceReference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "valueRelatedArtifact_resourceReference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "valueRelatedArtifact_resourceReference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.OnBehalfOf != nil { - if x.ValueSignature.OnBehalfOf.Reference != nil { - refVal := *x.ValueSignature.OnBehalfOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "valueSignature_onBehalfOf_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "onBehalfOf_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.OnBehalfOf != nil { - if x.ValueSignature.OnBehalfOf.Reference != nil { - refVal := *x.ValueSignature.OnBehalfOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "valueSignature_onBehalfOf_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "onBehalfOf_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.OnBehalfOf != nil { - if x.ValueSignature.OnBehalfOf.Reference != nil { - refVal := *x.ValueSignature.OnBehalfOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "valueSignature_onBehalfOf_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "onBehalfOf_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.OnBehalfOf != nil { - if x.ValueSignature.OnBehalfOf.Reference != nil { - refVal := *x.ValueSignature.OnBehalfOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "valueSignature_onBehalfOf_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "onBehalfOf_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.Who != nil { - if x.ValueSignature.Who.Reference != nil { - refVal := *x.ValueSignature.Who.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "valueSignature_who_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "who_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "who_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.Who != nil { - if x.ValueSignature.Who.Reference != nil { - refVal := *x.ValueSignature.Who.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "valueSignature_who_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "who_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "who_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.Who != nil { - if x.ValueSignature.Who.Reference != nil { - refVal := *x.ValueSignature.Who.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "valueSignature_who_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "who_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "who_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.Who != nil { - if x.ValueSignature.Who.Reference != nil { - refVal := *x.ValueSignature.Who.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "valueSignature_who_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "who_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "who_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueUsageContext != nil { - if x.ValueUsageContext.ValueReference != nil { - if x.ValueUsageContext.ValueReference.Reference != nil { - refVal := *x.ValueUsageContext.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueUsageContext_valueReference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "valueUsageContext_valueReference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "usage_context") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("context", id), - "usage_context", - projectJSON, - sourceType, - "context", - )) - } - } - } - } - } - } - if x.ValueUsageContext != nil { - if x.ValueUsageContext.ValueReference != nil { - if x.ValueUsageContext.ValueReference.Reference != nil { - refVal := *x.ValueUsageContext.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "valueUsageContext_valueReference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "valueUsageContext_valueReference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "usage_context") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("context", id), - "usage_context", - projectJSON, - sourceType, - "context", - )) - } - } - } - } - } - } - if x.ValueUsageContext != nil { - if x.ValueUsageContext.ValueReference != nil { - if x.ValueUsageContext.ValueReference.Reference != nil { - refVal := *x.ValueUsageContext.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueUsageContext_valueReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "valueUsageContext_valueReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "usage_context") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("context", id), - "usage_context", - projectJSON, - sourceType, - "context", - )) - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from FHIRPrimitiveExtension. -func (x *FHIRPrimitiveExtension) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "FHIRPrimitiveExtension" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from FamilyMemberHistory. -func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "FamilyMemberHistory" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Patient != nil { - if x.Patient.Reference != nil { - refVal := *x.Patient.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("patient", targetID), - "patient", - projectJSON, - sourceType, - "patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "family_member_history") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("history", id), - "family_member_history", - projectJSON, - sourceType, - "history", - )) - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "note_authorReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "note_authorReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "note_authorReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "note_authorReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Participant != nil { - for _, item_3_x_Participant := range x.Participant { - if item_3_x_Participant != nil { - if item_3_x_Participant.Actor != nil { - if item_3_x_Participant.Actor.Reference != nil { - refVal := *item_3_x_Participant.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "participant_actor_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "participant_actor_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "family_member_history_participant") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("participant", id), - "family_member_history_participant", - projectJSON, - sourceType, - "participant", - )) - } - } - } - } - } - } - } - } - if x.Participant != nil { - for _, item_3_x_Participant := range x.Participant { - if item_3_x_Participant != nil { - if item_3_x_Participant.Actor != nil { - if item_3_x_Participant.Actor.Reference != nil { - refVal := *item_3_x_Participant.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "participant_actor_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "participant_actor_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "family_member_history_participant") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("participant", id), - "family_member_history_participant", - projectJSON, - sourceType, - "participant", - )) - } - } - } - } - } - } - } - } - if x.Participant != nil { - for _, item_3_x_Participant := range x.Participant { - if item_3_x_Participant != nil { - if item_3_x_Participant.Actor != nil { - if item_3_x_Participant.Actor.Reference != nil { - refVal := *item_3_x_Participant.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "participant_actor_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "participant_actor_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "family_member_history_participant") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("participant", id), - "family_member_history_participant", - projectJSON, - sourceType, - "participant", - )) - } - } - } - } - } - } - } - } - if x.Participant != nil { - for _, item_3_x_Participant := range x.Participant { - if item_3_x_Participant != nil { - if item_3_x_Participant.Actor != nil { - if item_3_x_Participant.Actor.Reference != nil { - refVal := *item_3_x_Participant.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "participant_actor_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "participant_actor_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "family_member_history_participant") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("participant", id), - "family_member_history_participant", - projectJSON, - sourceType, - "participant", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "reason_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "reason_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "reason_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "reason_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "reason_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "reason_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "reason_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "reason_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "reason_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "reason_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "reason_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "reason_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "reason_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "reason_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "reason_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "reason_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "reason_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "reason_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "reason_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "reason_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "reason_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "reason_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "reason_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from FamilyMemberHistoryCondition. -func (x *FamilyMemberHistoryCondition) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "FamilyMemberHistoryCondition" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "note_authorReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "note_authorReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "note_authorReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "note_authorReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from FamilyMemberHistoryParticipant. -func (x *FamilyMemberHistoryParticipant) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "FamilyMemberHistoryParticipant" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Actor != nil { - if x.Actor.Reference != nil { - refVal := *x.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "actor_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "actor_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "family_member_history_participant") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("participant", id), - "family_member_history_participant", - projectJSON, - sourceType, - "participant", - )) - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - refVal := *x.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "actor_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "actor_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "family_member_history_participant") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("participant", id), - "family_member_history_participant", - projectJSON, - sourceType, - "participant", - )) - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - refVal := *x.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "actor_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "actor_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "family_member_history_participant") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("participant", id), - "family_member_history_participant", - projectJSON, - sourceType, - "participant", - )) - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - refVal := *x.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "actor_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "actor_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "family_member_history_participant") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("participant", id), - "family_member_history_participant", - projectJSON, - sourceType, - "participant", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from FamilyMemberHistoryProcedure. -func (x *FamilyMemberHistoryProcedure) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "FamilyMemberHistoryProcedure" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "note_authorReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "note_authorReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "note_authorReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "note_authorReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from Group. -func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Group" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.ManagingEntity != nil { - if x.ManagingEntity.Reference != nil { - refVal := *x.ManagingEntity.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "managingEntity_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "managingEntity_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("group", id), - "group", - projectJSON, - sourceType, - "group", - )) - } - } - } - } - } - if x.ManagingEntity != nil { - if x.ManagingEntity.Reference != nil { - refVal := *x.ManagingEntity.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "managingEntity_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "managingEntity_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("group", id), - "group", - projectJSON, - sourceType, - "group", - )) - } - } - } - } - } - if x.ManagingEntity != nil { - if x.ManagingEntity.Reference != nil { - refVal := *x.ManagingEntity.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "managingEntity_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "managingEntity_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("group", id), - "group", - projectJSON, - sourceType, - "group", - )) - } - } - } - } - } - if x.Characteristic != nil { - for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { - if item_3_x_Characteristic.ValueReference != nil { - if item_3_x_Characteristic.ValueReference.Reference != nil { - refVal := *item_3_x_Characteristic.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "characteristic_valueReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - } - } - } - if x.Characteristic != nil { - for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { - if item_3_x_Characteristic.ValueReference != nil { - if item_3_x_Characteristic.ValueReference.Reference != nil { - refVal := *item_3_x_Characteristic.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "characteristic_valueReference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - } - } - } - if x.Characteristic != nil { - for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { - if item_3_x_Characteristic.ValueReference != nil { - if item_3_x_Characteristic.ValueReference.Reference != nil { - refVal := *item_3_x_Characteristic.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "characteristic_valueReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - } - } - } - if x.Characteristic != nil { - for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { - if item_3_x_Characteristic.ValueReference != nil { - if item_3_x_Characteristic.ValueReference.Reference != nil { - refVal := *item_3_x_Characteristic.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "characteristic_valueReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - } - } - } - if x.Characteristic != nil { - for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { - if item_3_x_Characteristic.ValueReference != nil { - if item_3_x_Characteristic.ValueReference.Reference != nil { - refVal := *item_3_x_Characteristic.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "characteristic_valueReference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - } - } - } - if x.Characteristic != nil { - for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { - if item_3_x_Characteristic.ValueReference != nil { - if item_3_x_Characteristic.ValueReference.Reference != nil { - refVal := *item_3_x_Characteristic.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "characteristic_valueReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - } - } - } - if x.Characteristic != nil { - for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { - if item_3_x_Characteristic.ValueReference != nil { - if item_3_x_Characteristic.ValueReference.Reference != nil { - refVal := *item_3_x_Characteristic.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "characteristic_valueReference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - } - } - } - if x.Characteristic != nil { - for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { - if item_3_x_Characteristic.ValueReference != nil { - if item_3_x_Characteristic.ValueReference.Reference != nil { - refVal := *item_3_x_Characteristic.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "characteristic_valueReference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - } - } - } - if x.Characteristic != nil { - for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { - if item_3_x_Characteristic.ValueReference != nil { - if item_3_x_Characteristic.ValueReference.Reference != nil { - refVal := *item_3_x_Characteristic.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "characteristic_valueReference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - } - } - } - if x.Characteristic != nil { - for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { - if item_3_x_Characteristic.ValueReference != nil { - if item_3_x_Characteristic.ValueReference.Reference != nil { - refVal := *item_3_x_Characteristic.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "characteristic_valueReference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - } - } - } - if x.Characteristic != nil { - for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { - if item_3_x_Characteristic.ValueReference != nil { - if item_3_x_Characteristic.ValueReference.Reference != nil { - refVal := *item_3_x_Characteristic.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "characteristic_valueReference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - } - } - } - if x.Characteristic != nil { - for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { - if item_3_x_Characteristic.ValueReference != nil { - if item_3_x_Characteristic.ValueReference.Reference != nil { - refVal := *item_3_x_Characteristic.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "characteristic_valueReference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - } - } - } - if x.Characteristic != nil { - for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { - if item_3_x_Characteristic.ValueReference != nil { - if item_3_x_Characteristic.ValueReference.Reference != nil { - refVal := *item_3_x_Characteristic.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "characteristic_valueReference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - } - } - } - if x.Characteristic != nil { - for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { - if item_3_x_Characteristic.ValueReference != nil { - if item_3_x_Characteristic.ValueReference.Reference != nil { - refVal := *item_3_x_Characteristic.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "characteristic_valueReference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - } - } - } - if x.Characteristic != nil { - for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { - if item_3_x_Characteristic.ValueReference != nil { - if item_3_x_Characteristic.ValueReference.Reference != nil { - refVal := *item_3_x_Characteristic.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "characteristic_valueReference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - } - } - } - if x.Characteristic != nil { - for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { - if item_3_x_Characteristic.ValueReference != nil { - if item_3_x_Characteristic.ValueReference.Reference != nil { - refVal := *item_3_x_Characteristic.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "characteristic_valueReference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - } - } - } - if x.Characteristic != nil { - for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { - if item_3_x_Characteristic.ValueReference != nil { - if item_3_x_Characteristic.ValueReference.Reference != nil { - refVal := *item_3_x_Characteristic.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "characteristic_valueReference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - } - } - } - if x.Characteristic != nil { - for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { - if item_3_x_Characteristic.ValueReference != nil { - if item_3_x_Characteristic.ValueReference.Reference != nil { - refVal := *item_3_x_Characteristic.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "characteristic_valueReference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - } - } - } - if x.Characteristic != nil { - for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { - if item_3_x_Characteristic.ValueReference != nil { - if item_3_x_Characteristic.ValueReference.Reference != nil { - refVal := *item_3_x_Characteristic.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "characteristic_valueReference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - } - } - } - if x.Characteristic != nil { - for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { - if item_3_x_Characteristic.ValueReference != nil { - if item_3_x_Characteristic.ValueReference.Reference != nil { - refVal := *item_3_x_Characteristic.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "characteristic_valueReference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - } - } - } - if x.Characteristic != nil { - for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { - if item_3_x_Characteristic.ValueReference != nil { - if item_3_x_Characteristic.ValueReference.Reference != nil { - refVal := *item_3_x_Characteristic.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "characteristic_valueReference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - } - } - } - if x.Characteristic != nil { - for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { - if item_3_x_Characteristic.ValueReference != nil { - if item_3_x_Characteristic.ValueReference.Reference != nil { - refVal := *item_3_x_Characteristic.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "characteristic_valueReference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - } - } - } - if x.Characteristic != nil { - for _, item_3_x_Characteristic := range x.Characteristic { - if item_3_x_Characteristic != nil { - if item_3_x_Characteristic.ValueReference != nil { - if item_3_x_Characteristic.ValueReference.Reference != nil { - refVal := *item_3_x_Characteristic.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "characteristic_valueReference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - } - } - } - if x.Member != nil { - for _, item_3_x_Member := range x.Member { - if item_3_x_Member != nil { - if item_3_x_Member.Entity != nil { - if item_3_x_Member.Entity.Reference != nil { - refVal := *item_3_x_Member.Entity.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "member_entity_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "member_entity_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_member") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("member", id), - "group_member", - projectJSON, - sourceType, - "member", - )) - } - } - } - } - } - } - } - } - if x.Member != nil { - for _, item_3_x_Member := range x.Member { - if item_3_x_Member != nil { - if item_3_x_Member.Entity != nil { - if item_3_x_Member.Entity.Reference != nil { - refVal := *item_3_x_Member.Entity.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "member_entity_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "member_entity_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_member") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("member", id), - "group_member", - projectJSON, - sourceType, - "member", - )) - } - } - } - } - } - } - } - } - if x.Member != nil { - for _, item_3_x_Member := range x.Member { - if item_3_x_Member != nil { - if item_3_x_Member.Entity != nil { - if item_3_x_Member.Entity.Reference != nil { - refVal := *item_3_x_Member.Entity.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "member_entity_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "member_entity_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_member") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("member", id), - "group_member", - projectJSON, - sourceType, - "member", - )) - } - } - } - } - } - } - } - } - if x.Member != nil { - for _, item_3_x_Member := range x.Member { - if item_3_x_Member != nil { - if item_3_x_Member.Entity != nil { - if item_3_x_Member.Entity.Reference != nil { - refVal := *item_3_x_Member.Entity.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "member_entity_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "member_entity_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_member") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("member", id), - "group_member", - projectJSON, - sourceType, - "member", - )) - } - } - } - } - } - } - } - } - if x.Member != nil { - for _, item_3_x_Member := range x.Member { - if item_3_x_Member != nil { - if item_3_x_Member.Entity != nil { - if item_3_x_Member.Entity.Reference != nil { - refVal := *item_3_x_Member.Entity.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "member_entity_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "member_entity_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_member") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("member", id), - "group_member", - projectJSON, - sourceType, - "member", - )) - } - } - } - } - } - } - } - } - if x.Member != nil { - for _, item_3_x_Member := range x.Member { - if item_3_x_Member != nil { - if item_3_x_Member.Entity != nil { - if item_3_x_Member.Entity.Reference != nil { - refVal := *item_3_x_Member.Entity.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "member_entity_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "member_entity_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_member") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("member", id), - "group_member", - projectJSON, - sourceType, - "member", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from GroupCharacteristic. -func (x *GroupCharacteristic) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "GroupCharacteristic" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "valueReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "valueReference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "valueReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "valueReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "valueReference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "valueReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "valueReference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "valueReference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "valueReference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "valueReference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "valueReference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "valueReference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "valueReference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "valueReference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "valueReference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "valueReference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "valueReference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "valueReference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "valueReference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "valueReference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "valueReference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "valueReference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "valueReference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_characteristic") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("characteristic", id), - "group_characteristic", - projectJSON, - sourceType, - "characteristic", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from GroupMember. -func (x *GroupMember) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "GroupMember" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Entity != nil { - if x.Entity.Reference != nil { - refVal := *x.Entity.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "entity_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "entity_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_member") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("member", id), - "group_member", - projectJSON, - sourceType, - "member", - )) - } - } - } - } - } - if x.Entity != nil { - if x.Entity.Reference != nil { - refVal := *x.Entity.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "entity_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "entity_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_member") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("member", id), - "group_member", - projectJSON, - sourceType, - "member", - )) - } - } - } - } - } - if x.Entity != nil { - if x.Entity.Reference != nil { - refVal := *x.Entity.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "entity_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "entity_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_member") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("member", id), - "group_member", - projectJSON, - sourceType, - "member", - )) - } - } - } - } - } - if x.Entity != nil { - if x.Entity.Reference != nil { - refVal := *x.Entity.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "entity_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "entity_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_member") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("member", id), - "group_member", - projectJSON, - sourceType, - "member", - )) - } - } - } - } - } - if x.Entity != nil { - if x.Entity.Reference != nil { - refVal := *x.Entity.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "entity_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "entity_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_member") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("member", id), - "group_member", - projectJSON, - sourceType, - "member", - )) - } - } - } - } - } - if x.Entity != nil { - if x.Entity.Reference != nil { - refVal := *x.Entity.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "entity_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "entity_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "group_member") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("member", id), - "group_member", - projectJSON, - sourceType, - "member", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from HumanName. -func (x *HumanName) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "HumanName" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from Identifier. -func (x *Identifier) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Identifier" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Assigner != nil { - if x.Assigner.Reference != nil { - refVal := *x.Assigner.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "assigner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("assigner", targetID), - "assigner", - projectJSON, - sourceType, - "assigner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "identifier") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("identifier", id), - "identifier", - projectJSON, - sourceType, - "identifier", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from ImagingStudy. -func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ImagingStudy" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "basedOn_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_imaging_study") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("study", id), - "basedOn_imaging_study", - projectJSON, - sourceType, - "study", - )) - } - } - } - } - } - } - } - if x.PartOf != nil { - for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { - if item_2_x_PartOf.Reference != nil { - refVal := *item_2_x_PartOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "partOf") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("partOf", targetID), - "partOf", - projectJSON, - sourceType, - "partOf", - )) - } - backrefKey := getEdgeUUID(id, targetID, "partOf_imaging_study") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("study", id), - "partOf_imaging_study", - projectJSON, - sourceType, - "study", - )) - } - } - } - } - } - } - } - if x.Referrer != nil { - if x.Referrer.Reference != nil { - refVal := *x.Referrer.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "referrer_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "referrer_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "imaging_study") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("study", id), - "imaging_study", - projectJSON, - sourceType, - "study", - )) - } - } - } - } - } - if x.Referrer != nil { - if x.Referrer.Reference != nil { - refVal := *x.Referrer.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "referrer_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "referrer_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "imaging_study") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("study", id), - "imaging_study", - projectJSON, - sourceType, - "study", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "subject_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "subject_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "imaging_study") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("study", id), - "imaging_study", - projectJSON, - sourceType, - "study", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "subject_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "subject_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "imaging_study") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("study", id), - "imaging_study", - projectJSON, - sourceType, - "study", - )) - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "note_authorReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "note_authorReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "note_authorReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "note_authorReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Procedure != nil { - for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { - if item_3_x_Procedure.Reference != nil { - if item_3_x_Procedure.Reference.Reference != nil { - refVal := *item_3_x_Procedure.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "procedure_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "procedure_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Procedure != nil { - for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { - if item_3_x_Procedure.Reference != nil { - if item_3_x_Procedure.Reference.Reference != nil { - refVal := *item_3_x_Procedure.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "procedure_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "procedure_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Procedure != nil { - for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { - if item_3_x_Procedure.Reference != nil { - if item_3_x_Procedure.Reference.Reference != nil { - refVal := *item_3_x_Procedure.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "procedure_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "procedure_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Procedure != nil { - for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { - if item_3_x_Procedure.Reference != nil { - if item_3_x_Procedure.Reference.Reference != nil { - refVal := *item_3_x_Procedure.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "procedure_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "procedure_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Procedure != nil { - for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { - if item_3_x_Procedure.Reference != nil { - if item_3_x_Procedure.Reference.Reference != nil { - refVal := *item_3_x_Procedure.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "procedure_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "procedure_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Procedure != nil { - for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { - if item_3_x_Procedure.Reference != nil { - if item_3_x_Procedure.Reference.Reference != nil { - refVal := *item_3_x_Procedure.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "procedure_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "procedure_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Procedure != nil { - for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { - if item_3_x_Procedure.Reference != nil { - if item_3_x_Procedure.Reference.Reference != nil { - refVal := *item_3_x_Procedure.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "procedure_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "procedure_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Procedure != nil { - for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { - if item_3_x_Procedure.Reference != nil { - if item_3_x_Procedure.Reference.Reference != nil { - refVal := *item_3_x_Procedure.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "procedure_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "procedure_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Procedure != nil { - for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { - if item_3_x_Procedure.Reference != nil { - if item_3_x_Procedure.Reference.Reference != nil { - refVal := *item_3_x_Procedure.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "procedure_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "procedure_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Procedure != nil { - for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { - if item_3_x_Procedure.Reference != nil { - if item_3_x_Procedure.Reference.Reference != nil { - refVal := *item_3_x_Procedure.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "procedure_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "procedure_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Procedure != nil { - for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { - if item_3_x_Procedure.Reference != nil { - if item_3_x_Procedure.Reference.Reference != nil { - refVal := *item_3_x_Procedure.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "procedure_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "procedure_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Procedure != nil { - for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { - if item_3_x_Procedure.Reference != nil { - if item_3_x_Procedure.Reference.Reference != nil { - refVal := *item_3_x_Procedure.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "procedure_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "procedure_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Procedure != nil { - for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { - if item_3_x_Procedure.Reference != nil { - if item_3_x_Procedure.Reference.Reference != nil { - refVal := *item_3_x_Procedure.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "procedure_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "procedure_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Procedure != nil { - for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { - if item_3_x_Procedure.Reference != nil { - if item_3_x_Procedure.Reference.Reference != nil { - refVal := *item_3_x_Procedure.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "procedure_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "procedure_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Procedure != nil { - for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { - if item_3_x_Procedure.Reference != nil { - if item_3_x_Procedure.Reference.Reference != nil { - refVal := *item_3_x_Procedure.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "procedure_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "procedure_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Procedure != nil { - for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { - if item_3_x_Procedure.Reference != nil { - if item_3_x_Procedure.Reference.Reference != nil { - refVal := *item_3_x_Procedure.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "procedure_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "procedure_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Procedure != nil { - for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { - if item_3_x_Procedure.Reference != nil { - if item_3_x_Procedure.Reference.Reference != nil { - refVal := *item_3_x_Procedure.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "procedure_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "procedure_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Procedure != nil { - for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { - if item_3_x_Procedure.Reference != nil { - if item_3_x_Procedure.Reference.Reference != nil { - refVal := *item_3_x_Procedure.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "procedure_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "procedure_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Procedure != nil { - for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { - if item_3_x_Procedure.Reference != nil { - if item_3_x_Procedure.Reference.Reference != nil { - refVal := *item_3_x_Procedure.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "procedure_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "procedure_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Procedure != nil { - for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { - if item_3_x_Procedure.Reference != nil { - if item_3_x_Procedure.Reference.Reference != nil { - refVal := *item_3_x_Procedure.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "procedure_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "procedure_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Procedure != nil { - for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { - if item_3_x_Procedure.Reference != nil { - if item_3_x_Procedure.Reference.Reference != nil { - refVal := *item_3_x_Procedure.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "procedure_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "procedure_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Procedure != nil { - for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { - if item_3_x_Procedure.Reference != nil { - if item_3_x_Procedure.Reference.Reference != nil { - refVal := *item_3_x_Procedure.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "procedure_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "procedure_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Procedure != nil { - for _, item_3_x_Procedure := range x.Procedure { - if item_3_x_Procedure != nil { - if item_3_x_Procedure.Reference != nil { - if item_3_x_Procedure.Reference.Reference != nil { - refVal := *item_3_x_Procedure.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "procedure_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "procedure_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "reason_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "reason_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "reason_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "reason_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "reason_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "reason_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "reason_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "reason_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "reason_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "reason_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "reason_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "reason_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "reason_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "reason_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "reason_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "reason_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "reason_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "reason_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "reason_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "reason_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "reason_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "reason_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "reason_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Series != nil { - for _, item_4_x_Series := range x.Series { - if item_4_x_Series != nil { - if item_4_x_Series.Specimen != nil { - for _, item_2_item_4_x_Series_Specimen := range item_4_x_Series.Specimen { - if item_2_item_4_x_Series_Specimen != nil { - if item_2_item_4_x_Series_Specimen.Reference != nil { - refVal := *item_2_item_4_x_Series_Specimen.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "series_specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("specimen", targetID), - "series_specimen", - projectJSON, - sourceType, - "specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "specimen_imaging_study_series") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("series", id), - "specimen_imaging_study_series", - projectJSON, - sourceType, - "series", - )) - } - } - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from ImagingStudySeries. -func (x *ImagingStudySeries) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ImagingStudySeries" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Specimen != nil { - for _, item_2_x_Specimen := range x.Specimen { - if item_2_x_Specimen != nil { - if item_2_x_Specimen.Reference != nil { - refVal := *item_2_x_Specimen.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("specimen", targetID), - "specimen", - projectJSON, - sourceType, - "specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "specimen_imaging_study_series") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("series", id), - "specimen_imaging_study_series", - projectJSON, - sourceType, - "series", - )) - } - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "bodySite_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "bodySite_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "bodySite_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "bodySite_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "bodySite_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "bodySite_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "bodySite_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "bodySite_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "bodySite_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "bodySite_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "bodySite_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "bodySite_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "bodySite_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "bodySite_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "bodySite_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "bodySite_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "bodySite_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "bodySite_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "bodySite_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "bodySite_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "bodySite_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "bodySite_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "bodySite_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Performer != nil { - for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { - if item_3_x_Performer.Actor != nil { - if item_3_x_Performer.Actor.Reference != nil { - refVal := *item_3_x_Performer.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "performer_actor_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "performer_actor_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "imaging_study_series_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "imaging_study_series_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - } - } - } - if x.Performer != nil { - for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { - if item_3_x_Performer.Actor != nil { - if item_3_x_Performer.Actor.Reference != nil { - refVal := *item_3_x_Performer.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "performer_actor_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "performer_actor_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "imaging_study_series_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "imaging_study_series_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - } - } - } - if x.Performer != nil { - for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { - if item_3_x_Performer.Actor != nil { - if item_3_x_Performer.Actor.Reference != nil { - refVal := *item_3_x_Performer.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "performer_actor_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "performer_actor_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "imaging_study_series_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "imaging_study_series_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - } - } - } - if x.Performer != nil { - for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { - if item_3_x_Performer.Actor != nil { - if item_3_x_Performer.Actor.Reference != nil { - refVal := *item_3_x_Performer.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "performer_actor_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "performer_actor_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "imaging_study_series_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "imaging_study_series_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from ImagingStudySeriesInstance. -func (x *ImagingStudySeriesInstance) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ImagingStudySeriesInstance" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from ImagingStudySeriesPerformer. -func (x *ImagingStudySeriesPerformer) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ImagingStudySeriesPerformer" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Actor != nil { - if x.Actor.Reference != nil { - refVal := *x.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "actor_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "actor_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "imaging_study_series_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "imaging_study_series_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - refVal := *x.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "actor_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "actor_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "imaging_study_series_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "imaging_study_series_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - refVal := *x.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "actor_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "actor_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "imaging_study_series_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "imaging_study_series_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - refVal := *x.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "actor_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "actor_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "imaging_study_series_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "imaging_study_series_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from Medication. -func (x *Medication) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Medication" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.MarketingAuthorizationHolder != nil { - if x.MarketingAuthorizationHolder.Reference != nil { - refVal := *x.MarketingAuthorizationHolder.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "marketingAuthorizationHolder") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("marketingAuthorizationHolder", targetID), - "marketingAuthorizationHolder", - projectJSON, - sourceType, - "marketingAuthorizationHolder", - )) - } - backrefKey := getEdgeUUID(id, targetID, "medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("medication", id), - "medication", - projectJSON, - sourceType, - "medication", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from MedicationAdministration. -func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "MedicationAdministration" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.PartOf != nil { - for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { - if item_2_x_PartOf.Reference != nil { - refVal := *item_2_x_PartOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "partOf_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "partOf_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "partOf_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "partOf_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.PartOf != nil { - for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { - if item_2_x_PartOf.Reference != nil { - refVal := *item_2_x_PartOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "partOf_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "partOf_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "partOf_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "partOf_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.Request != nil { - if x.Request.Reference != nil { - refVal := *x.Request.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("request", targetID), - "request", - projectJSON, - sourceType, - "request", - )) - } - backrefKey := getEdgeUUID(id, targetID, "medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "subject_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "subject_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "subject_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "subject_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "supportingInformation_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "supportingInformation_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "supportingInformation_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "supportingInformation_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "supportingInformation_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "supportingInformation_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "supportingInformation_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "supportingInformation_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "supportingInformation_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "supportingInformation_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "supportingInformation_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "supportingInformation_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "supportingInformation_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "supportingInformation_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "supportingInformation_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "supportingInformation_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "supportingInformation_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "supportingInformation_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "supportingInformation_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "supportingInformation_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "supportingInformation_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "supportingInformation_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "supportingInformation_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "supportingInformation_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "supportingInformation_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "supportingInformation_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "supportingInformation_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "supportingInformation_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "supportingInformation_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "supportingInformation_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "supportingInformation_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "supportingInformation_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "supportingInformation_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "supportingInformation_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "supportingInformation_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "supportingInformation_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "supportingInformation_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "supportingInformation_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "supportingInformation_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "supportingInformation_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "supportingInformation_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "supportingInformation_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "supportingInformation_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "supportingInformation_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "supportingInformation_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("administration", id), - "supportingInformation_medication_administration", - projectJSON, - sourceType, - "administration", - )) - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "device_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "device_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "device_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "device_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "device_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "device_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "device_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "device_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "device_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "device_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "device_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "device_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "device_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "device_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "device_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "device_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "device_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "device_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "device_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "device_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "device_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "device_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "device_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "medication_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "medication_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "medication_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "medication_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "medication_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "medication_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "medication_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "medication_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "medication_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "medication_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "medication_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "medication_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "medication_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "medication_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "medication_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "medication_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "medication_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "medication_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "medication_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "medication_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "medication_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "medication_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "medication_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "note_authorReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "note_authorReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "note_authorReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "note_authorReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "reason_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "reason_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "reason_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "reason_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "reason_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "reason_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "reason_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "reason_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "reason_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "reason_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "reason_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "reason_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "reason_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "reason_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "reason_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "reason_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "reason_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "reason_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "reason_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "reason_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "reason_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "reason_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "reason_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from MedicationAdministrationDosage. -func (x *MedicationAdministrationDosage) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "MedicationAdministrationDosage" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from MedicationAdministrationPerformer. -func (x *MedicationAdministrationPerformer) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "MedicationAdministrationPerformer" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Actor != nil { - if x.Actor.Reference != nil { - if x.Actor.Reference.Reference != nil { - refVal := *x.Actor.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "actor_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "actor_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - if x.Actor.Reference.Reference != nil { - refVal := *x.Actor.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "actor_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "actor_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - if x.Actor.Reference.Reference != nil { - refVal := *x.Actor.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "actor_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "actor_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - if x.Actor.Reference.Reference != nil { - refVal := *x.Actor.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "actor_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "actor_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - if x.Actor.Reference.Reference != nil { - refVal := *x.Actor.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "actor_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "actor_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - if x.Actor.Reference.Reference != nil { - refVal := *x.Actor.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "actor_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "actor_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - if x.Actor.Reference.Reference != nil { - refVal := *x.Actor.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "actor_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "actor_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - if x.Actor.Reference.Reference != nil { - refVal := *x.Actor.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "actor_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "actor_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - if x.Actor.Reference.Reference != nil { - refVal := *x.Actor.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "actor_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "actor_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - if x.Actor.Reference.Reference != nil { - refVal := *x.Actor.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "actor_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "actor_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - if x.Actor.Reference.Reference != nil { - refVal := *x.Actor.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "actor_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "actor_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - if x.Actor.Reference.Reference != nil { - refVal := *x.Actor.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "actor_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "actor_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - if x.Actor.Reference.Reference != nil { - refVal := *x.Actor.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "actor_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "actor_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - if x.Actor.Reference.Reference != nil { - refVal := *x.Actor.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "actor_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "actor_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - if x.Actor.Reference.Reference != nil { - refVal := *x.Actor.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "actor_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "actor_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - if x.Actor.Reference.Reference != nil { - refVal := *x.Actor.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "actor_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "actor_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - if x.Actor.Reference.Reference != nil { - refVal := *x.Actor.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "actor_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "actor_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - if x.Actor.Reference.Reference != nil { - refVal := *x.Actor.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "actor_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "actor_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - if x.Actor.Reference.Reference != nil { - refVal := *x.Actor.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "actor_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "actor_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - if x.Actor.Reference.Reference != nil { - refVal := *x.Actor.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "actor_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "actor_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - if x.Actor.Reference.Reference != nil { - refVal := *x.Actor.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "actor_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "actor_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - if x.Actor.Reference.Reference != nil { - refVal := *x.Actor.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "actor_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "actor_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - if x.Actor.Reference.Reference != nil { - refVal := *x.Actor.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "actor_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "actor_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from MedicationBatch. -func (x *MedicationBatch) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "MedicationBatch" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from MedicationIngredient. -func (x *MedicationIngredient) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "MedicationIngredient" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Item != nil { - if x.Item.Reference != nil { - if x.Item.Reference.Reference != nil { - refVal := *x.Item.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "item_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "item_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Item != nil { - if x.Item.Reference != nil { - if x.Item.Reference.Reference != nil { - refVal := *x.Item.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "item_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "item_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Item != nil { - if x.Item.Reference != nil { - if x.Item.Reference.Reference != nil { - refVal := *x.Item.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "item_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "item_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Item != nil { - if x.Item.Reference != nil { - if x.Item.Reference.Reference != nil { - refVal := *x.Item.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "item_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "item_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Item != nil { - if x.Item.Reference != nil { - if x.Item.Reference.Reference != nil { - refVal := *x.Item.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "item_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "item_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Item != nil { - if x.Item.Reference != nil { - if x.Item.Reference.Reference != nil { - refVal := *x.Item.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "item_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "item_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Item != nil { - if x.Item.Reference != nil { - if x.Item.Reference.Reference != nil { - refVal := *x.Item.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "item_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "item_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Item != nil { - if x.Item.Reference != nil { - if x.Item.Reference.Reference != nil { - refVal := *x.Item.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "item_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "item_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Item != nil { - if x.Item.Reference != nil { - if x.Item.Reference.Reference != nil { - refVal := *x.Item.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "item_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "item_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Item != nil { - if x.Item.Reference != nil { - if x.Item.Reference.Reference != nil { - refVal := *x.Item.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "item_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "item_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Item != nil { - if x.Item.Reference != nil { - if x.Item.Reference.Reference != nil { - refVal := *x.Item.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "item_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "item_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Item != nil { - if x.Item.Reference != nil { - if x.Item.Reference.Reference != nil { - refVal := *x.Item.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "item_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "item_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Item != nil { - if x.Item.Reference != nil { - if x.Item.Reference.Reference != nil { - refVal := *x.Item.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "item_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "item_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Item != nil { - if x.Item.Reference != nil { - if x.Item.Reference.Reference != nil { - refVal := *x.Item.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "item_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "item_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Item != nil { - if x.Item.Reference != nil { - if x.Item.Reference.Reference != nil { - refVal := *x.Item.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "item_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "item_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Item != nil { - if x.Item.Reference != nil { - if x.Item.Reference.Reference != nil { - refVal := *x.Item.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "item_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "item_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Item != nil { - if x.Item.Reference != nil { - if x.Item.Reference.Reference != nil { - refVal := *x.Item.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "item_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "item_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Item != nil { - if x.Item.Reference != nil { - if x.Item.Reference.Reference != nil { - refVal := *x.Item.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "item_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "item_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Item != nil { - if x.Item.Reference != nil { - if x.Item.Reference.Reference != nil { - refVal := *x.Item.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "item_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "item_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Item != nil { - if x.Item.Reference != nil { - if x.Item.Reference.Reference != nil { - refVal := *x.Item.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "item_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "item_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Item != nil { - if x.Item.Reference != nil { - if x.Item.Reference.Reference != nil { - refVal := *x.Item.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "item_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "item_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Item != nil { - if x.Item.Reference != nil { - if x.Item.Reference.Reference != nil { - refVal := *x.Item.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "item_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "item_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Item != nil { - if x.Item.Reference != nil { - if x.Item.Reference.Reference != nil { - refVal := *x.Item.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "item_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "item_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from MedicationRequest. -func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "MedicationRequest" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "basedOn_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "basedOn_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.InformationSource != nil { - for _, item_2_x_InformationSource := range x.InformationSource { - if item_2_x_InformationSource != nil { - if item_2_x_InformationSource.Reference != nil { - refVal := *item_2_x_InformationSource.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "informationSource_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "informationSource_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "informationSource_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "informationSource_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.InformationSource != nil { - for _, item_2_x_InformationSource := range x.InformationSource { - if item_2_x_InformationSource != nil { - if item_2_x_InformationSource.Reference != nil { - refVal := *item_2_x_InformationSource.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "informationSource_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "informationSource_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "informationSource_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "informationSource_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.InformationSource != nil { - for _, item_2_x_InformationSource := range x.InformationSource { - if item_2_x_InformationSource != nil { - if item_2_x_InformationSource.Reference != nil { - refVal := *item_2_x_InformationSource.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "informationSource_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "informationSource_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "informationSource_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "informationSource_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.InformationSource != nil { - for _, item_2_x_InformationSource := range x.InformationSource { - if item_2_x_InformationSource != nil { - if item_2_x_InformationSource.Reference != nil { - refVal := *item_2_x_InformationSource.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "informationSource_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "informationSource_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "informationSource_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "informationSource_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.Performer != nil { - for _, item_2_x_Performer := range x.Performer { - if item_2_x_Performer != nil { - if item_2_x_Performer.Reference != nil { - refVal := *item_2_x_Performer.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "performer_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "performer_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "performer_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "performer_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.Performer != nil { - for _, item_2_x_Performer := range x.Performer { - if item_2_x_Performer != nil { - if item_2_x_Performer.Reference != nil { - refVal := *item_2_x_Performer.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "performer_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "performer_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "performer_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "performer_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.Performer != nil { - for _, item_2_x_Performer := range x.Performer { - if item_2_x_Performer != nil { - if item_2_x_Performer.Reference != nil { - refVal := *item_2_x_Performer.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "performer_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "performer_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "performer_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "performer_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.Performer != nil { - for _, item_2_x_Performer := range x.Performer { - if item_2_x_Performer != nil { - if item_2_x_Performer.Reference != nil { - refVal := *item_2_x_Performer.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "performer_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "performer_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "performer_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "performer_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.PriorPrescription != nil { - if x.PriorPrescription.Reference != nil { - refVal := *x.PriorPrescription.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "priorPrescription") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("priorPrescription", targetID), - "priorPrescription", - projectJSON, - sourceType, - "priorPrescription", - )) - } - backrefKey := getEdgeUUID(id, targetID, "priorPrescription_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "priorPrescription_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - if x.Recorder != nil { - if x.Recorder.Reference != nil { - refVal := *x.Recorder.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "recorder_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "recorder_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "recorder_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "recorder_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - if x.Recorder != nil { - if x.Recorder.Reference != nil { - refVal := *x.Recorder.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "recorder_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "recorder_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "recorder_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "recorder_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - if x.Requester != nil { - if x.Requester.Reference != nil { - refVal := *x.Requester.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "requester_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "requester_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "requester_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "requester_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - if x.Requester != nil { - if x.Requester.Reference != nil { - refVal := *x.Requester.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "requester_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "requester_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "requester_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "requester_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - if x.Requester != nil { - if x.Requester.Reference != nil { - refVal := *x.Requester.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "requester_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "requester_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "requester_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "requester_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - if x.Requester != nil { - if x.Requester.Reference != nil { - refVal := *x.Requester.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "requester_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "requester_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "requester_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "requester_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "subject_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "subject_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "subject_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "subject_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "subject_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "subject_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "subject_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "subject_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "supportingInformation_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "supportingInformation_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "supportingInformation_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "supportingInformation_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "supportingInformation_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "supportingInformation_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "supportingInformation_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "supportingInformation_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "supportingInformation_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "supportingInformation_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "supportingInformation_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "supportingInformation_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "supportingInformation_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "supportingInformation_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "supportingInformation_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "supportingInformation_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "supportingInformation_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "supportingInformation_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "supportingInformation_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "supportingInformation_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "supportingInformation_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "supportingInformation_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "supportingInformation_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "supportingInformation_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "supportingInformation_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "supportingInformation_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "supportingInformation_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "supportingInformation_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "supportingInformation_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "supportingInformation_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "supportingInformation_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "supportingInformation_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "supportingInformation_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "supportingInformation_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "supportingInformation_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "supportingInformation_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "supportingInformation_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "supportingInformation_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "supportingInformation_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "supportingInformation_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "supportingInformation_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "supportingInformation_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "supportingInformation_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "supportingInformation_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.SupportingInformation != nil { - for _, item_2_x_SupportingInformation := range x.SupportingInformation { - if item_2_x_SupportingInformation != nil { - if item_2_x_SupportingInformation.Reference != nil { - refVal := *item_2_x_SupportingInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "supportingInformation_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "supportingInformation_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "supportingInformation_medication_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "device_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "device_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "device_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "device_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "device_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "device_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "device_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "device_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "device_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "device_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "device_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "device_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "device_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "device_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "device_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "device_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "device_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "device_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "device_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "device_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "device_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "device_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Device != nil { - for _, item_3_x_Device := range x.Device { - if item_3_x_Device != nil { - if item_3_x_Device.Reference != nil { - if item_3_x_Device.Reference.Reference != nil { - refVal := *item_3_x_Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "device_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.DispenseRequest != nil { - if x.DispenseRequest.Dispenser != nil { - if x.DispenseRequest.Dispenser.Reference != nil { - refVal := *x.DispenseRequest.Dispenser.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "dispenseRequest_dispenser") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("dispenser", targetID), - "dispenseRequest_dispenser", - projectJSON, - sourceType, - "dispenser", - )) - } - backrefKey := getEdgeUUID(id, targetID, "medication_request_dispense_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "medication_request_dispense_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "medication_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "medication_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "medication_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "medication_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "medication_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "medication_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "medication_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "medication_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "medication_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "medication_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "medication_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "medication_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "medication_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "medication_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "medication_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "medication_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "medication_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "medication_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "medication_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "medication_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "medication_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "medication_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "medication_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "note_authorReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "note_authorReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "note_authorReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "note_authorReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "reason_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "reason_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "reason_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "reason_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "reason_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "reason_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "reason_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "reason_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "reason_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "reason_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "reason_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "reason_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "reason_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "reason_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "reason_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "reason_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "reason_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "reason_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "reason_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "reason_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "reason_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "reason_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "reason_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from MedicationRequestDispenseRequest. -func (x *MedicationRequestDispenseRequest) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "MedicationRequestDispenseRequest" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Dispenser != nil { - if x.Dispenser.Reference != nil { - refVal := *x.Dispenser.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "dispenser") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("dispenser", targetID), - "dispenser", - projectJSON, - sourceType, - "dispenser", - )) - } - backrefKey := getEdgeUUID(id, targetID, "medication_request_dispense_request") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("request", id), - "medication_request_dispense_request", - projectJSON, - sourceType, - "request", - )) - } - } - } - } - } - if x.DispenserInstruction != nil { - for _, item_3_x_DispenserInstruction := range x.DispenserInstruction { - if item_3_x_DispenserInstruction != nil { - if item_3_x_DispenserInstruction.AuthorReference != nil { - if item_3_x_DispenserInstruction.AuthorReference.Reference != nil { - refVal := *item_3_x_DispenserInstruction.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "dispenserInstruction_authorReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "dispenserInstruction_authorReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.DispenserInstruction != nil { - for _, item_3_x_DispenserInstruction := range x.DispenserInstruction { - if item_3_x_DispenserInstruction != nil { - if item_3_x_DispenserInstruction.AuthorReference != nil { - if item_3_x_DispenserInstruction.AuthorReference.Reference != nil { - refVal := *item_3_x_DispenserInstruction.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "dispenserInstruction_authorReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "dispenserInstruction_authorReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.DispenserInstruction != nil { - for _, item_3_x_DispenserInstruction := range x.DispenserInstruction { - if item_3_x_DispenserInstruction != nil { - if item_3_x_DispenserInstruction.AuthorReference != nil { - if item_3_x_DispenserInstruction.AuthorReference.Reference != nil { - refVal := *item_3_x_DispenserInstruction.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "dispenserInstruction_authorReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "dispenserInstruction_authorReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.DispenserInstruction != nil { - for _, item_3_x_DispenserInstruction := range x.DispenserInstruction { - if item_3_x_DispenserInstruction != nil { - if item_3_x_DispenserInstruction.AuthorReference != nil { - if item_3_x_DispenserInstruction.AuthorReference.Reference != nil { - refVal := *item_3_x_DispenserInstruction.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "dispenserInstruction_authorReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "dispenserInstruction_authorReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from MedicationRequestDispenseRequestInitialFill. -func (x *MedicationRequestDispenseRequestInitialFill) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "MedicationRequestDispenseRequestInitialFill" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from MedicationRequestSubstitution. -func (x *MedicationRequestSubstitution) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "MedicationRequestSubstitution" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from MedicationStatement. -func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "MedicationStatement" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "derivedFrom_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "derivedFrom_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "derivedFrom_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "derivedFrom_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "derivedFrom_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "derivedFrom_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "derivedFrom_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "derivedFrom_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "derivedFrom_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "derivedFrom_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "derivedFrom_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "derivedFrom_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "derivedFrom_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "derivedFrom_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "derivedFrom_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "derivedFrom_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "derivedFrom_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "derivedFrom_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "derivedFrom_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "derivedFrom_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "derivedFrom_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "derivedFrom_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "derivedFrom_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "derivedFrom_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "derivedFrom_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "derivedFrom_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "derivedFrom_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "derivedFrom_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "derivedFrom_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "derivedFrom_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "derivedFrom_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "derivedFrom_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "derivedFrom_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "derivedFrom_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "derivedFrom_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "derivedFrom_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "derivedFrom_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "derivedFrom_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "derivedFrom_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "derivedFrom_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "derivedFrom_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "derivedFrom_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "derivedFrom_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "derivedFrom_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "derivedFrom_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "derivedFrom_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.InformationSource != nil { - for _, item_2_x_InformationSource := range x.InformationSource { - if item_2_x_InformationSource != nil { - if item_2_x_InformationSource.Reference != nil { - refVal := *item_2_x_InformationSource.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "informationSource_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "informationSource_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "informationSource_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "informationSource_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.InformationSource != nil { - for _, item_2_x_InformationSource := range x.InformationSource { - if item_2_x_InformationSource != nil { - if item_2_x_InformationSource.Reference != nil { - refVal := *item_2_x_InformationSource.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "informationSource_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "informationSource_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "informationSource_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "informationSource_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.InformationSource != nil { - for _, item_2_x_InformationSource := range x.InformationSource { - if item_2_x_InformationSource != nil { - if item_2_x_InformationSource.Reference != nil { - refVal := *item_2_x_InformationSource.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "informationSource_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "informationSource_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "informationSource_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "informationSource_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.InformationSource != nil { - for _, item_2_x_InformationSource := range x.InformationSource { - if item_2_x_InformationSource != nil { - if item_2_x_InformationSource.Reference != nil { - refVal := *item_2_x_InformationSource.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "informationSource_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "informationSource_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "informationSource_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "informationSource_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.PartOf != nil { - for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { - if item_2_x_PartOf.Reference != nil { - refVal := *item_2_x_PartOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "partOf_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "partOf_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "partOf_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "partOf_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.PartOf != nil { - for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { - if item_2_x_PartOf.Reference != nil { - refVal := *item_2_x_PartOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "partOf_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "partOf_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "partOf_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "partOf_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.RelatedClinicalInformation != nil { - for _, item_2_x_RelatedClinicalInformation := range x.RelatedClinicalInformation { - if item_2_x_RelatedClinicalInformation != nil { - if item_2_x_RelatedClinicalInformation.Reference != nil { - refVal := *item_2_x_RelatedClinicalInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "relatedClinicalInformation_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "relatedClinicalInformation_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "relatedClinicalInformation_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "relatedClinicalInformation_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.RelatedClinicalInformation != nil { - for _, item_2_x_RelatedClinicalInformation := range x.RelatedClinicalInformation { - if item_2_x_RelatedClinicalInformation != nil { - if item_2_x_RelatedClinicalInformation.Reference != nil { - refVal := *item_2_x_RelatedClinicalInformation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "relatedClinicalInformation_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "relatedClinicalInformation_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "relatedClinicalInformation_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "relatedClinicalInformation_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "subject_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "subject_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "subject_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "subject_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "subject_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "subject_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "subject_medication_statement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("statement", id), - "subject_medication_statement", - projectJSON, - sourceType, - "statement", - )) - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "medication_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "medication_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "medication_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "medication_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "medication_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "medication_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "medication_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "medication_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "medication_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "medication_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "medication_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "medication_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "medication_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "medication_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "medication_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "medication_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "medication_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "medication_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "medication_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "medication_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "medication_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "medication_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Medication != nil { - if x.Medication.Reference != nil { - if x.Medication.Reference.Reference != nil { - refVal := *x.Medication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "medication_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "medication_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "note_authorReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "note_authorReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "note_authorReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "note_authorReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "reason_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "reason_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "reason_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "reason_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "reason_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "reason_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "reason_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "reason_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "reason_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "reason_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "reason_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "reason_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "reason_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "reason_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "reason_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "reason_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "reason_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "reason_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "reason_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "reason_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "reason_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "reason_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "reason_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from MedicationStatementAdherence. -func (x *MedicationStatementAdherence) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "MedicationStatementAdherence" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from Meta. -func (x *Meta) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Meta" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from Money. -func (x *Money) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Money" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from Narrative. -func (x *Narrative) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Narrative" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from Observation. -func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Observation" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "basedOn_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "basedOn_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.BodyStructure != nil { - if x.BodyStructure.Reference != nil { - refVal := *x.BodyStructure.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "bodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("bodyStructure", targetID), - "bodyStructure", - projectJSON, - sourceType, - "bodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "derivedFrom_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "derivedFrom_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "derivedFrom_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "derivedFrom_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.DerivedFrom != nil { - for _, item_2_x_DerivedFrom := range x.DerivedFrom { - if item_2_x_DerivedFrom != nil { - if item_2_x_DerivedFrom.Reference != nil { - refVal := *item_2_x_DerivedFrom.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "derivedFrom_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "derivedFrom_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "derivedFrom_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { - if item_2_x_Focus.Reference != nil { - refVal := *item_2_x_Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "focus_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "focus_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "focus_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { - if item_2_x_Focus.Reference != nil { - refVal := *item_2_x_Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "focus_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "focus_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "focus_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { - if item_2_x_Focus.Reference != nil { - refVal := *item_2_x_Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "focus_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "focus_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "focus_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { - if item_2_x_Focus.Reference != nil { - refVal := *item_2_x_Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "focus_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "focus_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "focus_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { - if item_2_x_Focus.Reference != nil { - refVal := *item_2_x_Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "focus_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "focus_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "focus_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { - if item_2_x_Focus.Reference != nil { - refVal := *item_2_x_Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "focus_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "focus_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "focus_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { - if item_2_x_Focus.Reference != nil { - refVal := *item_2_x_Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "focus_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "focus_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "focus_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { - if item_2_x_Focus.Reference != nil { - refVal := *item_2_x_Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "focus_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "focus_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "focus_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { - if item_2_x_Focus.Reference != nil { - refVal := *item_2_x_Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "focus_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "focus_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "focus_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { - if item_2_x_Focus.Reference != nil { - refVal := *item_2_x_Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "focus_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "focus_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "focus_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { - if item_2_x_Focus.Reference != nil { - refVal := *item_2_x_Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "focus_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "focus_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "focus_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { - if item_2_x_Focus.Reference != nil { - refVal := *item_2_x_Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "focus_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "focus_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "focus_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { - if item_2_x_Focus.Reference != nil { - refVal := *item_2_x_Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "focus_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "focus_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "focus_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { - if item_2_x_Focus.Reference != nil { - refVal := *item_2_x_Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "focus_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "focus_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "focus_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { - if item_2_x_Focus.Reference != nil { - refVal := *item_2_x_Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "focus_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "focus_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "focus_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { - if item_2_x_Focus.Reference != nil { - refVal := *item_2_x_Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "focus_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "focus_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "focus_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { - if item_2_x_Focus.Reference != nil { - refVal := *item_2_x_Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "focus_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "focus_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "focus_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { - if item_2_x_Focus.Reference != nil { - refVal := *item_2_x_Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "focus_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "focus_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "focus_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { - if item_2_x_Focus.Reference != nil { - refVal := *item_2_x_Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "focus_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "focus_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "focus_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { - if item_2_x_Focus.Reference != nil { - refVal := *item_2_x_Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "focus_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "focus_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "focus_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { - if item_2_x_Focus.Reference != nil { - refVal := *item_2_x_Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "focus_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "focus_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "focus_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { - if item_2_x_Focus.Reference != nil { - refVal := *item_2_x_Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "focus_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "focus_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "focus_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_2_x_Focus := range x.Focus { - if item_2_x_Focus != nil { - if item_2_x_Focus.Reference != nil { - refVal := *item_2_x_Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "focus_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "focus_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "focus_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.HasMember != nil { - for _, item_2_x_HasMember := range x.HasMember { - if item_2_x_HasMember != nil { - if item_2_x_HasMember.Reference != nil { - refVal := *item_2_x_HasMember.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "hasMember_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "hasMember_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "hasMember_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "hasMember_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.PartOf != nil { - for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { - if item_2_x_PartOf.Reference != nil { - refVal := *item_2_x_PartOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "partOf_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "partOf_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "partOf_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "partOf_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.PartOf != nil { - for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { - if item_2_x_PartOf.Reference != nil { - refVal := *item_2_x_PartOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "partOf_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "partOf_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "partOf_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "partOf_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.PartOf != nil { - for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { - if item_2_x_PartOf.Reference != nil { - refVal := *item_2_x_PartOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "partOf_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "partOf_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "partOf_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "partOf_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.PartOf != nil { - for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { - if item_2_x_PartOf.Reference != nil { - refVal := *item_2_x_PartOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "partOf_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "partOf_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "partOf_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "partOf_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Performer != nil { - for _, item_2_x_Performer := range x.Performer { - if item_2_x_Performer != nil { - if item_2_x_Performer.Reference != nil { - refVal := *item_2_x_Performer.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "performer_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "performer_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "performer_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "performer_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Performer != nil { - for _, item_2_x_Performer := range x.Performer { - if item_2_x_Performer != nil { - if item_2_x_Performer.Reference != nil { - refVal := *item_2_x_Performer.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "performer_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "performer_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "performer_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "performer_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Performer != nil { - for _, item_2_x_Performer := range x.Performer { - if item_2_x_Performer != nil { - if item_2_x_Performer.Reference != nil { - refVal := *item_2_x_Performer.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "performer_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "performer_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "performer_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "performer_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Performer != nil { - for _, item_2_x_Performer := range x.Performer { - if item_2_x_Performer != nil { - if item_2_x_Performer.Reference != nil { - refVal := *item_2_x_Performer.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "performer_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "performer_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "performer_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "performer_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - } - } - if x.Specimen != nil { - if x.Specimen.Reference != nil { - refVal := *x.Specimen.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "specimen_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "specimen_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "specimen_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "specimen_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - if x.Specimen != nil { - if x.Specimen.Reference != nil { - refVal := *x.Specimen.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "specimen_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "specimen_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "specimen_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "specimen_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "subject_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "subject_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "subject_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "subject_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "subject_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "subject_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "subject_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "subject_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "subject_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "subject_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "subject_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "subject_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "subject_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "subject_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "subject_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "subject_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "subject_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "subject_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "subject_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "subject_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "subject_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "subject_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "subject_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "subject_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "subject_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "subject_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "subject_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("observation", id), - "subject_observation", - projectJSON, - sourceType, - "observation", - )) - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "note_authorReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "note_authorReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "note_authorReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "note_authorReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.TriggeredBy != nil { - for _, item_3_x_TriggeredBy := range x.TriggeredBy { - if item_3_x_TriggeredBy != nil { - if item_3_x_TriggeredBy.Observation != nil { - if item_3_x_TriggeredBy.Observation.Reference != nil { - refVal := *item_3_x_TriggeredBy.Observation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "triggeredBy_observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("observation", targetID), - "triggeredBy_observation", - projectJSON, - sourceType, - "observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "observation_triggered_by") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("by", id), - "observation_triggered_by", - projectJSON, - sourceType, - "by", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from ObservationComponent. -func (x *ObservationComponent) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ObservationComponent" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from ObservationReferenceRange. -func (x *ObservationReferenceRange) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ObservationReferenceRange" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from ObservationTriggeredBy. -func (x *ObservationTriggeredBy) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ObservationTriggeredBy" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Observation != nil { - if x.Observation.Reference != nil { - refVal := *x.Observation.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("observation", targetID), - "observation", - projectJSON, - sourceType, - "observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "observation_triggered_by") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("by", id), - "observation_triggered_by", - projectJSON, - sourceType, - "by", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from Organization. -func (x *Organization) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Organization" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.PartOf != nil { - if x.PartOf.Reference != nil { - refVal := *x.PartOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "partOf") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("partOf", targetID), - "partOf", - projectJSON, - sourceType, - "partOf", - )) - } - backrefKey := getEdgeUUID(id, targetID, "organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("organization", id), - "organization", - projectJSON, - sourceType, - "organization", - )) - } - } - } - } - } - if x.Contact != nil { - for _, item_3_x_Contact := range x.Contact { - if item_3_x_Contact != nil { - if item_3_x_Contact.Organization != nil { - if item_3_x_Contact.Organization.Reference != nil { - refVal := *item_3_x_Contact.Organization.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "contact_organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("organization", targetID), - "contact_organization", - projectJSON, - sourceType, - "organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extended_contact_detail") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("detail", id), - "extended_contact_detail", - projectJSON, - sourceType, - "detail", - )) - } - } - } - } - } - } - } - } - if x.Qualification != nil { - for _, item_3_x_Qualification := range x.Qualification { - if item_3_x_Qualification != nil { - if item_3_x_Qualification.Issuer != nil { - if item_3_x_Qualification.Issuer.Reference != nil { - refVal := *item_3_x_Qualification.Issuer.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "qualification_issuer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("issuer", targetID), - "qualification_issuer", - projectJSON, - sourceType, - "issuer", - )) - } - backrefKey := getEdgeUUID(id, targetID, "organization_qualification") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("qualification", id), - "organization_qualification", - projectJSON, - sourceType, - "qualification", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from OrganizationQualification. -func (x *OrganizationQualification) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "OrganizationQualification" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Issuer != nil { - if x.Issuer.Reference != nil { - refVal := *x.Issuer.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "issuer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("issuer", targetID), - "issuer", - projectJSON, - sourceType, - "issuer", - )) - } - backrefKey := getEdgeUUID(id, targetID, "organization_qualification") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("qualification", id), - "organization_qualification", - projectJSON, - sourceType, - "qualification", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from ParameterDefinition. -func (x *ParameterDefinition) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ParameterDefinition" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from Patient. -func (x *Patient) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Patient" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.GeneralPractitioner != nil { - for _, item_2_x_GeneralPractitioner := range x.GeneralPractitioner { - if item_2_x_GeneralPractitioner != nil { - if item_2_x_GeneralPractitioner.Reference != nil { - refVal := *item_2_x_GeneralPractitioner.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "generalPractitioner_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "generalPractitioner_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "generalPractitioner_patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("patient", id), - "generalPractitioner_patient", - projectJSON, - sourceType, - "patient", - )) - } - } - } - } - } - } - } - if x.GeneralPractitioner != nil { - for _, item_2_x_GeneralPractitioner := range x.GeneralPractitioner { - if item_2_x_GeneralPractitioner != nil { - if item_2_x_GeneralPractitioner.Reference != nil { - refVal := *item_2_x_GeneralPractitioner.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "generalPractitioner_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "generalPractitioner_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "generalPractitioner_patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("patient", id), - "generalPractitioner_patient", - projectJSON, - sourceType, - "patient", - )) - } - } - } - } - } - } - } - if x.GeneralPractitioner != nil { - for _, item_2_x_GeneralPractitioner := range x.GeneralPractitioner { - if item_2_x_GeneralPractitioner != nil { - if item_2_x_GeneralPractitioner.Reference != nil { - refVal := *item_2_x_GeneralPractitioner.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "generalPractitioner_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "generalPractitioner_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "generalPractitioner_patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("patient", id), - "generalPractitioner_patient", - projectJSON, - sourceType, - "patient", - )) - } - } - } - } - } - } - } - if x.ManagingOrganization != nil { - if x.ManagingOrganization.Reference != nil { - refVal := *x.ManagingOrganization.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "managingOrganization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("managingOrganization", targetID), - "managingOrganization", - projectJSON, - sourceType, - "managingOrganization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "managingOrganization_patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("patient", id), - "managingOrganization_patient", - projectJSON, - sourceType, - "patient", - )) - } - } - } - } - } - if x.Contact != nil { - for _, item_3_x_Contact := range x.Contact { - if item_3_x_Contact != nil { - if item_3_x_Contact.Organization != nil { - if item_3_x_Contact.Organization.Reference != nil { - refVal := *item_3_x_Contact.Organization.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "contact_organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("organization", targetID), - "contact_organization", - projectJSON, - sourceType, - "organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "patient_contact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("contact", id), - "patient_contact", - projectJSON, - sourceType, - "contact", - )) - } - } - } - } - } - } - } - } - if x.Link != nil { - for _, item_3_x_Link := range x.Link { - if item_3_x_Link != nil { - if item_3_x_Link.Other != nil { - if item_3_x_Link.Other.Reference != nil { - refVal := *item_3_x_Link.Other.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "link_other_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "link_other_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "patient_link") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("link", id), - "patient_link", - projectJSON, - sourceType, - "link", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from PatientCommunication. -func (x *PatientCommunication) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "PatientCommunication" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from PatientContact. -func (x *PatientContact) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "PatientContact" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Organization != nil { - if x.Organization.Reference != nil { - refVal := *x.Organization.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("organization", targetID), - "organization", - projectJSON, - sourceType, - "organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "patient_contact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("contact", id), - "patient_contact", - projectJSON, - sourceType, - "contact", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from PatientLink. -func (x *PatientLink) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "PatientLink" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Other != nil { - if x.Other.Reference != nil { - refVal := *x.Other.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "other_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "other_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "patient_link") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("link", id), - "patient_link", - projectJSON, - sourceType, - "link", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from Period. -func (x *Period) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Period" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from Practitioner. -func (x *Practitioner) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Practitioner" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Qualification != nil { - for _, item_3_x_Qualification := range x.Qualification { - if item_3_x_Qualification != nil { - if item_3_x_Qualification.Issuer != nil { - if item_3_x_Qualification.Issuer.Reference != nil { - refVal := *item_3_x_Qualification.Issuer.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "qualification_issuer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("issuer", targetID), - "qualification_issuer", - projectJSON, - sourceType, - "issuer", - )) - } - backrefKey := getEdgeUUID(id, targetID, "practitioner_qualification") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("qualification", id), - "practitioner_qualification", - projectJSON, - sourceType, - "qualification", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from PractitionerCommunication. -func (x *PractitionerCommunication) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "PractitionerCommunication" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from PractitionerQualification. -func (x *PractitionerQualification) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "PractitionerQualification" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Issuer != nil { - if x.Issuer.Reference != nil { - refVal := *x.Issuer.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "issuer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("issuer", targetID), - "issuer", - projectJSON, - sourceType, - "issuer", - )) - } - backrefKey := getEdgeUUID(id, targetID, "practitioner_qualification") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("qualification", id), - "practitioner_qualification", - projectJSON, - sourceType, - "qualification", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from PractitionerRole. -func (x *PractitionerRole) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "PractitionerRole" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Organization != nil { - if x.Organization.Reference != nil { - refVal := *x.Organization.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("organization", targetID), - "organization", - projectJSON, - sourceType, - "organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "practitioner_role") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("role", id), - "practitioner_role", - projectJSON, - sourceType, - "role", - )) - } - } - } - } - } - if x.Practitioner != nil { - if x.Practitioner.Reference != nil { - refVal := *x.Practitioner.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("practitioner", targetID), - "practitioner", - projectJSON, - sourceType, - "practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "practitioner_role") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("role", id), - "practitioner_role", - projectJSON, - sourceType, - "role", - )) - } - } - } - } - } - if x.Contact != nil { - for _, item_3_x_Contact := range x.Contact { - if item_3_x_Contact != nil { - if item_3_x_Contact.Organization != nil { - if item_3_x_Contact.Organization.Reference != nil { - refVal := *item_3_x_Contact.Organization.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "contact_organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("organization", targetID), - "contact_organization", - projectJSON, - sourceType, - "organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extended_contact_detail") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("detail", id), - "extended_contact_detail", - projectJSON, - sourceType, - "detail", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from Procedure. -func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Procedure" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "focus_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "focus_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "focus_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "focus_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "focus_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "focus_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "focus_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "focus_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "focus_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "focus_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "focus_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "focus_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "focus_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "focus_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "focus_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "focus_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "focus_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "focus_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - if x.PartOf != nil { - for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { - if item_2_x_PartOf.Reference != nil { - refVal := *item_2_x_PartOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "partOf_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "partOf_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "partOf_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "partOf_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.PartOf != nil { - for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { - if item_2_x_PartOf.Reference != nil { - refVal := *item_2_x_PartOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "partOf_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "partOf_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "partOf_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "partOf_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.PartOf != nil { - for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { - if item_2_x_PartOf.Reference != nil { - refVal := *item_2_x_PartOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "partOf_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "partOf_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "partOf_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "partOf_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.Recorder != nil { - if x.Recorder.Reference != nil { - refVal := *x.Recorder.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "recorder_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "recorder_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "recorder_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "recorder_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - if x.Recorder != nil { - if x.Recorder.Reference != nil { - refVal := *x.Recorder.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "recorder_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "recorder_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "recorder_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "recorder_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - if x.Recorder != nil { - if x.Recorder.Reference != nil { - refVal := *x.Recorder.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "recorder_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "recorder_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "recorder_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "recorder_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - if x.Report != nil { - for _, item_2_x_Report := range x.Report { - if item_2_x_Report != nil { - if item_2_x_Report.Reference != nil { - refVal := *item_2_x_Report.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "report_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "report_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "report_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "report_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.Report != nil { - for _, item_2_x_Report := range x.Report { - if item_2_x_Report != nil { - if item_2_x_Report.Reference != nil { - refVal := *item_2_x_Report.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "report_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "report_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "report_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "report_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.ReportedReference != nil { - if x.ReportedReference.Reference != nil { - refVal := *x.ReportedReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "reportedReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "reportedReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "reportedReference_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "reportedReference_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - if x.ReportedReference != nil { - if x.ReportedReference.Reference != nil { - refVal := *x.ReportedReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "reportedReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "reportedReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "reportedReference_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "reportedReference_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - if x.ReportedReference != nil { - if x.ReportedReference.Reference != nil { - refVal := *x.ReportedReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "reportedReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "reportedReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "reportedReference_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "reportedReference_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - if x.ReportedReference != nil { - if x.ReportedReference.Reference != nil { - refVal := *x.ReportedReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "reportedReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "reportedReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "reportedReference_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "reportedReference_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "subject_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "subject_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "subject_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "subject_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "subject_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "subject_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "subject_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "subject_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "subject_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "subject_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "subject_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "subject_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "subject_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "subject_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "subject_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "subject_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { - if item_2_x_SupportingInfo.Reference != nil { - refVal := *item_2_x_SupportingInfo.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "supportingInfo_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "supportingInfo_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { - if item_2_x_SupportingInfo.Reference != nil { - refVal := *item_2_x_SupportingInfo.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "supportingInfo_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "supportingInfo_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { - if item_2_x_SupportingInfo.Reference != nil { - refVal := *item_2_x_SupportingInfo.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "supportingInfo_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "supportingInfo_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { - if item_2_x_SupportingInfo.Reference != nil { - refVal := *item_2_x_SupportingInfo.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "supportingInfo_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "supportingInfo_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { - if item_2_x_SupportingInfo.Reference != nil { - refVal := *item_2_x_SupportingInfo.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "supportingInfo_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "supportingInfo_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { - if item_2_x_SupportingInfo.Reference != nil { - refVal := *item_2_x_SupportingInfo.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "supportingInfo_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "supportingInfo_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { - if item_2_x_SupportingInfo.Reference != nil { - refVal := *item_2_x_SupportingInfo.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "supportingInfo_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "supportingInfo_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { - if item_2_x_SupportingInfo.Reference != nil { - refVal := *item_2_x_SupportingInfo.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "supportingInfo_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "supportingInfo_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { - if item_2_x_SupportingInfo.Reference != nil { - refVal := *item_2_x_SupportingInfo.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "supportingInfo_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "supportingInfo_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { - if item_2_x_SupportingInfo.Reference != nil { - refVal := *item_2_x_SupportingInfo.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "supportingInfo_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "supportingInfo_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { - if item_2_x_SupportingInfo.Reference != nil { - refVal := *item_2_x_SupportingInfo.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "supportingInfo_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "supportingInfo_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { - if item_2_x_SupportingInfo.Reference != nil { - refVal := *item_2_x_SupportingInfo.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "supportingInfo_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "supportingInfo_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { - if item_2_x_SupportingInfo.Reference != nil { - refVal := *item_2_x_SupportingInfo.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "supportingInfo_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "supportingInfo_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { - if item_2_x_SupportingInfo.Reference != nil { - refVal := *item_2_x_SupportingInfo.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "supportingInfo_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "supportingInfo_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { - if item_2_x_SupportingInfo.Reference != nil { - refVal := *item_2_x_SupportingInfo.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "supportingInfo_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "supportingInfo_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { - if item_2_x_SupportingInfo.Reference != nil { - refVal := *item_2_x_SupportingInfo.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "supportingInfo_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "supportingInfo_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { - if item_2_x_SupportingInfo.Reference != nil { - refVal := *item_2_x_SupportingInfo.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "supportingInfo_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "supportingInfo_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { - if item_2_x_SupportingInfo.Reference != nil { - refVal := *item_2_x_SupportingInfo.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "supportingInfo_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "supportingInfo_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { - if item_2_x_SupportingInfo.Reference != nil { - refVal := *item_2_x_SupportingInfo.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "supportingInfo_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "supportingInfo_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { - if item_2_x_SupportingInfo.Reference != nil { - refVal := *item_2_x_SupportingInfo.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "supportingInfo_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "supportingInfo_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { - if item_2_x_SupportingInfo.Reference != nil { - refVal := *item_2_x_SupportingInfo.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "supportingInfo_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "supportingInfo_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { - if item_2_x_SupportingInfo.Reference != nil { - refVal := *item_2_x_SupportingInfo.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "supportingInfo_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "supportingInfo_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.SupportingInfo != nil { - for _, item_2_x_SupportingInfo := range x.SupportingInfo { - if item_2_x_SupportingInfo != nil { - if item_2_x_SupportingInfo.Reference != nil { - refVal := *item_2_x_SupportingInfo.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "supportingInfo_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "supportingInfo_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("procedure", id), - "supportingInfo_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - } - } - } - } - } - } - if x.Complication != nil { - for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { - if item_3_x_Complication.Reference != nil { - if item_3_x_Complication.Reference.Reference != nil { - refVal := *item_3_x_Complication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "complication_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "complication_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Complication != nil { - for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { - if item_3_x_Complication.Reference != nil { - if item_3_x_Complication.Reference.Reference != nil { - refVal := *item_3_x_Complication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "complication_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "complication_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Complication != nil { - for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { - if item_3_x_Complication.Reference != nil { - if item_3_x_Complication.Reference.Reference != nil { - refVal := *item_3_x_Complication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "complication_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "complication_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Complication != nil { - for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { - if item_3_x_Complication.Reference != nil { - if item_3_x_Complication.Reference.Reference != nil { - refVal := *item_3_x_Complication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "complication_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "complication_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Complication != nil { - for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { - if item_3_x_Complication.Reference != nil { - if item_3_x_Complication.Reference.Reference != nil { - refVal := *item_3_x_Complication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "complication_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "complication_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Complication != nil { - for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { - if item_3_x_Complication.Reference != nil { - if item_3_x_Complication.Reference.Reference != nil { - refVal := *item_3_x_Complication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "complication_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "complication_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Complication != nil { - for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { - if item_3_x_Complication.Reference != nil { - if item_3_x_Complication.Reference.Reference != nil { - refVal := *item_3_x_Complication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "complication_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "complication_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Complication != nil { - for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { - if item_3_x_Complication.Reference != nil { - if item_3_x_Complication.Reference.Reference != nil { - refVal := *item_3_x_Complication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "complication_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "complication_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Complication != nil { - for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { - if item_3_x_Complication.Reference != nil { - if item_3_x_Complication.Reference.Reference != nil { - refVal := *item_3_x_Complication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "complication_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "complication_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Complication != nil { - for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { - if item_3_x_Complication.Reference != nil { - if item_3_x_Complication.Reference.Reference != nil { - refVal := *item_3_x_Complication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "complication_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "complication_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Complication != nil { - for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { - if item_3_x_Complication.Reference != nil { - if item_3_x_Complication.Reference.Reference != nil { - refVal := *item_3_x_Complication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "complication_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "complication_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Complication != nil { - for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { - if item_3_x_Complication.Reference != nil { - if item_3_x_Complication.Reference.Reference != nil { - refVal := *item_3_x_Complication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "complication_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "complication_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Complication != nil { - for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { - if item_3_x_Complication.Reference != nil { - if item_3_x_Complication.Reference.Reference != nil { - refVal := *item_3_x_Complication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "complication_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "complication_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Complication != nil { - for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { - if item_3_x_Complication.Reference != nil { - if item_3_x_Complication.Reference.Reference != nil { - refVal := *item_3_x_Complication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "complication_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "complication_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Complication != nil { - for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { - if item_3_x_Complication.Reference != nil { - if item_3_x_Complication.Reference.Reference != nil { - refVal := *item_3_x_Complication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "complication_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "complication_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Complication != nil { - for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { - if item_3_x_Complication.Reference != nil { - if item_3_x_Complication.Reference.Reference != nil { - refVal := *item_3_x_Complication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "complication_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "complication_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Complication != nil { - for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { - if item_3_x_Complication.Reference != nil { - if item_3_x_Complication.Reference.Reference != nil { - refVal := *item_3_x_Complication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "complication_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "complication_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Complication != nil { - for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { - if item_3_x_Complication.Reference != nil { - if item_3_x_Complication.Reference.Reference != nil { - refVal := *item_3_x_Complication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "complication_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "complication_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Complication != nil { - for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { - if item_3_x_Complication.Reference != nil { - if item_3_x_Complication.Reference.Reference != nil { - refVal := *item_3_x_Complication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "complication_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "complication_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Complication != nil { - for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { - if item_3_x_Complication.Reference != nil { - if item_3_x_Complication.Reference.Reference != nil { - refVal := *item_3_x_Complication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "complication_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "complication_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Complication != nil { - for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { - if item_3_x_Complication.Reference != nil { - if item_3_x_Complication.Reference.Reference != nil { - refVal := *item_3_x_Complication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "complication_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "complication_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Complication != nil { - for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { - if item_3_x_Complication.Reference != nil { - if item_3_x_Complication.Reference.Reference != nil { - refVal := *item_3_x_Complication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "complication_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "complication_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Complication != nil { - for _, item_3_x_Complication := range x.Complication { - if item_3_x_Complication != nil { - if item_3_x_Complication.Reference != nil { - if item_3_x_Complication.Reference.Reference != nil { - refVal := *item_3_x_Complication.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "complication_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "complication_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "note_authorReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "note_authorReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "note_authorReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "note_authorReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Performer != nil { - for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { - if item_3_x_Performer.Actor != nil { - if item_3_x_Performer.Actor.Reference != nil { - refVal := *item_3_x_Performer.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "performer_actor_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "performer_actor_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "actor_procedure_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "actor_procedure_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - } - } - } - if x.Performer != nil { - for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { - if item_3_x_Performer.Actor != nil { - if item_3_x_Performer.Actor.Reference != nil { - refVal := *item_3_x_Performer.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "performer_actor_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "performer_actor_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "actor_procedure_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "actor_procedure_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - } - } - } - if x.Performer != nil { - for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { - if item_3_x_Performer.Actor != nil { - if item_3_x_Performer.Actor.Reference != nil { - refVal := *item_3_x_Performer.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "performer_actor_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "performer_actor_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "actor_procedure_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "actor_procedure_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - } - } - } - if x.Performer != nil { - for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { - if item_3_x_Performer.Actor != nil { - if item_3_x_Performer.Actor.Reference != nil { - refVal := *item_3_x_Performer.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "performer_actor_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "performer_actor_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "actor_procedure_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "actor_procedure_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - } - } - } - if x.Performer != nil { - for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { - if item_3_x_Performer.OnBehalfOf != nil { - if item_3_x_Performer.OnBehalfOf.Reference != nil { - refVal := *item_3_x_Performer.OnBehalfOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "performer_onBehalfOf") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("onBehalfOf", targetID), - "performer_onBehalfOf", - projectJSON, - sourceType, - "onBehalfOf", - )) - } - backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_procedure_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "onBehalfOf_procedure_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "reason_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "reason_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "reason_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "reason_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "reason_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "reason_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "reason_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "reason_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "reason_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "reason_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "reason_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "reason_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "reason_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "reason_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "reason_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "reason_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "reason_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "reason_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "reason_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "reason_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "reason_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "reason_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "reason_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Used != nil { - for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { - if item_3_x_Used.Reference != nil { - if item_3_x_Used.Reference.Reference != nil { - refVal := *item_3_x_Used.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "used_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "used_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Used != nil { - for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { - if item_3_x_Used.Reference != nil { - if item_3_x_Used.Reference.Reference != nil { - refVal := *item_3_x_Used.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "used_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "used_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Used != nil { - for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { - if item_3_x_Used.Reference != nil { - if item_3_x_Used.Reference.Reference != nil { - refVal := *item_3_x_Used.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "used_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "used_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Used != nil { - for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { - if item_3_x_Used.Reference != nil { - if item_3_x_Used.Reference.Reference != nil { - refVal := *item_3_x_Used.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "used_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "used_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Used != nil { - for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { - if item_3_x_Used.Reference != nil { - if item_3_x_Used.Reference.Reference != nil { - refVal := *item_3_x_Used.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "used_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "used_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Used != nil { - for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { - if item_3_x_Used.Reference != nil { - if item_3_x_Used.Reference.Reference != nil { - refVal := *item_3_x_Used.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "used_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "used_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Used != nil { - for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { - if item_3_x_Used.Reference != nil { - if item_3_x_Used.Reference.Reference != nil { - refVal := *item_3_x_Used.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "used_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "used_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Used != nil { - for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { - if item_3_x_Used.Reference != nil { - if item_3_x_Used.Reference.Reference != nil { - refVal := *item_3_x_Used.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "used_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "used_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Used != nil { - for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { - if item_3_x_Used.Reference != nil { - if item_3_x_Used.Reference.Reference != nil { - refVal := *item_3_x_Used.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "used_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "used_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Used != nil { - for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { - if item_3_x_Used.Reference != nil { - if item_3_x_Used.Reference.Reference != nil { - refVal := *item_3_x_Used.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "used_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "used_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Used != nil { - for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { - if item_3_x_Used.Reference != nil { - if item_3_x_Used.Reference.Reference != nil { - refVal := *item_3_x_Used.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "used_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "used_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Used != nil { - for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { - if item_3_x_Used.Reference != nil { - if item_3_x_Used.Reference.Reference != nil { - refVal := *item_3_x_Used.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "used_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "used_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Used != nil { - for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { - if item_3_x_Used.Reference != nil { - if item_3_x_Used.Reference.Reference != nil { - refVal := *item_3_x_Used.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "used_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "used_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Used != nil { - for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { - if item_3_x_Used.Reference != nil { - if item_3_x_Used.Reference.Reference != nil { - refVal := *item_3_x_Used.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "used_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "used_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Used != nil { - for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { - if item_3_x_Used.Reference != nil { - if item_3_x_Used.Reference.Reference != nil { - refVal := *item_3_x_Used.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "used_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "used_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Used != nil { - for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { - if item_3_x_Used.Reference != nil { - if item_3_x_Used.Reference.Reference != nil { - refVal := *item_3_x_Used.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "used_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "used_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Used != nil { - for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { - if item_3_x_Used.Reference != nil { - if item_3_x_Used.Reference.Reference != nil { - refVal := *item_3_x_Used.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "used_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "used_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Used != nil { - for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { - if item_3_x_Used.Reference != nil { - if item_3_x_Used.Reference.Reference != nil { - refVal := *item_3_x_Used.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "used_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "used_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Used != nil { - for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { - if item_3_x_Used.Reference != nil { - if item_3_x_Used.Reference.Reference != nil { - refVal := *item_3_x_Used.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "used_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "used_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Used != nil { - for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { - if item_3_x_Used.Reference != nil { - if item_3_x_Used.Reference.Reference != nil { - refVal := *item_3_x_Used.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "used_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "used_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Used != nil { - for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { - if item_3_x_Used.Reference != nil { - if item_3_x_Used.Reference.Reference != nil { - refVal := *item_3_x_Used.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "used_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "used_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Used != nil { - for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { - if item_3_x_Used.Reference != nil { - if item_3_x_Used.Reference.Reference != nil { - refVal := *item_3_x_Used.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "used_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "used_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Used != nil { - for _, item_3_x_Used := range x.Used { - if item_3_x_Used != nil { - if item_3_x_Used.Reference != nil { - if item_3_x_Used.Reference.Reference != nil { - refVal := *item_3_x_Used.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "used_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "used_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from ProcedureFocalDevice. -func (x *ProcedureFocalDevice) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ProcedureFocalDevice" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from ProcedurePerformer. -func (x *ProcedurePerformer) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ProcedurePerformer" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Actor != nil { - if x.Actor.Reference != nil { - refVal := *x.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "actor_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "actor_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "actor_procedure_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "actor_procedure_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - refVal := *x.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "actor_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "actor_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "actor_procedure_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "actor_procedure_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - refVal := *x.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "actor_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "actor_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "actor_procedure_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "actor_procedure_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - refVal := *x.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "actor_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "actor_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "actor_procedure_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "actor_procedure_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - if x.OnBehalfOf != nil { - if x.OnBehalfOf.Reference != nil { - refVal := *x.OnBehalfOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "onBehalfOf") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("onBehalfOf", targetID), - "onBehalfOf", - projectJSON, - sourceType, - "onBehalfOf", - )) - } - backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_procedure_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "onBehalfOf_procedure_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from Quantity. -func (x *Quantity) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Quantity" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from Range. -func (x *Range) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Range" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from Ratio. -func (x *Ratio) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Ratio" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from RatioRange. -func (x *RatioRange) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "RatioRange" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from Reference. -func (x *Reference) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Reference" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from RelatedArtifact. -func (x *RelatedArtifact) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "RelatedArtifact" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.ResourceReference != nil { - if x.ResourceReference.Reference != nil { - refVal := *x.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "resourceReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "resourceReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - if x.ResourceReference != nil { - if x.ResourceReference.Reference != nil { - refVal := *x.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "resourceReference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "resourceReference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - if x.ResourceReference != nil { - if x.ResourceReference.Reference != nil { - refVal := *x.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "resourceReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "resourceReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - if x.ResourceReference != nil { - if x.ResourceReference.Reference != nil { - refVal := *x.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "resourceReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "resourceReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - if x.ResourceReference != nil { - if x.ResourceReference.Reference != nil { - refVal := *x.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "resourceReference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "resourceReference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - if x.ResourceReference != nil { - if x.ResourceReference.Reference != nil { - refVal := *x.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "resourceReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "resourceReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - if x.ResourceReference != nil { - if x.ResourceReference.Reference != nil { - refVal := *x.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "resourceReference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "resourceReference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - if x.ResourceReference != nil { - if x.ResourceReference.Reference != nil { - refVal := *x.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "resourceReference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "resourceReference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - if x.ResourceReference != nil { - if x.ResourceReference.Reference != nil { - refVal := *x.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "resourceReference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "resourceReference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - if x.ResourceReference != nil { - if x.ResourceReference.Reference != nil { - refVal := *x.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "resourceReference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "resourceReference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - if x.ResourceReference != nil { - if x.ResourceReference.Reference != nil { - refVal := *x.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "resourceReference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "resourceReference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - if x.ResourceReference != nil { - if x.ResourceReference.Reference != nil { - refVal := *x.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "resourceReference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "resourceReference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - if x.ResourceReference != nil { - if x.ResourceReference.Reference != nil { - refVal := *x.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "resourceReference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "resourceReference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - if x.ResourceReference != nil { - if x.ResourceReference.Reference != nil { - refVal := *x.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "resourceReference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "resourceReference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - if x.ResourceReference != nil { - if x.ResourceReference.Reference != nil { - refVal := *x.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "resourceReference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "resourceReference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - if x.ResourceReference != nil { - if x.ResourceReference.Reference != nil { - refVal := *x.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "resourceReference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "resourceReference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - if x.ResourceReference != nil { - if x.ResourceReference.Reference != nil { - refVal := *x.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "resourceReference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "resourceReference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - if x.ResourceReference != nil { - if x.ResourceReference.Reference != nil { - refVal := *x.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "resourceReference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "resourceReference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - if x.ResourceReference != nil { - if x.ResourceReference.Reference != nil { - refVal := *x.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "resourceReference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "resourceReference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - if x.ResourceReference != nil { - if x.ResourceReference.Reference != nil { - refVal := *x.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "resourceReference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "resourceReference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - if x.ResourceReference != nil { - if x.ResourceReference.Reference != nil { - refVal := *x.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "resourceReference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "resourceReference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - if x.ResourceReference != nil { - if x.ResourceReference.Reference != nil { - refVal := *x.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "resourceReference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "resourceReference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - if x.ResourceReference != nil { - if x.ResourceReference.Reference != nil { - refVal := *x.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "resourceReference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "resourceReference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from ResearchStudy. -func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ResearchStudy" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.RootDir != nil { - if x.RootDir.Reference != nil { - refVal := *x.RootDir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Directory" { - forwardKey := getEdgeUUID(targetID, id, "rootDir_Directory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Directory", targetID), - "rootDir_Directory", - projectJSON, - sourceType, - "Directory", - )) - } - } - } - } - } - if x.PartOf != nil { - for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { - if item_2_x_PartOf.Reference != nil { - refVal := *item_2_x_PartOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "partOf") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("partOf", targetID), - "partOf", - projectJSON, - sourceType, - "partOf", - )) - } - backrefKey := getEdgeUUID(id, targetID, "partOf_research_study") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("study", id), - "partOf_research_study", - projectJSON, - sourceType, - "study", - )) - } - } - } - } - } - } - } - if x.Result != nil { - for _, item_2_x_Result := range x.Result { - if item_2_x_Result != nil { - if item_2_x_Result.Reference != nil { - refVal := *item_2_x_Result.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "result_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "result_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "result_research_study") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("study", id), - "result_research_study", - projectJSON, - sourceType, - "study", - )) - } - } - } - } - } - } - } - if x.Site != nil { - for _, item_2_x_Site := range x.Site { - if item_2_x_Site != nil { - if item_2_x_Site.Reference != nil { - refVal := *item_2_x_Site.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "site_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "site_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "site_research_study") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("study", id), - "site_research_study", - projectJSON, - sourceType, - "study", - )) - } - } - } - } - } - } - } - if x.Site != nil { - for _, item_2_x_Site := range x.Site { - if item_2_x_Site != nil { - if item_2_x_Site.Reference != nil { - refVal := *item_2_x_Site.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "site_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "site_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "site_research_study") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("study", id), - "site_research_study", - projectJSON, - sourceType, - "study", - )) - } - } - } - } - } - } - } - if x.AssociatedParty != nil { - for _, item_3_x_AssociatedParty := range x.AssociatedParty { - if item_3_x_AssociatedParty != nil { - if item_3_x_AssociatedParty.Party != nil { - if item_3_x_AssociatedParty.Party.Reference != nil { - refVal := *item_3_x_AssociatedParty.Party.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "associatedParty_party_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "associatedParty_party_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "research_study_associated_party") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("party", id), - "research_study_associated_party", - projectJSON, - sourceType, - "party", - )) - } - } - } - } - } - } - } - } - if x.AssociatedParty != nil { - for _, item_3_x_AssociatedParty := range x.AssociatedParty { - if item_3_x_AssociatedParty != nil { - if item_3_x_AssociatedParty.Party != nil { - if item_3_x_AssociatedParty.Party.Reference != nil { - refVal := *item_3_x_AssociatedParty.Party.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "associatedParty_party_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "associatedParty_party_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "research_study_associated_party") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("party", id), - "research_study_associated_party", - projectJSON, - sourceType, - "party", - )) - } - } - } - } - } - } - } - } - if x.AssociatedParty != nil { - for _, item_3_x_AssociatedParty := range x.AssociatedParty { - if item_3_x_AssociatedParty != nil { - if item_3_x_AssociatedParty.Party != nil { - if item_3_x_AssociatedParty.Party.Reference != nil { - refVal := *item_3_x_AssociatedParty.Party.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "associatedParty_party_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "associatedParty_party_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "research_study_associated_party") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("party", id), - "research_study_associated_party", - projectJSON, - sourceType, - "party", - )) - } - } - } - } - } - } - } - } - if x.ComparisonGroup != nil { - for _, item_3_x_ComparisonGroup := range x.ComparisonGroup { - if item_3_x_ComparisonGroup != nil { - if item_3_x_ComparisonGroup.ObservedGroup != nil { - if item_3_x_ComparisonGroup.ObservedGroup.Reference != nil { - refVal := *item_3_x_ComparisonGroup.ObservedGroup.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "comparisonGroup_observedGroup") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("observedGroup", targetID), - "comparisonGroup_observedGroup", - projectJSON, - sourceType, - "observedGroup", - )) - } - backrefKey := getEdgeUUID(id, targetID, "research_study_comparison_group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("group", id), - "research_study_comparison_group", - projectJSON, - sourceType, - "group", - )) - } - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { - if item_3_x_Focus.Reference != nil { - if item_3_x_Focus.Reference.Reference != nil { - refVal := *item_3_x_Focus.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "focus_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "focus_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { - if item_3_x_Focus.Reference != nil { - if item_3_x_Focus.Reference.Reference != nil { - refVal := *item_3_x_Focus.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "focus_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "focus_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { - if item_3_x_Focus.Reference != nil { - if item_3_x_Focus.Reference.Reference != nil { - refVal := *item_3_x_Focus.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "focus_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "focus_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { - if item_3_x_Focus.Reference != nil { - if item_3_x_Focus.Reference.Reference != nil { - refVal := *item_3_x_Focus.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "focus_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "focus_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { - if item_3_x_Focus.Reference != nil { - if item_3_x_Focus.Reference.Reference != nil { - refVal := *item_3_x_Focus.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "focus_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "focus_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { - if item_3_x_Focus.Reference != nil { - if item_3_x_Focus.Reference.Reference != nil { - refVal := *item_3_x_Focus.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "focus_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "focus_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { - if item_3_x_Focus.Reference != nil { - if item_3_x_Focus.Reference.Reference != nil { - refVal := *item_3_x_Focus.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "focus_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "focus_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { - if item_3_x_Focus.Reference != nil { - if item_3_x_Focus.Reference.Reference != nil { - refVal := *item_3_x_Focus.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "focus_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "focus_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { - if item_3_x_Focus.Reference != nil { - if item_3_x_Focus.Reference.Reference != nil { - refVal := *item_3_x_Focus.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "focus_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "focus_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { - if item_3_x_Focus.Reference != nil { - if item_3_x_Focus.Reference.Reference != nil { - refVal := *item_3_x_Focus.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "focus_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "focus_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { - if item_3_x_Focus.Reference != nil { - if item_3_x_Focus.Reference.Reference != nil { - refVal := *item_3_x_Focus.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "focus_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "focus_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { - if item_3_x_Focus.Reference != nil { - if item_3_x_Focus.Reference.Reference != nil { - refVal := *item_3_x_Focus.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "focus_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "focus_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { - if item_3_x_Focus.Reference != nil { - if item_3_x_Focus.Reference.Reference != nil { - refVal := *item_3_x_Focus.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "focus_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "focus_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { - if item_3_x_Focus.Reference != nil { - if item_3_x_Focus.Reference.Reference != nil { - refVal := *item_3_x_Focus.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "focus_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "focus_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { - if item_3_x_Focus.Reference != nil { - if item_3_x_Focus.Reference.Reference != nil { - refVal := *item_3_x_Focus.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "focus_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "focus_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { - if item_3_x_Focus.Reference != nil { - if item_3_x_Focus.Reference.Reference != nil { - refVal := *item_3_x_Focus.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "focus_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "focus_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { - if item_3_x_Focus.Reference != nil { - if item_3_x_Focus.Reference.Reference != nil { - refVal := *item_3_x_Focus.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "focus_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "focus_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { - if item_3_x_Focus.Reference != nil { - if item_3_x_Focus.Reference.Reference != nil { - refVal := *item_3_x_Focus.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "focus_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "focus_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { - if item_3_x_Focus.Reference != nil { - if item_3_x_Focus.Reference.Reference != nil { - refVal := *item_3_x_Focus.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "focus_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "focus_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { - if item_3_x_Focus.Reference != nil { - if item_3_x_Focus.Reference.Reference != nil { - refVal := *item_3_x_Focus.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "focus_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "focus_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { - if item_3_x_Focus.Reference != nil { - if item_3_x_Focus.Reference.Reference != nil { - refVal := *item_3_x_Focus.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "focus_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "focus_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { - if item_3_x_Focus.Reference != nil { - if item_3_x_Focus.Reference.Reference != nil { - refVal := *item_3_x_Focus.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "focus_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "focus_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Focus != nil { - for _, item_3_x_Focus := range x.Focus { - if item_3_x_Focus != nil { - if item_3_x_Focus.Reference != nil { - if item_3_x_Focus.Reference.Reference != nil { - refVal := *item_3_x_Focus.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "focus_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "focus_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "note_authorReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "note_authorReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "note_authorReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "note_authorReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Recruitment != nil { - if x.Recruitment.ActualGroup != nil { - if x.Recruitment.ActualGroup.Reference != nil { - refVal := *x.Recruitment.ActualGroup.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "recruitment_actualGroup") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("actualGroup", targetID), - "recruitment_actualGroup", - projectJSON, - sourceType, - "actualGroup", - )) - } - backrefKey := getEdgeUUID(id, targetID, "actualGroup_research_study_recruitment") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("recruitment", id), - "actualGroup_research_study_recruitment", - projectJSON, - sourceType, - "recruitment", - )) - } - } - } - } - } - } - if x.Recruitment != nil { - if x.Recruitment.Eligibility != nil { - if x.Recruitment.Eligibility.Reference != nil { - refVal := *x.Recruitment.Eligibility.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "recruitment_eligibility_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "recruitment_eligibility_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "eligibility_research_study_recruitment") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("recruitment", id), - "eligibility_research_study_recruitment", - projectJSON, - sourceType, - "recruitment", - )) - } - } - } - } - } - } - if x.RelatedArtifact != nil { - for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { - if item_3_x_RelatedArtifact.ResourceReference != nil { - if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { - refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "relatedArtifact_resourceReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - } - } - if x.RelatedArtifact != nil { - for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { - if item_3_x_RelatedArtifact.ResourceReference != nil { - if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { - refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "relatedArtifact_resourceReference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - } - } - if x.RelatedArtifact != nil { - for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { - if item_3_x_RelatedArtifact.ResourceReference != nil { - if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { - refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "relatedArtifact_resourceReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - } - } - if x.RelatedArtifact != nil { - for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { - if item_3_x_RelatedArtifact.ResourceReference != nil { - if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { - refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "relatedArtifact_resourceReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - } - } - if x.RelatedArtifact != nil { - for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { - if item_3_x_RelatedArtifact.ResourceReference != nil { - if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { - refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "relatedArtifact_resourceReference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - } - } - if x.RelatedArtifact != nil { - for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { - if item_3_x_RelatedArtifact.ResourceReference != nil { - if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { - refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "relatedArtifact_resourceReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - } - } - if x.RelatedArtifact != nil { - for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { - if item_3_x_RelatedArtifact.ResourceReference != nil { - if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { - refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "relatedArtifact_resourceReference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - } - } - if x.RelatedArtifact != nil { - for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { - if item_3_x_RelatedArtifact.ResourceReference != nil { - if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { - refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "relatedArtifact_resourceReference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - } - } - if x.RelatedArtifact != nil { - for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { - if item_3_x_RelatedArtifact.ResourceReference != nil { - if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { - refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "relatedArtifact_resourceReference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - } - } - if x.RelatedArtifact != nil { - for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { - if item_3_x_RelatedArtifact.ResourceReference != nil { - if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { - refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "relatedArtifact_resourceReference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - } - } - if x.RelatedArtifact != nil { - for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { - if item_3_x_RelatedArtifact.ResourceReference != nil { - if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { - refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "relatedArtifact_resourceReference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - } - } - if x.RelatedArtifact != nil { - for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { - if item_3_x_RelatedArtifact.ResourceReference != nil { - if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { - refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "relatedArtifact_resourceReference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - } - } - if x.RelatedArtifact != nil { - for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { - if item_3_x_RelatedArtifact.ResourceReference != nil { - if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { - refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "relatedArtifact_resourceReference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - } - } - if x.RelatedArtifact != nil { - for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { - if item_3_x_RelatedArtifact.ResourceReference != nil { - if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { - refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "relatedArtifact_resourceReference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - } - } - if x.RelatedArtifact != nil { - for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { - if item_3_x_RelatedArtifact.ResourceReference != nil { - if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { - refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "relatedArtifact_resourceReference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - } - } - if x.RelatedArtifact != nil { - for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { - if item_3_x_RelatedArtifact.ResourceReference != nil { - if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { - refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "relatedArtifact_resourceReference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - } - } - if x.RelatedArtifact != nil { - for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { - if item_3_x_RelatedArtifact.ResourceReference != nil { - if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { - refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "relatedArtifact_resourceReference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - } - } - if x.RelatedArtifact != nil { - for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { - if item_3_x_RelatedArtifact.ResourceReference != nil { - if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { - refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "relatedArtifact_resourceReference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - } - } - if x.RelatedArtifact != nil { - for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { - if item_3_x_RelatedArtifact.ResourceReference != nil { - if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { - refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "relatedArtifact_resourceReference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - } - } - if x.RelatedArtifact != nil { - for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { - if item_3_x_RelatedArtifact.ResourceReference != nil { - if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { - refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "relatedArtifact_resourceReference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - } - } - if x.RelatedArtifact != nil { - for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { - if item_3_x_RelatedArtifact.ResourceReference != nil { - if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { - refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "relatedArtifact_resourceReference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - } - } - if x.RelatedArtifact != nil { - for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { - if item_3_x_RelatedArtifact.ResourceReference != nil { - if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { - refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "relatedArtifact_resourceReference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - } - } - if x.RelatedArtifact != nil { - for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { - if item_3_x_RelatedArtifact != nil { - if item_3_x_RelatedArtifact.ResourceReference != nil { - if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { - refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "relatedArtifact_resourceReference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from ResearchStudyAssociatedParty. -func (x *ResearchStudyAssociatedParty) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ResearchStudyAssociatedParty" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Party != nil { - if x.Party.Reference != nil { - refVal := *x.Party.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "party_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "party_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "research_study_associated_party") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("party", id), - "research_study_associated_party", - projectJSON, - sourceType, - "party", - )) - } - } - } - } - } - if x.Party != nil { - if x.Party.Reference != nil { - refVal := *x.Party.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "party_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "party_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "research_study_associated_party") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("party", id), - "research_study_associated_party", - projectJSON, - sourceType, - "party", - )) - } - } - } - } - } - if x.Party != nil { - if x.Party.Reference != nil { - refVal := *x.Party.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "party_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "party_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "research_study_associated_party") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("party", id), - "research_study_associated_party", - projectJSON, - sourceType, - "party", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from ResearchStudyComparisonGroup. -func (x *ResearchStudyComparisonGroup) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ResearchStudyComparisonGroup" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.ObservedGroup != nil { - if x.ObservedGroup.Reference != nil { - refVal := *x.ObservedGroup.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "observedGroup") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("observedGroup", targetID), - "observedGroup", - projectJSON, - sourceType, - "observedGroup", - )) - } - backrefKey := getEdgeUUID(id, targetID, "research_study_comparison_group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("group", id), - "research_study_comparison_group", - projectJSON, - sourceType, - "group", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from ResearchStudyLabel. -func (x *ResearchStudyLabel) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ResearchStudyLabel" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from ResearchStudyObjective. -func (x *ResearchStudyObjective) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ResearchStudyObjective" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from ResearchStudyOutcomeMeasure. -func (x *ResearchStudyOutcomeMeasure) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ResearchStudyOutcomeMeasure" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from ResearchStudyProgressStatus. -func (x *ResearchStudyProgressStatus) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ResearchStudyProgressStatus" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from ResearchStudyRecruitment. -func (x *ResearchStudyRecruitment) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ResearchStudyRecruitment" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.ActualGroup != nil { - if x.ActualGroup.Reference != nil { - refVal := *x.ActualGroup.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "actualGroup") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("actualGroup", targetID), - "actualGroup", - projectJSON, - sourceType, - "actualGroup", - )) - } - backrefKey := getEdgeUUID(id, targetID, "actualGroup_research_study_recruitment") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("recruitment", id), - "actualGroup_research_study_recruitment", - projectJSON, - sourceType, - "recruitment", - )) - } - } - } - } - } - if x.Eligibility != nil { - if x.Eligibility.Reference != nil { - refVal := *x.Eligibility.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "eligibility_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "eligibility_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "eligibility_research_study_recruitment") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("recruitment", id), - "eligibility_research_study_recruitment", - projectJSON, - sourceType, - "recruitment", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from ResearchSubject. -func (x *ResearchSubject) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ResearchSubject" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Study != nil { - if x.Study.Reference != nil { - refVal := *x.Study.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "study") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "study", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "research_subject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("subject", id), - "research_subject", - projectJSON, - sourceType, - "subject", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "subject_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "subject_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "research_subject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("subject", id), - "research_subject", - projectJSON, - sourceType, - "subject", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "subject_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "subject_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "research_subject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("subject", id), - "research_subject", - projectJSON, - sourceType, - "subject", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "subject_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "subject_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "research_subject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("subject", id), - "research_subject", - projectJSON, - sourceType, - "subject", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "subject_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "subject_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "research_subject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("subject", id), - "research_subject", - projectJSON, - sourceType, - "subject", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "subject_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "subject_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "research_subject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("subject", id), - "research_subject", - projectJSON, - sourceType, - "subject", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from ResearchSubjectProgress. -func (x *ResearchSubjectProgress) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "ResearchSubjectProgress" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from Resource. -func (x *Resource) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Resource" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from SampledData. -func (x *SampledData) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "SampledData" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from Signature. -func (x *Signature) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Signature" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.OnBehalfOf != nil { - if x.OnBehalfOf.Reference != nil { - refVal := *x.OnBehalfOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "onBehalfOf_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "onBehalfOf_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "onBehalfOf_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - if x.OnBehalfOf != nil { - if x.OnBehalfOf.Reference != nil { - refVal := *x.OnBehalfOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "onBehalfOf_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "onBehalfOf_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "onBehalfOf_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - if x.OnBehalfOf != nil { - if x.OnBehalfOf.Reference != nil { - refVal := *x.OnBehalfOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "onBehalfOf_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "onBehalfOf_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "onBehalfOf_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - if x.OnBehalfOf != nil { - if x.OnBehalfOf.Reference != nil { - refVal := *x.OnBehalfOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "onBehalfOf_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "onBehalfOf_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "onBehalfOf_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - if x.Who != nil { - if x.Who.Reference != nil { - refVal := *x.Who.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "who_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "who_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "who_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "who_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - if x.Who != nil { - if x.Who.Reference != nil { - refVal := *x.Who.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "who_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "who_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "who_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "who_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - if x.Who != nil { - if x.Who.Reference != nil { - refVal := *x.Who.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "who_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "who_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "who_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "who_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - if x.Who != nil { - if x.Who.Reference != nil { - refVal := *x.Who.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "who_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "who_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "who_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "who_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from Specimen. -func (x *Specimen) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Specimen" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Parent != nil { - for _, item_2_x_Parent := range x.Parent { - if item_2_x_Parent != nil { - if item_2_x_Parent.Reference != nil { - refVal := *item_2_x_Parent.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "parent") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("parent", targetID), - "parent", - projectJSON, - sourceType, - "parent", - )) - } - backrefKey := getEdgeUUID(id, targetID, "parent_specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("specimen", id), - "parent_specimen", - projectJSON, - sourceType, - "specimen", - )) - } - } - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "subject_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "subject_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("specimen", id), - "specimen", - projectJSON, - sourceType, - "specimen", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "subject_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "subject_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("specimen", id), - "specimen", - projectJSON, - sourceType, - "specimen", - )) - } - } - } - } - } - if x.Subject != nil { - if x.Subject.Reference != nil { - refVal := *x.Subject.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "subject_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "subject_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("specimen", id), - "specimen", - projectJSON, - sourceType, - "specimen", - )) - } - } - } - } - } - if x.Collection != nil { - if x.Collection.Collector != nil { - if x.Collection.Collector.Reference != nil { - refVal := *x.Collection.Collector.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "collection_collector_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "collection_collector_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "specimen_collection") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("collection", id), - "specimen_collection", - projectJSON, - sourceType, - "collection", - )) - } - } - } - } - } - } - if x.Collection != nil { - if x.Collection.Collector != nil { - if x.Collection.Collector.Reference != nil { - refVal := *x.Collection.Collector.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "collection_collector_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "collection_collector_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "specimen_collection") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("collection", id), - "specimen_collection", - projectJSON, - sourceType, - "collection", - )) - } - } - } - } - } - } - if x.Collection != nil { - if x.Collection.Collector != nil { - if x.Collection.Collector.Reference != nil { - refVal := *x.Collection.Collector.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "collection_collector_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "collection_collector_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "specimen_collection") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("collection", id), - "specimen_collection", - projectJSON, - sourceType, - "collection", - )) - } - } - } - } - } - } - if x.Collection != nil { - if x.Collection.Procedure != nil { - if x.Collection.Procedure.Reference != nil { - refVal := *x.Collection.Procedure.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "collection_procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("procedure", targetID), - "collection_procedure", - projectJSON, - sourceType, - "procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "specimen_collection") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("collection", id), - "specimen_collection", - projectJSON, - sourceType, - "collection", - )) - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "note_authorReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "note_authorReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "note_authorReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "note_authorReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Processing != nil { - for _, item_4_x_Processing := range x.Processing { - if item_4_x_Processing != nil { - if item_4_x_Processing.Additive != nil { - for _, item_2_item_4_x_Processing_Additive := range item_4_x_Processing.Additive { - if item_2_item_4_x_Processing_Additive != nil { - if item_2_item_4_x_Processing_Additive.Reference != nil { - refVal := *item_2_item_4_x_Processing_Additive.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "processing_additive") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("additive", targetID), - "processing_additive", - projectJSON, - sourceType, - "additive", - )) - } - backrefKey := getEdgeUUID(id, targetID, "additive_specimen_processing") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("processing", id), - "additive_specimen_processing", - projectJSON, - sourceType, - "processing", - )) - } - } - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from SpecimenCollection. -func (x *SpecimenCollection) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "SpecimenCollection" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Collector != nil { - if x.Collector.Reference != nil { - refVal := *x.Collector.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "collector_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "collector_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "specimen_collection") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("collection", id), - "specimen_collection", - projectJSON, - sourceType, - "collection", - )) - } - } - } - } - } - if x.Collector != nil { - if x.Collector.Reference != nil { - refVal := *x.Collector.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "collector_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "collector_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "specimen_collection") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("collection", id), - "specimen_collection", - projectJSON, - sourceType, - "collection", - )) - } - } - } - } - } - if x.Collector != nil { - if x.Collector.Reference != nil { - refVal := *x.Collector.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "collector_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "collector_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "specimen_collection") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("collection", id), - "specimen_collection", - projectJSON, - sourceType, - "collection", - )) - } - } - } - } - } - if x.Procedure != nil { - if x.Procedure.Reference != nil { - refVal := *x.Procedure.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("procedure", targetID), - "procedure", - projectJSON, - sourceType, - "procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "specimen_collection") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("collection", id), - "specimen_collection", - projectJSON, - sourceType, - "collection", - )) - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "bodySite_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "bodySite_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "bodySite_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "bodySite_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "bodySite_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "bodySite_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "bodySite_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "bodySite_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "bodySite_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "bodySite_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "bodySite_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "bodySite_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "bodySite_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "bodySite_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "bodySite_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "bodySite_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "bodySite_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "bodySite_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "bodySite_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "bodySite_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "bodySite_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "bodySite_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.BodySite != nil { - if x.BodySite.Reference != nil { - if x.BodySite.Reference.Reference != nil { - refVal := *x.BodySite.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "bodySite_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Device != nil { - if x.Device.Reference != nil { - if x.Device.Reference.Reference != nil { - refVal := *x.Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "device_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Device != nil { - if x.Device.Reference != nil { - if x.Device.Reference.Reference != nil { - refVal := *x.Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "device_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Device != nil { - if x.Device.Reference != nil { - if x.Device.Reference.Reference != nil { - refVal := *x.Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "device_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Device != nil { - if x.Device.Reference != nil { - if x.Device.Reference.Reference != nil { - refVal := *x.Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "device_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Device != nil { - if x.Device.Reference != nil { - if x.Device.Reference.Reference != nil { - refVal := *x.Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "device_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Device != nil { - if x.Device.Reference != nil { - if x.Device.Reference.Reference != nil { - refVal := *x.Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "device_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Device != nil { - if x.Device.Reference != nil { - if x.Device.Reference.Reference != nil { - refVal := *x.Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "device_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Device != nil { - if x.Device.Reference != nil { - if x.Device.Reference.Reference != nil { - refVal := *x.Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "device_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Device != nil { - if x.Device.Reference != nil { - if x.Device.Reference.Reference != nil { - refVal := *x.Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "device_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Device != nil { - if x.Device.Reference != nil { - if x.Device.Reference.Reference != nil { - refVal := *x.Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "device_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Device != nil { - if x.Device.Reference != nil { - if x.Device.Reference.Reference != nil { - refVal := *x.Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "device_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Device != nil { - if x.Device.Reference != nil { - if x.Device.Reference.Reference != nil { - refVal := *x.Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "device_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Device != nil { - if x.Device.Reference != nil { - if x.Device.Reference.Reference != nil { - refVal := *x.Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "device_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Device != nil { - if x.Device.Reference != nil { - if x.Device.Reference.Reference != nil { - refVal := *x.Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "device_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Device != nil { - if x.Device.Reference != nil { - if x.Device.Reference.Reference != nil { - refVal := *x.Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "device_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Device != nil { - if x.Device.Reference != nil { - if x.Device.Reference.Reference != nil { - refVal := *x.Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "device_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Device != nil { - if x.Device.Reference != nil { - if x.Device.Reference.Reference != nil { - refVal := *x.Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "device_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Device != nil { - if x.Device.Reference != nil { - if x.Device.Reference.Reference != nil { - refVal := *x.Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "device_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Device != nil { - if x.Device.Reference != nil { - if x.Device.Reference.Reference != nil { - refVal := *x.Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "device_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Device != nil { - if x.Device.Reference != nil { - if x.Device.Reference.Reference != nil { - refVal := *x.Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "device_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Device != nil { - if x.Device.Reference != nil { - if x.Device.Reference.Reference != nil { - refVal := *x.Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "device_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Device != nil { - if x.Device.Reference != nil { - if x.Device.Reference.Reference != nil { - refVal := *x.Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "device_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Device != nil { - if x.Device.Reference != nil { - if x.Device.Reference.Reference != nil { - refVal := *x.Device.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "device_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "device_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from SpecimenContainer. -func (x *SpecimenContainer) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "SpecimenContainer" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from SpecimenFeature. -func (x *SpecimenFeature) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "SpecimenFeature" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from SpecimenProcessing. -func (x *SpecimenProcessing) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "SpecimenProcessing" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Additive != nil { - for _, item_2_x_Additive := range x.Additive { - if item_2_x_Additive != nil { - if item_2_x_Additive.Reference != nil { - refVal := *item_2_x_Additive.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "additive") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("additive", targetID), - "additive", - projectJSON, - sourceType, - "additive", - )) - } - backrefKey := getEdgeUUID(id, targetID, "additive_specimen_processing") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("processing", id), - "additive_specimen_processing", - projectJSON, - sourceType, - "processing", - )) - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from Substance. -func (x *Substance) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Substance" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Code != nil { - if x.Code.Reference != nil { - if x.Code.Reference.Reference != nil { - refVal := *x.Code.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "code_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "code_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Code != nil { - if x.Code.Reference != nil { - if x.Code.Reference.Reference != nil { - refVal := *x.Code.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "code_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "code_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Code != nil { - if x.Code.Reference != nil { - if x.Code.Reference.Reference != nil { - refVal := *x.Code.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "code_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "code_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Code != nil { - if x.Code.Reference != nil { - if x.Code.Reference.Reference != nil { - refVal := *x.Code.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "code_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "code_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Code != nil { - if x.Code.Reference != nil { - if x.Code.Reference.Reference != nil { - refVal := *x.Code.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "code_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "code_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Code != nil { - if x.Code.Reference != nil { - if x.Code.Reference.Reference != nil { - refVal := *x.Code.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "code_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "code_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Code != nil { - if x.Code.Reference != nil { - if x.Code.Reference.Reference != nil { - refVal := *x.Code.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "code_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "code_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Code != nil { - if x.Code.Reference != nil { - if x.Code.Reference.Reference != nil { - refVal := *x.Code.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "code_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "code_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Code != nil { - if x.Code.Reference != nil { - if x.Code.Reference.Reference != nil { - refVal := *x.Code.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "code_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "code_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Code != nil { - if x.Code.Reference != nil { - if x.Code.Reference.Reference != nil { - refVal := *x.Code.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "code_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "code_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Code != nil { - if x.Code.Reference != nil { - if x.Code.Reference.Reference != nil { - refVal := *x.Code.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "code_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "code_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Code != nil { - if x.Code.Reference != nil { - if x.Code.Reference.Reference != nil { - refVal := *x.Code.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "code_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "code_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Code != nil { - if x.Code.Reference != nil { - if x.Code.Reference.Reference != nil { - refVal := *x.Code.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "code_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "code_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Code != nil { - if x.Code.Reference != nil { - if x.Code.Reference.Reference != nil { - refVal := *x.Code.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "code_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "code_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Code != nil { - if x.Code.Reference != nil { - if x.Code.Reference.Reference != nil { - refVal := *x.Code.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "code_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "code_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Code != nil { - if x.Code.Reference != nil { - if x.Code.Reference.Reference != nil { - refVal := *x.Code.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "code_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "code_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Code != nil { - if x.Code.Reference != nil { - if x.Code.Reference.Reference != nil { - refVal := *x.Code.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "code_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "code_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Code != nil { - if x.Code.Reference != nil { - if x.Code.Reference.Reference != nil { - refVal := *x.Code.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "code_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "code_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Code != nil { - if x.Code.Reference != nil { - if x.Code.Reference.Reference != nil { - refVal := *x.Code.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "code_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "code_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Code != nil { - if x.Code.Reference != nil { - if x.Code.Reference.Reference != nil { - refVal := *x.Code.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "code_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "code_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Code != nil { - if x.Code.Reference != nil { - if x.Code.Reference.Reference != nil { - refVal := *x.Code.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "code_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "code_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Code != nil { - if x.Code.Reference != nil { - if x.Code.Reference.Reference != nil { - refVal := *x.Code.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "code_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "code_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Code != nil { - if x.Code.Reference != nil { - if x.Code.Reference.Reference != nil { - refVal := *x.Code.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "code_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "code_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.Ingredient != nil { - for _, item_3_x_Ingredient := range x.Ingredient { - if item_3_x_Ingredient != nil { - if item_3_x_Ingredient.SubstanceReference != nil { - if item_3_x_Ingredient.SubstanceReference.Reference != nil { - refVal := *item_3_x_Ingredient.SubstanceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "ingredient_substanceReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("substanceReference", targetID), - "ingredient_substanceReference", - projectJSON, - sourceType, - "substanceReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "substance_ingredient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("ingredient", id), - "substance_ingredient", - projectJSON, - sourceType, - "ingredient", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from SubstanceDefinition. -func (x *SubstanceDefinition) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "SubstanceDefinition" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Manufacturer != nil { - for _, item_2_x_Manufacturer := range x.Manufacturer { - if item_2_x_Manufacturer != nil { - if item_2_x_Manufacturer.Reference != nil { - refVal := *item_2_x_Manufacturer.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "manufacturer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("manufacturer", targetID), - "manufacturer", - projectJSON, - sourceType, - "manufacturer", - )) - } - backrefKey := getEdgeUUID(id, targetID, "manufacturer_substance_definition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("definition", id), - "manufacturer_substance_definition", - projectJSON, - sourceType, - "definition", - )) - } - } - } - } - } - } - } - if x.Supplier != nil { - for _, item_2_x_Supplier := range x.Supplier { - if item_2_x_Supplier != nil { - if item_2_x_Supplier.Reference != nil { - refVal := *item_2_x_Supplier.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "supplier") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("supplier", targetID), - "supplier", - projectJSON, - sourceType, - "supplier", - )) - } - backrefKey := getEdgeUUID(id, targetID, "supplier_substance_definition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("definition", id), - "supplier_substance_definition", - projectJSON, - sourceType, - "definition", - )) - } - } - } - } - } - } - } - if x.Code != nil { - for _, item_4_x_Code := range x.Code { - if item_4_x_Code != nil { - if item_4_x_Code.Source != nil { - for _, item_2_item_4_x_Code_Source := range item_4_x_Code.Source { - if item_2_item_4_x_Code_Source != nil { - if item_2_item_4_x_Code_Source.Reference != nil { - refVal := *item_2_item_4_x_Code_Source.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "code_source") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("source", targetID), - "code_source", - projectJSON, - sourceType, - "source", - )) - } - backrefKey := getEdgeUUID(id, targetID, "source_substance_definition_code") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("code", id), - "source_substance_definition_code", - projectJSON, - sourceType, - "code", - )) - } - } - } - } - } - } - } - } - } - } - if x.Name != nil { - for _, item_4_x_Name := range x.Name { - if item_4_x_Name != nil { - if item_4_x_Name.Source != nil { - for _, item_2_item_4_x_Name_Source := range item_4_x_Name.Source { - if item_2_item_4_x_Name_Source != nil { - if item_2_item_4_x_Name_Source.Reference != nil { - refVal := *item_2_item_4_x_Name_Source.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "name_source") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("source", targetID), - "name_source", - projectJSON, - sourceType, - "source", - )) - } - backrefKey := getEdgeUUID(id, targetID, "source_substance_definition_name") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("name", id), - "source_substance_definition_name", - projectJSON, - sourceType, - "name", - )) - } - } - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "note_authorReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "note_authorReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "note_authorReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "note_authorReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Relationship != nil { - for _, item_4_x_Relationship := range x.Relationship { - if item_4_x_Relationship != nil { - if item_4_x_Relationship.Source != nil { - for _, item_2_item_4_x_Relationship_Source := range item_4_x_Relationship.Source { - if item_2_item_4_x_Relationship_Source != nil { - if item_2_item_4_x_Relationship_Source.Reference != nil { - refVal := *item_2_item_4_x_Relationship_Source.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "relationship_source") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("source", targetID), - "relationship_source", - projectJSON, - sourceType, - "source", - )) - } - backrefKey := getEdgeUUID(id, targetID, "source_substance_definition_relationship") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("relationship", id), - "source_substance_definition_relationship", - projectJSON, - sourceType, - "relationship", - )) - } - } - } - } - } - } - } - } - } - } - if x.Relationship != nil { - for _, item_3_x_Relationship := range x.Relationship { - if item_3_x_Relationship != nil { - if item_3_x_Relationship.SubstanceDefinitionReference != nil { - if item_3_x_Relationship.SubstanceDefinitionReference.Reference != nil { - refVal := *item_3_x_Relationship.SubstanceDefinitionReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "relationship_substanceDefinitionReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("substanceDefinitionReference", targetID), - "relationship_substanceDefinitionReference", - projectJSON, - sourceType, - "substanceDefinitionReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "substance_definition_relationship") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("relationship", id), - "substance_definition_relationship", - projectJSON, - sourceType, - "relationship", - )) - } - } - } - } - } - } - } - } - if x.Structure != nil { - if x.Structure.SourceDocument != nil { - for _, item_2_x_Structure_SourceDocument := range x.Structure.SourceDocument { - if item_2_x_Structure_SourceDocument != nil { - if item_2_x_Structure_SourceDocument.Reference != nil { - refVal := *item_2_x_Structure_SourceDocument.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "structure_sourceDocument") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("sourceDocument", targetID), - "structure_sourceDocument", - projectJSON, - sourceType, - "sourceDocument", - )) - } - backrefKey := getEdgeUUID(id, targetID, "sourceDocument_substance_definition_structure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("structure", id), - "sourceDocument_substance_definition_structure", - projectJSON, - sourceType, - "structure", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from SubstanceDefinitionCharacterization. -func (x *SubstanceDefinitionCharacterization) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "SubstanceDefinitionCharacterization" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from SubstanceDefinitionCode. -func (x *SubstanceDefinitionCode) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "SubstanceDefinitionCode" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Source != nil { - for _, item_2_x_Source := range x.Source { - if item_2_x_Source != nil { - if item_2_x_Source.Reference != nil { - refVal := *item_2_x_Source.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "source") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("source", targetID), - "source", - projectJSON, - sourceType, - "source", - )) - } - backrefKey := getEdgeUUID(id, targetID, "source_substance_definition_code") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("code", id), - "source_substance_definition_code", - projectJSON, - sourceType, - "code", - )) - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "note_authorReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "note_authorReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "note_authorReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "note_authorReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from SubstanceDefinitionMoiety. -func (x *SubstanceDefinitionMoiety) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "SubstanceDefinitionMoiety" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from SubstanceDefinitionMolecularWeight. -func (x *SubstanceDefinitionMolecularWeight) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "SubstanceDefinitionMolecularWeight" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from SubstanceDefinitionName. -func (x *SubstanceDefinitionName) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "SubstanceDefinitionName" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Source != nil { - for _, item_2_x_Source := range x.Source { - if item_2_x_Source != nil { - if item_2_x_Source.Reference != nil { - refVal := *item_2_x_Source.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "source") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("source", targetID), - "source", - projectJSON, - sourceType, - "source", - )) - } - backrefKey := getEdgeUUID(id, targetID, "source_substance_definition_name") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("name", id), - "source_substance_definition_name", - projectJSON, - sourceType, - "name", - )) - } - } - } - } - } - } - } - if x.Synonym != nil { - for _, item_4_x_Synonym := range x.Synonym { - if item_4_x_Synonym != nil { - if item_4_x_Synonym.Source != nil { - for _, item_2_item_4_x_Synonym_Source := range item_4_x_Synonym.Source { - if item_2_item_4_x_Synonym_Source != nil { - if item_2_item_4_x_Synonym_Source.Reference != nil { - refVal := *item_2_item_4_x_Synonym_Source.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "synonym_source") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("source", targetID), - "synonym_source", - projectJSON, - sourceType, - "source", - )) - } - backrefKey := getEdgeUUID(id, targetID, "source_substance_definition_name") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("name", id), - "source_substance_definition_name", - projectJSON, - sourceType, - "name", - )) - } - } - } - } - } - } - } - } - } - } - if x.Translation != nil { - for _, item_4_x_Translation := range x.Translation { - if item_4_x_Translation != nil { - if item_4_x_Translation.Source != nil { - for _, item_2_item_4_x_Translation_Source := range item_4_x_Translation.Source { - if item_2_item_4_x_Translation_Source != nil { - if item_2_item_4_x_Translation_Source.Reference != nil { - refVal := *item_2_item_4_x_Translation_Source.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "translation_source") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("source", targetID), - "translation_source", - projectJSON, - sourceType, - "source", - )) - } - backrefKey := getEdgeUUID(id, targetID, "source_substance_definition_name") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("name", id), - "source_substance_definition_name", - projectJSON, - sourceType, - "name", - )) - } - } - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from SubstanceDefinitionNameOfficial. -func (x *SubstanceDefinitionNameOfficial) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "SubstanceDefinitionNameOfficial" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from SubstanceDefinitionProperty. -func (x *SubstanceDefinitionProperty) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "SubstanceDefinitionProperty" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from SubstanceDefinitionRelationship. -func (x *SubstanceDefinitionRelationship) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "SubstanceDefinitionRelationship" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Source != nil { - for _, item_2_x_Source := range x.Source { - if item_2_x_Source != nil { - if item_2_x_Source.Reference != nil { - refVal := *item_2_x_Source.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "source") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("source", targetID), - "source", - projectJSON, - sourceType, - "source", - )) - } - backrefKey := getEdgeUUID(id, targetID, "source_substance_definition_relationship") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("relationship", id), - "source_substance_definition_relationship", - projectJSON, - sourceType, - "relationship", - )) - } - } - } - } - } - } - } - if x.SubstanceDefinitionReference != nil { - if x.SubstanceDefinitionReference.Reference != nil { - refVal := *x.SubstanceDefinitionReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "substanceDefinitionReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("substanceDefinitionReference", targetID), - "substanceDefinitionReference", - projectJSON, - sourceType, - "substanceDefinitionReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "substance_definition_relationship") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("relationship", id), - "substance_definition_relationship", - projectJSON, - sourceType, - "relationship", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from SubstanceDefinitionSourceMaterial. -func (x *SubstanceDefinitionSourceMaterial) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "SubstanceDefinitionSourceMaterial" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from SubstanceDefinitionStructure. -func (x *SubstanceDefinitionStructure) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "SubstanceDefinitionStructure" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.SourceDocument != nil { - for _, item_2_x_SourceDocument := range x.SourceDocument { - if item_2_x_SourceDocument != nil { - if item_2_x_SourceDocument.Reference != nil { - refVal := *item_2_x_SourceDocument.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "sourceDocument") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("sourceDocument", targetID), - "sourceDocument", - projectJSON, - sourceType, - "sourceDocument", - )) - } - backrefKey := getEdgeUUID(id, targetID, "sourceDocument_substance_definition_structure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("structure", id), - "sourceDocument_substance_definition_structure", - projectJSON, - sourceType, - "structure", - )) - } - } - } - } - } - } - } - if x.Representation != nil { - for _, item_3_x_Representation := range x.Representation { - if item_3_x_Representation != nil { - if item_3_x_Representation.Document != nil { - if item_3_x_Representation.Document.Reference != nil { - refVal := *item_3_x_Representation.Document.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "representation_document") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("document", targetID), - "representation_document", - projectJSON, - sourceType, - "document", - )) - } - backrefKey := getEdgeUUID(id, targetID, "substance_definition_structure_representation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("representation", id), - "substance_definition_structure_representation", - projectJSON, - sourceType, - "representation", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from SubstanceDefinitionStructureRepresentation. -func (x *SubstanceDefinitionStructureRepresentation) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "SubstanceDefinitionStructureRepresentation" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Document != nil { - if x.Document.Reference != nil { - refVal := *x.Document.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "document") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("document", targetID), - "document", - projectJSON, - sourceType, - "document", - )) - } - backrefKey := getEdgeUUID(id, targetID, "substance_definition_structure_representation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("representation", id), - "substance_definition_structure_representation", - projectJSON, - sourceType, - "representation", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from SubstanceIngredient. -func (x *SubstanceIngredient) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "SubstanceIngredient" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.SubstanceReference != nil { - if x.SubstanceReference.Reference != nil { - refVal := *x.SubstanceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "substanceReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("substanceReference", targetID), - "substanceReference", - projectJSON, - sourceType, - "substanceReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "substance_ingredient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("ingredient", id), - "substance_ingredient", - projectJSON, - sourceType, - "ingredient", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from Task. -func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Task" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "basedOn_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "basedOn_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "basedOn_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "basedOn_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "basedOn_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "basedOn_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "basedOn_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "basedOn_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "basedOn_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "basedOn_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "basedOn_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "basedOn_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "basedOn_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "basedOn_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "basedOn_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "basedOn_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "basedOn_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "basedOn_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "basedOn_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "basedOn_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "basedOn_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "basedOn_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "basedOn_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "basedOn_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "basedOn_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "basedOn_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "basedOn_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "basedOn_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "basedOn_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "basedOn_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "basedOn_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "basedOn_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "basedOn_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "basedOn_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "basedOn_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "basedOn_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "basedOn_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "basedOn_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "basedOn_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "basedOn_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "basedOn_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "basedOn_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "basedOn_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "basedOn_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.BasedOn != nil { - for _, item_2_x_BasedOn := range x.BasedOn { - if item_2_x_BasedOn != nil { - if item_2_x_BasedOn.Reference != nil { - refVal := *item_2_x_BasedOn.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "basedOn_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "basedOn_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "basedOn_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "basedOn_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "focus_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "focus_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "focus_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "focus_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "focus_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "focus_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "focus_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "focus_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "focus_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "focus_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "focus_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "focus_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "focus_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "focus_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "focus_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "focus_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "focus_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "focus_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "focus_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "focus_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "focus_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "focus_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "focus_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "focus_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "focus_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "focus_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "focus_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "focus_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "focus_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "focus_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "focus_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "focus_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "focus_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "focus_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "focus_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "focus_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "focus_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "focus_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "focus_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "focus_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "focus_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "focus_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "focus_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "focus_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "focus_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "focus_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "focus_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "focus_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "focus_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "focus_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "focus_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "focus_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "focus_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "focus_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "focus_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "focus_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "focus_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "focus_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "focus_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "focus_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "focus_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "focus_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "focus_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "focus_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "focus_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "focus_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Focus != nil { - if x.Focus.Reference != nil { - refVal := *x.Focus.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "focus_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "focus_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "focus_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "focus_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.ForFhir != nil { - if x.ForFhir.Reference != nil { - refVal := *x.ForFhir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "for_fhir_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "for_fhir_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "for_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "for_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.ForFhir != nil { - if x.ForFhir.Reference != nil { - refVal := *x.ForFhir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "for_fhir_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "for_fhir_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "for_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "for_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.ForFhir != nil { - if x.ForFhir.Reference != nil { - refVal := *x.ForFhir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "for_fhir_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "for_fhir_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "for_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "for_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.ForFhir != nil { - if x.ForFhir.Reference != nil { - refVal := *x.ForFhir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "for_fhir_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "for_fhir_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "for_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "for_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.ForFhir != nil { - if x.ForFhir.Reference != nil { - refVal := *x.ForFhir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "for_fhir_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "for_fhir_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "for_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "for_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.ForFhir != nil { - if x.ForFhir.Reference != nil { - refVal := *x.ForFhir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "for_fhir_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "for_fhir_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "for_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "for_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.ForFhir != nil { - if x.ForFhir.Reference != nil { - refVal := *x.ForFhir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "for_fhir_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "for_fhir_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "for_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "for_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.ForFhir != nil { - if x.ForFhir.Reference != nil { - refVal := *x.ForFhir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "for_fhir_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "for_fhir_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "for_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "for_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.ForFhir != nil { - if x.ForFhir.Reference != nil { - refVal := *x.ForFhir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "for_fhir_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "for_fhir_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "for_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "for_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.ForFhir != nil { - if x.ForFhir.Reference != nil { - refVal := *x.ForFhir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "for_fhir_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "for_fhir_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "for_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "for_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.ForFhir != nil { - if x.ForFhir.Reference != nil { - refVal := *x.ForFhir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "for_fhir_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "for_fhir_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "for_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "for_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.ForFhir != nil { - if x.ForFhir.Reference != nil { - refVal := *x.ForFhir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "for_fhir_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "for_fhir_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "for_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "for_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.ForFhir != nil { - if x.ForFhir.Reference != nil { - refVal := *x.ForFhir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "for_fhir_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "for_fhir_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "for_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "for_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.ForFhir != nil { - if x.ForFhir.Reference != nil { - refVal := *x.ForFhir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "for_fhir_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "for_fhir_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "for_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "for_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.ForFhir != nil { - if x.ForFhir.Reference != nil { - refVal := *x.ForFhir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "for_fhir_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "for_fhir_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "for_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "for_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.ForFhir != nil { - if x.ForFhir.Reference != nil { - refVal := *x.ForFhir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "for_fhir_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "for_fhir_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "for_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "for_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.ForFhir != nil { - if x.ForFhir.Reference != nil { - refVal := *x.ForFhir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "for_fhir_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "for_fhir_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "for_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "for_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.ForFhir != nil { - if x.ForFhir.Reference != nil { - refVal := *x.ForFhir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "for_fhir_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "for_fhir_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "for_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "for_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.ForFhir != nil { - if x.ForFhir.Reference != nil { - refVal := *x.ForFhir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "for_fhir_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "for_fhir_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "for_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "for_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.ForFhir != nil { - if x.ForFhir.Reference != nil { - refVal := *x.ForFhir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "for_fhir_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "for_fhir_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "for_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "for_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.ForFhir != nil { - if x.ForFhir.Reference != nil { - refVal := *x.ForFhir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "for_fhir_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "for_fhir_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "for_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "for_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.ForFhir != nil { - if x.ForFhir.Reference != nil { - refVal := *x.ForFhir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "for_fhir_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "for_fhir_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "for_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "for_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.ForFhir != nil { - if x.ForFhir.Reference != nil { - refVal := *x.ForFhir.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "for_fhir_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "for_fhir_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "for_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "for_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Owner != nil { - if x.Owner.Reference != nil { - refVal := *x.Owner.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "owner_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "owner_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "owner_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "owner_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Owner != nil { - if x.Owner.Reference != nil { - refVal := *x.Owner.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "owner_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "owner_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "owner_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "owner_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Owner != nil { - if x.Owner.Reference != nil { - refVal := *x.Owner.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "owner_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "owner_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "owner_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "owner_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Owner != nil { - if x.Owner.Reference != nil { - refVal := *x.Owner.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "owner_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "owner_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "owner_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "owner_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.PartOf != nil { - for _, item_2_x_PartOf := range x.PartOf { - if item_2_x_PartOf != nil { - if item_2_x_PartOf.Reference != nil { - refVal := *item_2_x_PartOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "partOf") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("partOf", targetID), - "partOf", - projectJSON, - sourceType, - "partOf", - )) - } - backrefKey := getEdgeUUID(id, targetID, "partOf_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "partOf_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - } - } - if x.Requester != nil { - if x.Requester.Reference != nil { - refVal := *x.Requester.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "requester_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "requester_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "requester_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "requester_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Requester != nil { - if x.Requester.Reference != nil { - refVal := *x.Requester.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "requester_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "requester_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "requester_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "requester_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Requester != nil { - if x.Requester.Reference != nil { - refVal := *x.Requester.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "requester_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "requester_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "requester_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "requester_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Requester != nil { - if x.Requester.Reference != nil { - refVal := *x.Requester.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "requester_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "requester_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "requester_task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("task", id), - "requester_task", - projectJSON, - sourceType, - "task", - )) - } - } - } - } - } - if x.Input != nil { - for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { - if item_3_x_Input.ValueReference != nil { - if item_3_x_Input.ValueReference.Reference != nil { - refVal := *item_3_x_Input.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "input_valueReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "input_valueReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - } - } - } - if x.Input != nil { - for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { - if item_3_x_Input.ValueReference != nil { - if item_3_x_Input.ValueReference.Reference != nil { - refVal := *item_3_x_Input.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "input_valueReference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "input_valueReference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - } - } - } - if x.Input != nil { - for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { - if item_3_x_Input.ValueReference != nil { - if item_3_x_Input.ValueReference.Reference != nil { - refVal := *item_3_x_Input.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "input_valueReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "input_valueReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - } - } - } - if x.Input != nil { - for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { - if item_3_x_Input.ValueReference != nil { - if item_3_x_Input.ValueReference.Reference != nil { - refVal := *item_3_x_Input.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "input_valueReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "input_valueReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - } - } - } - if x.Input != nil { - for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { - if item_3_x_Input.ValueReference != nil { - if item_3_x_Input.ValueReference.Reference != nil { - refVal := *item_3_x_Input.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "input_valueReference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "input_valueReference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - } - } - } - if x.Input != nil { - for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { - if item_3_x_Input.ValueReference != nil { - if item_3_x_Input.ValueReference.Reference != nil { - refVal := *item_3_x_Input.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "input_valueReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "input_valueReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - } - } - } - if x.Input != nil { - for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { - if item_3_x_Input.ValueReference != nil { - if item_3_x_Input.ValueReference.Reference != nil { - refVal := *item_3_x_Input.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "input_valueReference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "input_valueReference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - } - } - } - if x.Input != nil { - for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { - if item_3_x_Input.ValueReference != nil { - if item_3_x_Input.ValueReference.Reference != nil { - refVal := *item_3_x_Input.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "input_valueReference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "input_valueReference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - } - } - } - if x.Input != nil { - for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { - if item_3_x_Input.ValueReference != nil { - if item_3_x_Input.ValueReference.Reference != nil { - refVal := *item_3_x_Input.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "input_valueReference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "input_valueReference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - } - } - } - if x.Input != nil { - for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { - if item_3_x_Input.ValueReference != nil { - if item_3_x_Input.ValueReference.Reference != nil { - refVal := *item_3_x_Input.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "input_valueReference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "input_valueReference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - } - } - } - if x.Input != nil { - for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { - if item_3_x_Input.ValueReference != nil { - if item_3_x_Input.ValueReference.Reference != nil { - refVal := *item_3_x_Input.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "input_valueReference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "input_valueReference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - } - } - } - if x.Input != nil { - for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { - if item_3_x_Input.ValueReference != nil { - if item_3_x_Input.ValueReference.Reference != nil { - refVal := *item_3_x_Input.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "input_valueReference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "input_valueReference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - } - } - } - if x.Input != nil { - for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { - if item_3_x_Input.ValueReference != nil { - if item_3_x_Input.ValueReference.Reference != nil { - refVal := *item_3_x_Input.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "input_valueReference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "input_valueReference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - } - } - } - if x.Input != nil { - for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { - if item_3_x_Input.ValueReference != nil { - if item_3_x_Input.ValueReference.Reference != nil { - refVal := *item_3_x_Input.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "input_valueReference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "input_valueReference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - } - } - } - if x.Input != nil { - for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { - if item_3_x_Input.ValueReference != nil { - if item_3_x_Input.ValueReference.Reference != nil { - refVal := *item_3_x_Input.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "input_valueReference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "input_valueReference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - } - } - } - if x.Input != nil { - for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { - if item_3_x_Input.ValueReference != nil { - if item_3_x_Input.ValueReference.Reference != nil { - refVal := *item_3_x_Input.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "input_valueReference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "input_valueReference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - } - } - } - if x.Input != nil { - for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { - if item_3_x_Input.ValueReference != nil { - if item_3_x_Input.ValueReference.Reference != nil { - refVal := *item_3_x_Input.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "input_valueReference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "input_valueReference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - } - } - } - if x.Input != nil { - for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { - if item_3_x_Input.ValueReference != nil { - if item_3_x_Input.ValueReference.Reference != nil { - refVal := *item_3_x_Input.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "input_valueReference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "input_valueReference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - } - } - } - if x.Input != nil { - for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { - if item_3_x_Input.ValueReference != nil { - if item_3_x_Input.ValueReference.Reference != nil { - refVal := *item_3_x_Input.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "input_valueReference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "input_valueReference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - } - } - } - if x.Input != nil { - for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { - if item_3_x_Input.ValueReference != nil { - if item_3_x_Input.ValueReference.Reference != nil { - refVal := *item_3_x_Input.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "input_valueReference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "input_valueReference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - } - } - } - if x.Input != nil { - for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { - if item_3_x_Input.ValueReference != nil { - if item_3_x_Input.ValueReference.Reference != nil { - refVal := *item_3_x_Input.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "input_valueReference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "input_valueReference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - } - } - } - if x.Input != nil { - for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { - if item_3_x_Input.ValueReference != nil { - if item_3_x_Input.ValueReference.Reference != nil { - refVal := *item_3_x_Input.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "input_valueReference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "input_valueReference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - } - } - } - if x.Input != nil { - for _, item_3_x_Input := range x.Input { - if item_3_x_Input != nil { - if item_3_x_Input.ValueReference != nil { - if item_3_x_Input.ValueReference.Reference != nil { - refVal := *item_3_x_Input.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "input_valueReference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "input_valueReference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "note_authorReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "note_authorReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "note_authorReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Note != nil { - for _, item_3_x_Note := range x.Note { - if item_3_x_Note != nil { - if item_3_x_Note.AuthorReference != nil { - if item_3_x_Note.AuthorReference.Reference != nil { - refVal := *item_3_x_Note.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "note_authorReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - } - } - if x.Output != nil { - for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { - if item_3_x_Output.ValueReference != nil { - if item_3_x_Output.ValueReference.Reference != nil { - refVal := *item_3_x_Output.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "output_valueReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "output_valueReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - } - } - } - if x.Output != nil { - for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { - if item_3_x_Output.ValueReference != nil { - if item_3_x_Output.ValueReference.Reference != nil { - refVal := *item_3_x_Output.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "output_valueReference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "output_valueReference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - } - } - } - if x.Output != nil { - for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { - if item_3_x_Output.ValueReference != nil { - if item_3_x_Output.ValueReference.Reference != nil { - refVal := *item_3_x_Output.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "output_valueReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "output_valueReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - } - } - } - if x.Output != nil { - for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { - if item_3_x_Output.ValueReference != nil { - if item_3_x_Output.ValueReference.Reference != nil { - refVal := *item_3_x_Output.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "output_valueReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "output_valueReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - } - } - } - if x.Output != nil { - for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { - if item_3_x_Output.ValueReference != nil { - if item_3_x_Output.ValueReference.Reference != nil { - refVal := *item_3_x_Output.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "output_valueReference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "output_valueReference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - } - } - } - if x.Output != nil { - for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { - if item_3_x_Output.ValueReference != nil { - if item_3_x_Output.ValueReference.Reference != nil { - refVal := *item_3_x_Output.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "output_valueReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "output_valueReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - } - } - } - if x.Output != nil { - for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { - if item_3_x_Output.ValueReference != nil { - if item_3_x_Output.ValueReference.Reference != nil { - refVal := *item_3_x_Output.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "output_valueReference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "output_valueReference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - } - } - } - if x.Output != nil { - for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { - if item_3_x_Output.ValueReference != nil { - if item_3_x_Output.ValueReference.Reference != nil { - refVal := *item_3_x_Output.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "output_valueReference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "output_valueReference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - } - } - } - if x.Output != nil { - for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { - if item_3_x_Output.ValueReference != nil { - if item_3_x_Output.ValueReference.Reference != nil { - refVal := *item_3_x_Output.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "output_valueReference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "output_valueReference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - } - } - } - if x.Output != nil { - for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { - if item_3_x_Output.ValueReference != nil { - if item_3_x_Output.ValueReference.Reference != nil { - refVal := *item_3_x_Output.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "output_valueReference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "output_valueReference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - } - } - } - if x.Output != nil { - for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { - if item_3_x_Output.ValueReference != nil { - if item_3_x_Output.ValueReference.Reference != nil { - refVal := *item_3_x_Output.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "output_valueReference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "output_valueReference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - } - } - } - if x.Output != nil { - for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { - if item_3_x_Output.ValueReference != nil { - if item_3_x_Output.ValueReference.Reference != nil { - refVal := *item_3_x_Output.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "output_valueReference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "output_valueReference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - } - } - } - if x.Output != nil { - for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { - if item_3_x_Output.ValueReference != nil { - if item_3_x_Output.ValueReference.Reference != nil { - refVal := *item_3_x_Output.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "output_valueReference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "output_valueReference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - } - } - } - if x.Output != nil { - for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { - if item_3_x_Output.ValueReference != nil { - if item_3_x_Output.ValueReference.Reference != nil { - refVal := *item_3_x_Output.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "output_valueReference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "output_valueReference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - } - } - } - if x.Output != nil { - for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { - if item_3_x_Output.ValueReference != nil { - if item_3_x_Output.ValueReference.Reference != nil { - refVal := *item_3_x_Output.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "output_valueReference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "output_valueReference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - } - } - } - if x.Output != nil { - for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { - if item_3_x_Output.ValueReference != nil { - if item_3_x_Output.ValueReference.Reference != nil { - refVal := *item_3_x_Output.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "output_valueReference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "output_valueReference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - } - } - } - if x.Output != nil { - for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { - if item_3_x_Output.ValueReference != nil { - if item_3_x_Output.ValueReference.Reference != nil { - refVal := *item_3_x_Output.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "output_valueReference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "output_valueReference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - } - } - } - if x.Output != nil { - for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { - if item_3_x_Output.ValueReference != nil { - if item_3_x_Output.ValueReference.Reference != nil { - refVal := *item_3_x_Output.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "output_valueReference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "output_valueReference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - } - } - } - if x.Output != nil { - for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { - if item_3_x_Output.ValueReference != nil { - if item_3_x_Output.ValueReference.Reference != nil { - refVal := *item_3_x_Output.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "output_valueReference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "output_valueReference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - } - } - } - if x.Output != nil { - for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { - if item_3_x_Output.ValueReference != nil { - if item_3_x_Output.ValueReference.Reference != nil { - refVal := *item_3_x_Output.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "output_valueReference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "output_valueReference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - } - } - } - if x.Output != nil { - for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { - if item_3_x_Output.ValueReference != nil { - if item_3_x_Output.ValueReference.Reference != nil { - refVal := *item_3_x_Output.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "output_valueReference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "output_valueReference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - } - } - } - if x.Output != nil { - for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { - if item_3_x_Output.ValueReference != nil { - if item_3_x_Output.ValueReference.Reference != nil { - refVal := *item_3_x_Output.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "output_valueReference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "output_valueReference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - } - } - } - if x.Output != nil { - for _, item_3_x_Output := range x.Output { - if item_3_x_Output != nil { - if item_3_x_Output.ValueReference != nil { - if item_3_x_Output.ValueReference.Reference != nil { - refVal := *item_3_x_Output.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "output_valueReference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "output_valueReference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - } - } - } - if x.Performer != nil { - for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { - if item_3_x_Performer.Actor != nil { - if item_3_x_Performer.Actor.Reference != nil { - refVal := *item_3_x_Performer.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "performer_actor_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "performer_actor_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "task_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - } - } - } - if x.Performer != nil { - for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { - if item_3_x_Performer.Actor != nil { - if item_3_x_Performer.Actor.Reference != nil { - refVal := *item_3_x_Performer.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "performer_actor_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "performer_actor_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "task_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - } - } - } - if x.Performer != nil { - for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { - if item_3_x_Performer.Actor != nil { - if item_3_x_Performer.Actor.Reference != nil { - refVal := *item_3_x_Performer.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "performer_actor_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "performer_actor_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "task_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - } - } - } - if x.Performer != nil { - for _, item_3_x_Performer := range x.Performer { - if item_3_x_Performer != nil { - if item_3_x_Performer.Actor != nil { - if item_3_x_Performer.Actor.Reference != nil { - refVal := *item_3_x_Performer.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "performer_actor_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "performer_actor_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "task_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "reason_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "reason_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "reason_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "reason_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "reason_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "reason_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "reason_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "reason_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "reason_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "reason_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "reason_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "reason_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "reason_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "reason_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "reason_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "reason_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "reason_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "reason_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "reason_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "reason_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "reason_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "reason_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Reason != nil { - for _, item_3_x_Reason := range x.Reason { - if item_3_x_Reason != nil { - if item_3_x_Reason.Reference != nil { - if item_3_x_Reason.Reference.Reference != nil { - refVal := *item_3_x_Reason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "reason_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "reason_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RequestedPerformer != nil { - for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { - if item_3_x_RequestedPerformer.Reference != nil { - if item_3_x_RequestedPerformer.Reference.Reference != nil { - refVal := *item_3_x_RequestedPerformer.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "requestedPerformer_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RequestedPerformer != nil { - for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { - if item_3_x_RequestedPerformer.Reference != nil { - if item_3_x_RequestedPerformer.Reference.Reference != nil { - refVal := *item_3_x_RequestedPerformer.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "requestedPerformer_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RequestedPerformer != nil { - for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { - if item_3_x_RequestedPerformer.Reference != nil { - if item_3_x_RequestedPerformer.Reference.Reference != nil { - refVal := *item_3_x_RequestedPerformer.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "requestedPerformer_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RequestedPerformer != nil { - for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { - if item_3_x_RequestedPerformer.Reference != nil { - if item_3_x_RequestedPerformer.Reference.Reference != nil { - refVal := *item_3_x_RequestedPerformer.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "requestedPerformer_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RequestedPerformer != nil { - for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { - if item_3_x_RequestedPerformer.Reference != nil { - if item_3_x_RequestedPerformer.Reference.Reference != nil { - refVal := *item_3_x_RequestedPerformer.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "requestedPerformer_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RequestedPerformer != nil { - for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { - if item_3_x_RequestedPerformer.Reference != nil { - if item_3_x_RequestedPerformer.Reference.Reference != nil { - refVal := *item_3_x_RequestedPerformer.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "requestedPerformer_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RequestedPerformer != nil { - for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { - if item_3_x_RequestedPerformer.Reference != nil { - if item_3_x_RequestedPerformer.Reference.Reference != nil { - refVal := *item_3_x_RequestedPerformer.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "requestedPerformer_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RequestedPerformer != nil { - for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { - if item_3_x_RequestedPerformer.Reference != nil { - if item_3_x_RequestedPerformer.Reference.Reference != nil { - refVal := *item_3_x_RequestedPerformer.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "requestedPerformer_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RequestedPerformer != nil { - for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { - if item_3_x_RequestedPerformer.Reference != nil { - if item_3_x_RequestedPerformer.Reference.Reference != nil { - refVal := *item_3_x_RequestedPerformer.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "requestedPerformer_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RequestedPerformer != nil { - for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { - if item_3_x_RequestedPerformer.Reference != nil { - if item_3_x_RequestedPerformer.Reference.Reference != nil { - refVal := *item_3_x_RequestedPerformer.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "requestedPerformer_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RequestedPerformer != nil { - for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { - if item_3_x_RequestedPerformer.Reference != nil { - if item_3_x_RequestedPerformer.Reference.Reference != nil { - refVal := *item_3_x_RequestedPerformer.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "requestedPerformer_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RequestedPerformer != nil { - for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { - if item_3_x_RequestedPerformer.Reference != nil { - if item_3_x_RequestedPerformer.Reference.Reference != nil { - refVal := *item_3_x_RequestedPerformer.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "requestedPerformer_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RequestedPerformer != nil { - for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { - if item_3_x_RequestedPerformer.Reference != nil { - if item_3_x_RequestedPerformer.Reference.Reference != nil { - refVal := *item_3_x_RequestedPerformer.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "requestedPerformer_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RequestedPerformer != nil { - for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { - if item_3_x_RequestedPerformer.Reference != nil { - if item_3_x_RequestedPerformer.Reference.Reference != nil { - refVal := *item_3_x_RequestedPerformer.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "requestedPerformer_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RequestedPerformer != nil { - for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { - if item_3_x_RequestedPerformer.Reference != nil { - if item_3_x_RequestedPerformer.Reference.Reference != nil { - refVal := *item_3_x_RequestedPerformer.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "requestedPerformer_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RequestedPerformer != nil { - for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { - if item_3_x_RequestedPerformer.Reference != nil { - if item_3_x_RequestedPerformer.Reference.Reference != nil { - refVal := *item_3_x_RequestedPerformer.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "requestedPerformer_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RequestedPerformer != nil { - for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { - if item_3_x_RequestedPerformer.Reference != nil { - if item_3_x_RequestedPerformer.Reference.Reference != nil { - refVal := *item_3_x_RequestedPerformer.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "requestedPerformer_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RequestedPerformer != nil { - for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { - if item_3_x_RequestedPerformer.Reference != nil { - if item_3_x_RequestedPerformer.Reference.Reference != nil { - refVal := *item_3_x_RequestedPerformer.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "requestedPerformer_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RequestedPerformer != nil { - for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { - if item_3_x_RequestedPerformer.Reference != nil { - if item_3_x_RequestedPerformer.Reference.Reference != nil { - refVal := *item_3_x_RequestedPerformer.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "requestedPerformer_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RequestedPerformer != nil { - for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { - if item_3_x_RequestedPerformer.Reference != nil { - if item_3_x_RequestedPerformer.Reference.Reference != nil { - refVal := *item_3_x_RequestedPerformer.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "requestedPerformer_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RequestedPerformer != nil { - for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { - if item_3_x_RequestedPerformer.Reference != nil { - if item_3_x_RequestedPerformer.Reference.Reference != nil { - refVal := *item_3_x_RequestedPerformer.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "requestedPerformer_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RequestedPerformer != nil { - for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { - if item_3_x_RequestedPerformer.Reference != nil { - if item_3_x_RequestedPerformer.Reference.Reference != nil { - refVal := *item_3_x_RequestedPerformer.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "requestedPerformer_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.RequestedPerformer != nil { - for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { - if item_3_x_RequestedPerformer != nil { - if item_3_x_RequestedPerformer.Reference != nil { - if item_3_x_RequestedPerformer.Reference.Reference != nil { - refVal := *item_3_x_RequestedPerformer.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "requestedPerformer_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - } - } - if x.Restriction != nil { - if x.Restriction.Recipient != nil { - for _, item_2_x_Restriction_Recipient := range x.Restriction.Recipient { - if item_2_x_Restriction_Recipient != nil { - if item_2_x_Restriction_Recipient.Reference != nil { - refVal := *item_2_x_Restriction_Recipient.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "restriction_recipient_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "restriction_recipient_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "recipient_task_restriction") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("restriction", id), - "recipient_task_restriction", - projectJSON, - sourceType, - "restriction", - )) - } - } - } - } - } - } - } - } - if x.Restriction != nil { - if x.Restriction.Recipient != nil { - for _, item_2_x_Restriction_Recipient := range x.Restriction.Recipient { - if item_2_x_Restriction_Recipient != nil { - if item_2_x_Restriction_Recipient.Reference != nil { - refVal := *item_2_x_Restriction_Recipient.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "restriction_recipient_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "restriction_recipient_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "recipient_task_restriction") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("restriction", id), - "recipient_task_restriction", - projectJSON, - sourceType, - "restriction", - )) - } - } - } - } - } - } - } - } - if x.Restriction != nil { - if x.Restriction.Recipient != nil { - for _, item_2_x_Restriction_Recipient := range x.Restriction.Recipient { - if item_2_x_Restriction_Recipient != nil { - if item_2_x_Restriction_Recipient.Reference != nil { - refVal := *item_2_x_Restriction_Recipient.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "restriction_recipient_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "restriction_recipient_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "recipient_task_restriction") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("restriction", id), - "recipient_task_restriction", - projectJSON, - sourceType, - "restriction", - )) - } - } - } - } - } - } - } - } - if x.Restriction != nil { - if x.Restriction.Recipient != nil { - for _, item_2_x_Restriction_Recipient := range x.Restriction.Recipient { - if item_2_x_Restriction_Recipient != nil { - if item_2_x_Restriction_Recipient.Reference != nil { - refVal := *item_2_x_Restriction_Recipient.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "restriction_recipient_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "restriction_recipient_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "recipient_task_restriction") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("restriction", id), - "recipient_task_restriction", - projectJSON, - sourceType, - "restriction", - )) - } - } - } - } - } - } - } - } - if x.Restriction != nil { - if x.Restriction.Recipient != nil { - for _, item_2_x_Restriction_Recipient := range x.Restriction.Recipient { - if item_2_x_Restriction_Recipient != nil { - if item_2_x_Restriction_Recipient.Reference != nil { - refVal := *item_2_x_Restriction_Recipient.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "restriction_recipient_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "restriction_recipient_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "recipient_task_restriction") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("restriction", id), - "recipient_task_restriction", - projectJSON, - sourceType, - "restriction", - )) - } - } - } - } - } - } - } - } - if x.StatusReason != nil { - if x.StatusReason.Reference != nil { - if x.StatusReason.Reference.Reference != nil { - refVal := *x.StatusReason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "statusReason_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.StatusReason != nil { - if x.StatusReason.Reference != nil { - if x.StatusReason.Reference.Reference != nil { - refVal := *x.StatusReason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "statusReason_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.StatusReason != nil { - if x.StatusReason.Reference != nil { - if x.StatusReason.Reference.Reference != nil { - refVal := *x.StatusReason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "statusReason_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.StatusReason != nil { - if x.StatusReason.Reference != nil { - if x.StatusReason.Reference.Reference != nil { - refVal := *x.StatusReason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "statusReason_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.StatusReason != nil { - if x.StatusReason.Reference != nil { - if x.StatusReason.Reference.Reference != nil { - refVal := *x.StatusReason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "statusReason_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.StatusReason != nil { - if x.StatusReason.Reference != nil { - if x.StatusReason.Reference.Reference != nil { - refVal := *x.StatusReason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "statusReason_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.StatusReason != nil { - if x.StatusReason.Reference != nil { - if x.StatusReason.Reference.Reference != nil { - refVal := *x.StatusReason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "statusReason_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.StatusReason != nil { - if x.StatusReason.Reference != nil { - if x.StatusReason.Reference.Reference != nil { - refVal := *x.StatusReason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "statusReason_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.StatusReason != nil { - if x.StatusReason.Reference != nil { - if x.StatusReason.Reference.Reference != nil { - refVal := *x.StatusReason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "statusReason_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.StatusReason != nil { - if x.StatusReason.Reference != nil { - if x.StatusReason.Reference.Reference != nil { - refVal := *x.StatusReason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "statusReason_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.StatusReason != nil { - if x.StatusReason.Reference != nil { - if x.StatusReason.Reference.Reference != nil { - refVal := *x.StatusReason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "statusReason_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.StatusReason != nil { - if x.StatusReason.Reference != nil { - if x.StatusReason.Reference.Reference != nil { - refVal := *x.StatusReason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "statusReason_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.StatusReason != nil { - if x.StatusReason.Reference != nil { - if x.StatusReason.Reference.Reference != nil { - refVal := *x.StatusReason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "statusReason_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.StatusReason != nil { - if x.StatusReason.Reference != nil { - if x.StatusReason.Reference.Reference != nil { - refVal := *x.StatusReason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "statusReason_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.StatusReason != nil { - if x.StatusReason.Reference != nil { - if x.StatusReason.Reference.Reference != nil { - refVal := *x.StatusReason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "statusReason_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.StatusReason != nil { - if x.StatusReason.Reference != nil { - if x.StatusReason.Reference.Reference != nil { - refVal := *x.StatusReason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "statusReason_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.StatusReason != nil { - if x.StatusReason.Reference != nil { - if x.StatusReason.Reference.Reference != nil { - refVal := *x.StatusReason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "statusReason_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.StatusReason != nil { - if x.StatusReason.Reference != nil { - if x.StatusReason.Reference.Reference != nil { - refVal := *x.StatusReason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "statusReason_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.StatusReason != nil { - if x.StatusReason.Reference != nil { - if x.StatusReason.Reference.Reference != nil { - refVal := *x.StatusReason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "statusReason_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.StatusReason != nil { - if x.StatusReason.Reference != nil { - if x.StatusReason.Reference.Reference != nil { - refVal := *x.StatusReason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "statusReason_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.StatusReason != nil { - if x.StatusReason.Reference != nil { - if x.StatusReason.Reference.Reference != nil { - refVal := *x.StatusReason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "statusReason_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.StatusReason != nil { - if x.StatusReason.Reference != nil { - if x.StatusReason.Reference.Reference != nil { - refVal := *x.StatusReason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "statusReason_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.StatusReason != nil { - if x.StatusReason.Reference != nil { - if x.StatusReason.Reference.Reference != nil { - refVal := *x.StatusReason.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "statusReason_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from TaskInput. -func (x *TaskInput) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "TaskInput" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "valueReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "valueReference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "valueReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "valueReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "valueReference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "valueReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "valueReference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "valueReference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "valueReference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "valueReference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "valueReference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "valueReference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "valueReference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "valueReference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "valueReference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "valueReference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "valueReference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "valueReference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "valueReference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "valueReference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "valueReference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "valueReference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "valueReference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_input") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("input", id), - "task_input", - projectJSON, - sourceType, - "input", - )) - } - } - } - } - } - if x.ValueAnnotation != nil { - if x.ValueAnnotation.AuthorReference != nil { - if x.ValueAnnotation.AuthorReference.Reference != nil { - refVal := *x.ValueAnnotation.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "valueAnnotation_authorReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - if x.ValueAnnotation != nil { - if x.ValueAnnotation.AuthorReference != nil { - if x.ValueAnnotation.AuthorReference.Reference != nil { - refVal := *x.ValueAnnotation.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "valueAnnotation_authorReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - if x.ValueAnnotation != nil { - if x.ValueAnnotation.AuthorReference != nil { - if x.ValueAnnotation.AuthorReference.Reference != nil { - refVal := *x.ValueAnnotation.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "valueAnnotation_authorReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - if x.ValueAnnotation != nil { - if x.ValueAnnotation.AuthorReference != nil { - if x.ValueAnnotation.AuthorReference.Reference != nil { - refVal := *x.ValueAnnotation.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "valueAnnotation_authorReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "valueCodeableReference_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "valueCodeableReference_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "valueCodeableReference_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "valueCodeableReference_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "valueCodeableReference_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "valueCodeableReference_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "valueCodeableReference_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "valueCodeableReference_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "valueCodeableReference_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "valueCodeableReference_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "valueCodeableReference_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "valueCodeableReference_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "valueCodeableReference_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "valueCodeableReference_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "valueCodeableReference_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "valueCodeableReference_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "valueCodeableReference_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "valueCodeableReference_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "valueCodeableReference_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "valueCodeableReference_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "valueCodeableReference_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "valueCodeableReference_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "valueCodeableReference_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueDataRequirement != nil { - if x.ValueDataRequirement.SubjectReference != nil { - if x.ValueDataRequirement.SubjectReference.Reference != nil { - refVal := *x.ValueDataRequirement.SubjectReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "valueDataRequirement_subjectReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("subjectReference", targetID), - "valueDataRequirement_subjectReference", - projectJSON, - sourceType, - "subjectReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "data_requirement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("requirement", id), - "data_requirement", - projectJSON, - sourceType, - "requirement", - )) - } - } - } - } - } - } - if x.ValueExtendedContactDetail != nil { - if x.ValueExtendedContactDetail.Organization != nil { - if x.ValueExtendedContactDetail.Organization.Reference != nil { - refVal := *x.ValueExtendedContactDetail.Organization.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueExtendedContactDetail_organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("organization", targetID), - "valueExtendedContactDetail_organization", - projectJSON, - sourceType, - "organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extended_contact_detail") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("detail", id), - "extended_contact_detail", - projectJSON, - sourceType, - "detail", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "valueRelatedArtifact_resourceReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "valueRelatedArtifact_resourceReference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "valueRelatedArtifact_resourceReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "valueRelatedArtifact_resourceReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "valueRelatedArtifact_resourceReference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "valueRelatedArtifact_resourceReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "valueRelatedArtifact_resourceReference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "valueRelatedArtifact_resourceReference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "valueRelatedArtifact_resourceReference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "valueRelatedArtifact_resourceReference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "valueRelatedArtifact_resourceReference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "valueRelatedArtifact_resourceReference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "valueRelatedArtifact_resourceReference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "valueRelatedArtifact_resourceReference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "valueRelatedArtifact_resourceReference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "valueRelatedArtifact_resourceReference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "valueRelatedArtifact_resourceReference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "valueRelatedArtifact_resourceReference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "valueRelatedArtifact_resourceReference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "valueRelatedArtifact_resourceReference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "valueRelatedArtifact_resourceReference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "valueRelatedArtifact_resourceReference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "valueRelatedArtifact_resourceReference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.OnBehalfOf != nil { - if x.ValueSignature.OnBehalfOf.Reference != nil { - refVal := *x.ValueSignature.OnBehalfOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "valueSignature_onBehalfOf_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "onBehalfOf_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.OnBehalfOf != nil { - if x.ValueSignature.OnBehalfOf.Reference != nil { - refVal := *x.ValueSignature.OnBehalfOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "valueSignature_onBehalfOf_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "onBehalfOf_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.OnBehalfOf != nil { - if x.ValueSignature.OnBehalfOf.Reference != nil { - refVal := *x.ValueSignature.OnBehalfOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "valueSignature_onBehalfOf_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "onBehalfOf_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.OnBehalfOf != nil { - if x.ValueSignature.OnBehalfOf.Reference != nil { - refVal := *x.ValueSignature.OnBehalfOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "valueSignature_onBehalfOf_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "onBehalfOf_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.Who != nil { - if x.ValueSignature.Who.Reference != nil { - refVal := *x.ValueSignature.Who.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "valueSignature_who_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "who_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "who_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.Who != nil { - if x.ValueSignature.Who.Reference != nil { - refVal := *x.ValueSignature.Who.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "valueSignature_who_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "who_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "who_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.Who != nil { - if x.ValueSignature.Who.Reference != nil { - refVal := *x.ValueSignature.Who.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "valueSignature_who_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "who_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "who_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.Who != nil { - if x.ValueSignature.Who.Reference != nil { - refVal := *x.ValueSignature.Who.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "valueSignature_who_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "who_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "who_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueUsageContext != nil { - if x.ValueUsageContext.ValueReference != nil { - if x.ValueUsageContext.ValueReference.Reference != nil { - refVal := *x.ValueUsageContext.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueUsageContext_valueReference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "valueUsageContext_valueReference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "usage_context") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("context", id), - "usage_context", - projectJSON, - sourceType, - "context", - )) - } - } - } - } - } - } - if x.ValueUsageContext != nil { - if x.ValueUsageContext.ValueReference != nil { - if x.ValueUsageContext.ValueReference.Reference != nil { - refVal := *x.ValueUsageContext.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "valueUsageContext_valueReference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "valueUsageContext_valueReference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "usage_context") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("context", id), - "usage_context", - projectJSON, - sourceType, - "context", - )) - } - } - } - } - } - } - if x.ValueUsageContext != nil { - if x.ValueUsageContext.ValueReference != nil { - if x.ValueUsageContext.ValueReference.Reference != nil { - refVal := *x.ValueUsageContext.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueUsageContext_valueReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "valueUsageContext_valueReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "usage_context") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("context", id), - "usage_context", - projectJSON, - sourceType, - "context", - )) - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from TaskOutput. -func (x *TaskOutput) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "TaskOutput" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "valueReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "valueReference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "valueReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "valueReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "valueReference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "valueReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "valueReference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "valueReference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "valueReference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "valueReference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "valueReference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "valueReference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "valueReference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "valueReference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "valueReference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "valueReference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "valueReference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "valueReference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "valueReference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "valueReference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "valueReference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "valueReference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "valueReference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_output") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("output", id), - "task_output", - projectJSON, - sourceType, - "output", - )) - } - } - } - } - } - if x.ValueAnnotation != nil { - if x.ValueAnnotation.AuthorReference != nil { - if x.ValueAnnotation.AuthorReference.Reference != nil { - refVal := *x.ValueAnnotation.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "valueAnnotation_authorReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - if x.ValueAnnotation != nil { - if x.ValueAnnotation.AuthorReference != nil { - if x.ValueAnnotation.AuthorReference.Reference != nil { - refVal := *x.ValueAnnotation.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "valueAnnotation_authorReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - if x.ValueAnnotation != nil { - if x.ValueAnnotation.AuthorReference != nil { - if x.ValueAnnotation.AuthorReference.Reference != nil { - refVal := *x.ValueAnnotation.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "valueAnnotation_authorReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - if x.ValueAnnotation != nil { - if x.ValueAnnotation.AuthorReference != nil { - if x.ValueAnnotation.AuthorReference.Reference != nil { - refVal := *x.ValueAnnotation.AuthorReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "valueAnnotation_authorReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "annotation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("annotation", id), - "annotation", - projectJSON, - sourceType, - "annotation", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "valueCodeableReference_reference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "valueCodeableReference_reference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "valueCodeableReference_reference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "valueCodeableReference_reference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "valueCodeableReference_reference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "valueCodeableReference_reference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "valueCodeableReference_reference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "valueCodeableReference_reference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "valueCodeableReference_reference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "valueCodeableReference_reference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "valueCodeableReference_reference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "valueCodeableReference_reference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "valueCodeableReference_reference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "valueCodeableReference_reference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "valueCodeableReference_reference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "valueCodeableReference_reference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "valueCodeableReference_reference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "valueCodeableReference_reference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "valueCodeableReference_reference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "valueCodeableReference_reference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "valueCodeableReference_reference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "valueCodeableReference_reference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueCodeableReference != nil { - if x.ValueCodeableReference.Reference != nil { - if x.ValueCodeableReference.Reference.Reference != nil { - refVal := *x.ValueCodeableReference.Reference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "valueCodeableReference_reference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "codeable_reference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("reference", id), - "codeable_reference", - projectJSON, - sourceType, - "reference", - )) - } - } - } - } - } - } - if x.ValueDataRequirement != nil { - if x.ValueDataRequirement.SubjectReference != nil { - if x.ValueDataRequirement.SubjectReference.Reference != nil { - refVal := *x.ValueDataRequirement.SubjectReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "valueDataRequirement_subjectReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("subjectReference", targetID), - "valueDataRequirement_subjectReference", - projectJSON, - sourceType, - "subjectReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "data_requirement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("requirement", id), - "data_requirement", - projectJSON, - sourceType, - "requirement", - )) - } - } - } - } - } - } - if x.ValueExtendedContactDetail != nil { - if x.ValueExtendedContactDetail.Organization != nil { - if x.ValueExtendedContactDetail.Organization.Reference != nil { - refVal := *x.ValueExtendedContactDetail.Organization.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueExtendedContactDetail_organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("organization", targetID), - "valueExtendedContactDetail_organization", - projectJSON, - sourceType, - "organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "extended_contact_detail") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("detail", id), - "extended_contact_detail", - projectJSON, - sourceType, - "detail", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "valueRelatedArtifact_resourceReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "valueRelatedArtifact_resourceReference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "valueRelatedArtifact_resourceReference_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "valueRelatedArtifact_resourceReference_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "valueRelatedArtifact_resourceReference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "valueRelatedArtifact_resourceReference_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchSubject" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_ResearchSubject") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchSubject", targetID), - "valueRelatedArtifact_resourceReference_ResearchSubject", - projectJSON, - sourceType, - "ResearchSubject", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Substance" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Substance") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Substance", targetID), - "valueRelatedArtifact_resourceReference_Substance", - projectJSON, - sourceType, - "Substance", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "SubstanceDefinition" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_SubstanceDefinition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("SubstanceDefinition", targetID), - "valueRelatedArtifact_resourceReference_SubstanceDefinition", - projectJSON, - sourceType, - "SubstanceDefinition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Specimen" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Specimen") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Specimen", targetID), - "valueRelatedArtifact_resourceReference_Specimen", - projectJSON, - sourceType, - "Specimen", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Observation" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Observation") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Observation", targetID), - "valueRelatedArtifact_resourceReference_Observation", - projectJSON, - sourceType, - "Observation", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DiagnosticReport" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_DiagnosticReport") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DiagnosticReport", targetID), - "valueRelatedArtifact_resourceReference_DiagnosticReport", - projectJSON, - sourceType, - "DiagnosticReport", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Condition" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Condition") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Condition", targetID), - "valueRelatedArtifact_resourceReference_Condition", - projectJSON, - sourceType, - "Condition", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Medication" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Medication") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Medication", targetID), - "valueRelatedArtifact_resourceReference_Medication", - projectJSON, - sourceType, - "Medication", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationAdministration" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_MedicationAdministration") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationAdministration", targetID), - "valueRelatedArtifact_resourceReference_MedicationAdministration", - projectJSON, - sourceType, - "MedicationAdministration", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationStatement" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_MedicationStatement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationStatement", targetID), - "valueRelatedArtifact_resourceReference_MedicationStatement", - projectJSON, - sourceType, - "MedicationStatement", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "MedicationRequest" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_MedicationRequest") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("MedicationRequest", targetID), - "valueRelatedArtifact_resourceReference_MedicationRequest", - projectJSON, - sourceType, - "MedicationRequest", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Procedure" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Procedure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Procedure", targetID), - "valueRelatedArtifact_resourceReference_Procedure", - projectJSON, - sourceType, - "Procedure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "DocumentReference" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_DocumentReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("DocumentReference", targetID), - "valueRelatedArtifact_resourceReference_DocumentReference", - projectJSON, - sourceType, - "DocumentReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Task" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Task") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Task", targetID), - "valueRelatedArtifact_resourceReference_Task", - projectJSON, - sourceType, - "Task", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ImagingStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_ImagingStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ImagingStudy", targetID), - "valueRelatedArtifact_resourceReference_ImagingStudy", - projectJSON, - sourceType, - "ImagingStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "FamilyMemberHistory" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_FamilyMemberHistory") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("FamilyMemberHistory", targetID), - "valueRelatedArtifact_resourceReference_FamilyMemberHistory", - projectJSON, - sourceType, - "FamilyMemberHistory", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueRelatedArtifact != nil { - if x.ValueRelatedArtifact.ResourceReference != nil { - if x.ValueRelatedArtifact.ResourceReference.Reference != nil { - refVal := *x.ValueRelatedArtifact.ResourceReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "BodyStructure" { - forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_BodyStructure") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("BodyStructure", targetID), - "valueRelatedArtifact_resourceReference_BodyStructure", - projectJSON, - sourceType, - "BodyStructure", - )) - } - backrefKey := getEdgeUUID(id, targetID, "related_artifact") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("artifact", id), - "related_artifact", - projectJSON, - sourceType, - "artifact", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.OnBehalfOf != nil { - if x.ValueSignature.OnBehalfOf.Reference != nil { - refVal := *x.ValueSignature.OnBehalfOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "valueSignature_onBehalfOf_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "onBehalfOf_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.OnBehalfOf != nil { - if x.ValueSignature.OnBehalfOf.Reference != nil { - refVal := *x.ValueSignature.OnBehalfOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "valueSignature_onBehalfOf_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "onBehalfOf_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.OnBehalfOf != nil { - if x.ValueSignature.OnBehalfOf.Reference != nil { - refVal := *x.ValueSignature.OnBehalfOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "valueSignature_onBehalfOf_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "onBehalfOf_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.OnBehalfOf != nil { - if x.ValueSignature.OnBehalfOf.Reference != nil { - refVal := *x.ValueSignature.OnBehalfOf.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "valueSignature_onBehalfOf_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "onBehalfOf_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.Who != nil { - if x.ValueSignature.Who.Reference != nil { - refVal := *x.ValueSignature.Who.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "valueSignature_who_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "who_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "who_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.Who != nil { - if x.ValueSignature.Who.Reference != nil { - refVal := *x.ValueSignature.Who.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "valueSignature_who_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "who_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "who_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.Who != nil { - if x.ValueSignature.Who.Reference != nil { - refVal := *x.ValueSignature.Who.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "valueSignature_who_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "who_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "who_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueSignature != nil { - if x.ValueSignature.Who != nil { - if x.ValueSignature.Who.Reference != nil { - refVal := *x.ValueSignature.Who.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "valueSignature_who_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "who_signature") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("signature", id), - "who_signature", - projectJSON, - sourceType, - "signature", - )) - } - } - } - } - } - } - if x.ValueUsageContext != nil { - if x.ValueUsageContext.ValueReference != nil { - if x.ValueUsageContext.ValueReference.Reference != nil { - refVal := *x.ValueUsageContext.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueUsageContext_valueReference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "valueUsageContext_valueReference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "usage_context") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("context", id), - "usage_context", - projectJSON, - sourceType, - "context", - )) - } - } - } - } - } - } - if x.ValueUsageContext != nil { - if x.ValueUsageContext.ValueReference != nil { - if x.ValueUsageContext.ValueReference.Reference != nil { - refVal := *x.ValueUsageContext.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "valueUsageContext_valueReference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "valueUsageContext_valueReference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "usage_context") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("context", id), - "usage_context", - projectJSON, - sourceType, - "context", - )) - } - } - } - } - } - } - if x.ValueUsageContext != nil { - if x.ValueUsageContext.ValueReference != nil { - if x.ValueUsageContext.ValueReference.Reference != nil { - refVal := *x.ValueUsageContext.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueUsageContext_valueReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "valueUsageContext_valueReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "usage_context") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("context", id), - "usage_context", - projectJSON, - sourceType, - "context", - )) - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from TaskPerformer. -func (x *TaskPerformer) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "TaskPerformer" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Actor != nil { - if x.Actor.Reference != nil { - refVal := *x.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "actor_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "actor_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "task_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - refVal := *x.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "actor_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "actor_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "task_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - refVal := *x.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "actor_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "actor_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "task_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - if x.Actor != nil { - if x.Actor.Reference != nil { - refVal := *x.Actor.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "actor_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "actor_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "task_performer") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("performer", id), - "task_performer", - projectJSON, - sourceType, - "performer", - )) - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from TaskRestriction. -func (x *TaskRestriction) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "TaskRestriction" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Recipient != nil { - for _, item_2_x_Recipient := range x.Recipient { - if item_2_x_Recipient != nil { - if item_2_x_Recipient.Reference != nil { - refVal := *item_2_x_Recipient.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Patient" { - forwardKey := getEdgeUUID(targetID, id, "recipient_Patient") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Patient", targetID), - "recipient_Patient", - projectJSON, - sourceType, - "Patient", - )) - } - backrefKey := getEdgeUUID(id, targetID, "recipient_task_restriction") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("restriction", id), - "recipient_task_restriction", - projectJSON, - sourceType, - "restriction", - )) - } - } - } - } - } - } - } - if x.Recipient != nil { - for _, item_2_x_Recipient := range x.Recipient { - if item_2_x_Recipient != nil { - if item_2_x_Recipient.Reference != nil { - refVal := *item_2_x_Recipient.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Practitioner" { - forwardKey := getEdgeUUID(targetID, id, "recipient_Practitioner") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Practitioner", targetID), - "recipient_Practitioner", - projectJSON, - sourceType, - "Practitioner", - )) - } - backrefKey := getEdgeUUID(id, targetID, "recipient_task_restriction") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("restriction", id), - "recipient_task_restriction", - projectJSON, - sourceType, - "restriction", - )) - } - } - } - } - } - } - } - if x.Recipient != nil { - for _, item_2_x_Recipient := range x.Recipient { - if item_2_x_Recipient != nil { - if item_2_x_Recipient.Reference != nil { - refVal := *item_2_x_Recipient.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "PractitionerRole" { - forwardKey := getEdgeUUID(targetID, id, "recipient_PractitionerRole") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("PractitionerRole", targetID), - "recipient_PractitionerRole", - projectJSON, - sourceType, - "PractitionerRole", - )) - } - backrefKey := getEdgeUUID(id, targetID, "recipient_task_restriction") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("restriction", id), - "recipient_task_restriction", - projectJSON, - sourceType, - "restriction", - )) - } - } - } - } - } - } - } - if x.Recipient != nil { - for _, item_2_x_Recipient := range x.Recipient { - if item_2_x_Recipient != nil { - if item_2_x_Recipient.Reference != nil { - refVal := *item_2_x_Recipient.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "recipient_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "recipient_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "recipient_task_restriction") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("restriction", id), - "recipient_task_restriction", - projectJSON, - sourceType, - "restriction", - )) - } - } - } - } - } - } - } - if x.Recipient != nil { - for _, item_2_x_Recipient := range x.Recipient { - if item_2_x_Recipient != nil { - if item_2_x_Recipient.Reference != nil { - refVal := *item_2_x_Recipient.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "recipient_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "recipient_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "recipient_task_restriction") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("restriction", id), - "recipient_task_restriction", - projectJSON, - sourceType, - "restriction", - )) - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from Timing. -func (x *Timing) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "Timing" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from TimingRepeat. -func (x *TimingRepeat) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "TimingRepeat" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - return edges, nil -} - -// ExtractEdges extracts graph links from TriggerDefinition. -func (x *TriggerDefinition) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "TriggerDefinition" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.Data != nil { - for _, item_3_x_Data := range x.Data { - if item_3_x_Data != nil { - if item_3_x_Data.SubjectReference != nil { - if item_3_x_Data.SubjectReference.Reference != nil { - refVal := *item_3_x_Data.SubjectReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "data_subjectReference") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("subjectReference", targetID), - "data_subjectReference", - projectJSON, - sourceType, - "subjectReference", - )) - } - backrefKey := getEdgeUUID(id, targetID, "data_requirement") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("requirement", id), - "data_requirement", - projectJSON, - sourceType, - "requirement", - )) - } - } - } - } - } - } - } - } - return edges, nil -} - -// ExtractEdges extracts graph links from UsageContext. -func (x *UsageContext) ExtractEdges(project string) ([]json.RawMessage, error) { - var edges []json.RawMessage - if x == nil || x.ID == nil { - return edges, nil - } - id := *x.ID - sourceType := "UsageContext" - projectJSON := strconv.Quote(project) - _ = id - _ = sourceType - _ = projectJSON - var seen map[string]struct{} - _ = seen - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "ResearchStudy" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_ResearchStudy") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("ResearchStudy", targetID), - "valueReference_ResearchStudy", - projectJSON, - sourceType, - "ResearchStudy", - )) - } - backrefKey := getEdgeUUID(id, targetID, "usage_context") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("context", id), - "usage_context", - projectJSON, - sourceType, - "context", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Group" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Group") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Group", targetID), - "valueReference_Group", - projectJSON, - sourceType, - "Group", - )) - } - backrefKey := getEdgeUUID(id, targetID, "usage_context") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("context", id), - "usage_context", - projectJSON, - sourceType, - "context", - )) - } - } - } - } - } - if x.ValueReference != nil { - if x.ValueReference.Reference != nil { - refVal := *x.ValueReference.Reference - refType, targetID, ok := splitFHIRReference(refVal) - if ok { - if refType == "Organization" { - forwardKey := getEdgeUUID(targetID, id, "valueReference_Organization") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[forwardKey]; !exists { - seen[forwardKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - forwardKey, - collectionID(sourceType, id), - collectionID("Organization", targetID), - "valueReference_Organization", - projectJSON, - sourceType, - "Organization", - )) - } - backrefKey := getEdgeUUID(id, targetID, "usage_context") - if seen == nil { - seen = make(map[string]struct{}, 4) - } - if _, exists := seen[backrefKey]; !exists { - seen[backrefKey] = struct{}{} - edges = append(edges, buildEdgeRawJSON( - backrefKey, - collectionID(sourceType, targetID), - collectionID("context", id), - "usage_context", - projectJSON, - sourceType, - "context", - )) - } - } - } - } - } - return edges, nil -} - -// ValidateAndExtract parses, validates, and extracts edges for a FHIR resource. -func ValidateAndExtract(raw []byte, resourceType string, project string) (Result, error) { - switch resourceType { - case "Address": - var val Address - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Age": - var val Age - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Annotation": - var val Annotation - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Attachment": - var val Attachment - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Availability": - var val Availability - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "AvailabilityAvailableTime": - var val AvailabilityAvailableTime - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "AvailabilityNotAvailableTime": - var val AvailabilityNotAvailableTime - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "BodyStructure": - var val BodyStructure - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "BodyStructureIncludedStructure": - var val BodyStructureIncludedStructure - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "BodyStructureIncludedStructureBodyLandmarkOrientation": - var val BodyStructureIncludedStructureBodyLandmarkOrientation - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": - var val BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "CodeableConcept": - var val CodeableConcept - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "CodeableReference": - var val CodeableReference - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Coding": - var val Coding - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Condition": - var val Condition - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ConditionParticipant": - var val ConditionParticipant - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ConditionStage": - var val ConditionStage - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ContactDetail": - var val ContactDetail - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ContactPoint": - var val ContactPoint - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Count": - var val Count - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "DataRequirement": - var val DataRequirement - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "DataRequirementCodeFilter": - var val DataRequirementCodeFilter - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "DataRequirementDateFilter": - var val DataRequirementDateFilter - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "DataRequirementSort": - var val DataRequirementSort - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "DataRequirementValueFilter": - var val DataRequirementValueFilter - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "DiagnosticReport": - var val DiagnosticReport - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "DiagnosticReportMedia": - var val DiagnosticReportMedia - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "DiagnosticReportSupportingInfo": - var val DiagnosticReportSupportingInfo - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Directory": - var val Directory - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Distance": - var val Distance - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "DocumentReference": - var val DocumentReference - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "DocumentReferenceAttester": - var val DocumentReferenceAttester - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "DocumentReferenceContent": - var val DocumentReferenceContent - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "DocumentReferenceContentProfile": - var val DocumentReferenceContentProfile - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "DocumentReferenceRelatesTo": - var val DocumentReferenceRelatesTo - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Dosage": - var val Dosage - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "DosageDoseAndRate": - var val DosageDoseAndRate - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Duration": - var val Duration - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Expression": - var val Expression - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ExtendedContactDetail": - var val ExtendedContactDetail - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Extension": - var val Extension - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "FHIRPrimitiveExtension": - var val FHIRPrimitiveExtension - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "FamilyMemberHistory": - var val FamilyMemberHistory - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "FamilyMemberHistoryCondition": - var val FamilyMemberHistoryCondition - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "FamilyMemberHistoryParticipant": - var val FamilyMemberHistoryParticipant - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "FamilyMemberHistoryProcedure": - var val FamilyMemberHistoryProcedure - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Group": - var val Group - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "GroupCharacteristic": - var val GroupCharacteristic - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "GroupMember": - var val GroupMember - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "HumanName": - var val HumanName - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Identifier": - var val Identifier - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ImagingStudy": - var val ImagingStudy - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ImagingStudySeries": - var val ImagingStudySeries - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ImagingStudySeriesInstance": - var val ImagingStudySeriesInstance - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ImagingStudySeriesPerformer": - var val ImagingStudySeriesPerformer - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Medication": - var val Medication - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "MedicationAdministration": - var val MedicationAdministration - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "MedicationAdministrationDosage": - var val MedicationAdministrationDosage - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "MedicationAdministrationPerformer": - var val MedicationAdministrationPerformer - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "MedicationBatch": - var val MedicationBatch - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "MedicationIngredient": - var val MedicationIngredient - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "MedicationRequest": - var val MedicationRequest - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "MedicationRequestDispenseRequest": - var val MedicationRequestDispenseRequest - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "MedicationRequestDispenseRequestInitialFill": - var val MedicationRequestDispenseRequestInitialFill - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "MedicationRequestSubstitution": - var val MedicationRequestSubstitution - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "MedicationStatement": - var val MedicationStatement - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "MedicationStatementAdherence": - var val MedicationStatementAdherence - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Meta": - var val Meta - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Money": - var val Money - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Narrative": - var val Narrative - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Observation": - var val Observation - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ObservationComponent": - var val ObservationComponent - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ObservationReferenceRange": - var val ObservationReferenceRange - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ObservationTriggeredBy": - var val ObservationTriggeredBy - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Organization": - var val Organization - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "OrganizationQualification": - var val OrganizationQualification - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ParameterDefinition": - var val ParameterDefinition - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Patient": - var val Patient - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "PatientCommunication": - var val PatientCommunication - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "PatientContact": - var val PatientContact - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "PatientLink": - var val PatientLink - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Period": - var val Period - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Practitioner": - var val Practitioner - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "PractitionerCommunication": - var val PractitionerCommunication - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "PractitionerQualification": - var val PractitionerQualification - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "PractitionerRole": - var val PractitionerRole - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Procedure": - var val Procedure - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ProcedureFocalDevice": - var val ProcedureFocalDevice - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ProcedurePerformer": - var val ProcedurePerformer - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Quantity": - var val Quantity - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Range": - var val Range - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Ratio": - var val Ratio - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "RatioRange": - var val RatioRange - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Reference": - var val Reference - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "RelatedArtifact": - var val RelatedArtifact - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ResearchStudy": - var val ResearchStudy - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ResearchStudyAssociatedParty": - var val ResearchStudyAssociatedParty - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ResearchStudyComparisonGroup": - var val ResearchStudyComparisonGroup - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ResearchStudyLabel": - var val ResearchStudyLabel - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ResearchStudyObjective": - var val ResearchStudyObjective - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ResearchStudyOutcomeMeasure": - var val ResearchStudyOutcomeMeasure - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ResearchStudyProgressStatus": - var val ResearchStudyProgressStatus - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ResearchStudyRecruitment": - var val ResearchStudyRecruitment - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ResearchSubject": - var val ResearchSubject - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "ResearchSubjectProgress": - var val ResearchSubjectProgress - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Resource": - var val Resource - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "SampledData": - var val SampledData - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Signature": - var val Signature - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Specimen": - var val Specimen - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "SpecimenCollection": - var val SpecimenCollection - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "SpecimenContainer": - var val SpecimenContainer - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "SpecimenFeature": - var val SpecimenFeature - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "SpecimenProcessing": - var val SpecimenProcessing - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Substance": - var val Substance - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "SubstanceDefinition": - var val SubstanceDefinition - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "SubstanceDefinitionCharacterization": - var val SubstanceDefinitionCharacterization - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "SubstanceDefinitionCode": - var val SubstanceDefinitionCode - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "SubstanceDefinitionMoiety": - var val SubstanceDefinitionMoiety - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "SubstanceDefinitionMolecularWeight": - var val SubstanceDefinitionMolecularWeight - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "SubstanceDefinitionName": - var val SubstanceDefinitionName - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "SubstanceDefinitionNameOfficial": - var val SubstanceDefinitionNameOfficial - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "SubstanceDefinitionProperty": - var val SubstanceDefinitionProperty - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "SubstanceDefinitionRelationship": - var val SubstanceDefinitionRelationship - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "SubstanceDefinitionSourceMaterial": - var val SubstanceDefinitionSourceMaterial - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "SubstanceDefinitionStructure": - var val SubstanceDefinitionStructure - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "SubstanceDefinitionStructureRepresentation": - var val SubstanceDefinitionStructureRepresentation - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "SubstanceIngredient": - var val SubstanceIngredient - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Task": - var val Task - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "TaskInput": - var val TaskInput - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "TaskOutput": - var val TaskOutput - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "TaskPerformer": - var val TaskPerformer - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "TaskRestriction": - var val TaskRestriction - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "Timing": - var val Timing - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "TimingRepeat": - var val TimingRepeat - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "TriggerDefinition": - var val TriggerDefinition - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - case "UsageContext": - var val UsageContext - if err := sonic.Unmarshal(raw, &val); err != nil { - return Result{}, fmt.Errorf("decode error: %w", err) - } - if err := val.Validate(); err != nil { - return Result{}, fmt.Errorf("validation error: %w", err) - } - edges, err := val.ExtractEdges(project) - if err != nil { - return Result{}, fmt.Errorf("extraction error: %w", err) - } - var objectID string - if val.ID != nil { - objectID = *val.ID - } - return Result{ - ObjectID: objectID, - ResourceType: resourceType, - Vertex: json.RawMessage(raw), - Edges: edges, - }, nil - default: - return Result{}, fmt.Errorf("unsupported resource type %s", resourceType) - } -} diff --git a/internal/fhir/helpers.go b/internal/fhir/helpers.go deleted file mode 100644 index f1de27e..0000000 --- a/internal/fhir/helpers.go +++ /dev/null @@ -1,140 +0,0 @@ -package fhir - -import ( - "encoding/base64" - "encoding/json" - "fmt" - "net/url" - "strings" - "time" - - "github.com/google/uuid" -) - -// FHIRComments handles comments that can be a single JSON string or a JSON array of strings. -type FHIRComments []string - -// UnmarshalJSON unmarshals FHIR comments from a string or array of strings. -func (c *FHIRComments) UnmarshalJSON(data []byte) error { - if len(data) == 0 { - return nil - } - if data[0] == '"' { - var s string - if err := json.Unmarshal(data, &s); err != nil { - return err - } - *c = []string{s} - return nil - } - var arr []string - if err := json.Unmarshal(data, &arr); err != nil { - return err - } - *c = arr - return nil -} - -// MarshalJSON marshals FHIR comments to a single string (if length is 1) or an array of strings. -func (c FHIRComments) MarshalJSON() ([]byte, error) { - if len(c) == 1 { - return json.Marshal(c[0]) - } - return json.Marshal([]string(c)) -} - -// ValidateFhirDateTime checks a string against FHIR date-time rules (YYYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm] or partial date). -func ValidateFhirDateTime(s string) error { - if !strings.Contains(s, "T") { - return validatePartialFhirDate(s, "FHIR date-time") - } - if _, err := time.Parse(time.RFC3339Nano, s); err != nil { - return fmt.Errorf("value '%s' is not a valid FHIR date-time: %w", s, err) - } - return nil -} - -func validatePartialFhirDate(s, typeName string) error { - switch len(s) { - case 4: // YYYY - if _, err := time.Parse("2006", s); err != nil { - return fmt.Errorf("value '%s' is not a valid partial %s (YYYY): %w", s, typeName, err) - } - case 7: // YYYY-MM - if _, err := time.Parse("2006-01", s); err != nil { - return fmt.Errorf("value '%s' is not a valid partial %s (YYYY-MM): %w", s, typeName, err) - } - case 10: // YYYY-MM-DD - if _, err := time.Parse("2006-01-02", s); err != nil { - return fmt.Errorf("value '%s' is not a valid partial %s (YYYY-MM-DD): %w", s, typeName, err) - } - default: - return fmt.Errorf("value '%s' has invalid length for a partial %s", s, typeName) - } - return nil -} - -// ValidateFhirDate checks a string against FHIR date rules (YYYY[-MM[-DD]]). -func ValidateFhirDate(s string) error { - return validatePartialFhirDate(s, "FHIR date") -} - -// ValidateFhirTime checks a string against FHIR time rules (HH:MM:SS[.SSSS]). -func ValidateFhirTime(s string) error { - if len(s) < 8 { - return fmt.Errorf("value '%s' is too short for a FHIR time (minimum 8 characters)", s) - } - - timePart := s - if s[8] == '.' { - timePart = s[:8] - if len(s) == 9 { - return fmt.Errorf("value '%s' is not a valid FHIR time: missing fractional second digits after '.'", s) - } - for i := 9; i < len(s); i++ { - if s[i] < '0' || s[i] > '9' { - return fmt.Errorf("value '%s' is not a valid FHIR time: non-digit characters in fractional seconds", s) - } - } - } else if len(s) != 8 { - return fmt.Errorf("value '%s' has invalid length for FHIR time (expected 8 or 9+ with fractional seconds)", s) - } - - if timePart[2] != ':' || timePart[5] != ':' { - return fmt.Errorf("value '%s' is not a valid FHIR time: missing or misplaced colons", s) - } - - if _, err := time.Parse("15:04:05", timePart); err != nil { - return fmt.Errorf("value '%s' is not a valid FHIR time: invalid time components (%w)", s, err) - } - - return nil -} - -// ValidateFhirURI checks a string against FHIR URI rules (must be an absolute URI). -func ValidateFhirURI(s string) error { - u, err := url.ParseRequestURI(s) - if err != nil { - return fmt.Errorf("value '%s' is not a valid URI: %w", s, err) - } - if !u.IsAbs() { - return fmt.Errorf("value '%s' is not an absolute URI (must include a scheme like 'http://' or 'urn:')", s) - } - return nil -} - -// ValidateFhirUUID checks a string against FHIR UUID rules (RFC 4122). -func ValidateFhirUUID(s string) error { - if _, err := uuid.Parse(s); err != nil { - return fmt.Errorf("value '%s' is not a valid UUID (RFC 4122): %w", s, err) - } - return nil -} - -// ValidateFhirBinary checks that a string is a valid base64-encoded value. -func ValidateFhirBinary(s string) error { - if _, err := base64.StdEncoding.DecodeString(s); err != nil { - return fmt.Errorf("value is not a valid Base64 encoded string: %w", err) - } - return nil -} diff --git a/internal/fhir/model.go b/internal/fhir/model.go deleted file mode 100644 index b8164ba..0000000 --- a/internal/fhir/model.go +++ /dev/null @@ -1,3044 +0,0 @@ -// Code generated by cmd/generate/main.go. DO NOT EDIT. -package fhir - -// Address -type Address struct { - XCity *FHIRPrimitiveExtension `json:"_city,omitempty"` - XCountry *FHIRPrimitiveExtension `json:"_country,omitempty"` - XDistrict *FHIRPrimitiveExtension `json:"_district,omitempty"` - XLine []*FHIRPrimitiveExtension `json:"_line,omitempty"` - XPostalCode *FHIRPrimitiveExtension `json:"_postalCode,omitempty"` - XState *FHIRPrimitiveExtension `json:"_state,omitempty"` - XText *FHIRPrimitiveExtension `json:"_text,omitempty"` - XType *FHIRPrimitiveExtension `json:"_type,omitempty"` - XUse *FHIRPrimitiveExtension `json:"_use,omitempty"` - City *string `json:"city,omitempty"` - Country *string `json:"country,omitempty"` - District *string `json:"district,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Line []string `json:"line,omitempty"` - Links [][]any `json:"links,omitempty"` - Period *Period `json:"period,omitempty"` - PostalCode *string `json:"postalCode,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - State *string `json:"state,omitempty"` - Text *string `json:"text,omitempty"` - Type *string `json:"type,omitempty"` - Use *string `json:"use,omitempty"` -} - -// Age -type Age struct { - XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` - XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` - XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` - XUnit *FHIRPrimitiveExtension `json:"_unit,omitempty"` - XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` - Code *string `json:"code,omitempty"` - Comparator *string `json:"comparator,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - System *string `json:"system,omitempty"` - Unit *string `json:"unit,omitempty"` - Value *float64 `json:"value,omitempty"` -} - -// Annotation -type Annotation struct { - XAuthorString *FHIRPrimitiveExtension `json:"_authorString,omitempty"` - XText *FHIRPrimitiveExtension `json:"_text,omitempty"` - XTime *FHIRPrimitiveExtension `json:"_time,omitempty"` - AuthorReference *Reference `json:"authorReference,omitempty"` - AuthorString *string `json:"authorString,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Text *string `json:"text,omitempty"` - Time *string `json:"time,omitempty"` -} - -// Attachment -type Attachment struct { - XContentType *FHIRPrimitiveExtension `json:"_contentType,omitempty"` - XCreation *FHIRPrimitiveExtension `json:"_creation,omitempty"` - XData *FHIRPrimitiveExtension `json:"_data,omitempty"` - XDuration *FHIRPrimitiveExtension `json:"_duration,omitempty"` - XFrames *FHIRPrimitiveExtension `json:"_frames,omitempty"` - XHash *FHIRPrimitiveExtension `json:"_hash,omitempty"` - XHeight *FHIRPrimitiveExtension `json:"_height,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XPages *FHIRPrimitiveExtension `json:"_pages,omitempty"` - XSize *FHIRPrimitiveExtension `json:"_size,omitempty"` - XTitle *FHIRPrimitiveExtension `json:"_title,omitempty"` - XURL *FHIRPrimitiveExtension `json:"_url,omitempty"` - XWidth *FHIRPrimitiveExtension `json:"_width,omitempty"` - ContentType *string `json:"contentType,omitempty"` - Creation *string `json:"creation,omitempty"` - Data *string `json:"data,omitempty"` - Duration *float64 `json:"duration,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Frames *int64 `json:"frames,omitempty"` - Hash *string `json:"hash,omitempty"` - Height *int64 `json:"height,omitempty"` - ID *string `json:"id,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Pages *int64 `json:"pages,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Size *int64 `json:"size,omitempty"` - Title *string `json:"title,omitempty"` - URL *string `json:"url,omitempty"` - Width *int64 `json:"width,omitempty"` -} - -// Availability -type Availability struct { - AvailableTime []*AvailabilityAvailableTime `json:"availableTime,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - NotAvailableTime []*AvailabilityNotAvailableTime `json:"notAvailableTime,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// AvailabilityAvailableTime -type AvailabilityAvailableTime struct { - XAllDay *FHIRPrimitiveExtension `json:"_allDay,omitempty"` - XAvailableEndTime *FHIRPrimitiveExtension `json:"_availableEndTime,omitempty"` - XAvailableStartTime *FHIRPrimitiveExtension `json:"_availableStartTime,omitempty"` - XDaysOfWeek []*FHIRPrimitiveExtension `json:"_daysOfWeek,omitempty"` - AllDay *bool `json:"allDay,omitempty"` - AvailableEndTime *string `json:"availableEndTime,omitempty"` - AvailableStartTime *string `json:"availableStartTime,omitempty"` - DaysOfWeek []string `json:"daysOfWeek,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// AvailabilityNotAvailableTime -type AvailabilityNotAvailableTime struct { - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - Description *string `json:"description,omitempty"` - During *Period `json:"during,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// BodyStructure -type BodyStructure struct { - XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - Active *bool `json:"active,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Description *string `json:"description,omitempty"` - ExcludedStructure []*BodyStructureIncludedStructure `json:"excludedStructure,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - Image []*Attachment `json:"image,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - IncludedStructure []*BodyStructureIncludedStructure `json:"includedStructure"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Morphology *CodeableConcept `json:"morphology,omitempty"` - Patient *Reference `json:"patient"` - ResourceType *string `json:"resourceType,omitempty"` - Text *Narrative `json:"text,omitempty"` -} - -// BodyStructureIncludedStructure -type BodyStructureIncludedStructure struct { - BodyLandmarkOrientation []*BodyStructureIncludedStructureBodyLandmarkOrientation `json:"bodyLandmarkOrientation,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Laterality *CodeableConcept `json:"laterality,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Qualifier []*CodeableConcept `json:"qualifier,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SpatialReference []*Reference `json:"spatialReference,omitempty"` - Structure *CodeableConcept `json:"structure"` -} - -// BodyStructureIncludedStructureBodyLandmarkOrientation -type BodyStructureIncludedStructureBodyLandmarkOrientation struct { - ClockFacePosition []*CodeableConcept `json:"clockFacePosition,omitempty"` - DistanceFromLandmark []*BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark `json:"distanceFromLandmark,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - LandmarkDescription []*CodeableConcept `json:"landmarkDescription,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SurfaceOrientation []*CodeableConcept `json:"surfaceOrientation,omitempty"` -} - -// BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark -type BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark struct { - Device []*CodeableReference `json:"device,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Value []*Quantity `json:"value,omitempty"` -} - -// CodeableConcept -type CodeableConcept struct { - XText *FHIRPrimitiveExtension `json:"_text,omitempty"` - Coding []*Coding `json:"coding,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Text *string `json:"text,omitempty"` -} - -// CodeableReference -type CodeableReference struct { - Concept *CodeableConcept `json:"concept,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Reference *Reference `json:"reference,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// Coding -type Coding struct { - XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` - XDisplay *FHIRPrimitiveExtension `json:"_display,omitempty"` - XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` - XUserSelected *FHIRPrimitiveExtension `json:"_userSelected,omitempty"` - XVersion *FHIRPrimitiveExtension `json:"_version,omitempty"` - Code *string `json:"code,omitempty"` - Display *string `json:"display,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - System *string `json:"system,omitempty"` - UserSelected *bool `json:"userSelected,omitempty"` - Version *string `json:"version,omitempty"` -} - -// Condition -type Condition struct { - XAbatementDateTime *FHIRPrimitiveExtension `json:"_abatementDateTime,omitempty"` - XAbatementString *FHIRPrimitiveExtension `json:"_abatementString,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XOnsetDateTime *FHIRPrimitiveExtension `json:"_onsetDateTime,omitempty"` - XOnsetString *FHIRPrimitiveExtension `json:"_onsetString,omitempty"` - XRecordedDate *FHIRPrimitiveExtension `json:"_recordedDate,omitempty"` - AbatementAge *Age `json:"abatementAge,omitempty"` - AbatementDateTime *string `json:"abatementDateTime,omitempty"` - AbatementPeriod *Period `json:"abatementPeriod,omitempty"` - AbatementRange *Range `json:"abatementRange,omitempty"` - AbatementString *string `json:"abatementString,omitempty"` - BodySite []*CodeableConcept `json:"bodySite,omitempty"` - Category []*CodeableConcept `json:"category,omitempty"` - ClinicalStatus *CodeableConcept `json:"clinicalStatus"` - Code *CodeableConcept `json:"code,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Encounter *Reference `json:"encounter,omitempty"` - Evidence []*CodeableReference `json:"evidence,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - OnsetAge *Age `json:"onsetAge,omitempty"` - OnsetDateTime *string `json:"onsetDateTime,omitempty"` - OnsetPeriod *Period `json:"onsetPeriod,omitempty"` - OnsetRange *Range `json:"onsetRange,omitempty"` - OnsetString *string `json:"onsetString,omitempty"` - Participant []*ConditionParticipant `json:"participant,omitempty"` - RecordedDate *string `json:"recordedDate,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Severity *CodeableConcept `json:"severity,omitempty"` - Stage []*ConditionStage `json:"stage,omitempty"` - Subject *Reference `json:"subject"` - Text *Narrative `json:"text,omitempty"` - VerificationStatus *CodeableConcept `json:"verificationStatus,omitempty"` -} - -// ConditionParticipant -type ConditionParticipant struct { - Actor *Reference `json:"actor"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Function *CodeableConcept `json:"function,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// ConditionStage -type ConditionStage struct { - Assessment []*Reference `json:"assessment,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Summary *CodeableConcept `json:"summary,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` -} - -// ContactDetail -type ContactDetail struct { - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Name *string `json:"name,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Telecom []*ContactPoint `json:"telecom,omitempty"` -} - -// ContactPoint -type ContactPoint struct { - XRank *FHIRPrimitiveExtension `json:"_rank,omitempty"` - XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` - XUse *FHIRPrimitiveExtension `json:"_use,omitempty"` - XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Period *Period `json:"period,omitempty"` - Rank *int64 `json:"rank,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - System *string `json:"system,omitempty"` - Use *string `json:"use,omitempty"` - Value *string `json:"value,omitempty"` -} - -// Count -type Count struct { - XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` - XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` - XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` - XUnit *FHIRPrimitiveExtension `json:"_unit,omitempty"` - XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` - Code *string `json:"code,omitempty"` - Comparator *string `json:"comparator,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - System *string `json:"system,omitempty"` - Unit *string `json:"unit,omitempty"` - Value *float64 `json:"value,omitempty"` -} - -// DataRequirement -type DataRequirement struct { - XLimit *FHIRPrimitiveExtension `json:"_limit,omitempty"` - XMustSupport []*FHIRPrimitiveExtension `json:"_mustSupport,omitempty"` - XProfile []*FHIRPrimitiveExtension `json:"_profile,omitempty"` - XType *FHIRPrimitiveExtension `json:"_type,omitempty"` - CodeFilter []*DataRequirementCodeFilter `json:"codeFilter,omitempty"` - DateFilter []*DataRequirementDateFilter `json:"dateFilter,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Limit *int64 `json:"limit,omitempty"` - Links [][]any `json:"links,omitempty"` - MustSupport []string `json:"mustSupport,omitempty"` - Profile []string `json:"profile,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Sort []*DataRequirementSort `json:"sort,omitempty"` - SubjectCodeableConcept *CodeableConcept `json:"subjectCodeableConcept,omitempty"` - SubjectReference *Reference `json:"subjectReference,omitempty"` - Type *string `json:"type,omitempty"` - ValueFilter []*DataRequirementValueFilter `json:"valueFilter,omitempty"` -} - -// DataRequirementCodeFilter -type DataRequirementCodeFilter struct { - XPath *FHIRPrimitiveExtension `json:"_path,omitempty"` - XSearchParam *FHIRPrimitiveExtension `json:"_searchParam,omitempty"` - XValueSet *FHIRPrimitiveExtension `json:"_valueSet,omitempty"` - Code []*Coding `json:"code,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Path *string `json:"path,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SearchParam *string `json:"searchParam,omitempty"` - ValueSet *string `json:"valueSet,omitempty"` -} - -// DataRequirementDateFilter -type DataRequirementDateFilter struct { - XPath *FHIRPrimitiveExtension `json:"_path,omitempty"` - XSearchParam *FHIRPrimitiveExtension `json:"_searchParam,omitempty"` - XValueDateTime *FHIRPrimitiveExtension `json:"_valueDateTime,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Path *string `json:"path,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SearchParam *string `json:"searchParam,omitempty"` - ValueDateTime *string `json:"valueDateTime,omitempty"` - ValueDuration *Duration `json:"valueDuration,omitempty"` - ValuePeriod *Period `json:"valuePeriod,omitempty"` -} - -// DataRequirementSort -type DataRequirementSort struct { - XDirection *FHIRPrimitiveExtension `json:"_direction,omitempty"` - XPath *FHIRPrimitiveExtension `json:"_path,omitempty"` - Direction *string `json:"direction,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Path *string `json:"path,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// DataRequirementValueFilter -type DataRequirementValueFilter struct { - XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` - XPath *FHIRPrimitiveExtension `json:"_path,omitempty"` - XSearchParam *FHIRPrimitiveExtension `json:"_searchParam,omitempty"` - XValueDateTime *FHIRPrimitiveExtension `json:"_valueDateTime,omitempty"` - Comparator *string `json:"comparator,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Path *string `json:"path,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SearchParam *string `json:"searchParam,omitempty"` - ValueDateTime *string `json:"valueDateTime,omitempty"` - ValueDuration *Duration `json:"valueDuration,omitempty"` - ValuePeriod *Period `json:"valuePeriod,omitempty"` -} - -// DiagnosticReport -type DiagnosticReport struct { - XConclusion *FHIRPrimitiveExtension `json:"_conclusion,omitempty"` - XEffectiveDateTime *FHIRPrimitiveExtension `json:"_effectiveDateTime,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XIssued *FHIRPrimitiveExtension `json:"_issued,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - BasedOn []*Reference `json:"basedOn,omitempty"` - Category []*CodeableConcept `json:"category,omitempty"` - Code *CodeableConcept `json:"code"` - Composition *Reference `json:"composition,omitempty"` - Conclusion *string `json:"conclusion,omitempty"` - ConclusionCode []*CodeableConcept `json:"conclusionCode,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - EffectiveDateTime *string `json:"effectiveDateTime,omitempty"` - EffectivePeriod *Period `json:"effectivePeriod,omitempty"` - Encounter *Reference `json:"encounter,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Issued *string `json:"issued,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Media []*DiagnosticReportMedia `json:"media,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - Performer []*Reference `json:"performer,omitempty"` - PresentedForm []*Attachment `json:"presentedForm,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Result []*Reference `json:"result,omitempty"` - ResultsInterpreter []*Reference `json:"resultsInterpreter,omitempty"` - Specimen []*Reference `json:"specimen,omitempty"` - Status *string `json:"status,omitempty"` - Study []*Reference `json:"study,omitempty"` - Subject *Reference `json:"subject,omitempty"` - SupportingInfo []*DiagnosticReportSupportingInfo `json:"supportingInfo,omitempty"` - Text *Narrative `json:"text,omitempty"` -} - -// DiagnosticReportMedia -type DiagnosticReportMedia struct { - XComment *FHIRPrimitiveExtension `json:"_comment,omitempty"` - Comment *string `json:"comment,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Link *Reference `json:"link"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// DiagnosticReportSupportingInfo -type DiagnosticReportSupportingInfo struct { - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Reference *Reference `json:"reference"` - ResourceType *string `json:"resourceType,omitempty"` - Type *CodeableConcept `json:"type"` -} - -// Directory -type Directory struct { - Child []*Reference `json:"child"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Name *string `json:"name"` - Path *string `json:"path,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// Distance -type Distance struct { - XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` - XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` - XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` - XUnit *FHIRPrimitiveExtension `json:"_unit,omitempty"` - XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` - Code *string `json:"code,omitempty"` - Comparator *string `json:"comparator,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - System *string `json:"system,omitempty"` - Unit *string `json:"unit,omitempty"` - Value *float64 `json:"value,omitempty"` -} - -// DocumentReference -type DocumentReference struct { - XDate *FHIRPrimitiveExtension `json:"_date,omitempty"` - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XDocStatus *FHIRPrimitiveExtension `json:"_docStatus,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - XVersion *FHIRPrimitiveExtension `json:"_version,omitempty"` - Attester []*DocumentReferenceAttester `json:"attester,omitempty"` - Author []*Reference `json:"author,omitempty"` - BasedOn []*Reference `json:"basedOn,omitempty"` - BodySite []*CodeableReference `json:"bodySite,omitempty"` - Category []*CodeableConcept `json:"category,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Content []*DocumentReferenceContent `json:"content"` - Context []*Reference `json:"context,omitempty"` - Custodian *Reference `json:"custodian,omitempty"` - Date *string `json:"date,omitempty"` - Description *string `json:"description,omitempty"` - DocStatus *string `json:"docStatus,omitempty"` - Event []*CodeableReference `json:"event,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FacilityType *CodeableConcept `json:"facilityType,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - Modality []*CodeableConcept `json:"modality,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Period *Period `json:"period,omitempty"` - PracticeSetting *CodeableConcept `json:"practiceSetting,omitempty"` - RelatesTo []*DocumentReferenceRelatesTo `json:"relatesTo,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SecurityLabel []*CodeableConcept `json:"securityLabel,omitempty"` - Status *string `json:"status,omitempty"` - Subject *Reference `json:"subject,omitempty"` - Text *Narrative `json:"text,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` - Version *string `json:"version,omitempty"` -} - -// DocumentReferenceAttester -type DocumentReferenceAttester struct { - XTime *FHIRPrimitiveExtension `json:"_time,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Mode *CodeableConcept `json:"mode"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Party *Reference `json:"party,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Time *string `json:"time,omitempty"` -} - -// DocumentReferenceContent -type DocumentReferenceContent struct { - Attachment *Attachment `json:"attachment"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Profile []*DocumentReferenceContentProfile `json:"profile,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// DocumentReferenceContentProfile -type DocumentReferenceContentProfile struct { - XValueCanonical *FHIRPrimitiveExtension `json:"_valueCanonical,omitempty"` - XValueURI *FHIRPrimitiveExtension `json:"_valueUri,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - ValueCanonical *string `json:"valueCanonical,omitempty"` - ValueCoding *Coding `json:"valueCoding,omitempty"` - ValueURI *string `json:"valueUri,omitempty"` -} - -// DocumentReferenceRelatesTo -type DocumentReferenceRelatesTo struct { - Code *CodeableConcept `json:"code"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Target *Reference `json:"target"` -} - -// Dosage -type Dosage struct { - XAsNeeded *FHIRPrimitiveExtension `json:"_asNeeded,omitempty"` - XPatientInstruction *FHIRPrimitiveExtension `json:"_patientInstruction,omitempty"` - XSequence *FHIRPrimitiveExtension `json:"_sequence,omitempty"` - XText *FHIRPrimitiveExtension `json:"_text,omitempty"` - AdditionalInstruction []*CodeableConcept `json:"additionalInstruction,omitempty"` - AsNeeded *bool `json:"asNeeded,omitempty"` - AsNeededFor []*CodeableConcept `json:"asNeededFor,omitempty"` - DoseAndRate []*DosageDoseAndRate `json:"doseAndRate,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - MaxDosePerAdministration *Quantity `json:"maxDosePerAdministration,omitempty"` - MaxDosePerLifetime *Quantity `json:"maxDosePerLifetime,omitempty"` - MaxDosePerPeriod []*Ratio `json:"maxDosePerPeriod,omitempty"` - Method *CodeableConcept `json:"method,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - PatientInstruction *string `json:"patientInstruction,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Route *CodeableConcept `json:"route,omitempty"` - Sequence *int64 `json:"sequence,omitempty"` - Site *CodeableConcept `json:"site,omitempty"` - Text *string `json:"text,omitempty"` - Timing *Timing `json:"timing,omitempty"` -} - -// DosageDoseAndRate -type DosageDoseAndRate struct { - DoseQuantity *Quantity `json:"doseQuantity,omitempty"` - DoseRange *Range `json:"doseRange,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - RateQuantity *Quantity `json:"rateQuantity,omitempty"` - RateRange *Range `json:"rateRange,omitempty"` - RateRatio *Ratio `json:"rateRatio,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` -} - -// Duration -type Duration struct { - XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` - XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` - XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` - XUnit *FHIRPrimitiveExtension `json:"_unit,omitempty"` - XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` - Code *string `json:"code,omitempty"` - Comparator *string `json:"comparator,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - System *string `json:"system,omitempty"` - Unit *string `json:"unit,omitempty"` - Value *float64 `json:"value,omitempty"` -} - -// Expression -type Expression struct { - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XExpression *FHIRPrimitiveExtension `json:"_expression,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - XReference *FHIRPrimitiveExtension `json:"_reference,omitempty"` - Description *string `json:"description,omitempty"` - Expression *string `json:"expression,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Name *string `json:"name,omitempty"` - Reference *string `json:"reference,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// ExtendedContactDetail -type ExtendedContactDetail struct { - Address *Address `json:"address,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Name []*HumanName `json:"name,omitempty"` - Organization *Reference `json:"organization,omitempty"` - Period *Period `json:"period,omitempty"` - Purpose *CodeableConcept `json:"purpose,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Telecom []*ContactPoint `json:"telecom,omitempty"` -} - -// Extension -type Extension struct { - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - URL *string `json:"url,omitempty"` - ValueAddress *Address `json:"valueAddress,omitempty"` - ValueAge *Age `json:"valueAge,omitempty"` - ValueAnnotation *Annotation `json:"valueAnnotation,omitempty"` - ValueAttachment *Attachment `json:"valueAttachment,omitempty"` - ValueAvailability *Availability `json:"valueAvailability,omitempty"` - ValueBase64Binary *string `json:"valueBase64Binary,omitempty"` - ValueBoolean *bool `json:"valueBoolean,omitempty"` - ValueCanonical *string `json:"valueCanonical,omitempty"` - ValueCode *string `json:"valueCode,omitempty"` - ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` - ValueCodeableReference *CodeableReference `json:"valueCodeableReference,omitempty"` - ValueCoding *Coding `json:"valueCoding,omitempty"` - ValueContactDetail *ContactDetail `json:"valueContactDetail,omitempty"` - ValueContactPoint *ContactPoint `json:"valueContactPoint,omitempty"` - ValueCount *Count `json:"valueCount,omitempty"` - ValueDataRequirement *DataRequirement `json:"valueDataRequirement,omitempty"` - ValueDate *string `json:"valueDate,omitempty"` - ValueDateTime *string `json:"valueDateTime,omitempty"` - ValueDecimal *float64 `json:"valueDecimal,omitempty"` - ValueDistance *Distance `json:"valueDistance,omitempty"` - ValueDosage *Dosage `json:"valueDosage,omitempty"` - ValueDuration *Duration `json:"valueDuration,omitempty"` - ValueExpression *Expression `json:"valueExpression,omitempty"` - ValueExtendedContactDetail *ExtendedContactDetail `json:"valueExtendedContactDetail,omitempty"` - ValueHumanName *HumanName `json:"valueHumanName,omitempty"` - ValueID *string `json:"valueId,omitempty"` - ValueIDentifier *Identifier `json:"valueIdentifier,omitempty"` - ValueInstant *string `json:"valueInstant,omitempty"` - ValueInteger *int64 `json:"valueInteger,omitempty"` - ValueInteger64 *int64 `json:"valueInteger64,omitempty"` - ValueMarkdown *string `json:"valueMarkdown,omitempty"` - ValueMeta *Meta `json:"valueMeta,omitempty"` - ValueMoney *Money `json:"valueMoney,omitempty"` - ValueOid *string `json:"valueOid,omitempty"` - ValueParameterDefinition *ParameterDefinition `json:"valueParameterDefinition,omitempty"` - ValuePeriod *Period `json:"valuePeriod,omitempty"` - ValuePositiveInt *int64 `json:"valuePositiveInt,omitempty"` - ValueQuantity *Quantity `json:"valueQuantity,omitempty"` - ValueRange *Range `json:"valueRange,omitempty"` - ValueRatio *Ratio `json:"valueRatio,omitempty"` - ValueRatioRange *RatioRange `json:"valueRatioRange,omitempty"` - ValueReference *Reference `json:"valueReference,omitempty"` - ValueRelatedArtifact *RelatedArtifact `json:"valueRelatedArtifact,omitempty"` - ValueSampledData *SampledData `json:"valueSampledData,omitempty"` - ValueSignature *Signature `json:"valueSignature,omitempty"` - ValueString *string `json:"valueString,omitempty"` - ValueTime *string `json:"valueTime,omitempty"` - ValueTiming *Timing `json:"valueTiming,omitempty"` - ValueTriggerDefinition *TriggerDefinition `json:"valueTriggerDefinition,omitempty"` - ValueUnsignedInt *int64 `json:"valueUnsignedInt,omitempty"` - ValueURI *string `json:"valueUri,omitempty"` - ValueURL *string `json:"valueUrl,omitempty"` - ValueUsageContext *UsageContext `json:"valueUsageContext,omitempty"` - ValueUUID *string `json:"valueUuid,omitempty"` -} - -// FHIRPrimitiveExtension -type FHIRPrimitiveExtension struct { - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// FamilyMemberHistory -type FamilyMemberHistory struct { - XAgeString *FHIRPrimitiveExtension `json:"_ageString,omitempty"` - XBornDate *FHIRPrimitiveExtension `json:"_bornDate,omitempty"` - XBornString *FHIRPrimitiveExtension `json:"_bornString,omitempty"` - XDate *FHIRPrimitiveExtension `json:"_date,omitempty"` - XDeceasedBoolean *FHIRPrimitiveExtension `json:"_deceasedBoolean,omitempty"` - XDeceasedDate *FHIRPrimitiveExtension `json:"_deceasedDate,omitempty"` - XDeceasedString *FHIRPrimitiveExtension `json:"_deceasedString,omitempty"` - XEstimatedAge *FHIRPrimitiveExtension `json:"_estimatedAge,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XInstantiatesCanonical []*FHIRPrimitiveExtension `json:"_instantiatesCanonical,omitempty"` - XInstantiatesURI []*FHIRPrimitiveExtension `json:"_instantiatesUri,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - AgeAge *Age `json:"ageAge,omitempty"` - AgeRange *Range `json:"ageRange,omitempty"` - AgeString *string `json:"ageString,omitempty"` - BornDate *string `json:"bornDate,omitempty"` - BornPeriod *Period `json:"bornPeriod,omitempty"` - BornString *string `json:"bornString,omitempty"` - Condition []*FamilyMemberHistoryCondition `json:"condition,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - DataAbsentReason *CodeableConcept `json:"dataAbsentReason,omitempty"` - Date *string `json:"date,omitempty"` - DeceasedAge *Age `json:"deceasedAge,omitempty"` - DeceasedBoolean *bool `json:"deceasedBoolean,omitempty"` - DeceasedDate *string `json:"deceasedDate,omitempty"` - DeceasedRange *Range `json:"deceasedRange,omitempty"` - DeceasedString *string `json:"deceasedString,omitempty"` - EstimatedAge *bool `json:"estimatedAge,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - InstantiatesCanonical []string `json:"instantiatesCanonical,omitempty"` - InstantiatesURI []string `json:"instantiatesUri,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Name *string `json:"name,omitempty"` - Note []*Annotation `json:"note,omitempty"` - Participant []*FamilyMemberHistoryParticipant `json:"participant,omitempty"` - Patient *Reference `json:"patient"` - Procedure []*FamilyMemberHistoryProcedure `json:"procedure,omitempty"` - Reason []*CodeableReference `json:"reason,omitempty"` - Relationship *CodeableConcept `json:"relationship"` - ResourceType *string `json:"resourceType,omitempty"` - Sex *CodeableConcept `json:"sex,omitempty"` - Status *string `json:"status,omitempty"` - Text *Narrative `json:"text,omitempty"` -} - -// FamilyMemberHistoryCondition -type FamilyMemberHistoryCondition struct { - XContributedToDeath *FHIRPrimitiveExtension `json:"_contributedToDeath,omitempty"` - XOnsetString *FHIRPrimitiveExtension `json:"_onsetString,omitempty"` - Code *CodeableConcept `json:"code"` - ContributedToDeath *bool `json:"contributedToDeath,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - OnsetAge *Age `json:"onsetAge,omitempty"` - OnsetPeriod *Period `json:"onsetPeriod,omitempty"` - OnsetRange *Range `json:"onsetRange,omitempty"` - OnsetString *string `json:"onsetString,omitempty"` - Outcome *CodeableConcept `json:"outcome,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// FamilyMemberHistoryParticipant -type FamilyMemberHistoryParticipant struct { - Actor *Reference `json:"actor"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Function *CodeableConcept `json:"function,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// FamilyMemberHistoryProcedure -type FamilyMemberHistoryProcedure struct { - XContributedToDeath *FHIRPrimitiveExtension `json:"_contributedToDeath,omitempty"` - XPerformedDateTime *FHIRPrimitiveExtension `json:"_performedDateTime,omitempty"` - XPerformedString *FHIRPrimitiveExtension `json:"_performedString,omitempty"` - Code *CodeableConcept `json:"code"` - ContributedToDeath *bool `json:"contributedToDeath,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - Outcome *CodeableConcept `json:"outcome,omitempty"` - PerformedAge *Age `json:"performedAge,omitempty"` - PerformedDateTime *string `json:"performedDateTime,omitempty"` - PerformedPeriod *Period `json:"performedPeriod,omitempty"` - PerformedRange *Range `json:"performedRange,omitempty"` - PerformedString *string `json:"performedString,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// Group -type Group struct { - XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XMembership *FHIRPrimitiveExtension `json:"_membership,omitempty"` - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - XQuantity *FHIRPrimitiveExtension `json:"_quantity,omitempty"` - XType *FHIRPrimitiveExtension `json:"_type,omitempty"` - Active *bool `json:"active,omitempty"` - Characteristic []*GroupCharacteristic `json:"characteristic,omitempty"` - Code *CodeableConcept `json:"code,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Description *string `json:"description,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - ManagingEntity *Reference `json:"managingEntity,omitempty"` - Member []*GroupMember `json:"member,omitempty"` - Membership *string `json:"membership,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Name *string `json:"name,omitempty"` - Quantity *int64 `json:"quantity,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Text *Narrative `json:"text,omitempty"` - Type *string `json:"type,omitempty"` -} - -// GroupCharacteristic -type GroupCharacteristic struct { - XExclude *FHIRPrimitiveExtension `json:"_exclude,omitempty"` - XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` - Code *CodeableConcept `json:"code"` - Exclude *bool `json:"exclude,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Period *Period `json:"period,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - ValueBoolean *bool `json:"valueBoolean,omitempty"` - ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` - ValueQuantity *Quantity `json:"valueQuantity,omitempty"` - ValueRange *Range `json:"valueRange,omitempty"` - ValueReference *Reference `json:"valueReference,omitempty"` -} - -// GroupMember -type GroupMember struct { - XInactive *FHIRPrimitiveExtension `json:"_inactive,omitempty"` - Entity *Reference `json:"entity"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Inactive *bool `json:"inactive,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Period *Period `json:"period,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// HumanName -type HumanName struct { - XFamily *FHIRPrimitiveExtension `json:"_family,omitempty"` - XGiven []*FHIRPrimitiveExtension `json:"_given,omitempty"` - XPrefix []*FHIRPrimitiveExtension `json:"_prefix,omitempty"` - XSuffix []*FHIRPrimitiveExtension `json:"_suffix,omitempty"` - XText *FHIRPrimitiveExtension `json:"_text,omitempty"` - XUse *FHIRPrimitiveExtension `json:"_use,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - Family *string `json:"family,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Given []string `json:"given,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Period *Period `json:"period,omitempty"` - Prefix []string `json:"prefix,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Suffix []string `json:"suffix,omitempty"` - Text *string `json:"text,omitempty"` - Use *string `json:"use,omitempty"` -} - -// Identifier -type Identifier struct { - XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` - XUse *FHIRPrimitiveExtension `json:"_use,omitempty"` - XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` - Assigner *Reference `json:"assigner,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Period *Period `json:"period,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - System *string `json:"system,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` - Use *string `json:"use,omitempty"` - Value *string `json:"value,omitempty"` -} - -// ImagingStudy -type ImagingStudy struct { - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XNumberOfInstances *FHIRPrimitiveExtension `json:"_numberOfInstances,omitempty"` - XNumberOfSeries *FHIRPrimitiveExtension `json:"_numberOfSeries,omitempty"` - XStarted *FHIRPrimitiveExtension `json:"_started,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - BasedOn []*Reference `json:"basedOn,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Description *string `json:"description,omitempty"` - Encounter *Reference `json:"encounter,omitempty"` - Endpoint []*Reference `json:"endpoint,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Location *Reference `json:"location,omitempty"` - Meta *Meta `json:"meta,omitempty"` - Modality []*CodeableConcept `json:"modality,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - NumberOfInstances *int64 `json:"numberOfInstances,omitempty"` - NumberOfSeries *int64 `json:"numberOfSeries,omitempty"` - PartOf []*Reference `json:"partOf,omitempty"` - Procedure []*CodeableReference `json:"procedure,omitempty"` - Reason []*CodeableReference `json:"reason,omitempty"` - Referrer *Reference `json:"referrer,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Series []*ImagingStudySeries `json:"series,omitempty"` - Started *string `json:"started,omitempty"` - Status *string `json:"status,omitempty"` - Subject *Reference `json:"subject"` - Text *Narrative `json:"text,omitempty"` -} - -// ImagingStudySeries -type ImagingStudySeries struct { - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XNumber *FHIRPrimitiveExtension `json:"_number,omitempty"` - XNumberOfInstances *FHIRPrimitiveExtension `json:"_numberOfInstances,omitempty"` - XStarted *FHIRPrimitiveExtension `json:"_started,omitempty"` - XUid *FHIRPrimitiveExtension `json:"_uid,omitempty"` - BodySite *CodeableReference `json:"bodySite,omitempty"` - Description *string `json:"description,omitempty"` - Endpoint []*Reference `json:"endpoint,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Instance []*ImagingStudySeriesInstance `json:"instance,omitempty"` - Laterality *CodeableConcept `json:"laterality,omitempty"` - Links [][]any `json:"links,omitempty"` - Modality *CodeableConcept `json:"modality"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Number *int64 `json:"number,omitempty"` - NumberOfInstances *int64 `json:"numberOfInstances,omitempty"` - Performer []*ImagingStudySeriesPerformer `json:"performer,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Specimen []*Reference `json:"specimen,omitempty"` - Started *string `json:"started,omitempty"` - Uid *string `json:"uid,omitempty"` -} - -// ImagingStudySeriesInstance -type ImagingStudySeriesInstance struct { - XNumber *FHIRPrimitiveExtension `json:"_number,omitempty"` - XTitle *FHIRPrimitiveExtension `json:"_title,omitempty"` - XUid *FHIRPrimitiveExtension `json:"_uid,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Number *int64 `json:"number,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SopClass *Coding `json:"sopClass"` - Title *string `json:"title,omitempty"` - Uid *string `json:"uid,omitempty"` -} - -// ImagingStudySeriesPerformer -type ImagingStudySeriesPerformer struct { - Actor *Reference `json:"actor"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Function *CodeableConcept `json:"function,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// Medication -type Medication struct { - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - Batch *MedicationBatch `json:"batch,omitempty"` - Code *CodeableConcept `json:"code,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Definition *Reference `json:"definition,omitempty"` - DoseForm *CodeableConcept `json:"doseForm,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Ingredient []*MedicationIngredient `json:"ingredient,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - MarketingAuthorizationHolder *Reference `json:"marketingAuthorizationHolder,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Status *string `json:"status,omitempty"` - Text *Narrative `json:"text,omitempty"` - TotalVolume *Quantity `json:"totalVolume,omitempty"` -} - -// MedicationAdministration -type MedicationAdministration struct { - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XIsSubPotent *FHIRPrimitiveExtension `json:"_isSubPotent,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XOccurenceDateTime *FHIRPrimitiveExtension `json:"_occurenceDateTime,omitempty"` - XRecorded *FHIRPrimitiveExtension `json:"_recorded,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - BasedOn []*Reference `json:"basedOn,omitempty"` - Category []*CodeableConcept `json:"category,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Device []*CodeableReference `json:"device,omitempty"` - Dosage *MedicationAdministrationDosage `json:"dosage,omitempty"` - Encounter *Reference `json:"encounter,omitempty"` - EventHistory []*Reference `json:"eventHistory,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - IsSubPotent *bool `json:"isSubPotent,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Medication *CodeableReference `json:"medication"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - OccurenceDateTime *string `json:"occurenceDateTime,omitempty"` - OccurencePeriod *Period `json:"occurencePeriod,omitempty"` - OccurenceTiming *Timing `json:"occurenceTiming,omitempty"` - PartOf []*Reference `json:"partOf,omitempty"` - Performer []*MedicationAdministrationPerformer `json:"performer,omitempty"` - Reason []*CodeableReference `json:"reason,omitempty"` - Recorded *string `json:"recorded,omitempty"` - Request *Reference `json:"request,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Status *string `json:"status,omitempty"` - StatusReason []*CodeableConcept `json:"statusReason,omitempty"` - SubPotentReason []*CodeableConcept `json:"subPotentReason,omitempty"` - Subject *Reference `json:"subject"` - SupportingInformation []*Reference `json:"supportingInformation,omitempty"` - Text *Narrative `json:"text,omitempty"` -} - -// MedicationAdministrationDosage -type MedicationAdministrationDosage struct { - XText *FHIRPrimitiveExtension `json:"_text,omitempty"` - Dose *Quantity `json:"dose,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Method *CodeableConcept `json:"method,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - RateQuantity *Quantity `json:"rateQuantity,omitempty"` - RateRatio *Ratio `json:"rateRatio,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Route *CodeableConcept `json:"route,omitempty"` - Site *CodeableConcept `json:"site,omitempty"` - Text *string `json:"text,omitempty"` -} - -// MedicationAdministrationPerformer -type MedicationAdministrationPerformer struct { - Actor *CodeableReference `json:"actor"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Function *CodeableConcept `json:"function,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// MedicationBatch -type MedicationBatch struct { - XExpirationDate *FHIRPrimitiveExtension `json:"_expirationDate,omitempty"` - XLotNumber *FHIRPrimitiveExtension `json:"_lotNumber,omitempty"` - ExpirationDate *string `json:"expirationDate,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - LotNumber *string `json:"lotNumber,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// MedicationIngredient -type MedicationIngredient struct { - XIsActive *FHIRPrimitiveExtension `json:"_isActive,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IsActive *bool `json:"isActive,omitempty"` - Item *CodeableReference `json:"item"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - StrengthCodeableConcept *CodeableConcept `json:"strengthCodeableConcept,omitempty"` - StrengthQuantity *Quantity `json:"strengthQuantity,omitempty"` - StrengthRatio *Ratio `json:"strengthRatio,omitempty"` -} - -// MedicationRequest -type MedicationRequest struct { - XAuthoredOn *FHIRPrimitiveExtension `json:"_authoredOn,omitempty"` - XDoNotPerform *FHIRPrimitiveExtension `json:"_doNotPerform,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XIntent *FHIRPrimitiveExtension `json:"_intent,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XPriority *FHIRPrimitiveExtension `json:"_priority,omitempty"` - XRenderedDosageInstruction *FHIRPrimitiveExtension `json:"_renderedDosageInstruction,omitempty"` - XReported *FHIRPrimitiveExtension `json:"_reported,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - XStatusChanged *FHIRPrimitiveExtension `json:"_statusChanged,omitempty"` - AuthoredOn *string `json:"authoredOn,omitempty"` - BasedOn []*Reference `json:"basedOn,omitempty"` - Category []*CodeableConcept `json:"category,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - CourseOfTherapyType *CodeableConcept `json:"courseOfTherapyType,omitempty"` - Device []*CodeableReference `json:"device,omitempty"` - DispenseRequest *MedicationRequestDispenseRequest `json:"dispenseRequest,omitempty"` - DoNotPerform *bool `json:"doNotPerform,omitempty"` - DosageInstruction []*Dosage `json:"dosageInstruction,omitempty"` - EffectiveDosePeriod *Period `json:"effectiveDosePeriod,omitempty"` - Encounter *Reference `json:"encounter,omitempty"` - EventHistory []*Reference `json:"eventHistory,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - GroupIDentifier *Identifier `json:"groupIdentifier,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - InformationSource []*Reference `json:"informationSource,omitempty"` - Insurance []*Reference `json:"insurance,omitempty"` - Intent *string `json:"intent,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Medication *CodeableReference `json:"medication"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - Performer []*Reference `json:"performer,omitempty"` - PerformerType *CodeableConcept `json:"performerType,omitempty"` - PriorPrescription *Reference `json:"priorPrescription,omitempty"` - Priority *string `json:"priority,omitempty"` - Reason []*CodeableReference `json:"reason,omitempty"` - Recorder *Reference `json:"recorder,omitempty"` - RenderedDosageInstruction *string `json:"renderedDosageInstruction,omitempty"` - Reported *bool `json:"reported,omitempty"` - Requester *Reference `json:"requester,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Status *string `json:"status,omitempty"` - StatusChanged *string `json:"statusChanged,omitempty"` - StatusReason *CodeableConcept `json:"statusReason,omitempty"` - Subject *Reference `json:"subject"` - Substitution *MedicationRequestSubstitution `json:"substitution,omitempty"` - SupportingInformation []*Reference `json:"supportingInformation,omitempty"` - Text *Narrative `json:"text,omitempty"` -} - -// MedicationRequestDispenseRequest -type MedicationRequestDispenseRequest struct { - XNumberOfRepeatsAllowed *FHIRPrimitiveExtension `json:"_numberOfRepeatsAllowed,omitempty"` - DispenseInterval *Duration `json:"dispenseInterval,omitempty"` - Dispenser *Reference `json:"dispenser,omitempty"` - DispenserInstruction []*Annotation `json:"dispenserInstruction,omitempty"` - DoseAdministrationAid *CodeableConcept `json:"doseAdministrationAid,omitempty"` - ExpectedSupplyDuration *Duration `json:"expectedSupplyDuration,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - InitialFill *MedicationRequestDispenseRequestInitialFill `json:"initialFill,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - NumberOfRepeatsAllowed *int64 `json:"numberOfRepeatsAllowed,omitempty"` - Quantity *Quantity `json:"quantity,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - ValidityPeriod *Period `json:"validityPeriod,omitempty"` -} - -// MedicationRequestDispenseRequestInitialFill -type MedicationRequestDispenseRequestInitialFill struct { - Duration *Duration `json:"duration,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Quantity *Quantity `json:"quantity,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// MedicationRequestSubstitution -type MedicationRequestSubstitution struct { - XAllowedBoolean *FHIRPrimitiveExtension `json:"_allowedBoolean,omitempty"` - AllowedBoolean *bool `json:"allowedBoolean,omitempty"` - AllowedCodeableConcept *CodeableConcept `json:"allowedCodeableConcept,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Reason *CodeableConcept `json:"reason,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// MedicationStatement -type MedicationStatement struct { - XDateAsserted *FHIRPrimitiveExtension `json:"_dateAsserted,omitempty"` - XEffectiveDateTime *FHIRPrimitiveExtension `json:"_effectiveDateTime,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XRenderedDosageInstruction *FHIRPrimitiveExtension `json:"_renderedDosageInstruction,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - Adherence *MedicationStatementAdherence `json:"adherence,omitempty"` - Category []*CodeableConcept `json:"category,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - DateAsserted *string `json:"dateAsserted,omitempty"` - DerivedFrom []*Reference `json:"derivedFrom,omitempty"` - Dosage []*Dosage `json:"dosage,omitempty"` - EffectiveDateTime *string `json:"effectiveDateTime,omitempty"` - EffectivePeriod *Period `json:"effectivePeriod,omitempty"` - EffectiveTiming *Timing `json:"effectiveTiming,omitempty"` - Encounter *Reference `json:"encounter,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - InformationSource []*Reference `json:"informationSource,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Medication *CodeableReference `json:"medication"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - PartOf []*Reference `json:"partOf,omitempty"` - Reason []*CodeableReference `json:"reason,omitempty"` - RelatedClinicalInformation []*Reference `json:"relatedClinicalInformation,omitempty"` - RenderedDosageInstruction *string `json:"renderedDosageInstruction,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Status *string `json:"status,omitempty"` - Subject *Reference `json:"subject"` - Text *Narrative `json:"text,omitempty"` -} - -// MedicationStatementAdherence -type MedicationStatementAdherence struct { - Code *CodeableConcept `json:"code"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Reason *CodeableConcept `json:"reason,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// Meta -type Meta struct { - XLastUpdated *FHIRPrimitiveExtension `json:"_lastUpdated,omitempty"` - XProfile []*FHIRPrimitiveExtension `json:"_profile,omitempty"` - XSource *FHIRPrimitiveExtension `json:"_source,omitempty"` - XVersionID *FHIRPrimitiveExtension `json:"_versionId,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - LastUpdated *string `json:"lastUpdated,omitempty"` - Links [][]any `json:"links,omitempty"` - Profile []string `json:"profile,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Security []*Coding `json:"security,omitempty"` - Source *string `json:"source,omitempty"` - Tag []*Coding `json:"tag,omitempty"` - VersionID *string `json:"versionId,omitempty"` -} - -// Money -type Money struct { - XCurrency *FHIRPrimitiveExtension `json:"_currency,omitempty"` - XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` - Currency *string `json:"currency,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Value *float64 `json:"value,omitempty"` -} - -// Narrative -type Narrative struct { - XDiv *FHIRPrimitiveExtension `json:"_div,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - Div *string `json:"div,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Status *string `json:"status,omitempty"` -} - -// Observation -type Observation struct { - XEffectiveDateTime *FHIRPrimitiveExtension `json:"_effectiveDateTime,omitempty"` - XEffectiveInstant *FHIRPrimitiveExtension `json:"_effectiveInstant,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XInstantiatesCanonical *FHIRPrimitiveExtension `json:"_instantiatesCanonical,omitempty"` - XIssued *FHIRPrimitiveExtension `json:"_issued,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` - XValueDateTime *FHIRPrimitiveExtension `json:"_valueDateTime,omitempty"` - XValueInteger *FHIRPrimitiveExtension `json:"_valueInteger,omitempty"` - XValueString *FHIRPrimitiveExtension `json:"_valueString,omitempty"` - XValueTime *FHIRPrimitiveExtension `json:"_valueTime,omitempty"` - BasedOn []*Reference `json:"basedOn,omitempty"` - BodySite *CodeableConcept `json:"bodySite,omitempty"` - BodyStructure *Reference `json:"bodyStructure,omitempty"` - Category []*CodeableConcept `json:"category,omitempty"` - Code *CodeableConcept `json:"code"` - Component []*ObservationComponent `json:"component,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - DataAbsentReason *CodeableConcept `json:"dataAbsentReason,omitempty"` - DerivedFrom []*Reference `json:"derivedFrom,omitempty"` - Device *Reference `json:"device,omitempty"` - EffectiveDateTime *string `json:"effectiveDateTime,omitempty"` - EffectiveInstant *string `json:"effectiveInstant,omitempty"` - EffectivePeriod *Period `json:"effectivePeriod,omitempty"` - EffectiveTiming *Timing `json:"effectiveTiming,omitempty"` - Encounter *Reference `json:"encounter,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Focus []*Reference `json:"focus,omitempty"` - HasMember []*Reference `json:"hasMember,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - InstantiatesCanonical *string `json:"instantiatesCanonical,omitempty"` - InstantiatesReference *Reference `json:"instantiatesReference,omitempty"` - Interpretation []*CodeableConcept `json:"interpretation,omitempty"` - Issued *string `json:"issued,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - Method *CodeableConcept `json:"method,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - PartOf []*Reference `json:"partOf,omitempty"` - Performer []*Reference `json:"performer,omitempty"` - ReferenceRange []*ObservationReferenceRange `json:"referenceRange,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Specimen *Reference `json:"specimen,omitempty"` - Status *string `json:"status,omitempty"` - Subject *Reference `json:"subject,omitempty"` - Text *Narrative `json:"text,omitempty"` - TriggeredBy []*ObservationTriggeredBy `json:"triggeredBy,omitempty"` - ValueAttachment *Attachment `json:"valueAttachment,omitempty"` - ValueBoolean *bool `json:"valueBoolean,omitempty"` - ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` - ValueDateTime *string `json:"valueDateTime,omitempty"` - ValueInteger *int64 `json:"valueInteger,omitempty"` - ValuePeriod *Period `json:"valuePeriod,omitempty"` - ValueQuantity *Quantity `json:"valueQuantity,omitempty"` - ValueRange *Range `json:"valueRange,omitempty"` - ValueRatio *Ratio `json:"valueRatio,omitempty"` - ValueReference *Reference `json:"valueReference,omitempty"` - ValueSampledData *SampledData `json:"valueSampledData,omitempty"` - ValueString *string `json:"valueString,omitempty"` - ValueTime *string `json:"valueTime,omitempty"` -} - -// ObservationComponent -type ObservationComponent struct { - XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` - XValueDateTime *FHIRPrimitiveExtension `json:"_valueDateTime,omitempty"` - XValueInteger *FHIRPrimitiveExtension `json:"_valueInteger,omitempty"` - XValueString *FHIRPrimitiveExtension `json:"_valueString,omitempty"` - XValueTime *FHIRPrimitiveExtension `json:"_valueTime,omitempty"` - Code *CodeableConcept `json:"code"` - DataAbsentReason *CodeableConcept `json:"dataAbsentReason,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Interpretation []*CodeableConcept `json:"interpretation,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ReferenceRange []*ObservationReferenceRange `json:"referenceRange,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - ValueAttachment *Attachment `json:"valueAttachment,omitempty"` - ValueBoolean *bool `json:"valueBoolean,omitempty"` - ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` - ValueDateTime *string `json:"valueDateTime,omitempty"` - ValueInteger *int64 `json:"valueInteger,omitempty"` - ValuePeriod *Period `json:"valuePeriod,omitempty"` - ValueQuantity *Quantity `json:"valueQuantity,omitempty"` - ValueRange *Range `json:"valueRange,omitempty"` - ValueRatio *Ratio `json:"valueRatio,omitempty"` - ValueReference *Reference `json:"valueReference,omitempty"` - ValueSampledData *SampledData `json:"valueSampledData,omitempty"` - ValueString *string `json:"valueString,omitempty"` - ValueTime *string `json:"valueTime,omitempty"` -} - -// ObservationReferenceRange -type ObservationReferenceRange struct { - XText *FHIRPrimitiveExtension `json:"_text,omitempty"` - Age *Range `json:"age,omitempty"` - AppliesTo []*CodeableConcept `json:"appliesTo,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - High *Quantity `json:"high,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Low *Quantity `json:"low,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - NormalValue *CodeableConcept `json:"normalValue,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Text *string `json:"text,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` -} - -// ObservationTriggeredBy -type ObservationTriggeredBy struct { - XReason *FHIRPrimitiveExtension `json:"_reason,omitempty"` - XType *FHIRPrimitiveExtension `json:"_type,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Observation *Reference `json:"observation"` - Reason *string `json:"reason,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *string `json:"type,omitempty"` -} - -// Organization -type Organization struct { - XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` - XAlias []*FHIRPrimitiveExtension `json:"_alias,omitempty"` - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - Active *bool `json:"active,omitempty"` - Alias []string `json:"alias,omitempty"` - Contact []*ExtendedContactDetail `json:"contact,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Description *string `json:"description,omitempty"` - Endpoint []*Reference `json:"endpoint,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Name *string `json:"name,omitempty"` - PartOf *Reference `json:"partOf,omitempty"` - Qualification []*OrganizationQualification `json:"qualification,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Text *Narrative `json:"text,omitempty"` - Type []*CodeableConcept `json:"type,omitempty"` -} - -// OrganizationQualification -type OrganizationQualification struct { - Code *CodeableConcept `json:"code"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - Issuer *Reference `json:"issuer,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Period *Period `json:"period,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// ParameterDefinition -type ParameterDefinition struct { - XDocumentation *FHIRPrimitiveExtension `json:"_documentation,omitempty"` - XMax *FHIRPrimitiveExtension `json:"_max,omitempty"` - XMin *FHIRPrimitiveExtension `json:"_min,omitempty"` - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - XProfile *FHIRPrimitiveExtension `json:"_profile,omitempty"` - XType *FHIRPrimitiveExtension `json:"_type,omitempty"` - XUse *FHIRPrimitiveExtension `json:"_use,omitempty"` - Documentation *string `json:"documentation,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Max *string `json:"max,omitempty"` - Min *int64 `json:"min,omitempty"` - Name *string `json:"name,omitempty"` - Profile *string `json:"profile,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *string `json:"type,omitempty"` - Use *string `json:"use,omitempty"` -} - -// Patient -type Patient struct { - XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` - XBirthDate *FHIRPrimitiveExtension `json:"_birthDate,omitempty"` - XDeceasedBoolean *FHIRPrimitiveExtension `json:"_deceasedBoolean,omitempty"` - XDeceasedDateTime *FHIRPrimitiveExtension `json:"_deceasedDateTime,omitempty"` - XGender *FHIRPrimitiveExtension `json:"_gender,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XMultipleBirthBoolean *FHIRPrimitiveExtension `json:"_multipleBirthBoolean,omitempty"` - XMultipleBirthInteger *FHIRPrimitiveExtension `json:"_multipleBirthInteger,omitempty"` - Active *bool `json:"active,omitempty"` - Address []*Address `json:"address,omitempty"` - BirthDate *string `json:"birthDate,omitempty"` - Communication []*PatientCommunication `json:"communication,omitempty"` - Contact []*PatientContact `json:"contact,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - DeceasedBoolean *bool `json:"deceasedBoolean,omitempty"` - DeceasedDateTime *string `json:"deceasedDateTime,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Gender *string `json:"gender,omitempty"` - GeneralPractitioner []*Reference `json:"generalPractitioner,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Language *string `json:"language,omitempty"` - Link []*PatientLink `json:"link,omitempty"` - Links [][]any `json:"links,omitempty"` - ManagingOrganization *Reference `json:"managingOrganization,omitempty"` - MaritalStatus *CodeableConcept `json:"maritalStatus,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - MultipleBirthBoolean *bool `json:"multipleBirthBoolean,omitempty"` - MultipleBirthInteger *int64 `json:"multipleBirthInteger,omitempty"` - Name []*HumanName `json:"name,omitempty"` - Photo []*Attachment `json:"photo,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Telecom []*ContactPoint `json:"telecom,omitempty"` - Text *Narrative `json:"text,omitempty"` -} - -// PatientCommunication -type PatientCommunication struct { - XPreferred *FHIRPrimitiveExtension `json:"_preferred,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Language *CodeableConcept `json:"language"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Preferred *bool `json:"preferred,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// PatientContact -type PatientContact struct { - XGender *FHIRPrimitiveExtension `json:"_gender,omitempty"` - Address *Address `json:"address,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Gender *string `json:"gender,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Name *HumanName `json:"name,omitempty"` - Organization *Reference `json:"organization,omitempty"` - Period *Period `json:"period,omitempty"` - Relationship []*CodeableConcept `json:"relationship,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Telecom []*ContactPoint `json:"telecom,omitempty"` -} - -// PatientLink -type PatientLink struct { - XType *FHIRPrimitiveExtension `json:"_type,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Other *Reference `json:"other"` - ResourceType *string `json:"resourceType,omitempty"` - Type *string `json:"type,omitempty"` -} - -// Period -type Period struct { - XEnd *FHIRPrimitiveExtension `json:"_end,omitempty"` - XStart *FHIRPrimitiveExtension `json:"_start,omitempty"` - End *string `json:"end,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Start *string `json:"start,omitempty"` -} - -// Practitioner -type Practitioner struct { - XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` - XBirthDate *FHIRPrimitiveExtension `json:"_birthDate,omitempty"` - XDeceasedBoolean *FHIRPrimitiveExtension `json:"_deceasedBoolean,omitempty"` - XDeceasedDateTime *FHIRPrimitiveExtension `json:"_deceasedDateTime,omitempty"` - XGender *FHIRPrimitiveExtension `json:"_gender,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - Active *bool `json:"active,omitempty"` - Address []*Address `json:"address,omitempty"` - BirthDate *string `json:"birthDate,omitempty"` - Communication []*PractitionerCommunication `json:"communication,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - DeceasedBoolean *bool `json:"deceasedBoolean,omitempty"` - DeceasedDateTime *string `json:"deceasedDateTime,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Gender *string `json:"gender,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Name []*HumanName `json:"name,omitempty"` - Photo []*Attachment `json:"photo,omitempty"` - Qualification []*PractitionerQualification `json:"qualification,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Telecom []*ContactPoint `json:"telecom,omitempty"` - Text *Narrative `json:"text,omitempty"` -} - -// PractitionerCommunication -type PractitionerCommunication struct { - XPreferred *FHIRPrimitiveExtension `json:"_preferred,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Language *CodeableConcept `json:"language"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Preferred *bool `json:"preferred,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// PractitionerQualification -type PractitionerQualification struct { - Code *CodeableConcept `json:"code"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - Issuer *Reference `json:"issuer,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Period *Period `json:"period,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// PractitionerRole -type PractitionerRole struct { - XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - Active *bool `json:"active,omitempty"` - Availability []*Availability `json:"availability,omitempty"` - Characteristic []*CodeableConcept `json:"characteristic,omitempty"` - Code []*CodeableConcept `json:"code,omitempty"` - Communication []*CodeableConcept `json:"communication,omitempty"` - Contact []*ExtendedContactDetail `json:"contact,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Endpoint []*Reference `json:"endpoint,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - HealthcareService []*Reference `json:"healthcareService,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Location []*Reference `json:"location,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Organization *Reference `json:"organization,omitempty"` - Period *Period `json:"period,omitempty"` - Practitioner *Reference `json:"practitioner,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Specialty []*CodeableConcept `json:"specialty,omitempty"` - Text *Narrative `json:"text,omitempty"` -} - -// Procedure -type Procedure struct { - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XInstantiatesCanonical []*FHIRPrimitiveExtension `json:"_instantiatesCanonical,omitempty"` - XInstantiatesURI []*FHIRPrimitiveExtension `json:"_instantiatesUri,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XOccurrenceDateTime *FHIRPrimitiveExtension `json:"_occurrenceDateTime,omitempty"` - XOccurrenceString *FHIRPrimitiveExtension `json:"_occurrenceString,omitempty"` - XRecorded *FHIRPrimitiveExtension `json:"_recorded,omitempty"` - XReportedBoolean *FHIRPrimitiveExtension `json:"_reportedBoolean,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - BasedOn []*Reference `json:"basedOn,omitempty"` - BodySite []*CodeableConcept `json:"bodySite,omitempty"` - Category []*CodeableConcept `json:"category,omitempty"` - Code *CodeableConcept `json:"code,omitempty"` - Complication []*CodeableReference `json:"complication,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Encounter *Reference `json:"encounter,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - FocalDevice []*ProcedureFocalDevice `json:"focalDevice,omitempty"` - Focus *Reference `json:"focus,omitempty"` - FollowUp []*CodeableConcept `json:"followUp,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - InstantiatesCanonical []string `json:"instantiatesCanonical,omitempty"` - InstantiatesURI []string `json:"instantiatesUri,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Location *Reference `json:"location,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - OccurrenceAge *Age `json:"occurrenceAge,omitempty"` - OccurrenceDateTime *string `json:"occurrenceDateTime,omitempty"` - OccurrencePeriod *Period `json:"occurrencePeriod,omitempty"` - OccurrenceRange *Range `json:"occurrenceRange,omitempty"` - OccurrenceString *string `json:"occurrenceString,omitempty"` - OccurrenceTiming *Timing `json:"occurrenceTiming,omitempty"` - Outcome *CodeableConcept `json:"outcome,omitempty"` - PartOf []*Reference `json:"partOf,omitempty"` - Performer []*ProcedurePerformer `json:"performer,omitempty"` - Reason []*CodeableReference `json:"reason,omitempty"` - Recorded *string `json:"recorded,omitempty"` - Recorder *Reference `json:"recorder,omitempty"` - Report []*Reference `json:"report,omitempty"` - ReportedBoolean *bool `json:"reportedBoolean,omitempty"` - ReportedReference *Reference `json:"reportedReference,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Status *string `json:"status,omitempty"` - StatusReason *CodeableConcept `json:"statusReason,omitempty"` - Subject *Reference `json:"subject"` - SupportingInfo []*Reference `json:"supportingInfo,omitempty"` - Text *Narrative `json:"text,omitempty"` - Used []*CodeableReference `json:"used,omitempty"` -} - -// ProcedureFocalDevice -type ProcedureFocalDevice struct { - Action *CodeableConcept `json:"action,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Manipulated *Reference `json:"manipulated"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// ProcedurePerformer -type ProcedurePerformer struct { - Actor *Reference `json:"actor"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Function *CodeableConcept `json:"function,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - OnBehalfOf *Reference `json:"onBehalfOf,omitempty"` - Period *Period `json:"period,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// Quantity -type Quantity struct { - XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` - XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` - XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` - XUnit *FHIRPrimitiveExtension `json:"_unit,omitempty"` - XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` - Code *string `json:"code,omitempty"` - Comparator *string `json:"comparator,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - System *string `json:"system,omitempty"` - Unit *string `json:"unit,omitempty"` - Value *float64 `json:"value,omitempty"` -} - -// Range -type Range struct { - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - High *Quantity `json:"high,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Low *Quantity `json:"low,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// Ratio -type Ratio struct { - Denominator *Quantity `json:"denominator,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Numerator *Quantity `json:"numerator,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// RatioRange -type RatioRange struct { - Denominator *Quantity `json:"denominator,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - HighNumerator *Quantity `json:"highNumerator,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - LowNumerator *Quantity `json:"lowNumerator,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// Reference -type Reference struct { - XDisplay *FHIRPrimitiveExtension `json:"_display,omitempty"` - XReference *FHIRPrimitiveExtension `json:"_reference,omitempty"` - XType *FHIRPrimitiveExtension `json:"_type,omitempty"` - Display *string `json:"display,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier *Identifier `json:"identifier,omitempty"` - Links [][]any `json:"links,omitempty"` - Reference *string `json:"reference,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *string `json:"type,omitempty"` -} - -// RelatedArtifact -type RelatedArtifact struct { - XCitation *FHIRPrimitiveExtension `json:"_citation,omitempty"` - XDisplay *FHIRPrimitiveExtension `json:"_display,omitempty"` - XLabel *FHIRPrimitiveExtension `json:"_label,omitempty"` - XPublicationDate *FHIRPrimitiveExtension `json:"_publicationDate,omitempty"` - XPublicationStatus *FHIRPrimitiveExtension `json:"_publicationStatus,omitempty"` - XResource *FHIRPrimitiveExtension `json:"_resource,omitempty"` - XType *FHIRPrimitiveExtension `json:"_type,omitempty"` - Citation *string `json:"citation,omitempty"` - Classifier []*CodeableConcept `json:"classifier,omitempty"` - Display *string `json:"display,omitempty"` - Document *Attachment `json:"document,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Label *string `json:"label,omitempty"` - Links [][]any `json:"links,omitempty"` - PublicationDate *string `json:"publicationDate,omitempty"` - PublicationStatus *string `json:"publicationStatus,omitempty"` - Resource *string `json:"resource,omitempty"` - ResourceReference *Reference `json:"resourceReference,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *string `json:"type,omitempty"` -} - -// ResearchStudy -type ResearchStudy struct { - XDate *FHIRPrimitiveExtension `json:"_date,omitempty"` - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XDescriptionSummary *FHIRPrimitiveExtension `json:"_descriptionSummary,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - XTitle *FHIRPrimitiveExtension `json:"_title,omitempty"` - XURL *FHIRPrimitiveExtension `json:"_url,omitempty"` - XVersion *FHIRPrimitiveExtension `json:"_version,omitempty"` - AssociatedParty []*ResearchStudyAssociatedParty `json:"associatedParty,omitempty"` - Classifier []*CodeableConcept `json:"classifier,omitempty"` - ComparisonGroup []*ResearchStudyComparisonGroup `json:"comparisonGroup,omitempty"` - Condition []*CodeableConcept `json:"condition,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Date *string `json:"date,omitempty"` - Description *string `json:"description,omitempty"` - DescriptionSummary *string `json:"descriptionSummary,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Focus []*CodeableReference `json:"focus,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Keyword []*CodeableConcept `json:"keyword,omitempty"` - Label []*ResearchStudyLabel `json:"label,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Name *string `json:"name,omitempty"` - Note []*Annotation `json:"note,omitempty"` - Objective []*ResearchStudyObjective `json:"objective,omitempty"` - OutcomeMeasure []*ResearchStudyOutcomeMeasure `json:"outcomeMeasure,omitempty"` - PartOf []*Reference `json:"partOf,omitempty"` - Period *Period `json:"period,omitempty"` - Phase *CodeableConcept `json:"phase,omitempty"` - PrimaryPurposeType *CodeableConcept `json:"primaryPurposeType,omitempty"` - ProgressStatus []*ResearchStudyProgressStatus `json:"progressStatus,omitempty"` - Protocol []*Reference `json:"protocol,omitempty"` - Recruitment *ResearchStudyRecruitment `json:"recruitment,omitempty"` - Region []*CodeableConcept `json:"region,omitempty"` - RelatedArtifact []*RelatedArtifact `json:"relatedArtifact,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Result []*Reference `json:"result,omitempty"` - RootDir *Reference `json:"rootDir,omitempty"` - Site []*Reference `json:"site,omitempty"` - Status *string `json:"status,omitempty"` - StudyDesign []*CodeableConcept `json:"studyDesign,omitempty"` - Text *Narrative `json:"text,omitempty"` - Title *string `json:"title,omitempty"` - URL *string `json:"url,omitempty"` - Version *string `json:"version,omitempty"` - WhyStopped *CodeableConcept `json:"whyStopped,omitempty"` -} - -// ResearchStudyAssociatedParty -type ResearchStudyAssociatedParty struct { - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - Classifier []*CodeableConcept `json:"classifier,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Name *string `json:"name,omitempty"` - Party *Reference `json:"party,omitempty"` - Period []*Period `json:"period,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Role *CodeableConcept `json:"role"` -} - -// ResearchStudyComparisonGroup -type ResearchStudyComparisonGroup struct { - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XLinkID *FHIRPrimitiveExtension `json:"_linkId,omitempty"` - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - Description *string `json:"description,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IntendedExposure []*Reference `json:"intendedExposure,omitempty"` - LinkID *string `json:"linkId,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Name *string `json:"name,omitempty"` - ObservedGroup *Reference `json:"observedGroup,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` -} - -// ResearchStudyLabel -type ResearchStudyLabel struct { - XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` - Value *string `json:"value,omitempty"` -} - -// ResearchStudyObjective -type ResearchStudyObjective struct { - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - Description *string `json:"description,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Name *string `json:"name,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` -} - -// ResearchStudyOutcomeMeasure -type ResearchStudyOutcomeMeasure struct { - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - Description *string `json:"description,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Name *string `json:"name,omitempty"` - Reference *Reference `json:"reference,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type []*CodeableConcept `json:"type,omitempty"` -} - -// ResearchStudyProgressStatus -type ResearchStudyProgressStatus struct { - XActual *FHIRPrimitiveExtension `json:"_actual,omitempty"` - Actual *bool `json:"actual,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Period *Period `json:"period,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - State *CodeableConcept `json:"state"` -} - -// ResearchStudyRecruitment -type ResearchStudyRecruitment struct { - XActualNumber *FHIRPrimitiveExtension `json:"_actualNumber,omitempty"` - XTargetNumber *FHIRPrimitiveExtension `json:"_targetNumber,omitempty"` - ActualGroup *Reference `json:"actualGroup,omitempty"` - ActualNumber *int64 `json:"actualNumber,omitempty"` - Eligibility *Reference `json:"eligibility,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - TargetNumber *int64 `json:"targetNumber,omitempty"` -} - -// ResearchSubject -type ResearchSubject struct { - XActualComparisonGroup *FHIRPrimitiveExtension `json:"_actualComparisonGroup,omitempty"` - XAssignedComparisonGroup *FHIRPrimitiveExtension `json:"_assignedComparisonGroup,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - ActualComparisonGroup *string `json:"actualComparisonGroup,omitempty"` - AssignedComparisonGroup *string `json:"assignedComparisonGroup,omitempty"` - Consent []*Reference `json:"consent,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Period *Period `json:"period,omitempty"` - Progress []*ResearchSubjectProgress `json:"progress,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Status *string `json:"status,omitempty"` - Study *Reference `json:"study"` - Subject *Reference `json:"subject"` - Text *Narrative `json:"text,omitempty"` -} - -// ResearchSubjectProgress -type ResearchSubjectProgress struct { - XEndDate *FHIRPrimitiveExtension `json:"_endDate,omitempty"` - XStartDate *FHIRPrimitiveExtension `json:"_startDate,omitempty"` - EndDate *string `json:"endDate,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Milestone *CodeableConcept `json:"milestone,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Reason *CodeableConcept `json:"reason,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - StartDate *string `json:"startDate,omitempty"` - SubjectState *CodeableConcept `json:"subjectState,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` -} - -// Resource -type Resource struct { - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// SampledData -type SampledData struct { - XCodeMap *FHIRPrimitiveExtension `json:"_codeMap,omitempty"` - XData *FHIRPrimitiveExtension `json:"_data,omitempty"` - XDimensions *FHIRPrimitiveExtension `json:"_dimensions,omitempty"` - XFactor *FHIRPrimitiveExtension `json:"_factor,omitempty"` - XInterval *FHIRPrimitiveExtension `json:"_interval,omitempty"` - XIntervalUnit *FHIRPrimitiveExtension `json:"_intervalUnit,omitempty"` - XLowerLimit *FHIRPrimitiveExtension `json:"_lowerLimit,omitempty"` - XOffsets *FHIRPrimitiveExtension `json:"_offsets,omitempty"` - XUpperLimit *FHIRPrimitiveExtension `json:"_upperLimit,omitempty"` - CodeMap *string `json:"codeMap,omitempty"` - Data *string `json:"data,omitempty"` - Dimensions *int64 `json:"dimensions,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - Factor *float64 `json:"factor,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Interval *float64 `json:"interval,omitempty"` - IntervalUnit *string `json:"intervalUnit,omitempty"` - Links [][]any `json:"links,omitempty"` - LowerLimit *float64 `json:"lowerLimit,omitempty"` - Offsets *string `json:"offsets,omitempty"` - Origin *Quantity `json:"origin"` - ResourceType *string `json:"resourceType,omitempty"` - UpperLimit *float64 `json:"upperLimit,omitempty"` -} - -// Signature -type Signature struct { - XData *FHIRPrimitiveExtension `json:"_data,omitempty"` - XSigFormat *FHIRPrimitiveExtension `json:"_sigFormat,omitempty"` - XTargetFormat *FHIRPrimitiveExtension `json:"_targetFormat,omitempty"` - XWhen *FHIRPrimitiveExtension `json:"_when,omitempty"` - Data *string `json:"data,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - OnBehalfOf *Reference `json:"onBehalfOf,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SigFormat *string `json:"sigFormat,omitempty"` - TargetFormat *string `json:"targetFormat,omitempty"` - Type []*Coding `json:"type,omitempty"` - When *string `json:"when,omitempty"` - Who *Reference `json:"who,omitempty"` -} - -// Specimen -type Specimen struct { - XCombined *FHIRPrimitiveExtension `json:"_combined,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XReceivedTime *FHIRPrimitiveExtension `json:"_receivedTime,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - AccessionIDentifier *Identifier `json:"accessionIdentifier,omitempty"` - Collection *SpecimenCollection `json:"collection,omitempty"` - Combined *string `json:"combined,omitempty"` - Condition []*CodeableConcept `json:"condition,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Container []*SpecimenContainer `json:"container,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - Feature []*SpecimenFeature `json:"feature,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - Parent []*Reference `json:"parent,omitempty"` - Processing []*SpecimenProcessing `json:"processing,omitempty"` - ReceivedTime *string `json:"receivedTime,omitempty"` - Request []*Reference `json:"request,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Role []*CodeableConcept `json:"role,omitempty"` - Status *string `json:"status,omitempty"` - Subject *Reference `json:"subject,omitempty"` - Text *Narrative `json:"text,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` -} - -// SpecimenCollection -type SpecimenCollection struct { - XCollectedDateTime *FHIRPrimitiveExtension `json:"_collectedDateTime,omitempty"` - BodySite *CodeableReference `json:"bodySite,omitempty"` - CollectedDateTime *string `json:"collectedDateTime,omitempty"` - CollectedPeriod *Period `json:"collectedPeriod,omitempty"` - Collector *Reference `json:"collector,omitempty"` - Device *CodeableReference `json:"device,omitempty"` - Duration *Duration `json:"duration,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FastingStatusCodeableConcept *CodeableConcept `json:"fastingStatusCodeableConcept,omitempty"` - FastingStatusDuration *Duration `json:"fastingStatusDuration,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Method *CodeableConcept `json:"method,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Procedure *Reference `json:"procedure,omitempty"` - Quantity *Quantity `json:"quantity,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// SpecimenContainer -type SpecimenContainer struct { - Device *Reference `json:"device"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Location *Reference `json:"location,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SpecimenQuantity *Quantity `json:"specimenQuantity,omitempty"` -} - -// SpecimenFeature -type SpecimenFeature struct { - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - Description *string `json:"description,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *CodeableConcept `json:"type"` -} - -// SpecimenProcessing -type SpecimenProcessing struct { - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XTimeDateTime *FHIRPrimitiveExtension `json:"_timeDateTime,omitempty"` - Additive []*Reference `json:"additive,omitempty"` - Description *string `json:"description,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Method *CodeableConcept `json:"method,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - TimeDateTime *string `json:"timeDateTime,omitempty"` - TimePeriod *Period `json:"timePeriod,omitempty"` -} - -// Substance -type Substance struct { - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XExpiry *FHIRPrimitiveExtension `json:"_expiry,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XInstance *FHIRPrimitiveExtension `json:"_instance,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - Category []*CodeableConcept `json:"category,omitempty"` - Code *CodeableReference `json:"code"` - Contained []*Resource `json:"contained,omitempty"` - Description *string `json:"description,omitempty"` - Expiry *string `json:"expiry,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Ingredient []*SubstanceIngredient `json:"ingredient,omitempty"` - Instance *bool `json:"instance,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Quantity *Quantity `json:"quantity,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Status *string `json:"status,omitempty"` - Text *Narrative `json:"text,omitempty"` -} - -// SubstanceDefinition -type SubstanceDefinition struct { - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XVersion *FHIRPrimitiveExtension `json:"_version,omitempty"` - Characterization []*SubstanceDefinitionCharacterization `json:"characterization,omitempty"` - Classification []*CodeableConcept `json:"classification,omitempty"` - Code []*SubstanceDefinitionCode `json:"code,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Description *string `json:"description,omitempty"` - Domain *CodeableConcept `json:"domain,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Grade []*CodeableConcept `json:"grade,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - InformationSource []*Reference `json:"informationSource,omitempty"` - Language *string `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - Manufacturer []*Reference `json:"manufacturer,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Moiety []*SubstanceDefinitionMoiety `json:"moiety,omitempty"` - MolecularWeight []*SubstanceDefinitionMolecularWeight `json:"molecularWeight,omitempty"` - Name []*SubstanceDefinitionName `json:"name,omitempty"` - Note []*Annotation `json:"note,omitempty"` - NucleicAcid *Reference `json:"nucleicAcid,omitempty"` - Polymer *Reference `json:"polymer,omitempty"` - Property []*SubstanceDefinitionProperty `json:"property,omitempty"` - Protein *Reference `json:"protein,omitempty"` - ReferenceInformation *Reference `json:"referenceInformation,omitempty"` - Relationship []*SubstanceDefinitionRelationship `json:"relationship,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SourceMaterial *SubstanceDefinitionSourceMaterial `json:"sourceMaterial,omitempty"` - Status *CodeableConcept `json:"status,omitempty"` - Structure *SubstanceDefinitionStructure `json:"structure,omitempty"` - Supplier []*Reference `json:"supplier,omitempty"` - Text *Narrative `json:"text,omitempty"` - Version *string `json:"version,omitempty"` -} - -// SubstanceDefinitionCharacterization -type SubstanceDefinitionCharacterization struct { - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - Description *string `json:"description,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - File []*Attachment `json:"file,omitempty"` - Form *CodeableConcept `json:"form,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Technique *CodeableConcept `json:"technique,omitempty"` -} - -// SubstanceDefinitionCode -type SubstanceDefinitionCode struct { - XStatusDate *FHIRPrimitiveExtension `json:"_statusDate,omitempty"` - Code *CodeableConcept `json:"code,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Source []*Reference `json:"source,omitempty"` - Status *CodeableConcept `json:"status,omitempty"` - StatusDate *string `json:"statusDate,omitempty"` -} - -// SubstanceDefinitionMoiety -type SubstanceDefinitionMoiety struct { - XAmountString *FHIRPrimitiveExtension `json:"_amountString,omitempty"` - XMolecularFormula *FHIRPrimitiveExtension `json:"_molecularFormula,omitempty"` - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - AmountQuantity *Quantity `json:"amountQuantity,omitempty"` - AmountString *string `json:"amountString,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier *Identifier `json:"identifier,omitempty"` - Links [][]any `json:"links,omitempty"` - MeasurementType *CodeableConcept `json:"measurementType,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - MolecularFormula *string `json:"molecularFormula,omitempty"` - Name *string `json:"name,omitempty"` - OpticalActivity *CodeableConcept `json:"opticalActivity,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Role *CodeableConcept `json:"role,omitempty"` - Stereochemistry *CodeableConcept `json:"stereochemistry,omitempty"` -} - -// SubstanceDefinitionMolecularWeight -type SubstanceDefinitionMolecularWeight struct { - Amount *Quantity `json:"amount"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Method *CodeableConcept `json:"method,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` -} - -// SubstanceDefinitionName -type SubstanceDefinitionName struct { - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - XPreferred *FHIRPrimitiveExtension `json:"_preferred,omitempty"` - Domain []*CodeableConcept `json:"domain,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Jurisdiction []*CodeableConcept `json:"jurisdiction,omitempty"` - Language []*CodeableConcept `json:"language,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Name *string `json:"name,omitempty"` - Official []*SubstanceDefinitionNameOfficial `json:"official,omitempty"` - Preferred *bool `json:"preferred,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Source []*Reference `json:"source,omitempty"` - Status *CodeableConcept `json:"status,omitempty"` - Synonym []*SubstanceDefinitionName `json:"synonym,omitempty"` - Translation []*SubstanceDefinitionName `json:"translation,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` -} - -// SubstanceDefinitionNameOfficial -type SubstanceDefinitionNameOfficial struct { - XDate *FHIRPrimitiveExtension `json:"_date,omitempty"` - Authority *CodeableConcept `json:"authority,omitempty"` - Date *string `json:"date,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Status *CodeableConcept `json:"status,omitempty"` -} - -// SubstanceDefinitionProperty -type SubstanceDefinitionProperty struct { - XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` - XValueDate *FHIRPrimitiveExtension `json:"_valueDate,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *CodeableConcept `json:"type"` - ValueAttachment *Attachment `json:"valueAttachment,omitempty"` - ValueBoolean *bool `json:"valueBoolean,omitempty"` - ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` - ValueDate *string `json:"valueDate,omitempty"` - ValueQuantity *Quantity `json:"valueQuantity,omitempty"` -} - -// SubstanceDefinitionRelationship -type SubstanceDefinitionRelationship struct { - XAmountString *FHIRPrimitiveExtension `json:"_amountString,omitempty"` - XIsDefining *FHIRPrimitiveExtension `json:"_isDefining,omitempty"` - AmountQuantity *Quantity `json:"amountQuantity,omitempty"` - AmountRatio *Ratio `json:"amountRatio,omitempty"` - AmountString *string `json:"amountString,omitempty"` - Comparator *CodeableConcept `json:"comparator,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - IsDefining *bool `json:"isDefining,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - RatioHighLimitAmount *Ratio `json:"ratioHighLimitAmount,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Source []*Reference `json:"source,omitempty"` - SubstanceDefinitionCodeableConcept *CodeableConcept `json:"substanceDefinitionCodeableConcept,omitempty"` - SubstanceDefinitionReference *Reference `json:"substanceDefinitionReference,omitempty"` - Type *CodeableConcept `json:"type"` -} - -// SubstanceDefinitionSourceMaterial -type SubstanceDefinitionSourceMaterial struct { - CountryOfOrigin []*CodeableConcept `json:"countryOfOrigin,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Genus *CodeableConcept `json:"genus,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Part *CodeableConcept `json:"part,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Species *CodeableConcept `json:"species,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` -} - -// SubstanceDefinitionStructure -type SubstanceDefinitionStructure struct { - XMolecularFormula *FHIRPrimitiveExtension `json:"_molecularFormula,omitempty"` - XMolecularFormulaByMoiety *FHIRPrimitiveExtension `json:"_molecularFormulaByMoiety,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - MolecularFormula *string `json:"molecularFormula,omitempty"` - MolecularFormulaByMoiety *string `json:"molecularFormulaByMoiety,omitempty"` - MolecularWeight *SubstanceDefinitionMolecularWeight `json:"molecularWeight,omitempty"` - OpticalActivity *CodeableConcept `json:"opticalActivity,omitempty"` - Representation []*SubstanceDefinitionStructureRepresentation `json:"representation,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SourceDocument []*Reference `json:"sourceDocument,omitempty"` - Stereochemistry *CodeableConcept `json:"stereochemistry,omitempty"` - Technique []*CodeableConcept `json:"technique,omitempty"` -} - -// SubstanceDefinitionStructureRepresentation -type SubstanceDefinitionStructureRepresentation struct { - XRepresentation *FHIRPrimitiveExtension `json:"_representation,omitempty"` - Document *Reference `json:"document,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Format *CodeableConcept `json:"format,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Representation *string `json:"representation,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *CodeableConcept `json:"type,omitempty"` -} - -// SubstanceIngredient -type SubstanceIngredient struct { - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Quantity *Ratio `json:"quantity,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SubstanceCodeableConcept *CodeableConcept `json:"substanceCodeableConcept,omitempty"` - SubstanceReference *Reference `json:"substanceReference,omitempty"` -} - -// Task -type Task struct { - XAuthoredOn *FHIRPrimitiveExtension `json:"_authoredOn,omitempty"` - XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` - XDoNotPerform *FHIRPrimitiveExtension `json:"_doNotPerform,omitempty"` - XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` - XInstantiatesCanonical *FHIRPrimitiveExtension `json:"_instantiatesCanonical,omitempty"` - XInstantiatesURI *FHIRPrimitiveExtension `json:"_instantiatesUri,omitempty"` - XIntent *FHIRPrimitiveExtension `json:"_intent,omitempty"` - XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` - XLastModified *FHIRPrimitiveExtension `json:"_lastModified,omitempty"` - XPriority *FHIRPrimitiveExtension `json:"_priority,omitempty"` - XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` - AuthoredOn *string `json:"authoredOn,omitempty"` - BasedOn []*Reference `json:"basedOn,omitempty"` - BusinessStatus *CodeableConcept `json:"businessStatus,omitempty"` - Code *CodeableConcept `json:"code,omitempty"` - Contained []*Resource `json:"contained,omitempty"` - Description *string `json:"description,omitempty"` - DoNotPerform *bool `json:"doNotPerform,omitempty"` - Encounter *Reference `json:"encounter,omitempty"` - ExecutionPeriod *Period `json:"executionPeriod,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Focus *Reference `json:"focus,omitempty"` - ForFhir *Reference `json:"for_fhir,omitempty"` - GroupIDentifier *Identifier `json:"groupIdentifier,omitempty"` - ID *string `json:"id,omitempty"` - IDentifier []*Identifier `json:"identifier,omitempty"` - ImplicitRules *string `json:"implicitRules,omitempty"` - Input []*TaskInput `json:"input,omitempty"` - InstantiatesCanonical *string `json:"instantiatesCanonical,omitempty"` - InstantiatesURI *string `json:"instantiatesUri,omitempty"` - Insurance []*Reference `json:"insurance,omitempty"` - Intent *string `json:"intent,omitempty"` - Language *string `json:"language,omitempty"` - LastModified *string `json:"lastModified,omitempty"` - Links [][]any `json:"links,omitempty"` - Location *Reference `json:"location,omitempty"` - Meta *Meta `json:"meta,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Note []*Annotation `json:"note,omitempty"` - Output []*TaskOutput `json:"output,omitempty"` - Owner *Reference `json:"owner,omitempty"` - PartOf []*Reference `json:"partOf,omitempty"` - Performer []*TaskPerformer `json:"performer,omitempty"` - Priority *string `json:"priority,omitempty"` - Reason []*CodeableReference `json:"reason,omitempty"` - RelevantHistory []*Reference `json:"relevantHistory,omitempty"` - RequestedPerformer []*CodeableReference `json:"requestedPerformer,omitempty"` - RequestedPeriod *Period `json:"requestedPeriod,omitempty"` - Requester *Reference `json:"requester,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Restriction *TaskRestriction `json:"restriction,omitempty"` - Status *string `json:"status,omitempty"` - StatusReason *CodeableReference `json:"statusReason,omitempty"` - Text *Narrative `json:"text,omitempty"` -} - -// TaskInput -type TaskInput struct { - XValueBase64Binary *FHIRPrimitiveExtension `json:"_valueBase64Binary,omitempty"` - XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` - XValueCanonical *FHIRPrimitiveExtension `json:"_valueCanonical,omitempty"` - XValueCode *FHIRPrimitiveExtension `json:"_valueCode,omitempty"` - XValueDate *FHIRPrimitiveExtension `json:"_valueDate,omitempty"` - XValueDateTime *FHIRPrimitiveExtension `json:"_valueDateTime,omitempty"` - XValueDecimal *FHIRPrimitiveExtension `json:"_valueDecimal,omitempty"` - XValueID *FHIRPrimitiveExtension `json:"_valueId,omitempty"` - XValueInstant *FHIRPrimitiveExtension `json:"_valueInstant,omitempty"` - XValueInteger *FHIRPrimitiveExtension `json:"_valueInteger,omitempty"` - XValueInteger64 *FHIRPrimitiveExtension `json:"_valueInteger64,omitempty"` - XValueMarkdown *FHIRPrimitiveExtension `json:"_valueMarkdown,omitempty"` - XValueOid *FHIRPrimitiveExtension `json:"_valueOid,omitempty"` - XValuePositiveInt *FHIRPrimitiveExtension `json:"_valuePositiveInt,omitempty"` - XValueString *FHIRPrimitiveExtension `json:"_valueString,omitempty"` - XValueTime *FHIRPrimitiveExtension `json:"_valueTime,omitempty"` - XValueUnsignedInt *FHIRPrimitiveExtension `json:"_valueUnsignedInt,omitempty"` - XValueURI *FHIRPrimitiveExtension `json:"_valueUri,omitempty"` - XValueURL *FHIRPrimitiveExtension `json:"_valueUrl,omitempty"` - XValueUUID *FHIRPrimitiveExtension `json:"_valueUuid,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *CodeableConcept `json:"type"` - ValueAddress *Address `json:"valueAddress,omitempty"` - ValueAge *Age `json:"valueAge,omitempty"` - ValueAnnotation *Annotation `json:"valueAnnotation,omitempty"` - ValueAttachment *Attachment `json:"valueAttachment,omitempty"` - ValueAvailability *Availability `json:"valueAvailability,omitempty"` - ValueBase64Binary *string `json:"valueBase64Binary,omitempty"` - ValueBoolean *bool `json:"valueBoolean,omitempty"` - ValueCanonical *string `json:"valueCanonical,omitempty"` - ValueCode *string `json:"valueCode,omitempty"` - ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` - ValueCodeableReference *CodeableReference `json:"valueCodeableReference,omitempty"` - ValueCoding *Coding `json:"valueCoding,omitempty"` - ValueContactDetail *ContactDetail `json:"valueContactDetail,omitempty"` - ValueContactPoint *ContactPoint `json:"valueContactPoint,omitempty"` - ValueCount *Count `json:"valueCount,omitempty"` - ValueDataRequirement *DataRequirement `json:"valueDataRequirement,omitempty"` - ValueDate *string `json:"valueDate,omitempty"` - ValueDateTime *string `json:"valueDateTime,omitempty"` - ValueDecimal *float64 `json:"valueDecimal,omitempty"` - ValueDistance *Distance `json:"valueDistance,omitempty"` - ValueDosage *Dosage `json:"valueDosage,omitempty"` - ValueDuration *Duration `json:"valueDuration,omitempty"` - ValueExpression *Expression `json:"valueExpression,omitempty"` - ValueExtendedContactDetail *ExtendedContactDetail `json:"valueExtendedContactDetail,omitempty"` - ValueHumanName *HumanName `json:"valueHumanName,omitempty"` - ValueID *string `json:"valueId,omitempty"` - ValueIDentifier *Identifier `json:"valueIdentifier,omitempty"` - ValueInstant *string `json:"valueInstant,omitempty"` - ValueInteger *int64 `json:"valueInteger,omitempty"` - ValueInteger64 *int64 `json:"valueInteger64,omitempty"` - ValueMarkdown *string `json:"valueMarkdown,omitempty"` - ValueMeta *Meta `json:"valueMeta,omitempty"` - ValueMoney *Money `json:"valueMoney,omitempty"` - ValueOid *string `json:"valueOid,omitempty"` - ValueParameterDefinition *ParameterDefinition `json:"valueParameterDefinition,omitempty"` - ValuePeriod *Period `json:"valuePeriod,omitempty"` - ValuePositiveInt *int64 `json:"valuePositiveInt,omitempty"` - ValueQuantity *Quantity `json:"valueQuantity,omitempty"` - ValueRange *Range `json:"valueRange,omitempty"` - ValueRatio *Ratio `json:"valueRatio,omitempty"` - ValueRatioRange *RatioRange `json:"valueRatioRange,omitempty"` - ValueReference *Reference `json:"valueReference,omitempty"` - ValueRelatedArtifact *RelatedArtifact `json:"valueRelatedArtifact,omitempty"` - ValueSampledData *SampledData `json:"valueSampledData,omitempty"` - ValueSignature *Signature `json:"valueSignature,omitempty"` - ValueString *string `json:"valueString,omitempty"` - ValueTime *string `json:"valueTime,omitempty"` - ValueTiming *Timing `json:"valueTiming,omitempty"` - ValueTriggerDefinition *TriggerDefinition `json:"valueTriggerDefinition,omitempty"` - ValueUnsignedInt *int64 `json:"valueUnsignedInt,omitempty"` - ValueURI *string `json:"valueUri,omitempty"` - ValueURL *string `json:"valueUrl,omitempty"` - ValueUsageContext *UsageContext `json:"valueUsageContext,omitempty"` - ValueUUID *string `json:"valueUuid,omitempty"` -} - -// TaskOutput -type TaskOutput struct { - XValueBase64Binary *FHIRPrimitiveExtension `json:"_valueBase64Binary,omitempty"` - XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` - XValueCanonical *FHIRPrimitiveExtension `json:"_valueCanonical,omitempty"` - XValueCode *FHIRPrimitiveExtension `json:"_valueCode,omitempty"` - XValueDate *FHIRPrimitiveExtension `json:"_valueDate,omitempty"` - XValueDateTime *FHIRPrimitiveExtension `json:"_valueDateTime,omitempty"` - XValueDecimal *FHIRPrimitiveExtension `json:"_valueDecimal,omitempty"` - XValueID *FHIRPrimitiveExtension `json:"_valueId,omitempty"` - XValueInstant *FHIRPrimitiveExtension `json:"_valueInstant,omitempty"` - XValueInteger *FHIRPrimitiveExtension `json:"_valueInteger,omitempty"` - XValueInteger64 *FHIRPrimitiveExtension `json:"_valueInteger64,omitempty"` - XValueMarkdown *FHIRPrimitiveExtension `json:"_valueMarkdown,omitempty"` - XValueOid *FHIRPrimitiveExtension `json:"_valueOid,omitempty"` - XValuePositiveInt *FHIRPrimitiveExtension `json:"_valuePositiveInt,omitempty"` - XValueString *FHIRPrimitiveExtension `json:"_valueString,omitempty"` - XValueTime *FHIRPrimitiveExtension `json:"_valueTime,omitempty"` - XValueUnsignedInt *FHIRPrimitiveExtension `json:"_valueUnsignedInt,omitempty"` - XValueURI *FHIRPrimitiveExtension `json:"_valueUri,omitempty"` - XValueURL *FHIRPrimitiveExtension `json:"_valueUrl,omitempty"` - XValueUUID *FHIRPrimitiveExtension `json:"_valueUuid,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - Type *CodeableConcept `json:"type"` - ValueAddress *Address `json:"valueAddress,omitempty"` - ValueAge *Age `json:"valueAge,omitempty"` - ValueAnnotation *Annotation `json:"valueAnnotation,omitempty"` - ValueAttachment *Attachment `json:"valueAttachment,omitempty"` - ValueAvailability *Availability `json:"valueAvailability,omitempty"` - ValueBase64Binary *string `json:"valueBase64Binary,omitempty"` - ValueBoolean *bool `json:"valueBoolean,omitempty"` - ValueCanonical *string `json:"valueCanonical,omitempty"` - ValueCode *string `json:"valueCode,omitempty"` - ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` - ValueCodeableReference *CodeableReference `json:"valueCodeableReference,omitempty"` - ValueCoding *Coding `json:"valueCoding,omitempty"` - ValueContactDetail *ContactDetail `json:"valueContactDetail,omitempty"` - ValueContactPoint *ContactPoint `json:"valueContactPoint,omitempty"` - ValueCount *Count `json:"valueCount,omitempty"` - ValueDataRequirement *DataRequirement `json:"valueDataRequirement,omitempty"` - ValueDate *string `json:"valueDate,omitempty"` - ValueDateTime *string `json:"valueDateTime,omitempty"` - ValueDecimal *float64 `json:"valueDecimal,omitempty"` - ValueDistance *Distance `json:"valueDistance,omitempty"` - ValueDosage *Dosage `json:"valueDosage,omitempty"` - ValueDuration *Duration `json:"valueDuration,omitempty"` - ValueExpression *Expression `json:"valueExpression,omitempty"` - ValueExtendedContactDetail *ExtendedContactDetail `json:"valueExtendedContactDetail,omitempty"` - ValueHumanName *HumanName `json:"valueHumanName,omitempty"` - ValueID *string `json:"valueId,omitempty"` - ValueIDentifier *Identifier `json:"valueIdentifier,omitempty"` - ValueInstant *string `json:"valueInstant,omitempty"` - ValueInteger *int64 `json:"valueInteger,omitempty"` - ValueInteger64 *int64 `json:"valueInteger64,omitempty"` - ValueMarkdown *string `json:"valueMarkdown,omitempty"` - ValueMeta *Meta `json:"valueMeta,omitempty"` - ValueMoney *Money `json:"valueMoney,omitempty"` - ValueOid *string `json:"valueOid,omitempty"` - ValueParameterDefinition *ParameterDefinition `json:"valueParameterDefinition,omitempty"` - ValuePeriod *Period `json:"valuePeriod,omitempty"` - ValuePositiveInt *int64 `json:"valuePositiveInt,omitempty"` - ValueQuantity *Quantity `json:"valueQuantity,omitempty"` - ValueRange *Range `json:"valueRange,omitempty"` - ValueRatio *Ratio `json:"valueRatio,omitempty"` - ValueRatioRange *RatioRange `json:"valueRatioRange,omitempty"` - ValueReference *Reference `json:"valueReference,omitempty"` - ValueRelatedArtifact *RelatedArtifact `json:"valueRelatedArtifact,omitempty"` - ValueSampledData *SampledData `json:"valueSampledData,omitempty"` - ValueSignature *Signature `json:"valueSignature,omitempty"` - ValueString *string `json:"valueString,omitempty"` - ValueTime *string `json:"valueTime,omitempty"` - ValueTiming *Timing `json:"valueTiming,omitempty"` - ValueTriggerDefinition *TriggerDefinition `json:"valueTriggerDefinition,omitempty"` - ValueUnsignedInt *int64 `json:"valueUnsignedInt,omitempty"` - ValueURI *string `json:"valueUri,omitempty"` - ValueURL *string `json:"valueUrl,omitempty"` - ValueUsageContext *UsageContext `json:"valueUsageContext,omitempty"` - ValueUUID *string `json:"valueUuid,omitempty"` -} - -// TaskPerformer -type TaskPerformer struct { - Actor *Reference `json:"actor"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Function *CodeableConcept `json:"function,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// TaskRestriction -type TaskRestriction struct { - XRepetitions *FHIRPrimitiveExtension `json:"_repetitions,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Period *Period `json:"period,omitempty"` - Recipient []*Reference `json:"recipient,omitempty"` - Repetitions *int64 `json:"repetitions,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// Timing -type Timing struct { - XEvent []*FHIRPrimitiveExtension `json:"_event,omitempty"` - Code *CodeableConcept `json:"code,omitempty"` - Event []string `json:"event,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ModifierExtension []*Extension `json:"modifierExtension,omitempty"` - Repeat *TimingRepeat `json:"repeat,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` -} - -// TimingRepeat -type TimingRepeat struct { - XCount *FHIRPrimitiveExtension `json:"_count,omitempty"` - XCountMax *FHIRPrimitiveExtension `json:"_countMax,omitempty"` - XDayOfWeek []*FHIRPrimitiveExtension `json:"_dayOfWeek,omitempty"` - XDuration *FHIRPrimitiveExtension `json:"_duration,omitempty"` - XDurationMax *FHIRPrimitiveExtension `json:"_durationMax,omitempty"` - XDurationUnit *FHIRPrimitiveExtension `json:"_durationUnit,omitempty"` - XFrequency *FHIRPrimitiveExtension `json:"_frequency,omitempty"` - XFrequencyMax *FHIRPrimitiveExtension `json:"_frequencyMax,omitempty"` - XOffset *FHIRPrimitiveExtension `json:"_offset,omitempty"` - XPeriod *FHIRPrimitiveExtension `json:"_period,omitempty"` - XPeriodMax *FHIRPrimitiveExtension `json:"_periodMax,omitempty"` - XPeriodUnit *FHIRPrimitiveExtension `json:"_periodUnit,omitempty"` - XTimeOfDay []*FHIRPrimitiveExtension `json:"_timeOfDay,omitempty"` - XWhen []*FHIRPrimitiveExtension `json:"_when,omitempty"` - BoundsDuration *Duration `json:"boundsDuration,omitempty"` - BoundsPeriod *Period `json:"boundsPeriod,omitempty"` - BoundsRange *Range `json:"boundsRange,omitempty"` - Count *int64 `json:"count,omitempty"` - CountMax *int64 `json:"countMax,omitempty"` - DayOfWeek []string `json:"dayOfWeek,omitempty"` - Duration *float64 `json:"duration,omitempty"` - DurationMax *float64 `json:"durationMax,omitempty"` - DurationUnit *string `json:"durationUnit,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - Frequency *int64 `json:"frequency,omitempty"` - FrequencyMax *int64 `json:"frequencyMax,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Offset *int64 `json:"offset,omitempty"` - Period *float64 `json:"period,omitempty"` - PeriodMax *float64 `json:"periodMax,omitempty"` - PeriodUnit *string `json:"periodUnit,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - TimeOfDay []string `json:"timeOfDay,omitempty"` - When []string `json:"when,omitempty"` -} - -// TriggerDefinition -type TriggerDefinition struct { - XName *FHIRPrimitiveExtension `json:"_name,omitempty"` - XSubscriptionTopic *FHIRPrimitiveExtension `json:"_subscriptionTopic,omitempty"` - XTimingDate *FHIRPrimitiveExtension `json:"_timingDate,omitempty"` - XTimingDateTime *FHIRPrimitiveExtension `json:"_timingDateTime,omitempty"` - XType *FHIRPrimitiveExtension `json:"_type,omitempty"` - Code *CodeableConcept `json:"code,omitempty"` - Condition *Expression `json:"condition,omitempty"` - Data []*DataRequirement `json:"data,omitempty"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - Name *string `json:"name,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - SubscriptionTopic *string `json:"subscriptionTopic,omitempty"` - TimingDate *string `json:"timingDate,omitempty"` - TimingDateTime *string `json:"timingDateTime,omitempty"` - TimingReference *Reference `json:"timingReference,omitempty"` - TimingTiming *Timing `json:"timingTiming,omitempty"` - Type *string `json:"type,omitempty"` -} - -// UsageContext -type UsageContext struct { - Code *Coding `json:"code"` - Extension []*Extension `json:"extension,omitempty"` - FhirComments FHIRComments `json:"fhir_comments,omitempty"` - ID *string `json:"id,omitempty"` - Links [][]any `json:"links,omitempty"` - ResourceType *string `json:"resourceType,omitempty"` - ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` - ValueQuantity *Quantity `json:"valueQuantity,omitempty"` - ValueRange *Range `json:"valueRange,omitempty"` - ValueReference *Reference `json:"valueReference,omitempty"` -} diff --git a/internal/fhir/validate.go b/internal/fhir/validate.go deleted file mode 100644 index 2af3296..0000000 --- a/internal/fhir/validate.go +++ /dev/null @@ -1,14864 +0,0 @@ -// Code generated by cmd/generate/main.go. DO NOT EDIT. -package fhir - -import ( - "fmt" - "regexp" - "unicode/utf8" -) - -// Pre-compiled regular expressions for pattern validation -var ( - rx_Address_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Address_Use = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Age_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Age_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Annotation_Text = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_Attachment_ContentType = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Attachment_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_AvailabilityAvailableTime_DaysOfWeek_items = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_BodyStructure_Description = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_BodyStructure_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_BodyStructure_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Coding_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Condition_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Condition_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ContactPoint_System = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ContactPoint_Use = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Count_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Count_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_DataRequirement_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_DataRequirementSort_Direction = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_DataRequirementValueFilter_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_DiagnosticReport_Conclusion = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_DiagnosticReport_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_DiagnosticReport_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_DiagnosticReport_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Directory_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Distance_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Distance_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_DocumentReference_Description = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_DocumentReference_DocStatus = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_DocumentReference_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_DocumentReference_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_DocumentReference_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Duration_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Duration_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Expression_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Expression_Name = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Extension_ValueCode = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Extension_ValueID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Extension_ValueMarkdown = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_Extension_ValueOid = regexp.MustCompile("^urn:oid:[0-2](\\.(0|[1-9][0-9]*))+$") - rx_FamilyMemberHistory_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_FamilyMemberHistory_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_FamilyMemberHistory_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Group_Description = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_Group_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Group_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Group_Membership = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Group_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_HumanName_Use = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Identifier_Use = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ImagingStudy_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_ImagingStudy_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ImagingStudy_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ImagingStudySeries_Uid = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_ImagingStudySeriesInstance_Uid = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Medication_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Medication_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Medication_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_MedicationAdministration_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_MedicationAdministration_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_MedicationAdministration_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_MedicationRequest_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_MedicationRequest_Intent = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_MedicationRequest_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_MedicationRequest_Priority = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_MedicationRequest_RenderedDosageInstruction = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_MedicationRequest_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_MedicationStatement_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_MedicationStatement_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_MedicationStatement_RenderedDosageInstruction = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_MedicationStatement_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Meta_VersionID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Money_Currency = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Narrative_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Observation_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Observation_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Observation_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ObservationReferenceRange_Text = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_ObservationTriggeredBy_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Organization_Description = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_Organization_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Organization_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ParameterDefinition_Name = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ParameterDefinition_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ParameterDefinition_Use = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Patient_Gender = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Patient_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Patient_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_PatientContact_Gender = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_PatientLink_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Practitioner_Gender = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Practitioner_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Practitioner_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_PractitionerRole_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_PractitionerRole_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Procedure_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Procedure_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Procedure_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Quantity_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Quantity_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_RelatedArtifact_Citation = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_RelatedArtifact_PublicationStatus = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_RelatedArtifact_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ResearchStudy_Description = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_ResearchStudy_DescriptionSummary = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_ResearchStudy_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_ResearchStudy_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ResearchStudy_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ResearchStudyComparisonGroup_Description = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_ResearchStudyComparisonGroup_LinkID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_ResearchStudyObjective_Description = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_ResearchStudyOutcomeMeasure_Description = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_ResearchSubject_ActualComparisonGroup = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_ResearchSubject_AssignedComparisonGroup = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_ResearchSubject_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_ResearchSubject_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_ResearchSubject_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Resource_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Resource_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_SampledData_IntervalUnit = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Signature_SigFormat = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Signature_TargetFormat = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Specimen_Combined = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Specimen_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Specimen_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Specimen_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Substance_Description = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_Substance_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Substance_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Substance_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_SubstanceDefinition_Description = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_SubstanceDefinition_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_SubstanceDefinition_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_SubstanceDefinitionCharacterization_Description = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_Task_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_Task_Intent = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Task_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Task_Priority = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_Task_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_TaskInput_ValueCode = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_TaskInput_ValueID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_TaskInput_ValueMarkdown = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_TaskInput_ValueOid = regexp.MustCompile("^urn:oid:[0-2](\\.(0|[1-9][0-9]*))+$") - rx_TaskOutput_ValueCode = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_TaskOutput_ValueID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") - rx_TaskOutput_ValueMarkdown = regexp.MustCompile("\\s*(\\S|\\s)*") - rx_TaskOutput_ValueOid = regexp.MustCompile("^urn:oid:[0-2](\\.(0|[1-9][0-9]*))+$") - rx_TimingRepeat_DayOfWeek_items = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_TimingRepeat_DurationUnit = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_TimingRepeat_PeriodUnit = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_TimingRepeat_When_items = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") - rx_TriggerDefinition_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") -) - -// Validate validates a Address struct against its schema constraints. -func (x *Address) Validate() error { - if x == nil { - return nil - } - if x.XCity != nil { - if err := x.XCity.Validate(); err != nil { - return fmt.Errorf("field '_city' is invalid: %w", err) - } - } - if x.XCountry != nil { - if err := x.XCountry.Validate(); err != nil { - return fmt.Errorf("field '_country' is invalid: %w", err) - } - } - if x.XDistrict != nil { - if err := x.XDistrict.Validate(); err != nil { - return fmt.Errorf("field '_district' is invalid: %w", err) - } - } - if x.XLine != nil { - for i, item := range x.XLine { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field '_line[%d]' is invalid: %w", i, err) - } - } - } - } - if x.XPostalCode != nil { - if err := x.XPostalCode.Validate(); err != nil { - return fmt.Errorf("field '_postalCode' is invalid: %w", err) - } - } - if x.XState != nil { - if err := x.XState.Validate(); err != nil { - return fmt.Errorf("field '_state' is invalid: %w", err) - } - } - if x.XText != nil { - if err := x.XText.Validate(); err != nil { - return fmt.Errorf("field '_text' is invalid: %w", err) - } - } - if x.XType != nil { - if err := x.XType.Validate(); err != nil { - return fmt.Errorf("field '_type' is invalid: %w", err) - } - } - if x.XUse != nil { - if err := x.XUse.Validate(); err != nil { - return fmt.Errorf("field '_use' is invalid: %w", err) - } - } - if x.City != nil { - if *x.City == "" { - return fmt.Errorf("field 'city' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Country != nil { - if *x.Country == "" { - return fmt.Errorf("field 'country' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.District != nil { - if *x.District == "" { - return fmt.Errorf("field 'district' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Line != nil { - for i, item := range x.Line { - if item == "" { - return fmt.Errorf("field 'line[%d]' does not match pattern '[ \\r\\n\\t\\S]+'", i) - } - } - } - if x.Links != nil { - } - if x.Period != nil { - if err := x.Period.Validate(); err != nil { - return fmt.Errorf("field 'period' is invalid: %w", err) - } - } - if x.PostalCode != nil { - if *x.PostalCode == "" { - return fmt.Errorf("field 'postalCode' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.ResourceType != nil { - if *x.ResourceType != "Address" { - return fmt.Errorf("field 'resourceType' must be exactly 'Address'") - } - } - if x.State != nil { - if *x.State == "" { - return fmt.Errorf("field 'state' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Text != nil { - if *x.Text == "" { - return fmt.Errorf("field 'text' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Type != nil { - if !rx_Address_Type.MatchString(*x.Type) { - return fmt.Errorf("field 'type' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Use != nil { - if !rx_Address_Use.MatchString(*x.Use) { - return fmt.Errorf("field 'use' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - return nil -} - -// Validate validates a Age struct against its schema constraints. -func (x *Age) Validate() error { - if x == nil { - return nil - } - if x.XCode != nil { - if err := x.XCode.Validate(); err != nil { - return fmt.Errorf("field '_code' is invalid: %w", err) - } - } - if x.XComparator != nil { - if err := x.XComparator.Validate(); err != nil { - return fmt.Errorf("field '_comparator' is invalid: %w", err) - } - } - if x.XSystem != nil { - if err := x.XSystem.Validate(); err != nil { - return fmt.Errorf("field '_system' is invalid: %w", err) - } - } - if x.XUnit != nil { - if err := x.XUnit.Validate(); err != nil { - return fmt.Errorf("field '_unit' is invalid: %w", err) - } - } - if x.XValue != nil { - if err := x.XValue.Validate(); err != nil { - return fmt.Errorf("field '_value' is invalid: %w", err) - } - } - if x.Code != nil { - if !rx_Age_Code.MatchString(*x.Code) { - return fmt.Errorf("field 'code' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Comparator != nil { - if !rx_Age_Comparator.MatchString(*x.Comparator) { - return fmt.Errorf("field 'comparator' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "Age" { - return fmt.Errorf("field 'resourceType' must be exactly 'Age'") - } - } - if x.System != nil { - } - if x.Unit != nil { - if *x.Unit == "" { - return fmt.Errorf("field 'unit' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Value != nil { - } - return nil -} - -// Validate validates a Annotation struct against its schema constraints. -func (x *Annotation) Validate() error { - if x == nil { - return nil - } - if x.XAuthorString != nil { - if err := x.XAuthorString.Validate(); err != nil { - return fmt.Errorf("field '_authorString' is invalid: %w", err) - } - } - if x.XText != nil { - if err := x.XText.Validate(); err != nil { - return fmt.Errorf("field '_text' is invalid: %w", err) - } - } - if x.XTime != nil { - if err := x.XTime.Validate(); err != nil { - return fmt.Errorf("field '_time' is invalid: %w", err) - } - } - if x.AuthorReference != nil { - if err := x.AuthorReference.Validate(); err != nil { - return fmt.Errorf("field 'authorReference' is invalid: %w", err) - } - } - if x.AuthorString != nil { - if *x.AuthorString == "" { - return fmt.Errorf("field 'authorString' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "Annotation" { - return fmt.Errorf("field 'resourceType' must be exactly 'Annotation'") - } - } - if x.Text != nil { - if !rx_Annotation_Text.MatchString(*x.Text) { - return fmt.Errorf("field 'text' does not match pattern '\\s*(\\S|\\s)*'") - } - } - if x.Time != nil { - if err := ValidateFhirDateTime(*x.Time); err != nil { - return fmt.Errorf("field 'time' has invalid date-time format: %w", err) - } - } - return nil -} - -// Validate validates a Attachment struct against its schema constraints. -func (x *Attachment) Validate() error { - if x == nil { - return nil - } - if x.XContentType != nil { - if err := x.XContentType.Validate(); err != nil { - return fmt.Errorf("field '_contentType' is invalid: %w", err) - } - } - if x.XCreation != nil { - if err := x.XCreation.Validate(); err != nil { - return fmt.Errorf("field '_creation' is invalid: %w", err) - } - } - if x.XData != nil { - if err := x.XData.Validate(); err != nil { - return fmt.Errorf("field '_data' is invalid: %w", err) - } - } - if x.XDuration != nil { - if err := x.XDuration.Validate(); err != nil { - return fmt.Errorf("field '_duration' is invalid: %w", err) - } - } - if x.XFrames != nil { - if err := x.XFrames.Validate(); err != nil { - return fmt.Errorf("field '_frames' is invalid: %w", err) - } - } - if x.XHash != nil { - if err := x.XHash.Validate(); err != nil { - return fmt.Errorf("field '_hash' is invalid: %w", err) - } - } - if x.XHeight != nil { - if err := x.XHeight.Validate(); err != nil { - return fmt.Errorf("field '_height' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.XPages != nil { - if err := x.XPages.Validate(); err != nil { - return fmt.Errorf("field '_pages' is invalid: %w", err) - } - } - if x.XSize != nil { - if err := x.XSize.Validate(); err != nil { - return fmt.Errorf("field '_size' is invalid: %w", err) - } - } - if x.XTitle != nil { - if err := x.XTitle.Validate(); err != nil { - return fmt.Errorf("field '_title' is invalid: %w", err) - } - } - if x.XURL != nil { - if err := x.XURL.Validate(); err != nil { - return fmt.Errorf("field '_url' is invalid: %w", err) - } - } - if x.XWidth != nil { - if err := x.XWidth.Validate(); err != nil { - return fmt.Errorf("field '_width' is invalid: %w", err) - } - } - if x.ContentType != nil { - if !rx_Attachment_ContentType.MatchString(*x.ContentType) { - return fmt.Errorf("field 'contentType' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Creation != nil { - if err := ValidateFhirDateTime(*x.Creation); err != nil { - return fmt.Errorf("field 'creation' has invalid date-time format: %w", err) - } - } - if x.Data != nil { - if err := ValidateFhirBinary(*x.Data); err != nil { - return fmt.Errorf("field 'data' has invalid binary format: %w", err) - } - } - if x.Duration != nil { - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Frames != nil { - if *x.Frames <= 0.000000 { - return fmt.Errorf("field 'frames' is below exclusive minimum 0.000000") - } - } - if x.Hash != nil { - if err := ValidateFhirBinary(*x.Hash); err != nil { - return fmt.Errorf("field 'hash' has invalid binary format: %w", err) - } - } - if x.Height != nil { - if *x.Height <= 0.000000 { - return fmt.Errorf("field 'height' is below exclusive minimum 0.000000") - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Language != nil { - if !rx_Attachment_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.Pages != nil { - if *x.Pages <= 0.000000 { - return fmt.Errorf("field 'pages' is below exclusive minimum 0.000000") - } - } - if x.ResourceType != nil { - if *x.ResourceType != "Attachment" { - return fmt.Errorf("field 'resourceType' must be exactly 'Attachment'") - } - } - if x.Size != nil { - } - if x.Title != nil { - if *x.Title == "" { - return fmt.Errorf("field 'title' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.URL != nil { - if utf8.RuneCountInString(*x.URL) < 1 { - return fmt.Errorf("field 'url' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.URL) > 65536 { - return fmt.Errorf("field 'url' is too long (max 65536 characters)") - } - if err := ValidateFhirURI(*x.URL); err != nil { - return fmt.Errorf("field 'url' has invalid URI format: %w", err) - } - } - if x.Width != nil { - if *x.Width <= 0.000000 { - return fmt.Errorf("field 'width' is below exclusive minimum 0.000000") - } - } - return nil -} - -// Validate validates a Availability struct against its schema constraints. -func (x *Availability) Validate() error { - if x == nil { - return nil - } - if x.AvailableTime != nil { - for i, item := range x.AvailableTime { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'availableTime[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.NotAvailableTime != nil { - for i, item := range x.NotAvailableTime { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'notAvailableTime[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "Availability" { - return fmt.Errorf("field 'resourceType' must be exactly 'Availability'") - } - } - return nil -} - -// Validate validates a AvailabilityAvailableTime struct against its schema constraints. -func (x *AvailabilityAvailableTime) Validate() error { - if x == nil { - return nil - } - if x.XAllDay != nil { - if err := x.XAllDay.Validate(); err != nil { - return fmt.Errorf("field '_allDay' is invalid: %w", err) - } - } - if x.XAvailableEndTime != nil { - if err := x.XAvailableEndTime.Validate(); err != nil { - return fmt.Errorf("field '_availableEndTime' is invalid: %w", err) - } - } - if x.XAvailableStartTime != nil { - if err := x.XAvailableStartTime.Validate(); err != nil { - return fmt.Errorf("field '_availableStartTime' is invalid: %w", err) - } - } - if x.XDaysOfWeek != nil { - for i, item := range x.XDaysOfWeek { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field '_daysOfWeek[%d]' is invalid: %w", i, err) - } - } - } - } - if x.AllDay != nil { - } - if x.AvailableEndTime != nil { - if err := ValidateFhirTime(*x.AvailableEndTime); err != nil { - return fmt.Errorf("field 'availableEndTime' has invalid time format: %w", err) - } - } - if x.AvailableStartTime != nil { - if err := ValidateFhirTime(*x.AvailableStartTime); err != nil { - return fmt.Errorf("field 'availableStartTime' has invalid time format: %w", err) - } - } - if x.DaysOfWeek != nil { - for i, item := range x.DaysOfWeek { - if !rx_AvailabilityAvailableTime_DaysOfWeek_items.MatchString(item) { - return fmt.Errorf("field 'daysOfWeek[%d]' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'", i) - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "AvailabilityAvailableTime" { - return fmt.Errorf("field 'resourceType' must be exactly 'AvailabilityAvailableTime'") - } - } - return nil -} - -// Validate validates a AvailabilityNotAvailableTime struct against its schema constraints. -func (x *AvailabilityNotAvailableTime) Validate() error { - if x == nil { - return nil - } - if x.XDescription != nil { - if err := x.XDescription.Validate(); err != nil { - return fmt.Errorf("field '_description' is invalid: %w", err) - } - } - if x.Description != nil { - if *x.Description == "" { - return fmt.Errorf("field 'description' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.During != nil { - if err := x.During.Validate(); err != nil { - return fmt.Errorf("field 'during' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "AvailabilityNotAvailableTime" { - return fmt.Errorf("field 'resourceType' must be exactly 'AvailabilityNotAvailableTime'") - } - } - return nil -} - -// Validate validates a BodyStructure struct against its schema constraints. -func (x *BodyStructure) Validate() error { - if x == nil { - return nil - } - if x.XActive != nil { - if err := x.XActive.Validate(); err != nil { - return fmt.Errorf("field '_active' is invalid: %w", err) - } - } - if x.XDescription != nil { - if err := x.XDescription.Validate(); err != nil { - return fmt.Errorf("field '_description' is invalid: %w", err) - } - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.Active != nil { - } - if x.Contained != nil { - for i, item := range x.Contained { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Description != nil { - if !rx_BodyStructure_Description.MatchString(*x.Description) { - return fmt.Errorf("field 'description' does not match pattern '\\s*(\\S|\\s)*'") - } - } - if x.ExcludedStructure != nil { - for i, item := range x.ExcludedStructure { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'excludedStructure[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if !rx_BodyStructure_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Image != nil { - for i, item := range x.Image { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'image[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ImplicitRules != nil { - } - if x.IncludedStructure == nil { - return fmt.Errorf("required field 'includedStructure' is missing") - } - if x.IncludedStructure != nil { - for i, item := range x.IncludedStructure { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'includedStructure[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Language != nil { - if !rx_BodyStructure_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Morphology != nil { - if err := x.Morphology.Validate(); err != nil { - return fmt.Errorf("field 'morphology' is invalid: %w", err) - } - } - if x.Patient == nil { - return fmt.Errorf("required field 'patient' is missing") - } - if x.Patient != nil { - if err := x.Patient.Validate(); err != nil { - return fmt.Errorf("field 'patient' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "BodyStructure" { - return fmt.Errorf("field 'resourceType' must be exactly 'BodyStructure'") - } - } - if x.Text != nil { - if err := x.Text.Validate(); err != nil { - return fmt.Errorf("field 'text' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a BodyStructureIncludedStructure struct against its schema constraints. -func (x *BodyStructureIncludedStructure) Validate() error { - if x == nil { - return nil - } - if x.BodyLandmarkOrientation != nil { - for i, item := range x.BodyLandmarkOrientation { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'bodyLandmarkOrientation[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Laterality != nil { - if err := x.Laterality.Validate(); err != nil { - return fmt.Errorf("field 'laterality' is invalid: %w", err) - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Qualifier != nil { - for i, item := range x.Qualifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'qualifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "BodyStructureIncludedStructure" { - return fmt.Errorf("field 'resourceType' must be exactly 'BodyStructureIncludedStructure'") - } - } - if x.SpatialReference != nil { - for i, item := range x.SpatialReference { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'spatialReference[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Structure == nil { - return fmt.Errorf("required field 'structure' is missing") - } - if x.Structure != nil { - if err := x.Structure.Validate(); err != nil { - return fmt.Errorf("field 'structure' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a BodyStructureIncludedStructureBodyLandmarkOrientation struct against its schema constraints. -func (x *BodyStructureIncludedStructureBodyLandmarkOrientation) Validate() error { - if x == nil { - return nil - } - if x.ClockFacePosition != nil { - for i, item := range x.ClockFacePosition { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'clockFacePosition[%d]' is invalid: %w", i, err) - } - } - } - } - if x.DistanceFromLandmark != nil { - for i, item := range x.DistanceFromLandmark { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'distanceFromLandmark[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.LandmarkDescription != nil { - for i, item := range x.LandmarkDescription { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'landmarkDescription[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "BodyStructureIncludedStructureBodyLandmarkOrientation" { - return fmt.Errorf("field 'resourceType' must be exactly 'BodyStructureIncludedStructureBodyLandmarkOrientation'") - } - } - if x.SurfaceOrientation != nil { - for i, item := range x.SurfaceOrientation { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'surfaceOrientation[%d]' is invalid: %w", i, err) - } - } - } - } - return nil -} - -// Validate validates a BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark struct against its schema constraints. -func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark) Validate() error { - if x == nil { - return nil - } - if x.Device != nil { - for i, item := range x.Device { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'device[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark" { - return fmt.Errorf("field 'resourceType' must be exactly 'BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark'") - } - } - if x.Value != nil { - for i, item := range x.Value { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'value[%d]' is invalid: %w", i, err) - } - } - } - } - return nil -} - -// Validate validates a CodeableConcept struct against its schema constraints. -func (x *CodeableConcept) Validate() error { - if x == nil { - return nil - } - if x.XText != nil { - if err := x.XText.Validate(); err != nil { - return fmt.Errorf("field '_text' is invalid: %w", err) - } - } - if x.Coding != nil { - for i, item := range x.Coding { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'coding[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "CodeableConcept" { - return fmt.Errorf("field 'resourceType' must be exactly 'CodeableConcept'") - } - } - if x.Text != nil { - if *x.Text == "" { - return fmt.Errorf("field 'text' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - return nil -} - -// Validate validates a CodeableReference struct against its schema constraints. -func (x *CodeableReference) Validate() error { - if x == nil { - return nil - } - if x.Concept != nil { - if err := x.Concept.Validate(); err != nil { - return fmt.Errorf("field 'concept' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Reference != nil { - if err := x.Reference.Validate(); err != nil { - return fmt.Errorf("field 'reference' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "CodeableReference" { - return fmt.Errorf("field 'resourceType' must be exactly 'CodeableReference'") - } - } - return nil -} - -// Validate validates a Coding struct against its schema constraints. -func (x *Coding) Validate() error { - if x == nil { - return nil - } - if x.XCode != nil { - if err := x.XCode.Validate(); err != nil { - return fmt.Errorf("field '_code' is invalid: %w", err) - } - } - if x.XDisplay != nil { - if err := x.XDisplay.Validate(); err != nil { - return fmt.Errorf("field '_display' is invalid: %w", err) - } - } - if x.XSystem != nil { - if err := x.XSystem.Validate(); err != nil { - return fmt.Errorf("field '_system' is invalid: %w", err) - } - } - if x.XUserSelected != nil { - if err := x.XUserSelected.Validate(); err != nil { - return fmt.Errorf("field '_userSelected' is invalid: %w", err) - } - } - if x.XVersion != nil { - if err := x.XVersion.Validate(); err != nil { - return fmt.Errorf("field '_version' is invalid: %w", err) - } - } - if x.Code != nil { - if !rx_Coding_Code.MatchString(*x.Code) { - return fmt.Errorf("field 'code' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Display != nil { - if *x.Display == "" { - return fmt.Errorf("field 'display' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "Coding" { - return fmt.Errorf("field 'resourceType' must be exactly 'Coding'") - } - } - if x.System != nil { - } - if x.UserSelected != nil { - } - if x.Version != nil { - if *x.Version == "" { - return fmt.Errorf("field 'version' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - return nil -} - -// Validate validates a Condition struct against its schema constraints. -func (x *Condition) Validate() error { - if x == nil { - return nil - } - if x.XAbatementDateTime != nil { - if err := x.XAbatementDateTime.Validate(); err != nil { - return fmt.Errorf("field '_abatementDateTime' is invalid: %w", err) - } - } - if x.XAbatementString != nil { - if err := x.XAbatementString.Validate(); err != nil { - return fmt.Errorf("field '_abatementString' is invalid: %w", err) - } - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.XOnsetDateTime != nil { - if err := x.XOnsetDateTime.Validate(); err != nil { - return fmt.Errorf("field '_onsetDateTime' is invalid: %w", err) - } - } - if x.XOnsetString != nil { - if err := x.XOnsetString.Validate(); err != nil { - return fmt.Errorf("field '_onsetString' is invalid: %w", err) - } - } - if x.XRecordedDate != nil { - if err := x.XRecordedDate.Validate(); err != nil { - return fmt.Errorf("field '_recordedDate' is invalid: %w", err) - } - } - if x.AbatementAge != nil { - if err := x.AbatementAge.Validate(); err != nil { - return fmt.Errorf("field 'abatementAge' is invalid: %w", err) - } - } - if x.AbatementDateTime != nil { - if err := ValidateFhirDateTime(*x.AbatementDateTime); err != nil { - return fmt.Errorf("field 'abatementDateTime' has invalid date-time format: %w", err) - } - } - if x.AbatementPeriod != nil { - if err := x.AbatementPeriod.Validate(); err != nil { - return fmt.Errorf("field 'abatementPeriod' is invalid: %w", err) - } - } - if x.AbatementRange != nil { - if err := x.AbatementRange.Validate(); err != nil { - return fmt.Errorf("field 'abatementRange' is invalid: %w", err) - } - } - if x.AbatementString != nil { - if *x.AbatementString == "" { - return fmt.Errorf("field 'abatementString' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.BodySite != nil { - for i, item := range x.BodySite { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'bodySite[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Category != nil { - for i, item := range x.Category { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'category[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ClinicalStatus == nil { - return fmt.Errorf("required field 'clinicalStatus' is missing") - } - if x.ClinicalStatus != nil { - if err := x.ClinicalStatus.Validate(); err != nil { - return fmt.Errorf("field 'clinicalStatus' is invalid: %w", err) - } - } - if x.Code != nil { - if err := x.Code.Validate(); err != nil { - return fmt.Errorf("field 'code' is invalid: %w", err) - } - } - if x.Contained != nil { - for i, item := range x.Contained { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Encounter != nil { - if err := x.Encounter.Validate(); err != nil { - return fmt.Errorf("field 'encounter' is invalid: %w", err) - } - } - if x.Evidence != nil { - for i, item := range x.Evidence { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'evidence[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if !rx_Condition_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ImplicitRules != nil { - } - if x.Language != nil { - if !rx_Condition_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Note != nil { - for i, item := range x.Note { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) - } - } - } - } - if x.OnsetAge != nil { - if err := x.OnsetAge.Validate(); err != nil { - return fmt.Errorf("field 'onsetAge' is invalid: %w", err) - } - } - if x.OnsetDateTime != nil { - if err := ValidateFhirDateTime(*x.OnsetDateTime); err != nil { - return fmt.Errorf("field 'onsetDateTime' has invalid date-time format: %w", err) - } - } - if x.OnsetPeriod != nil { - if err := x.OnsetPeriod.Validate(); err != nil { - return fmt.Errorf("field 'onsetPeriod' is invalid: %w", err) - } - } - if x.OnsetRange != nil { - if err := x.OnsetRange.Validate(); err != nil { - return fmt.Errorf("field 'onsetRange' is invalid: %w", err) - } - } - if x.OnsetString != nil { - if *x.OnsetString == "" { - return fmt.Errorf("field 'onsetString' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Participant != nil { - for i, item := range x.Participant { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'participant[%d]' is invalid: %w", i, err) - } - } - } - } - if x.RecordedDate != nil { - if err := ValidateFhirDateTime(*x.RecordedDate); err != nil { - return fmt.Errorf("field 'recordedDate' has invalid date-time format: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "Condition" { - return fmt.Errorf("field 'resourceType' must be exactly 'Condition'") - } - } - if x.Severity != nil { - if err := x.Severity.Validate(); err != nil { - return fmt.Errorf("field 'severity' is invalid: %w", err) - } - } - if x.Stage != nil { - for i, item := range x.Stage { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'stage[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Subject == nil { - return fmt.Errorf("required field 'subject' is missing") - } - if x.Subject != nil { - if err := x.Subject.Validate(); err != nil { - return fmt.Errorf("field 'subject' is invalid: %w", err) - } - } - if x.Text != nil { - if err := x.Text.Validate(); err != nil { - return fmt.Errorf("field 'text' is invalid: %w", err) - } - } - if x.VerificationStatus != nil { - if err := x.VerificationStatus.Validate(); err != nil { - return fmt.Errorf("field 'verificationStatus' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a ConditionParticipant struct against its schema constraints. -func (x *ConditionParticipant) Validate() error { - if x == nil { - return nil - } - if x.Actor == nil { - return fmt.Errorf("required field 'actor' is missing") - } - if x.Actor != nil { - if err := x.Actor.Validate(); err != nil { - return fmt.Errorf("field 'actor' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Function != nil { - if err := x.Function.Validate(); err != nil { - return fmt.Errorf("field 'function' is invalid: %w", err) - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ConditionParticipant" { - return fmt.Errorf("field 'resourceType' must be exactly 'ConditionParticipant'") - } - } - return nil -} - -// Validate validates a ConditionStage struct against its schema constraints. -func (x *ConditionStage) Validate() error { - if x == nil { - return nil - } - if x.Assessment != nil { - for i, item := range x.Assessment { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'assessment[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ConditionStage" { - return fmt.Errorf("field 'resourceType' must be exactly 'ConditionStage'") - } - } - if x.Summary != nil { - if err := x.Summary.Validate(); err != nil { - return fmt.Errorf("field 'summary' is invalid: %w", err) - } - } - if x.Type != nil { - if err := x.Type.Validate(); err != nil { - return fmt.Errorf("field 'type' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a ContactDetail struct against its schema constraints. -func (x *ContactDetail) Validate() error { - if x == nil { - return nil - } - if x.XName != nil { - if err := x.XName.Validate(); err != nil { - return fmt.Errorf("field '_name' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Name != nil { - if *x.Name == "" { - return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ContactDetail" { - return fmt.Errorf("field 'resourceType' must be exactly 'ContactDetail'") - } - } - if x.Telecom != nil { - for i, item := range x.Telecom { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'telecom[%d]' is invalid: %w", i, err) - } - } - } - } - return nil -} - -// Validate validates a ContactPoint struct against its schema constraints. -func (x *ContactPoint) Validate() error { - if x == nil { - return nil - } - if x.XRank != nil { - if err := x.XRank.Validate(); err != nil { - return fmt.Errorf("field '_rank' is invalid: %w", err) - } - } - if x.XSystem != nil { - if err := x.XSystem.Validate(); err != nil { - return fmt.Errorf("field '_system' is invalid: %w", err) - } - } - if x.XUse != nil { - if err := x.XUse.Validate(); err != nil { - return fmt.Errorf("field '_use' is invalid: %w", err) - } - } - if x.XValue != nil { - if err := x.XValue.Validate(); err != nil { - return fmt.Errorf("field '_value' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Period != nil { - if err := x.Period.Validate(); err != nil { - return fmt.Errorf("field 'period' is invalid: %w", err) - } - } - if x.Rank != nil { - if *x.Rank <= 0.000000 { - return fmt.Errorf("field 'rank' is below exclusive minimum 0.000000") - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ContactPoint" { - return fmt.Errorf("field 'resourceType' must be exactly 'ContactPoint'") - } - } - if x.System != nil { - if !rx_ContactPoint_System.MatchString(*x.System) { - return fmt.Errorf("field 'system' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Use != nil { - if !rx_ContactPoint_Use.MatchString(*x.Use) { - return fmt.Errorf("field 'use' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Value != nil { - if *x.Value == "" { - return fmt.Errorf("field 'value' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - return nil -} - -// Validate validates a Count struct against its schema constraints. -func (x *Count) Validate() error { - if x == nil { - return nil - } - if x.XCode != nil { - if err := x.XCode.Validate(); err != nil { - return fmt.Errorf("field '_code' is invalid: %w", err) - } - } - if x.XComparator != nil { - if err := x.XComparator.Validate(); err != nil { - return fmt.Errorf("field '_comparator' is invalid: %w", err) - } - } - if x.XSystem != nil { - if err := x.XSystem.Validate(); err != nil { - return fmt.Errorf("field '_system' is invalid: %w", err) - } - } - if x.XUnit != nil { - if err := x.XUnit.Validate(); err != nil { - return fmt.Errorf("field '_unit' is invalid: %w", err) - } - } - if x.XValue != nil { - if err := x.XValue.Validate(); err != nil { - return fmt.Errorf("field '_value' is invalid: %w", err) - } - } - if x.Code != nil { - if !rx_Count_Code.MatchString(*x.Code) { - return fmt.Errorf("field 'code' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Comparator != nil { - if !rx_Count_Comparator.MatchString(*x.Comparator) { - return fmt.Errorf("field 'comparator' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "Count" { - return fmt.Errorf("field 'resourceType' must be exactly 'Count'") - } - } - if x.System != nil { - } - if x.Unit != nil { - if *x.Unit == "" { - return fmt.Errorf("field 'unit' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Value != nil { - } - return nil -} - -// Validate validates a DataRequirement struct against its schema constraints. -func (x *DataRequirement) Validate() error { - if x == nil { - return nil - } - if x.XLimit != nil { - if err := x.XLimit.Validate(); err != nil { - return fmt.Errorf("field '_limit' is invalid: %w", err) - } - } - if x.XMustSupport != nil { - for i, item := range x.XMustSupport { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field '_mustSupport[%d]' is invalid: %w", i, err) - } - } - } - } - if x.XProfile != nil { - for i, item := range x.XProfile { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field '_profile[%d]' is invalid: %w", i, err) - } - } - } - } - if x.XType != nil { - if err := x.XType.Validate(); err != nil { - return fmt.Errorf("field '_type' is invalid: %w", err) - } - } - if x.CodeFilter != nil { - for i, item := range x.CodeFilter { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'codeFilter[%d]' is invalid: %w", i, err) - } - } - } - } - if x.DateFilter != nil { - for i, item := range x.DateFilter { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'dateFilter[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Limit != nil { - if *x.Limit <= 0.000000 { - return fmt.Errorf("field 'limit' is below exclusive minimum 0.000000") - } - } - if x.Links != nil { - } - if x.MustSupport != nil { - for i, item := range x.MustSupport { - if item == "" { - return fmt.Errorf("field 'mustSupport[%d]' does not match pattern '[ \\r\\n\\t\\S]+'", i) - } - } - } - if x.Profile != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "DataRequirement" { - return fmt.Errorf("field 'resourceType' must be exactly 'DataRequirement'") - } - } - if x.Sort != nil { - for i, item := range x.Sort { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'sort[%d]' is invalid: %w", i, err) - } - } - } - } - if x.SubjectCodeableConcept != nil { - if err := x.SubjectCodeableConcept.Validate(); err != nil { - return fmt.Errorf("field 'subjectCodeableConcept' is invalid: %w", err) - } - } - if x.SubjectReference != nil { - if err := x.SubjectReference.Validate(); err != nil { - return fmt.Errorf("field 'subjectReference' is invalid: %w", err) - } - } - if x.Type != nil { - if !rx_DataRequirement_Type.MatchString(*x.Type) { - return fmt.Errorf("field 'type' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.ValueFilter != nil { - for i, item := range x.ValueFilter { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'valueFilter[%d]' is invalid: %w", i, err) - } - } - } - } - return nil -} - -// Validate validates a DataRequirementCodeFilter struct against its schema constraints. -func (x *DataRequirementCodeFilter) Validate() error { - if x == nil { - return nil - } - if x.XPath != nil { - if err := x.XPath.Validate(); err != nil { - return fmt.Errorf("field '_path' is invalid: %w", err) - } - } - if x.XSearchParam != nil { - if err := x.XSearchParam.Validate(); err != nil { - return fmt.Errorf("field '_searchParam' is invalid: %w", err) - } - } - if x.XValueSet != nil { - if err := x.XValueSet.Validate(); err != nil { - return fmt.Errorf("field '_valueSet' is invalid: %w", err) - } - } - if x.Code != nil { - for i, item := range x.Code { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'code[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Path != nil { - if *x.Path == "" { - return fmt.Errorf("field 'path' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.ResourceType != nil { - if *x.ResourceType != "DataRequirementCodeFilter" { - return fmt.Errorf("field 'resourceType' must be exactly 'DataRequirementCodeFilter'") - } - } - if x.SearchParam != nil { - if *x.SearchParam == "" { - return fmt.Errorf("field 'searchParam' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.ValueSet != nil { - } - return nil -} - -// Validate validates a DataRequirementDateFilter struct against its schema constraints. -func (x *DataRequirementDateFilter) Validate() error { - if x == nil { - return nil - } - if x.XPath != nil { - if err := x.XPath.Validate(); err != nil { - return fmt.Errorf("field '_path' is invalid: %w", err) - } - } - if x.XSearchParam != nil { - if err := x.XSearchParam.Validate(); err != nil { - return fmt.Errorf("field '_searchParam' is invalid: %w", err) - } - } - if x.XValueDateTime != nil { - if err := x.XValueDateTime.Validate(); err != nil { - return fmt.Errorf("field '_valueDateTime' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Path != nil { - if *x.Path == "" { - return fmt.Errorf("field 'path' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.ResourceType != nil { - if *x.ResourceType != "DataRequirementDateFilter" { - return fmt.Errorf("field 'resourceType' must be exactly 'DataRequirementDateFilter'") - } - } - if x.SearchParam != nil { - if *x.SearchParam == "" { - return fmt.Errorf("field 'searchParam' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.ValueDateTime != nil { - if err := ValidateFhirDateTime(*x.ValueDateTime); err != nil { - return fmt.Errorf("field 'valueDateTime' has invalid date-time format: %w", err) - } - } - if x.ValueDuration != nil { - if err := x.ValueDuration.Validate(); err != nil { - return fmt.Errorf("field 'valueDuration' is invalid: %w", err) - } - } - if x.ValuePeriod != nil { - if err := x.ValuePeriod.Validate(); err != nil { - return fmt.Errorf("field 'valuePeriod' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a DataRequirementSort struct against its schema constraints. -func (x *DataRequirementSort) Validate() error { - if x == nil { - return nil - } - if x.XDirection != nil { - if err := x.XDirection.Validate(); err != nil { - return fmt.Errorf("field '_direction' is invalid: %w", err) - } - } - if x.XPath != nil { - if err := x.XPath.Validate(); err != nil { - return fmt.Errorf("field '_path' is invalid: %w", err) - } - } - if x.Direction != nil { - if !rx_DataRequirementSort_Direction.MatchString(*x.Direction) { - return fmt.Errorf("field 'direction' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Path != nil { - if *x.Path == "" { - return fmt.Errorf("field 'path' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.ResourceType != nil { - if *x.ResourceType != "DataRequirementSort" { - return fmt.Errorf("field 'resourceType' must be exactly 'DataRequirementSort'") - } - } - return nil -} - -// Validate validates a DataRequirementValueFilter struct against its schema constraints. -func (x *DataRequirementValueFilter) Validate() error { - if x == nil { - return nil - } - if x.XComparator != nil { - if err := x.XComparator.Validate(); err != nil { - return fmt.Errorf("field '_comparator' is invalid: %w", err) - } - } - if x.XPath != nil { - if err := x.XPath.Validate(); err != nil { - return fmt.Errorf("field '_path' is invalid: %w", err) - } - } - if x.XSearchParam != nil { - if err := x.XSearchParam.Validate(); err != nil { - return fmt.Errorf("field '_searchParam' is invalid: %w", err) - } - } - if x.XValueDateTime != nil { - if err := x.XValueDateTime.Validate(); err != nil { - return fmt.Errorf("field '_valueDateTime' is invalid: %w", err) - } - } - if x.Comparator != nil { - if !rx_DataRequirementValueFilter_Comparator.MatchString(*x.Comparator) { - return fmt.Errorf("field 'comparator' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Path != nil { - if *x.Path == "" { - return fmt.Errorf("field 'path' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.ResourceType != nil { - if *x.ResourceType != "DataRequirementValueFilter" { - return fmt.Errorf("field 'resourceType' must be exactly 'DataRequirementValueFilter'") - } - } - if x.SearchParam != nil { - if *x.SearchParam == "" { - return fmt.Errorf("field 'searchParam' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.ValueDateTime != nil { - if err := ValidateFhirDateTime(*x.ValueDateTime); err != nil { - return fmt.Errorf("field 'valueDateTime' has invalid date-time format: %w", err) - } - } - if x.ValueDuration != nil { - if err := x.ValueDuration.Validate(); err != nil { - return fmt.Errorf("field 'valueDuration' is invalid: %w", err) - } - } - if x.ValuePeriod != nil { - if err := x.ValuePeriod.Validate(); err != nil { - return fmt.Errorf("field 'valuePeriod' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a DiagnosticReport struct against its schema constraints. -func (x *DiagnosticReport) Validate() error { - if x == nil { - return nil - } - if x.XConclusion != nil { - if err := x.XConclusion.Validate(); err != nil { - return fmt.Errorf("field '_conclusion' is invalid: %w", err) - } - } - if x.XEffectiveDateTime != nil { - if err := x.XEffectiveDateTime.Validate(); err != nil { - return fmt.Errorf("field '_effectiveDateTime' is invalid: %w", err) - } - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XIssued != nil { - if err := x.XIssued.Validate(); err != nil { - return fmt.Errorf("field '_issued' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.XStatus != nil { - if err := x.XStatus.Validate(); err != nil { - return fmt.Errorf("field '_status' is invalid: %w", err) - } - } - if x.BasedOn != nil { - for i, item := range x.BasedOn { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'basedOn[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Category != nil { - for i, item := range x.Category { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'category[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Code == nil { - return fmt.Errorf("required field 'code' is missing") - } - if x.Code != nil { - if err := x.Code.Validate(); err != nil { - return fmt.Errorf("field 'code' is invalid: %w", err) - } - } - if x.Composition != nil { - if err := x.Composition.Validate(); err != nil { - return fmt.Errorf("field 'composition' is invalid: %w", err) - } - } - if x.Conclusion != nil { - if !rx_DiagnosticReport_Conclusion.MatchString(*x.Conclusion) { - return fmt.Errorf("field 'conclusion' does not match pattern '\\s*(\\S|\\s)*'") - } - } - if x.ConclusionCode != nil { - for i, item := range x.ConclusionCode { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'conclusionCode[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Contained != nil { - for i, item := range x.Contained { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) - } - } - } - } - if x.EffectiveDateTime != nil { - if err := ValidateFhirDateTime(*x.EffectiveDateTime); err != nil { - return fmt.Errorf("field 'effectiveDateTime' has invalid date-time format: %w", err) - } - } - if x.EffectivePeriod != nil { - if err := x.EffectivePeriod.Validate(); err != nil { - return fmt.Errorf("field 'effectivePeriod' is invalid: %w", err) - } - } - if x.Encounter != nil { - if err := x.Encounter.Validate(); err != nil { - return fmt.Errorf("field 'encounter' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if !rx_DiagnosticReport_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ImplicitRules != nil { - } - if x.Issued != nil { - if err := ValidateFhirDateTime(*x.Issued); err != nil { - return fmt.Errorf("field 'issued' has invalid date-time format: %w", err) - } - } - if x.Language != nil { - if !rx_DiagnosticReport_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.Media != nil { - for i, item := range x.Media { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'media[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Note != nil { - for i, item := range x.Note { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Performer != nil { - for i, item := range x.Performer { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'performer[%d]' is invalid: %w", i, err) - } - } - } - } - if x.PresentedForm != nil { - for i, item := range x.PresentedForm { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'presentedForm[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "DiagnosticReport" { - return fmt.Errorf("field 'resourceType' must be exactly 'DiagnosticReport'") - } - } - if x.Result != nil { - for i, item := range x.Result { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'result[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResultsInterpreter != nil { - for i, item := range x.ResultsInterpreter { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'resultsInterpreter[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Specimen != nil { - for i, item := range x.Specimen { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'specimen[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Status != nil { - if !rx_DiagnosticReport_Status.MatchString(*x.Status) { - return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Study != nil { - for i, item := range x.Study { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'study[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Subject != nil { - if err := x.Subject.Validate(); err != nil { - return fmt.Errorf("field 'subject' is invalid: %w", err) - } - } - if x.SupportingInfo != nil { - for i, item := range x.SupportingInfo { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'supportingInfo[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Text != nil { - if err := x.Text.Validate(); err != nil { - return fmt.Errorf("field 'text' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a DiagnosticReportMedia struct against its schema constraints. -func (x *DiagnosticReportMedia) Validate() error { - if x == nil { - return nil - } - if x.XComment != nil { - if err := x.XComment.Validate(); err != nil { - return fmt.Errorf("field '_comment' is invalid: %w", err) - } - } - if x.Comment != nil { - if *x.Comment == "" { - return fmt.Errorf("field 'comment' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Link == nil { - return fmt.Errorf("required field 'link' is missing") - } - if x.Link != nil { - if err := x.Link.Validate(); err != nil { - return fmt.Errorf("field 'link' is invalid: %w", err) - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "DiagnosticReportMedia" { - return fmt.Errorf("field 'resourceType' must be exactly 'DiagnosticReportMedia'") - } - } - return nil -} - -// Validate validates a DiagnosticReportSupportingInfo struct against its schema constraints. -func (x *DiagnosticReportSupportingInfo) Validate() error { - if x == nil { - return nil - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Reference == nil { - return fmt.Errorf("required field 'reference' is missing") - } - if x.Reference != nil { - if err := x.Reference.Validate(); err != nil { - return fmt.Errorf("field 'reference' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "DiagnosticReportSupportingInfo" { - return fmt.Errorf("field 'resourceType' must be exactly 'DiagnosticReportSupportingInfo'") - } - } - if x.Type == nil { - return fmt.Errorf("required field 'type' is missing") - } - if x.Type != nil { - if err := x.Type.Validate(); err != nil { - return fmt.Errorf("field 'type' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a Directory struct against its schema constraints. -func (x *Directory) Validate() error { - if x == nil { - return nil - } - if x.Child == nil { - return fmt.Errorf("required field 'child' is missing") - } - if x.Child != nil { - for i, item := range x.Child { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'child[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if !rx_Directory_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.Links != nil { - } - if x.Name == nil { - return fmt.Errorf("required field 'name' is missing") - } - if x.Name != nil { - } - if x.Path != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "Directory" { - return fmt.Errorf("field 'resourceType' must be exactly 'Directory'") - } - } - return nil -} - -// Validate validates a Distance struct against its schema constraints. -func (x *Distance) Validate() error { - if x == nil { - return nil - } - if x.XCode != nil { - if err := x.XCode.Validate(); err != nil { - return fmt.Errorf("field '_code' is invalid: %w", err) - } - } - if x.XComparator != nil { - if err := x.XComparator.Validate(); err != nil { - return fmt.Errorf("field '_comparator' is invalid: %w", err) - } - } - if x.XSystem != nil { - if err := x.XSystem.Validate(); err != nil { - return fmt.Errorf("field '_system' is invalid: %w", err) - } - } - if x.XUnit != nil { - if err := x.XUnit.Validate(); err != nil { - return fmt.Errorf("field '_unit' is invalid: %w", err) - } - } - if x.XValue != nil { - if err := x.XValue.Validate(); err != nil { - return fmt.Errorf("field '_value' is invalid: %w", err) - } - } - if x.Code != nil { - if !rx_Distance_Code.MatchString(*x.Code) { - return fmt.Errorf("field 'code' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Comparator != nil { - if !rx_Distance_Comparator.MatchString(*x.Comparator) { - return fmt.Errorf("field 'comparator' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "Distance" { - return fmt.Errorf("field 'resourceType' must be exactly 'Distance'") - } - } - if x.System != nil { - } - if x.Unit != nil { - if *x.Unit == "" { - return fmt.Errorf("field 'unit' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Value != nil { - } - return nil -} - -// Validate validates a DocumentReference struct against its schema constraints. -func (x *DocumentReference) Validate() error { - if x == nil { - return nil - } - if x.XDate != nil { - if err := x.XDate.Validate(); err != nil { - return fmt.Errorf("field '_date' is invalid: %w", err) - } - } - if x.XDescription != nil { - if err := x.XDescription.Validate(); err != nil { - return fmt.Errorf("field '_description' is invalid: %w", err) - } - } - if x.XDocStatus != nil { - if err := x.XDocStatus.Validate(); err != nil { - return fmt.Errorf("field '_docStatus' is invalid: %w", err) - } - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.XStatus != nil { - if err := x.XStatus.Validate(); err != nil { - return fmt.Errorf("field '_status' is invalid: %w", err) - } - } - if x.XVersion != nil { - if err := x.XVersion.Validate(); err != nil { - return fmt.Errorf("field '_version' is invalid: %w", err) - } - } - if x.Attester != nil { - for i, item := range x.Attester { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'attester[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Author != nil { - for i, item := range x.Author { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'author[%d]' is invalid: %w", i, err) - } - } - } - } - if x.BasedOn != nil { - for i, item := range x.BasedOn { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'basedOn[%d]' is invalid: %w", i, err) - } - } - } - } - if x.BodySite != nil { - for i, item := range x.BodySite { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'bodySite[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Category != nil { - for i, item := range x.Category { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'category[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Contained != nil { - for i, item := range x.Contained { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Content == nil { - return fmt.Errorf("required field 'content' is missing") - } - if x.Content != nil { - for i, item := range x.Content { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'content[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Context != nil { - for i, item := range x.Context { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'context[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Custodian != nil { - if err := x.Custodian.Validate(); err != nil { - return fmt.Errorf("field 'custodian' is invalid: %w", err) - } - } - if x.Date != nil { - if err := ValidateFhirDateTime(*x.Date); err != nil { - return fmt.Errorf("field 'date' has invalid date-time format: %w", err) - } - } - if x.Description != nil { - if !rx_DocumentReference_Description.MatchString(*x.Description) { - return fmt.Errorf("field 'description' does not match pattern '\\s*(\\S|\\s)*'") - } - } - if x.DocStatus != nil { - if !rx_DocumentReference_DocStatus.MatchString(*x.DocStatus) { - return fmt.Errorf("field 'docStatus' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Event != nil { - for i, item := range x.Event { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'event[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.FacilityType != nil { - if err := x.FacilityType.Validate(); err != nil { - return fmt.Errorf("field 'facilityType' is invalid: %w", err) - } - } - if x.ID != nil { - if !rx_DocumentReference_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ImplicitRules != nil { - } - if x.Language != nil { - if !rx_DocumentReference_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.Modality != nil { - for i, item := range x.Modality { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modality[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Period != nil { - if err := x.Period.Validate(); err != nil { - return fmt.Errorf("field 'period' is invalid: %w", err) - } - } - if x.PracticeSetting != nil { - if err := x.PracticeSetting.Validate(); err != nil { - return fmt.Errorf("field 'practiceSetting' is invalid: %w", err) - } - } - if x.RelatesTo != nil { - for i, item := range x.RelatesTo { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'relatesTo[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "DocumentReference" { - return fmt.Errorf("field 'resourceType' must be exactly 'DocumentReference'") - } - } - if x.SecurityLabel != nil { - for i, item := range x.SecurityLabel { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'securityLabel[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Status != nil { - if !rx_DocumentReference_Status.MatchString(*x.Status) { - return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Subject != nil { - if err := x.Subject.Validate(); err != nil { - return fmt.Errorf("field 'subject' is invalid: %w", err) - } - } - if x.Text != nil { - if err := x.Text.Validate(); err != nil { - return fmt.Errorf("field 'text' is invalid: %w", err) - } - } - if x.Type != nil { - if err := x.Type.Validate(); err != nil { - return fmt.Errorf("field 'type' is invalid: %w", err) - } - } - if x.Version != nil { - if *x.Version == "" { - return fmt.Errorf("field 'version' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - return nil -} - -// Validate validates a DocumentReferenceAttester struct against its schema constraints. -func (x *DocumentReferenceAttester) Validate() error { - if x == nil { - return nil - } - if x.XTime != nil { - if err := x.XTime.Validate(); err != nil { - return fmt.Errorf("field '_time' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Mode == nil { - return fmt.Errorf("required field 'mode' is missing") - } - if x.Mode != nil { - if err := x.Mode.Validate(); err != nil { - return fmt.Errorf("field 'mode' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Party != nil { - if err := x.Party.Validate(); err != nil { - return fmt.Errorf("field 'party' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "DocumentReferenceAttester" { - return fmt.Errorf("field 'resourceType' must be exactly 'DocumentReferenceAttester'") - } - } - if x.Time != nil { - if err := ValidateFhirDateTime(*x.Time); err != nil { - return fmt.Errorf("field 'time' has invalid date-time format: %w", err) - } - } - return nil -} - -// Validate validates a DocumentReferenceContent struct against its schema constraints. -func (x *DocumentReferenceContent) Validate() error { - if x == nil { - return nil - } - if x.Attachment == nil { - return fmt.Errorf("required field 'attachment' is missing") - } - if x.Attachment != nil { - if err := x.Attachment.Validate(); err != nil { - return fmt.Errorf("field 'attachment' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Profile != nil { - for i, item := range x.Profile { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'profile[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "DocumentReferenceContent" { - return fmt.Errorf("field 'resourceType' must be exactly 'DocumentReferenceContent'") - } - } - return nil -} - -// Validate validates a DocumentReferenceContentProfile struct against its schema constraints. -func (x *DocumentReferenceContentProfile) Validate() error { - if x == nil { - return nil - } - if x.XValueCanonical != nil { - if err := x.XValueCanonical.Validate(); err != nil { - return fmt.Errorf("field '_valueCanonical' is invalid: %w", err) - } - } - if x.XValueURI != nil { - if err := x.XValueURI.Validate(); err != nil { - return fmt.Errorf("field '_valueUri' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "DocumentReferenceContentProfile" { - return fmt.Errorf("field 'resourceType' must be exactly 'DocumentReferenceContentProfile'") - } - } - if x.ValueCanonical != nil { - } - if x.ValueCoding != nil { - if err := x.ValueCoding.Validate(); err != nil { - return fmt.Errorf("field 'valueCoding' is invalid: %w", err) - } - } - if x.ValueURI != nil { - } - return nil -} - -// Validate validates a DocumentReferenceRelatesTo struct against its schema constraints. -func (x *DocumentReferenceRelatesTo) Validate() error { - if x == nil { - return nil - } - if x.Code == nil { - return fmt.Errorf("required field 'code' is missing") - } - if x.Code != nil { - if err := x.Code.Validate(); err != nil { - return fmt.Errorf("field 'code' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "DocumentReferenceRelatesTo" { - return fmt.Errorf("field 'resourceType' must be exactly 'DocumentReferenceRelatesTo'") - } - } - if x.Target == nil { - return fmt.Errorf("required field 'target' is missing") - } - if x.Target != nil { - if err := x.Target.Validate(); err != nil { - return fmt.Errorf("field 'target' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a Dosage struct against its schema constraints. -func (x *Dosage) Validate() error { - if x == nil { - return nil - } - if x.XAsNeeded != nil { - if err := x.XAsNeeded.Validate(); err != nil { - return fmt.Errorf("field '_asNeeded' is invalid: %w", err) - } - } - if x.XPatientInstruction != nil { - if err := x.XPatientInstruction.Validate(); err != nil { - return fmt.Errorf("field '_patientInstruction' is invalid: %w", err) - } - } - if x.XSequence != nil { - if err := x.XSequence.Validate(); err != nil { - return fmt.Errorf("field '_sequence' is invalid: %w", err) - } - } - if x.XText != nil { - if err := x.XText.Validate(); err != nil { - return fmt.Errorf("field '_text' is invalid: %w", err) - } - } - if x.AdditionalInstruction != nil { - for i, item := range x.AdditionalInstruction { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'additionalInstruction[%d]' is invalid: %w", i, err) - } - } - } - } - if x.AsNeeded != nil { - } - if x.AsNeededFor != nil { - for i, item := range x.AsNeededFor { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'asNeededFor[%d]' is invalid: %w", i, err) - } - } - } - } - if x.DoseAndRate != nil { - for i, item := range x.DoseAndRate { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'doseAndRate[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.MaxDosePerAdministration != nil { - if err := x.MaxDosePerAdministration.Validate(); err != nil { - return fmt.Errorf("field 'maxDosePerAdministration' is invalid: %w", err) - } - } - if x.MaxDosePerLifetime != nil { - if err := x.MaxDosePerLifetime.Validate(); err != nil { - return fmt.Errorf("field 'maxDosePerLifetime' is invalid: %w", err) - } - } - if x.MaxDosePerPeriod != nil { - for i, item := range x.MaxDosePerPeriod { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'maxDosePerPeriod[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Method != nil { - if err := x.Method.Validate(); err != nil { - return fmt.Errorf("field 'method' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.PatientInstruction != nil { - if *x.PatientInstruction == "" { - return fmt.Errorf("field 'patientInstruction' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.ResourceType != nil { - if *x.ResourceType != "Dosage" { - return fmt.Errorf("field 'resourceType' must be exactly 'Dosage'") - } - } - if x.Route != nil { - if err := x.Route.Validate(); err != nil { - return fmt.Errorf("field 'route' is invalid: %w", err) - } - } - if x.Sequence != nil { - } - if x.Site != nil { - if err := x.Site.Validate(); err != nil { - return fmt.Errorf("field 'site' is invalid: %w", err) - } - } - if x.Text != nil { - if *x.Text == "" { - return fmt.Errorf("field 'text' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Timing != nil { - if err := x.Timing.Validate(); err != nil { - return fmt.Errorf("field 'timing' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a DosageDoseAndRate struct against its schema constraints. -func (x *DosageDoseAndRate) Validate() error { - if x == nil { - return nil - } - if x.DoseQuantity != nil { - if err := x.DoseQuantity.Validate(); err != nil { - return fmt.Errorf("field 'doseQuantity' is invalid: %w", err) - } - } - if x.DoseRange != nil { - if err := x.DoseRange.Validate(); err != nil { - return fmt.Errorf("field 'doseRange' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.RateQuantity != nil { - if err := x.RateQuantity.Validate(); err != nil { - return fmt.Errorf("field 'rateQuantity' is invalid: %w", err) - } - } - if x.RateRange != nil { - if err := x.RateRange.Validate(); err != nil { - return fmt.Errorf("field 'rateRange' is invalid: %w", err) - } - } - if x.RateRatio != nil { - if err := x.RateRatio.Validate(); err != nil { - return fmt.Errorf("field 'rateRatio' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "DosageDoseAndRate" { - return fmt.Errorf("field 'resourceType' must be exactly 'DosageDoseAndRate'") - } - } - if x.Type != nil { - if err := x.Type.Validate(); err != nil { - return fmt.Errorf("field 'type' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a Duration struct against its schema constraints. -func (x *Duration) Validate() error { - if x == nil { - return nil - } - if x.XCode != nil { - if err := x.XCode.Validate(); err != nil { - return fmt.Errorf("field '_code' is invalid: %w", err) - } - } - if x.XComparator != nil { - if err := x.XComparator.Validate(); err != nil { - return fmt.Errorf("field '_comparator' is invalid: %w", err) - } - } - if x.XSystem != nil { - if err := x.XSystem.Validate(); err != nil { - return fmt.Errorf("field '_system' is invalid: %w", err) - } - } - if x.XUnit != nil { - if err := x.XUnit.Validate(); err != nil { - return fmt.Errorf("field '_unit' is invalid: %w", err) - } - } - if x.XValue != nil { - if err := x.XValue.Validate(); err != nil { - return fmt.Errorf("field '_value' is invalid: %w", err) - } - } - if x.Code != nil { - if !rx_Duration_Code.MatchString(*x.Code) { - return fmt.Errorf("field 'code' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Comparator != nil { - if !rx_Duration_Comparator.MatchString(*x.Comparator) { - return fmt.Errorf("field 'comparator' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "Duration" { - return fmt.Errorf("field 'resourceType' must be exactly 'Duration'") - } - } - if x.System != nil { - } - if x.Unit != nil { - if *x.Unit == "" { - return fmt.Errorf("field 'unit' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Value != nil { - } - return nil -} - -// Validate validates a Expression struct against its schema constraints. -func (x *Expression) Validate() error { - if x == nil { - return nil - } - if x.XDescription != nil { - if err := x.XDescription.Validate(); err != nil { - return fmt.Errorf("field '_description' is invalid: %w", err) - } - } - if x.XExpression != nil { - if err := x.XExpression.Validate(); err != nil { - return fmt.Errorf("field '_expression' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.XName != nil { - if err := x.XName.Validate(); err != nil { - return fmt.Errorf("field '_name' is invalid: %w", err) - } - } - if x.XReference != nil { - if err := x.XReference.Validate(); err != nil { - return fmt.Errorf("field '_reference' is invalid: %w", err) - } - } - if x.Description != nil { - if *x.Description == "" { - return fmt.Errorf("field 'description' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Expression != nil { - if *x.Expression == "" { - return fmt.Errorf("field 'expression' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Language != nil { - if !rx_Expression_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.Name != nil { - if !rx_Expression_Name.MatchString(*x.Name) { - return fmt.Errorf("field 'name' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Reference != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "Expression" { - return fmt.Errorf("field 'resourceType' must be exactly 'Expression'") - } - } - return nil -} - -// Validate validates a ExtendedContactDetail struct against its schema constraints. -func (x *ExtendedContactDetail) Validate() error { - if x == nil { - return nil - } - if x.Address != nil { - if err := x.Address.Validate(); err != nil { - return fmt.Errorf("field 'address' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Name != nil { - for i, item := range x.Name { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'name[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Organization != nil { - if err := x.Organization.Validate(); err != nil { - return fmt.Errorf("field 'organization' is invalid: %w", err) - } - } - if x.Period != nil { - if err := x.Period.Validate(); err != nil { - return fmt.Errorf("field 'period' is invalid: %w", err) - } - } - if x.Purpose != nil { - if err := x.Purpose.Validate(); err != nil { - return fmt.Errorf("field 'purpose' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ExtendedContactDetail" { - return fmt.Errorf("field 'resourceType' must be exactly 'ExtendedContactDetail'") - } - } - if x.Telecom != nil { - for i, item := range x.Telecom { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'telecom[%d]' is invalid: %w", i, err) - } - } - } - } - return nil -} - -// Validate validates a Extension struct against its schema constraints. -func (x *Extension) Validate() error { - if x == nil { - return nil - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "Extension" { - return fmt.Errorf("field 'resourceType' must be exactly 'Extension'") - } - } - if x.URL != nil { - } - if x.ValueAddress != nil { - if err := x.ValueAddress.Validate(); err != nil { - return fmt.Errorf("field 'valueAddress' is invalid: %w", err) - } - } - if x.ValueAge != nil { - if err := x.ValueAge.Validate(); err != nil { - return fmt.Errorf("field 'valueAge' is invalid: %w", err) - } - } - if x.ValueAnnotation != nil { - if err := x.ValueAnnotation.Validate(); err != nil { - return fmt.Errorf("field 'valueAnnotation' is invalid: %w", err) - } - } - if x.ValueAttachment != nil { - if err := x.ValueAttachment.Validate(); err != nil { - return fmt.Errorf("field 'valueAttachment' is invalid: %w", err) - } - } - if x.ValueAvailability != nil { - if err := x.ValueAvailability.Validate(); err != nil { - return fmt.Errorf("field 'valueAvailability' is invalid: %w", err) - } - } - if x.ValueBase64Binary != nil { - if err := ValidateFhirBinary(*x.ValueBase64Binary); err != nil { - return fmt.Errorf("field 'valueBase64Binary' has invalid binary format: %w", err) - } - } - if x.ValueBoolean != nil { - } - if x.ValueCanonical != nil { - } - if x.ValueCode != nil { - if !rx_Extension_ValueCode.MatchString(*x.ValueCode) { - return fmt.Errorf("field 'valueCode' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.ValueCodeableConcept != nil { - if err := x.ValueCodeableConcept.Validate(); err != nil { - return fmt.Errorf("field 'valueCodeableConcept' is invalid: %w", err) - } - } - if x.ValueCodeableReference != nil { - if err := x.ValueCodeableReference.Validate(); err != nil { - return fmt.Errorf("field 'valueCodeableReference' is invalid: %w", err) - } - } - if x.ValueCoding != nil { - if err := x.ValueCoding.Validate(); err != nil { - return fmt.Errorf("field 'valueCoding' is invalid: %w", err) - } - } - if x.ValueContactDetail != nil { - if err := x.ValueContactDetail.Validate(); err != nil { - return fmt.Errorf("field 'valueContactDetail' is invalid: %w", err) - } - } - if x.ValueContactPoint != nil { - if err := x.ValueContactPoint.Validate(); err != nil { - return fmt.Errorf("field 'valueContactPoint' is invalid: %w", err) - } - } - if x.ValueCount != nil { - if err := x.ValueCount.Validate(); err != nil { - return fmt.Errorf("field 'valueCount' is invalid: %w", err) - } - } - if x.ValueDataRequirement != nil { - if err := x.ValueDataRequirement.Validate(); err != nil { - return fmt.Errorf("field 'valueDataRequirement' is invalid: %w", err) - } - } - if x.ValueDate != nil { - if err := ValidateFhirDate(*x.ValueDate); err != nil { - return fmt.Errorf("field 'valueDate' has invalid date format: %w", err) - } - } - if x.ValueDateTime != nil { - if err := ValidateFhirDateTime(*x.ValueDateTime); err != nil { - return fmt.Errorf("field 'valueDateTime' has invalid date-time format: %w", err) - } - } - if x.ValueDecimal != nil { - } - if x.ValueDistance != nil { - if err := x.ValueDistance.Validate(); err != nil { - return fmt.Errorf("field 'valueDistance' is invalid: %w", err) - } - } - if x.ValueDosage != nil { - if err := x.ValueDosage.Validate(); err != nil { - return fmt.Errorf("field 'valueDosage' is invalid: %w", err) - } - } - if x.ValueDuration != nil { - if err := x.ValueDuration.Validate(); err != nil { - return fmt.Errorf("field 'valueDuration' is invalid: %w", err) - } - } - if x.ValueExpression != nil { - if err := x.ValueExpression.Validate(); err != nil { - return fmt.Errorf("field 'valueExpression' is invalid: %w", err) - } - } - if x.ValueExtendedContactDetail != nil { - if err := x.ValueExtendedContactDetail.Validate(); err != nil { - return fmt.Errorf("field 'valueExtendedContactDetail' is invalid: %w", err) - } - } - if x.ValueHumanName != nil { - if err := x.ValueHumanName.Validate(); err != nil { - return fmt.Errorf("field 'valueHumanName' is invalid: %w", err) - } - } - if x.ValueID != nil { - if !rx_Extension_ValueID.MatchString(*x.ValueID) { - return fmt.Errorf("field 'valueId' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ValueID) < 1 { - return fmt.Errorf("field 'valueId' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ValueID) > 64 { - return fmt.Errorf("field 'valueId' is too long (max 64 characters)") - } - } - if x.ValueIDentifier != nil { - if err := x.ValueIDentifier.Validate(); err != nil { - return fmt.Errorf("field 'valueIdentifier' is invalid: %w", err) - } - } - if x.ValueInstant != nil { - if err := ValidateFhirDateTime(*x.ValueInstant); err != nil { - return fmt.Errorf("field 'valueInstant' has invalid date-time format: %w", err) - } - } - if x.ValueInteger != nil { - } - if x.ValueInteger64 != nil { - } - if x.ValueMarkdown != nil { - if !rx_Extension_ValueMarkdown.MatchString(*x.ValueMarkdown) { - return fmt.Errorf("field 'valueMarkdown' does not match pattern '\\s*(\\S|\\s)*'") - } - } - if x.ValueMeta != nil { - if err := x.ValueMeta.Validate(); err != nil { - return fmt.Errorf("field 'valueMeta' is invalid: %w", err) - } - } - if x.ValueMoney != nil { - if err := x.ValueMoney.Validate(); err != nil { - return fmt.Errorf("field 'valueMoney' is invalid: %w", err) - } - } - if x.ValueOid != nil { - if !rx_Extension_ValueOid.MatchString(*x.ValueOid) { - return fmt.Errorf("field 'valueOid' does not match pattern '^urn:oid:[0-2](\\.(0|[1-9][0-9]*))+$'") - } - } - if x.ValueParameterDefinition != nil { - if err := x.ValueParameterDefinition.Validate(); err != nil { - return fmt.Errorf("field 'valueParameterDefinition' is invalid: %w", err) - } - } - if x.ValuePeriod != nil { - if err := x.ValuePeriod.Validate(); err != nil { - return fmt.Errorf("field 'valuePeriod' is invalid: %w", err) - } - } - if x.ValuePositiveInt != nil { - if *x.ValuePositiveInt <= 0.000000 { - return fmt.Errorf("field 'valuePositiveInt' is below exclusive minimum 0.000000") - } - } - if x.ValueQuantity != nil { - if err := x.ValueQuantity.Validate(); err != nil { - return fmt.Errorf("field 'valueQuantity' is invalid: %w", err) - } - } - if x.ValueRange != nil { - if err := x.ValueRange.Validate(); err != nil { - return fmt.Errorf("field 'valueRange' is invalid: %w", err) - } - } - if x.ValueRatio != nil { - if err := x.ValueRatio.Validate(); err != nil { - return fmt.Errorf("field 'valueRatio' is invalid: %w", err) - } - } - if x.ValueRatioRange != nil { - if err := x.ValueRatioRange.Validate(); err != nil { - return fmt.Errorf("field 'valueRatioRange' is invalid: %w", err) - } - } - if x.ValueReference != nil { - if err := x.ValueReference.Validate(); err != nil { - return fmt.Errorf("field 'valueReference' is invalid: %w", err) - } - } - if x.ValueRelatedArtifact != nil { - if err := x.ValueRelatedArtifact.Validate(); err != nil { - return fmt.Errorf("field 'valueRelatedArtifact' is invalid: %w", err) - } - } - if x.ValueSampledData != nil { - if err := x.ValueSampledData.Validate(); err != nil { - return fmt.Errorf("field 'valueSampledData' is invalid: %w", err) - } - } - if x.ValueSignature != nil { - if err := x.ValueSignature.Validate(); err != nil { - return fmt.Errorf("field 'valueSignature' is invalid: %w", err) - } - } - if x.ValueString != nil { - if *x.ValueString == "" { - return fmt.Errorf("field 'valueString' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.ValueTime != nil { - if err := ValidateFhirTime(*x.ValueTime); err != nil { - return fmt.Errorf("field 'valueTime' has invalid time format: %w", err) - } - } - if x.ValueTiming != nil { - if err := x.ValueTiming.Validate(); err != nil { - return fmt.Errorf("field 'valueTiming' is invalid: %w", err) - } - } - if x.ValueTriggerDefinition != nil { - if err := x.ValueTriggerDefinition.Validate(); err != nil { - return fmt.Errorf("field 'valueTriggerDefinition' is invalid: %w", err) - } - } - if x.ValueUnsignedInt != nil { - if *x.ValueUnsignedInt < 0.000000 { - return fmt.Errorf("field 'valueUnsignedInt' is below minimum 0.000000") - } - } - if x.ValueURI != nil { - } - if x.ValueURL != nil { - if utf8.RuneCountInString(*x.ValueURL) < 1 { - return fmt.Errorf("field 'valueUrl' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ValueURL) > 65536 { - return fmt.Errorf("field 'valueUrl' is too long (max 65536 characters)") - } - if err := ValidateFhirURI(*x.ValueURL); err != nil { - return fmt.Errorf("field 'valueUrl' has invalid URI format: %w", err) - } - } - if x.ValueUsageContext != nil { - if err := x.ValueUsageContext.Validate(); err != nil { - return fmt.Errorf("field 'valueUsageContext' is invalid: %w", err) - } - } - if x.ValueUUID != nil { - if err := ValidateFhirUUID(*x.ValueUUID); err != nil { - return fmt.Errorf("field 'valueUuid' has invalid UUID format: %w", err) - } - } - return nil -} - -// Validate validates a FHIRPrimitiveExtension struct against its schema constraints. -func (x *FHIRPrimitiveExtension) Validate() error { - if x == nil { - return nil - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "FHIRPrimitiveExtension" { - return fmt.Errorf("field 'resourceType' must be exactly 'FHIRPrimitiveExtension'") - } - } - return nil -} - -// Validate validates a FamilyMemberHistory struct against its schema constraints. -func (x *FamilyMemberHistory) Validate() error { - if x == nil { - return nil - } - if x.XAgeString != nil { - if err := x.XAgeString.Validate(); err != nil { - return fmt.Errorf("field '_ageString' is invalid: %w", err) - } - } - if x.XBornDate != nil { - if err := x.XBornDate.Validate(); err != nil { - return fmt.Errorf("field '_bornDate' is invalid: %w", err) - } - } - if x.XBornString != nil { - if err := x.XBornString.Validate(); err != nil { - return fmt.Errorf("field '_bornString' is invalid: %w", err) - } - } - if x.XDate != nil { - if err := x.XDate.Validate(); err != nil { - return fmt.Errorf("field '_date' is invalid: %w", err) - } - } - if x.XDeceasedBoolean != nil { - if err := x.XDeceasedBoolean.Validate(); err != nil { - return fmt.Errorf("field '_deceasedBoolean' is invalid: %w", err) - } - } - if x.XDeceasedDate != nil { - if err := x.XDeceasedDate.Validate(); err != nil { - return fmt.Errorf("field '_deceasedDate' is invalid: %w", err) - } - } - if x.XDeceasedString != nil { - if err := x.XDeceasedString.Validate(); err != nil { - return fmt.Errorf("field '_deceasedString' is invalid: %w", err) - } - } - if x.XEstimatedAge != nil { - if err := x.XEstimatedAge.Validate(); err != nil { - return fmt.Errorf("field '_estimatedAge' is invalid: %w", err) - } - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XInstantiatesCanonical != nil { - for i, item := range x.XInstantiatesCanonical { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field '_instantiatesCanonical[%d]' is invalid: %w", i, err) - } - } - } - } - if x.XInstantiatesURI != nil { - for i, item := range x.XInstantiatesURI { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field '_instantiatesUri[%d]' is invalid: %w", i, err) - } - } - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.XName != nil { - if err := x.XName.Validate(); err != nil { - return fmt.Errorf("field '_name' is invalid: %w", err) - } - } - if x.XStatus != nil { - if err := x.XStatus.Validate(); err != nil { - return fmt.Errorf("field '_status' is invalid: %w", err) - } - } - if x.AgeAge != nil { - if err := x.AgeAge.Validate(); err != nil { - return fmt.Errorf("field 'ageAge' is invalid: %w", err) - } - } - if x.AgeRange != nil { - if err := x.AgeRange.Validate(); err != nil { - return fmt.Errorf("field 'ageRange' is invalid: %w", err) - } - } - if x.AgeString != nil { - if *x.AgeString == "" { - return fmt.Errorf("field 'ageString' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.BornDate != nil { - if err := ValidateFhirDate(*x.BornDate); err != nil { - return fmt.Errorf("field 'bornDate' has invalid date format: %w", err) - } - } - if x.BornPeriod != nil { - if err := x.BornPeriod.Validate(); err != nil { - return fmt.Errorf("field 'bornPeriod' is invalid: %w", err) - } - } - if x.BornString != nil { - if *x.BornString == "" { - return fmt.Errorf("field 'bornString' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Condition != nil { - for i, item := range x.Condition { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'condition[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Contained != nil { - for i, item := range x.Contained { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) - } - } - } - } - if x.DataAbsentReason != nil { - if err := x.DataAbsentReason.Validate(); err != nil { - return fmt.Errorf("field 'dataAbsentReason' is invalid: %w", err) - } - } - if x.Date != nil { - if err := ValidateFhirDateTime(*x.Date); err != nil { - return fmt.Errorf("field 'date' has invalid date-time format: %w", err) - } - } - if x.DeceasedAge != nil { - if err := x.DeceasedAge.Validate(); err != nil { - return fmt.Errorf("field 'deceasedAge' is invalid: %w", err) - } - } - if x.DeceasedBoolean != nil { - } - if x.DeceasedDate != nil { - if err := ValidateFhirDate(*x.DeceasedDate); err != nil { - return fmt.Errorf("field 'deceasedDate' has invalid date format: %w", err) - } - } - if x.DeceasedRange != nil { - if err := x.DeceasedRange.Validate(); err != nil { - return fmt.Errorf("field 'deceasedRange' is invalid: %w", err) - } - } - if x.DeceasedString != nil { - if *x.DeceasedString == "" { - return fmt.Errorf("field 'deceasedString' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.EstimatedAge != nil { - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if !rx_FamilyMemberHistory_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ImplicitRules != nil { - } - if x.InstantiatesCanonical != nil { - } - if x.InstantiatesURI != nil { - } - if x.Language != nil { - if !rx_FamilyMemberHistory_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Name != nil { - if *x.Name == "" { - return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Note != nil { - for i, item := range x.Note { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Participant != nil { - for i, item := range x.Participant { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'participant[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Patient == nil { - return fmt.Errorf("required field 'patient' is missing") - } - if x.Patient != nil { - if err := x.Patient.Validate(); err != nil { - return fmt.Errorf("field 'patient' is invalid: %w", err) - } - } - if x.Procedure != nil { - for i, item := range x.Procedure { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'procedure[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Reason != nil { - for i, item := range x.Reason { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'reason[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Relationship == nil { - return fmt.Errorf("required field 'relationship' is missing") - } - if x.Relationship != nil { - if err := x.Relationship.Validate(); err != nil { - return fmt.Errorf("field 'relationship' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "FamilyMemberHistory" { - return fmt.Errorf("field 'resourceType' must be exactly 'FamilyMemberHistory'") - } - } - if x.Sex != nil { - if err := x.Sex.Validate(); err != nil { - return fmt.Errorf("field 'sex' is invalid: %w", err) - } - } - if x.Status != nil { - if !rx_FamilyMemberHistory_Status.MatchString(*x.Status) { - return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Text != nil { - if err := x.Text.Validate(); err != nil { - return fmt.Errorf("field 'text' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a FamilyMemberHistoryCondition struct against its schema constraints. -func (x *FamilyMemberHistoryCondition) Validate() error { - if x == nil { - return nil - } - if x.XContributedToDeath != nil { - if err := x.XContributedToDeath.Validate(); err != nil { - return fmt.Errorf("field '_contributedToDeath' is invalid: %w", err) - } - } - if x.XOnsetString != nil { - if err := x.XOnsetString.Validate(); err != nil { - return fmt.Errorf("field '_onsetString' is invalid: %w", err) - } - } - if x.Code == nil { - return fmt.Errorf("required field 'code' is missing") - } - if x.Code != nil { - if err := x.Code.Validate(); err != nil { - return fmt.Errorf("field 'code' is invalid: %w", err) - } - } - if x.ContributedToDeath != nil { - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Note != nil { - for i, item := range x.Note { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) - } - } - } - } - if x.OnsetAge != nil { - if err := x.OnsetAge.Validate(); err != nil { - return fmt.Errorf("field 'onsetAge' is invalid: %w", err) - } - } - if x.OnsetPeriod != nil { - if err := x.OnsetPeriod.Validate(); err != nil { - return fmt.Errorf("field 'onsetPeriod' is invalid: %w", err) - } - } - if x.OnsetRange != nil { - if err := x.OnsetRange.Validate(); err != nil { - return fmt.Errorf("field 'onsetRange' is invalid: %w", err) - } - } - if x.OnsetString != nil { - if *x.OnsetString == "" { - return fmt.Errorf("field 'onsetString' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Outcome != nil { - if err := x.Outcome.Validate(); err != nil { - return fmt.Errorf("field 'outcome' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "FamilyMemberHistoryCondition" { - return fmt.Errorf("field 'resourceType' must be exactly 'FamilyMemberHistoryCondition'") - } - } - return nil -} - -// Validate validates a FamilyMemberHistoryParticipant struct against its schema constraints. -func (x *FamilyMemberHistoryParticipant) Validate() error { - if x == nil { - return nil - } - if x.Actor == nil { - return fmt.Errorf("required field 'actor' is missing") - } - if x.Actor != nil { - if err := x.Actor.Validate(); err != nil { - return fmt.Errorf("field 'actor' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Function != nil { - if err := x.Function.Validate(); err != nil { - return fmt.Errorf("field 'function' is invalid: %w", err) - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "FamilyMemberHistoryParticipant" { - return fmt.Errorf("field 'resourceType' must be exactly 'FamilyMemberHistoryParticipant'") - } - } - return nil -} - -// Validate validates a FamilyMemberHistoryProcedure struct against its schema constraints. -func (x *FamilyMemberHistoryProcedure) Validate() error { - if x == nil { - return nil - } - if x.XContributedToDeath != nil { - if err := x.XContributedToDeath.Validate(); err != nil { - return fmt.Errorf("field '_contributedToDeath' is invalid: %w", err) - } - } - if x.XPerformedDateTime != nil { - if err := x.XPerformedDateTime.Validate(); err != nil { - return fmt.Errorf("field '_performedDateTime' is invalid: %w", err) - } - } - if x.XPerformedString != nil { - if err := x.XPerformedString.Validate(); err != nil { - return fmt.Errorf("field '_performedString' is invalid: %w", err) - } - } - if x.Code == nil { - return fmt.Errorf("required field 'code' is missing") - } - if x.Code != nil { - if err := x.Code.Validate(); err != nil { - return fmt.Errorf("field 'code' is invalid: %w", err) - } - } - if x.ContributedToDeath != nil { - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Note != nil { - for i, item := range x.Note { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Outcome != nil { - if err := x.Outcome.Validate(); err != nil { - return fmt.Errorf("field 'outcome' is invalid: %w", err) - } - } - if x.PerformedAge != nil { - if err := x.PerformedAge.Validate(); err != nil { - return fmt.Errorf("field 'performedAge' is invalid: %w", err) - } - } - if x.PerformedDateTime != nil { - if err := ValidateFhirDateTime(*x.PerformedDateTime); err != nil { - return fmt.Errorf("field 'performedDateTime' has invalid date-time format: %w", err) - } - } - if x.PerformedPeriod != nil { - if err := x.PerformedPeriod.Validate(); err != nil { - return fmt.Errorf("field 'performedPeriod' is invalid: %w", err) - } - } - if x.PerformedRange != nil { - if err := x.PerformedRange.Validate(); err != nil { - return fmt.Errorf("field 'performedRange' is invalid: %w", err) - } - } - if x.PerformedString != nil { - if *x.PerformedString == "" { - return fmt.Errorf("field 'performedString' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.ResourceType != nil { - if *x.ResourceType != "FamilyMemberHistoryProcedure" { - return fmt.Errorf("field 'resourceType' must be exactly 'FamilyMemberHistoryProcedure'") - } - } - return nil -} - -// Validate validates a Group struct against its schema constraints. -func (x *Group) Validate() error { - if x == nil { - return nil - } - if x.XActive != nil { - if err := x.XActive.Validate(); err != nil { - return fmt.Errorf("field '_active' is invalid: %w", err) - } - } - if x.XDescription != nil { - if err := x.XDescription.Validate(); err != nil { - return fmt.Errorf("field '_description' is invalid: %w", err) - } - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.XMembership != nil { - if err := x.XMembership.Validate(); err != nil { - return fmt.Errorf("field '_membership' is invalid: %w", err) - } - } - if x.XName != nil { - if err := x.XName.Validate(); err != nil { - return fmt.Errorf("field '_name' is invalid: %w", err) - } - } - if x.XQuantity != nil { - if err := x.XQuantity.Validate(); err != nil { - return fmt.Errorf("field '_quantity' is invalid: %w", err) - } - } - if x.XType != nil { - if err := x.XType.Validate(); err != nil { - return fmt.Errorf("field '_type' is invalid: %w", err) - } - } - if x.Active != nil { - } - if x.Characteristic != nil { - for i, item := range x.Characteristic { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'characteristic[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Code != nil { - if err := x.Code.Validate(); err != nil { - return fmt.Errorf("field 'code' is invalid: %w", err) - } - } - if x.Contained != nil { - for i, item := range x.Contained { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Description != nil { - if !rx_Group_Description.MatchString(*x.Description) { - return fmt.Errorf("field 'description' does not match pattern '\\s*(\\S|\\s)*'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if !rx_Group_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ImplicitRules != nil { - } - if x.Language != nil { - if !rx_Group_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.ManagingEntity != nil { - if err := x.ManagingEntity.Validate(); err != nil { - return fmt.Errorf("field 'managingEntity' is invalid: %w", err) - } - } - if x.Member != nil { - for i, item := range x.Member { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'member[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Membership != nil { - if !rx_Group_Membership.MatchString(*x.Membership) { - return fmt.Errorf("field 'membership' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Name != nil { - if *x.Name == "" { - return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Quantity != nil { - if *x.Quantity < 0.000000 { - return fmt.Errorf("field 'quantity' is below minimum 0.000000") - } - } - if x.ResourceType != nil { - if *x.ResourceType != "Group" { - return fmt.Errorf("field 'resourceType' must be exactly 'Group'") - } - } - if x.Text != nil { - if err := x.Text.Validate(); err != nil { - return fmt.Errorf("field 'text' is invalid: %w", err) - } - } - if x.Type != nil { - if !rx_Group_Type.MatchString(*x.Type) { - return fmt.Errorf("field 'type' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - return nil -} - -// Validate validates a GroupCharacteristic struct against its schema constraints. -func (x *GroupCharacteristic) Validate() error { - if x == nil { - return nil - } - if x.XExclude != nil { - if err := x.XExclude.Validate(); err != nil { - return fmt.Errorf("field '_exclude' is invalid: %w", err) - } - } - if x.XValueBoolean != nil { - if err := x.XValueBoolean.Validate(); err != nil { - return fmt.Errorf("field '_valueBoolean' is invalid: %w", err) - } - } - if x.Code == nil { - return fmt.Errorf("required field 'code' is missing") - } - if x.Code != nil { - if err := x.Code.Validate(); err != nil { - return fmt.Errorf("field 'code' is invalid: %w", err) - } - } - if x.Exclude != nil { - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Period != nil { - if err := x.Period.Validate(); err != nil { - return fmt.Errorf("field 'period' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "GroupCharacteristic" { - return fmt.Errorf("field 'resourceType' must be exactly 'GroupCharacteristic'") - } - } - if x.ValueBoolean != nil { - } - if x.ValueCodeableConcept != nil { - if err := x.ValueCodeableConcept.Validate(); err != nil { - return fmt.Errorf("field 'valueCodeableConcept' is invalid: %w", err) - } - } - if x.ValueQuantity != nil { - if err := x.ValueQuantity.Validate(); err != nil { - return fmt.Errorf("field 'valueQuantity' is invalid: %w", err) - } - } - if x.ValueRange != nil { - if err := x.ValueRange.Validate(); err != nil { - return fmt.Errorf("field 'valueRange' is invalid: %w", err) - } - } - if x.ValueReference != nil { - if err := x.ValueReference.Validate(); err != nil { - return fmt.Errorf("field 'valueReference' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a GroupMember struct against its schema constraints. -func (x *GroupMember) Validate() error { - if x == nil { - return nil - } - if x.XInactive != nil { - if err := x.XInactive.Validate(); err != nil { - return fmt.Errorf("field '_inactive' is invalid: %w", err) - } - } - if x.Entity == nil { - return fmt.Errorf("required field 'entity' is missing") - } - if x.Entity != nil { - if err := x.Entity.Validate(); err != nil { - return fmt.Errorf("field 'entity' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Inactive != nil { - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Period != nil { - if err := x.Period.Validate(); err != nil { - return fmt.Errorf("field 'period' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "GroupMember" { - return fmt.Errorf("field 'resourceType' must be exactly 'GroupMember'") - } - } - return nil -} - -// Validate validates a HumanName struct against its schema constraints. -func (x *HumanName) Validate() error { - if x == nil { - return nil - } - if x.XFamily != nil { - if err := x.XFamily.Validate(); err != nil { - return fmt.Errorf("field '_family' is invalid: %w", err) - } - } - if x.XGiven != nil { - for i, item := range x.XGiven { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field '_given[%d]' is invalid: %w", i, err) - } - } - } - } - if x.XPrefix != nil { - for i, item := range x.XPrefix { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field '_prefix[%d]' is invalid: %w", i, err) - } - } - } - } - if x.XSuffix != nil { - for i, item := range x.XSuffix { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field '_suffix[%d]' is invalid: %w", i, err) - } - } - } - } - if x.XText != nil { - if err := x.XText.Validate(); err != nil { - return fmt.Errorf("field '_text' is invalid: %w", err) - } - } - if x.XUse != nil { - if err := x.XUse.Validate(); err != nil { - return fmt.Errorf("field '_use' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Family != nil { - if *x.Family == "" { - return fmt.Errorf("field 'family' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Given != nil { - for i, item := range x.Given { - if item == "" { - return fmt.Errorf("field 'given[%d]' does not match pattern '[ \\r\\n\\t\\S]+'", i) - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Period != nil { - if err := x.Period.Validate(); err != nil { - return fmt.Errorf("field 'period' is invalid: %w", err) - } - } - if x.Prefix != nil { - for i, item := range x.Prefix { - if item == "" { - return fmt.Errorf("field 'prefix[%d]' does not match pattern '[ \\r\\n\\t\\S]+'", i) - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "HumanName" { - return fmt.Errorf("field 'resourceType' must be exactly 'HumanName'") - } - } - if x.Suffix != nil { - for i, item := range x.Suffix { - if item == "" { - return fmt.Errorf("field 'suffix[%d]' does not match pattern '[ \\r\\n\\t\\S]+'", i) - } - } - } - if x.Text != nil { - if *x.Text == "" { - return fmt.Errorf("field 'text' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Use != nil { - if !rx_HumanName_Use.MatchString(*x.Use) { - return fmt.Errorf("field 'use' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - return nil -} - -// Validate validates a Identifier struct against its schema constraints. -func (x *Identifier) Validate() error { - if x == nil { - return nil - } - if x.XSystem != nil { - if err := x.XSystem.Validate(); err != nil { - return fmt.Errorf("field '_system' is invalid: %w", err) - } - } - if x.XUse != nil { - if err := x.XUse.Validate(); err != nil { - return fmt.Errorf("field '_use' is invalid: %w", err) - } - } - if x.XValue != nil { - if err := x.XValue.Validate(); err != nil { - return fmt.Errorf("field '_value' is invalid: %w", err) - } - } - if x.Assigner != nil { - if err := x.Assigner.Validate(); err != nil { - return fmt.Errorf("field 'assigner' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Period != nil { - if err := x.Period.Validate(); err != nil { - return fmt.Errorf("field 'period' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "Identifier" { - return fmt.Errorf("field 'resourceType' must be exactly 'Identifier'") - } - } - if x.System != nil { - } - if x.Type != nil { - if err := x.Type.Validate(); err != nil { - return fmt.Errorf("field 'type' is invalid: %w", err) - } - } - if x.Use != nil { - if !rx_Identifier_Use.MatchString(*x.Use) { - return fmt.Errorf("field 'use' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Value != nil { - if *x.Value == "" { - return fmt.Errorf("field 'value' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - return nil -} - -// Validate validates a ImagingStudy struct against its schema constraints. -func (x *ImagingStudy) Validate() error { - if x == nil { - return nil - } - if x.XDescription != nil { - if err := x.XDescription.Validate(); err != nil { - return fmt.Errorf("field '_description' is invalid: %w", err) - } - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.XNumberOfInstances != nil { - if err := x.XNumberOfInstances.Validate(); err != nil { - return fmt.Errorf("field '_numberOfInstances' is invalid: %w", err) - } - } - if x.XNumberOfSeries != nil { - if err := x.XNumberOfSeries.Validate(); err != nil { - return fmt.Errorf("field '_numberOfSeries' is invalid: %w", err) - } - } - if x.XStarted != nil { - if err := x.XStarted.Validate(); err != nil { - return fmt.Errorf("field '_started' is invalid: %w", err) - } - } - if x.XStatus != nil { - if err := x.XStatus.Validate(); err != nil { - return fmt.Errorf("field '_status' is invalid: %w", err) - } - } - if x.BasedOn != nil { - for i, item := range x.BasedOn { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'basedOn[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Contained != nil { - for i, item := range x.Contained { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Description != nil { - if *x.Description == "" { - return fmt.Errorf("field 'description' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Encounter != nil { - if err := x.Encounter.Validate(); err != nil { - return fmt.Errorf("field 'encounter' is invalid: %w", err) - } - } - if x.Endpoint != nil { - for i, item := range x.Endpoint { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'endpoint[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if !rx_ImagingStudy_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ImplicitRules != nil { - } - if x.Language != nil { - if !rx_ImagingStudy_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.Location != nil { - if err := x.Location.Validate(); err != nil { - return fmt.Errorf("field 'location' is invalid: %w", err) - } - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.Modality != nil { - for i, item := range x.Modality { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modality[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Note != nil { - for i, item := range x.Note { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) - } - } - } - } - if x.NumberOfInstances != nil { - if *x.NumberOfInstances < 0.000000 { - return fmt.Errorf("field 'numberOfInstances' is below minimum 0.000000") - } - } - if x.NumberOfSeries != nil { - if *x.NumberOfSeries < 0.000000 { - return fmt.Errorf("field 'numberOfSeries' is below minimum 0.000000") - } - } - if x.PartOf != nil { - for i, item := range x.PartOf { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'partOf[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Procedure != nil { - for i, item := range x.Procedure { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'procedure[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Reason != nil { - for i, item := range x.Reason { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'reason[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Referrer != nil { - if err := x.Referrer.Validate(); err != nil { - return fmt.Errorf("field 'referrer' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ImagingStudy" { - return fmt.Errorf("field 'resourceType' must be exactly 'ImagingStudy'") - } - } - if x.Series != nil { - for i, item := range x.Series { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'series[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Started != nil { - if err := ValidateFhirDateTime(*x.Started); err != nil { - return fmt.Errorf("field 'started' has invalid date-time format: %w", err) - } - } - if x.Status != nil { - if !rx_ImagingStudy_Status.MatchString(*x.Status) { - return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Subject == nil { - return fmt.Errorf("required field 'subject' is missing") - } - if x.Subject != nil { - if err := x.Subject.Validate(); err != nil { - return fmt.Errorf("field 'subject' is invalid: %w", err) - } - } - if x.Text != nil { - if err := x.Text.Validate(); err != nil { - return fmt.Errorf("field 'text' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a ImagingStudySeries struct against its schema constraints. -func (x *ImagingStudySeries) Validate() error { - if x == nil { - return nil - } - if x.XDescription != nil { - if err := x.XDescription.Validate(); err != nil { - return fmt.Errorf("field '_description' is invalid: %w", err) - } - } - if x.XNumber != nil { - if err := x.XNumber.Validate(); err != nil { - return fmt.Errorf("field '_number' is invalid: %w", err) - } - } - if x.XNumberOfInstances != nil { - if err := x.XNumberOfInstances.Validate(); err != nil { - return fmt.Errorf("field '_numberOfInstances' is invalid: %w", err) - } - } - if x.XStarted != nil { - if err := x.XStarted.Validate(); err != nil { - return fmt.Errorf("field '_started' is invalid: %w", err) - } - } - if x.XUid != nil { - if err := x.XUid.Validate(); err != nil { - return fmt.Errorf("field '_uid' is invalid: %w", err) - } - } - if x.BodySite != nil { - if err := x.BodySite.Validate(); err != nil { - return fmt.Errorf("field 'bodySite' is invalid: %w", err) - } - } - if x.Description != nil { - if *x.Description == "" { - return fmt.Errorf("field 'description' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Endpoint != nil { - for i, item := range x.Endpoint { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'endpoint[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Instance != nil { - for i, item := range x.Instance { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'instance[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Laterality != nil { - if err := x.Laterality.Validate(); err != nil { - return fmt.Errorf("field 'laterality' is invalid: %w", err) - } - } - if x.Links != nil { - } - if x.Modality == nil { - return fmt.Errorf("required field 'modality' is missing") - } - if x.Modality != nil { - if err := x.Modality.Validate(); err != nil { - return fmt.Errorf("field 'modality' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Number != nil { - if *x.Number < 0.000000 { - return fmt.Errorf("field 'number' is below minimum 0.000000") - } - } - if x.NumberOfInstances != nil { - if *x.NumberOfInstances < 0.000000 { - return fmt.Errorf("field 'numberOfInstances' is below minimum 0.000000") - } - } - if x.Performer != nil { - for i, item := range x.Performer { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'performer[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ImagingStudySeries" { - return fmt.Errorf("field 'resourceType' must be exactly 'ImagingStudySeries'") - } - } - if x.Specimen != nil { - for i, item := range x.Specimen { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'specimen[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Started != nil { - if err := ValidateFhirDateTime(*x.Started); err != nil { - return fmt.Errorf("field 'started' has invalid date-time format: %w", err) - } - } - if x.Uid != nil { - if !rx_ImagingStudySeries_Uid.MatchString(*x.Uid) { - return fmt.Errorf("field 'uid' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.Uid) < 1 { - return fmt.Errorf("field 'uid' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.Uid) > 64 { - return fmt.Errorf("field 'uid' is too long (max 64 characters)") - } - } - return nil -} - -// Validate validates a ImagingStudySeriesInstance struct against its schema constraints. -func (x *ImagingStudySeriesInstance) Validate() error { - if x == nil { - return nil - } - if x.XNumber != nil { - if err := x.XNumber.Validate(); err != nil { - return fmt.Errorf("field '_number' is invalid: %w", err) - } - } - if x.XTitle != nil { - if err := x.XTitle.Validate(); err != nil { - return fmt.Errorf("field '_title' is invalid: %w", err) - } - } - if x.XUid != nil { - if err := x.XUid.Validate(); err != nil { - return fmt.Errorf("field '_uid' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Number != nil { - if *x.Number < 0.000000 { - return fmt.Errorf("field 'number' is below minimum 0.000000") - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ImagingStudySeriesInstance" { - return fmt.Errorf("field 'resourceType' must be exactly 'ImagingStudySeriesInstance'") - } - } - if x.SopClass == nil { - return fmt.Errorf("required field 'sopClass' is missing") - } - if x.SopClass != nil { - if err := x.SopClass.Validate(); err != nil { - return fmt.Errorf("field 'sopClass' is invalid: %w", err) - } - } - if x.Title != nil { - if *x.Title == "" { - return fmt.Errorf("field 'title' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Uid != nil { - if !rx_ImagingStudySeriesInstance_Uid.MatchString(*x.Uid) { - return fmt.Errorf("field 'uid' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.Uid) < 1 { - return fmt.Errorf("field 'uid' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.Uid) > 64 { - return fmt.Errorf("field 'uid' is too long (max 64 characters)") - } - } - return nil -} - -// Validate validates a ImagingStudySeriesPerformer struct against its schema constraints. -func (x *ImagingStudySeriesPerformer) Validate() error { - if x == nil { - return nil - } - if x.Actor == nil { - return fmt.Errorf("required field 'actor' is missing") - } - if x.Actor != nil { - if err := x.Actor.Validate(); err != nil { - return fmt.Errorf("field 'actor' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Function != nil { - if err := x.Function.Validate(); err != nil { - return fmt.Errorf("field 'function' is invalid: %w", err) - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ImagingStudySeriesPerformer" { - return fmt.Errorf("field 'resourceType' must be exactly 'ImagingStudySeriesPerformer'") - } - } - return nil -} - -// Validate validates a Medication struct against its schema constraints. -func (x *Medication) Validate() error { - if x == nil { - return nil - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.XStatus != nil { - if err := x.XStatus.Validate(); err != nil { - return fmt.Errorf("field '_status' is invalid: %w", err) - } - } - if x.Batch != nil { - if err := x.Batch.Validate(); err != nil { - return fmt.Errorf("field 'batch' is invalid: %w", err) - } - } - if x.Code != nil { - if err := x.Code.Validate(); err != nil { - return fmt.Errorf("field 'code' is invalid: %w", err) - } - } - if x.Contained != nil { - for i, item := range x.Contained { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Definition != nil { - if err := x.Definition.Validate(); err != nil { - return fmt.Errorf("field 'definition' is invalid: %w", err) - } - } - if x.DoseForm != nil { - if err := x.DoseForm.Validate(); err != nil { - return fmt.Errorf("field 'doseForm' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if !rx_Medication_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ImplicitRules != nil { - } - if x.Ingredient != nil { - for i, item := range x.Ingredient { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'ingredient[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Language != nil { - if !rx_Medication_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.MarketingAuthorizationHolder != nil { - if err := x.MarketingAuthorizationHolder.Validate(); err != nil { - return fmt.Errorf("field 'marketingAuthorizationHolder' is invalid: %w", err) - } - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "Medication" { - return fmt.Errorf("field 'resourceType' must be exactly 'Medication'") - } - } - if x.Status != nil { - if !rx_Medication_Status.MatchString(*x.Status) { - return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Text != nil { - if err := x.Text.Validate(); err != nil { - return fmt.Errorf("field 'text' is invalid: %w", err) - } - } - if x.TotalVolume != nil { - if err := x.TotalVolume.Validate(); err != nil { - return fmt.Errorf("field 'totalVolume' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a MedicationAdministration struct against its schema constraints. -func (x *MedicationAdministration) Validate() error { - if x == nil { - return nil - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XIsSubPotent != nil { - if err := x.XIsSubPotent.Validate(); err != nil { - return fmt.Errorf("field '_isSubPotent' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.XOccurenceDateTime != nil { - if err := x.XOccurenceDateTime.Validate(); err != nil { - return fmt.Errorf("field '_occurenceDateTime' is invalid: %w", err) - } - } - if x.XRecorded != nil { - if err := x.XRecorded.Validate(); err != nil { - return fmt.Errorf("field '_recorded' is invalid: %w", err) - } - } - if x.XStatus != nil { - if err := x.XStatus.Validate(); err != nil { - return fmt.Errorf("field '_status' is invalid: %w", err) - } - } - if x.BasedOn != nil { - for i, item := range x.BasedOn { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'basedOn[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Category != nil { - for i, item := range x.Category { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'category[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Contained != nil { - for i, item := range x.Contained { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Device != nil { - for i, item := range x.Device { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'device[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Dosage != nil { - if err := x.Dosage.Validate(); err != nil { - return fmt.Errorf("field 'dosage' is invalid: %w", err) - } - } - if x.Encounter != nil { - if err := x.Encounter.Validate(); err != nil { - return fmt.Errorf("field 'encounter' is invalid: %w", err) - } - } - if x.EventHistory != nil { - for i, item := range x.EventHistory { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'eventHistory[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if !rx_MedicationAdministration_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ImplicitRules != nil { - } - if x.IsSubPotent != nil { - } - if x.Language != nil { - if !rx_MedicationAdministration_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.Medication == nil { - return fmt.Errorf("required field 'medication' is missing") - } - if x.Medication != nil { - if err := x.Medication.Validate(); err != nil { - return fmt.Errorf("field 'medication' is invalid: %w", err) - } - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Note != nil { - for i, item := range x.Note { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) - } - } - } - } - if x.OccurenceDateTime != nil { - if err := ValidateFhirDateTime(*x.OccurenceDateTime); err != nil { - return fmt.Errorf("field 'occurenceDateTime' has invalid date-time format: %w", err) - } - } - if x.OccurencePeriod != nil { - if err := x.OccurencePeriod.Validate(); err != nil { - return fmt.Errorf("field 'occurencePeriod' is invalid: %w", err) - } - } - if x.OccurenceTiming != nil { - if err := x.OccurenceTiming.Validate(); err != nil { - return fmt.Errorf("field 'occurenceTiming' is invalid: %w", err) - } - } - if x.PartOf != nil { - for i, item := range x.PartOf { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'partOf[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Performer != nil { - for i, item := range x.Performer { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'performer[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Reason != nil { - for i, item := range x.Reason { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'reason[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Recorded != nil { - if err := ValidateFhirDateTime(*x.Recorded); err != nil { - return fmt.Errorf("field 'recorded' has invalid date-time format: %w", err) - } - } - if x.Request != nil { - if err := x.Request.Validate(); err != nil { - return fmt.Errorf("field 'request' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "MedicationAdministration" { - return fmt.Errorf("field 'resourceType' must be exactly 'MedicationAdministration'") - } - } - if x.Status != nil { - if !rx_MedicationAdministration_Status.MatchString(*x.Status) { - return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.StatusReason != nil { - for i, item := range x.StatusReason { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'statusReason[%d]' is invalid: %w", i, err) - } - } - } - } - if x.SubPotentReason != nil { - for i, item := range x.SubPotentReason { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'subPotentReason[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Subject == nil { - return fmt.Errorf("required field 'subject' is missing") - } - if x.Subject != nil { - if err := x.Subject.Validate(); err != nil { - return fmt.Errorf("field 'subject' is invalid: %w", err) - } - } - if x.SupportingInformation != nil { - for i, item := range x.SupportingInformation { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'supportingInformation[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Text != nil { - if err := x.Text.Validate(); err != nil { - return fmt.Errorf("field 'text' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a MedicationAdministrationDosage struct against its schema constraints. -func (x *MedicationAdministrationDosage) Validate() error { - if x == nil { - return nil - } - if x.XText != nil { - if err := x.XText.Validate(); err != nil { - return fmt.Errorf("field '_text' is invalid: %w", err) - } - } - if x.Dose != nil { - if err := x.Dose.Validate(); err != nil { - return fmt.Errorf("field 'dose' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Method != nil { - if err := x.Method.Validate(); err != nil { - return fmt.Errorf("field 'method' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.RateQuantity != nil { - if err := x.RateQuantity.Validate(); err != nil { - return fmt.Errorf("field 'rateQuantity' is invalid: %w", err) - } - } - if x.RateRatio != nil { - if err := x.RateRatio.Validate(); err != nil { - return fmt.Errorf("field 'rateRatio' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "MedicationAdministrationDosage" { - return fmt.Errorf("field 'resourceType' must be exactly 'MedicationAdministrationDosage'") - } - } - if x.Route != nil { - if err := x.Route.Validate(); err != nil { - return fmt.Errorf("field 'route' is invalid: %w", err) - } - } - if x.Site != nil { - if err := x.Site.Validate(); err != nil { - return fmt.Errorf("field 'site' is invalid: %w", err) - } - } - if x.Text != nil { - if *x.Text == "" { - return fmt.Errorf("field 'text' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - return nil -} - -// Validate validates a MedicationAdministrationPerformer struct against its schema constraints. -func (x *MedicationAdministrationPerformer) Validate() error { - if x == nil { - return nil - } - if x.Actor == nil { - return fmt.Errorf("required field 'actor' is missing") - } - if x.Actor != nil { - if err := x.Actor.Validate(); err != nil { - return fmt.Errorf("field 'actor' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Function != nil { - if err := x.Function.Validate(); err != nil { - return fmt.Errorf("field 'function' is invalid: %w", err) - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "MedicationAdministrationPerformer" { - return fmt.Errorf("field 'resourceType' must be exactly 'MedicationAdministrationPerformer'") - } - } - return nil -} - -// Validate validates a MedicationBatch struct against its schema constraints. -func (x *MedicationBatch) Validate() error { - if x == nil { - return nil - } - if x.XExpirationDate != nil { - if err := x.XExpirationDate.Validate(); err != nil { - return fmt.Errorf("field '_expirationDate' is invalid: %w", err) - } - } - if x.XLotNumber != nil { - if err := x.XLotNumber.Validate(); err != nil { - return fmt.Errorf("field '_lotNumber' is invalid: %w", err) - } - } - if x.ExpirationDate != nil { - if err := ValidateFhirDateTime(*x.ExpirationDate); err != nil { - return fmt.Errorf("field 'expirationDate' has invalid date-time format: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.LotNumber != nil { - if *x.LotNumber == "" { - return fmt.Errorf("field 'lotNumber' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "MedicationBatch" { - return fmt.Errorf("field 'resourceType' must be exactly 'MedicationBatch'") - } - } - return nil -} - -// Validate validates a MedicationIngredient struct against its schema constraints. -func (x *MedicationIngredient) Validate() error { - if x == nil { - return nil - } - if x.XIsActive != nil { - if err := x.XIsActive.Validate(); err != nil { - return fmt.Errorf("field '_isActive' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.IsActive != nil { - } - if x.Item == nil { - return fmt.Errorf("required field 'item' is missing") - } - if x.Item != nil { - if err := x.Item.Validate(); err != nil { - return fmt.Errorf("field 'item' is invalid: %w", err) - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "MedicationIngredient" { - return fmt.Errorf("field 'resourceType' must be exactly 'MedicationIngredient'") - } - } - if x.StrengthCodeableConcept != nil { - if err := x.StrengthCodeableConcept.Validate(); err != nil { - return fmt.Errorf("field 'strengthCodeableConcept' is invalid: %w", err) - } - } - if x.StrengthQuantity != nil { - if err := x.StrengthQuantity.Validate(); err != nil { - return fmt.Errorf("field 'strengthQuantity' is invalid: %w", err) - } - } - if x.StrengthRatio != nil { - if err := x.StrengthRatio.Validate(); err != nil { - return fmt.Errorf("field 'strengthRatio' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a MedicationRequest struct against its schema constraints. -func (x *MedicationRequest) Validate() error { - if x == nil { - return nil - } - if x.XAuthoredOn != nil { - if err := x.XAuthoredOn.Validate(); err != nil { - return fmt.Errorf("field '_authoredOn' is invalid: %w", err) - } - } - if x.XDoNotPerform != nil { - if err := x.XDoNotPerform.Validate(); err != nil { - return fmt.Errorf("field '_doNotPerform' is invalid: %w", err) - } - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XIntent != nil { - if err := x.XIntent.Validate(); err != nil { - return fmt.Errorf("field '_intent' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.XPriority != nil { - if err := x.XPriority.Validate(); err != nil { - return fmt.Errorf("field '_priority' is invalid: %w", err) - } - } - if x.XRenderedDosageInstruction != nil { - if err := x.XRenderedDosageInstruction.Validate(); err != nil { - return fmt.Errorf("field '_renderedDosageInstruction' is invalid: %w", err) - } - } - if x.XReported != nil { - if err := x.XReported.Validate(); err != nil { - return fmt.Errorf("field '_reported' is invalid: %w", err) - } - } - if x.XStatus != nil { - if err := x.XStatus.Validate(); err != nil { - return fmt.Errorf("field '_status' is invalid: %w", err) - } - } - if x.XStatusChanged != nil { - if err := x.XStatusChanged.Validate(); err != nil { - return fmt.Errorf("field '_statusChanged' is invalid: %w", err) - } - } - if x.AuthoredOn != nil { - if err := ValidateFhirDateTime(*x.AuthoredOn); err != nil { - return fmt.Errorf("field 'authoredOn' has invalid date-time format: %w", err) - } - } - if x.BasedOn != nil { - for i, item := range x.BasedOn { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'basedOn[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Category != nil { - for i, item := range x.Category { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'category[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Contained != nil { - for i, item := range x.Contained { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) - } - } - } - } - if x.CourseOfTherapyType != nil { - if err := x.CourseOfTherapyType.Validate(); err != nil { - return fmt.Errorf("field 'courseOfTherapyType' is invalid: %w", err) - } - } - if x.Device != nil { - for i, item := range x.Device { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'device[%d]' is invalid: %w", i, err) - } - } - } - } - if x.DispenseRequest != nil { - if err := x.DispenseRequest.Validate(); err != nil { - return fmt.Errorf("field 'dispenseRequest' is invalid: %w", err) - } - } - if x.DoNotPerform != nil { - } - if x.DosageInstruction != nil { - for i, item := range x.DosageInstruction { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'dosageInstruction[%d]' is invalid: %w", i, err) - } - } - } - } - if x.EffectiveDosePeriod != nil { - if err := x.EffectiveDosePeriod.Validate(); err != nil { - return fmt.Errorf("field 'effectiveDosePeriod' is invalid: %w", err) - } - } - if x.Encounter != nil { - if err := x.Encounter.Validate(); err != nil { - return fmt.Errorf("field 'encounter' is invalid: %w", err) - } - } - if x.EventHistory != nil { - for i, item := range x.EventHistory { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'eventHistory[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.GroupIDentifier != nil { - if err := x.GroupIDentifier.Validate(); err != nil { - return fmt.Errorf("field 'groupIdentifier' is invalid: %w", err) - } - } - if x.ID != nil { - if !rx_MedicationRequest_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ImplicitRules != nil { - } - if x.InformationSource != nil { - for i, item := range x.InformationSource { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'informationSource[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Insurance != nil { - for i, item := range x.Insurance { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'insurance[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Intent != nil { - if !rx_MedicationRequest_Intent.MatchString(*x.Intent) { - return fmt.Errorf("field 'intent' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Language != nil { - if !rx_MedicationRequest_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.Medication == nil { - return fmt.Errorf("required field 'medication' is missing") - } - if x.Medication != nil { - if err := x.Medication.Validate(); err != nil { - return fmt.Errorf("field 'medication' is invalid: %w", err) - } - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Note != nil { - for i, item := range x.Note { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Performer != nil { - for i, item := range x.Performer { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'performer[%d]' is invalid: %w", i, err) - } - } - } - } - if x.PerformerType != nil { - if err := x.PerformerType.Validate(); err != nil { - return fmt.Errorf("field 'performerType' is invalid: %w", err) - } - } - if x.PriorPrescription != nil { - if err := x.PriorPrescription.Validate(); err != nil { - return fmt.Errorf("field 'priorPrescription' is invalid: %w", err) - } - } - if x.Priority != nil { - if !rx_MedicationRequest_Priority.MatchString(*x.Priority) { - return fmt.Errorf("field 'priority' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Reason != nil { - for i, item := range x.Reason { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'reason[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Recorder != nil { - if err := x.Recorder.Validate(); err != nil { - return fmt.Errorf("field 'recorder' is invalid: %w", err) - } - } - if x.RenderedDosageInstruction != nil { - if !rx_MedicationRequest_RenderedDosageInstruction.MatchString(*x.RenderedDosageInstruction) { - return fmt.Errorf("field 'renderedDosageInstruction' does not match pattern '\\s*(\\S|\\s)*'") - } - } - if x.Reported != nil { - } - if x.Requester != nil { - if err := x.Requester.Validate(); err != nil { - return fmt.Errorf("field 'requester' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "MedicationRequest" { - return fmt.Errorf("field 'resourceType' must be exactly 'MedicationRequest'") - } - } - if x.Status != nil { - if !rx_MedicationRequest_Status.MatchString(*x.Status) { - return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.StatusChanged != nil { - if err := ValidateFhirDateTime(*x.StatusChanged); err != nil { - return fmt.Errorf("field 'statusChanged' has invalid date-time format: %w", err) - } - } - if x.StatusReason != nil { - if err := x.StatusReason.Validate(); err != nil { - return fmt.Errorf("field 'statusReason' is invalid: %w", err) - } - } - if x.Subject == nil { - return fmt.Errorf("required field 'subject' is missing") - } - if x.Subject != nil { - if err := x.Subject.Validate(); err != nil { - return fmt.Errorf("field 'subject' is invalid: %w", err) - } - } - if x.Substitution != nil { - if err := x.Substitution.Validate(); err != nil { - return fmt.Errorf("field 'substitution' is invalid: %w", err) - } - } - if x.SupportingInformation != nil { - for i, item := range x.SupportingInformation { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'supportingInformation[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Text != nil { - if err := x.Text.Validate(); err != nil { - return fmt.Errorf("field 'text' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a MedicationRequestDispenseRequest struct against its schema constraints. -func (x *MedicationRequestDispenseRequest) Validate() error { - if x == nil { - return nil - } - if x.XNumberOfRepeatsAllowed != nil { - if err := x.XNumberOfRepeatsAllowed.Validate(); err != nil { - return fmt.Errorf("field '_numberOfRepeatsAllowed' is invalid: %w", err) - } - } - if x.DispenseInterval != nil { - if err := x.DispenseInterval.Validate(); err != nil { - return fmt.Errorf("field 'dispenseInterval' is invalid: %w", err) - } - } - if x.Dispenser != nil { - if err := x.Dispenser.Validate(); err != nil { - return fmt.Errorf("field 'dispenser' is invalid: %w", err) - } - } - if x.DispenserInstruction != nil { - for i, item := range x.DispenserInstruction { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'dispenserInstruction[%d]' is invalid: %w", i, err) - } - } - } - } - if x.DoseAdministrationAid != nil { - if err := x.DoseAdministrationAid.Validate(); err != nil { - return fmt.Errorf("field 'doseAdministrationAid' is invalid: %w", err) - } - } - if x.ExpectedSupplyDuration != nil { - if err := x.ExpectedSupplyDuration.Validate(); err != nil { - return fmt.Errorf("field 'expectedSupplyDuration' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.InitialFill != nil { - if err := x.InitialFill.Validate(); err != nil { - return fmt.Errorf("field 'initialFill' is invalid: %w", err) - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.NumberOfRepeatsAllowed != nil { - if *x.NumberOfRepeatsAllowed < 0.000000 { - return fmt.Errorf("field 'numberOfRepeatsAllowed' is below minimum 0.000000") - } - } - if x.Quantity != nil { - if err := x.Quantity.Validate(); err != nil { - return fmt.Errorf("field 'quantity' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "MedicationRequestDispenseRequest" { - return fmt.Errorf("field 'resourceType' must be exactly 'MedicationRequestDispenseRequest'") - } - } - if x.ValidityPeriod != nil { - if err := x.ValidityPeriod.Validate(); err != nil { - return fmt.Errorf("field 'validityPeriod' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a MedicationRequestDispenseRequestInitialFill struct against its schema constraints. -func (x *MedicationRequestDispenseRequestInitialFill) Validate() error { - if x == nil { - return nil - } - if x.Duration != nil { - if err := x.Duration.Validate(); err != nil { - return fmt.Errorf("field 'duration' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Quantity != nil { - if err := x.Quantity.Validate(); err != nil { - return fmt.Errorf("field 'quantity' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "MedicationRequestDispenseRequestInitialFill" { - return fmt.Errorf("field 'resourceType' must be exactly 'MedicationRequestDispenseRequestInitialFill'") - } - } - return nil -} - -// Validate validates a MedicationRequestSubstitution struct against its schema constraints. -func (x *MedicationRequestSubstitution) Validate() error { - if x == nil { - return nil - } - if x.XAllowedBoolean != nil { - if err := x.XAllowedBoolean.Validate(); err != nil { - return fmt.Errorf("field '_allowedBoolean' is invalid: %w", err) - } - } - if x.AllowedBoolean != nil { - } - if x.AllowedCodeableConcept != nil { - if err := x.AllowedCodeableConcept.Validate(); err != nil { - return fmt.Errorf("field 'allowedCodeableConcept' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Reason != nil { - if err := x.Reason.Validate(); err != nil { - return fmt.Errorf("field 'reason' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "MedicationRequestSubstitution" { - return fmt.Errorf("field 'resourceType' must be exactly 'MedicationRequestSubstitution'") - } - } - return nil -} - -// Validate validates a MedicationStatement struct against its schema constraints. -func (x *MedicationStatement) Validate() error { - if x == nil { - return nil - } - if x.XDateAsserted != nil { - if err := x.XDateAsserted.Validate(); err != nil { - return fmt.Errorf("field '_dateAsserted' is invalid: %w", err) - } - } - if x.XEffectiveDateTime != nil { - if err := x.XEffectiveDateTime.Validate(); err != nil { - return fmt.Errorf("field '_effectiveDateTime' is invalid: %w", err) - } - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.XRenderedDosageInstruction != nil { - if err := x.XRenderedDosageInstruction.Validate(); err != nil { - return fmt.Errorf("field '_renderedDosageInstruction' is invalid: %w", err) - } - } - if x.XStatus != nil { - if err := x.XStatus.Validate(); err != nil { - return fmt.Errorf("field '_status' is invalid: %w", err) - } - } - if x.Adherence != nil { - if err := x.Adherence.Validate(); err != nil { - return fmt.Errorf("field 'adherence' is invalid: %w", err) - } - } - if x.Category != nil { - for i, item := range x.Category { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'category[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Contained != nil { - for i, item := range x.Contained { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) - } - } - } - } - if x.DateAsserted != nil { - if err := ValidateFhirDateTime(*x.DateAsserted); err != nil { - return fmt.Errorf("field 'dateAsserted' has invalid date-time format: %w", err) - } - } - if x.DerivedFrom != nil { - for i, item := range x.DerivedFrom { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'derivedFrom[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Dosage != nil { - for i, item := range x.Dosage { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'dosage[%d]' is invalid: %w", i, err) - } - } - } - } - if x.EffectiveDateTime != nil { - if err := ValidateFhirDateTime(*x.EffectiveDateTime); err != nil { - return fmt.Errorf("field 'effectiveDateTime' has invalid date-time format: %w", err) - } - } - if x.EffectivePeriod != nil { - if err := x.EffectivePeriod.Validate(); err != nil { - return fmt.Errorf("field 'effectivePeriod' is invalid: %w", err) - } - } - if x.EffectiveTiming != nil { - if err := x.EffectiveTiming.Validate(); err != nil { - return fmt.Errorf("field 'effectiveTiming' is invalid: %w", err) - } - } - if x.Encounter != nil { - if err := x.Encounter.Validate(); err != nil { - return fmt.Errorf("field 'encounter' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if !rx_MedicationStatement_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ImplicitRules != nil { - } - if x.InformationSource != nil { - for i, item := range x.InformationSource { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'informationSource[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Language != nil { - if !rx_MedicationStatement_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.Medication == nil { - return fmt.Errorf("required field 'medication' is missing") - } - if x.Medication != nil { - if err := x.Medication.Validate(); err != nil { - return fmt.Errorf("field 'medication' is invalid: %w", err) - } - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Note != nil { - for i, item := range x.Note { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) - } - } - } - } - if x.PartOf != nil { - for i, item := range x.PartOf { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'partOf[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Reason != nil { - for i, item := range x.Reason { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'reason[%d]' is invalid: %w", i, err) - } - } - } - } - if x.RelatedClinicalInformation != nil { - for i, item := range x.RelatedClinicalInformation { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'relatedClinicalInformation[%d]' is invalid: %w", i, err) - } - } - } - } - if x.RenderedDosageInstruction != nil { - if !rx_MedicationStatement_RenderedDosageInstruction.MatchString(*x.RenderedDosageInstruction) { - return fmt.Errorf("field 'renderedDosageInstruction' does not match pattern '\\s*(\\S|\\s)*'") - } - } - if x.ResourceType != nil { - if *x.ResourceType != "MedicationStatement" { - return fmt.Errorf("field 'resourceType' must be exactly 'MedicationStatement'") - } - } - if x.Status != nil { - if !rx_MedicationStatement_Status.MatchString(*x.Status) { - return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Subject == nil { - return fmt.Errorf("required field 'subject' is missing") - } - if x.Subject != nil { - if err := x.Subject.Validate(); err != nil { - return fmt.Errorf("field 'subject' is invalid: %w", err) - } - } - if x.Text != nil { - if err := x.Text.Validate(); err != nil { - return fmt.Errorf("field 'text' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a MedicationStatementAdherence struct against its schema constraints. -func (x *MedicationStatementAdherence) Validate() error { - if x == nil { - return nil - } - if x.Code == nil { - return fmt.Errorf("required field 'code' is missing") - } - if x.Code != nil { - if err := x.Code.Validate(); err != nil { - return fmt.Errorf("field 'code' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Reason != nil { - if err := x.Reason.Validate(); err != nil { - return fmt.Errorf("field 'reason' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "MedicationStatementAdherence" { - return fmt.Errorf("field 'resourceType' must be exactly 'MedicationStatementAdherence'") - } - } - return nil -} - -// Validate validates a Meta struct against its schema constraints. -func (x *Meta) Validate() error { - if x == nil { - return nil - } - if x.XLastUpdated != nil { - if err := x.XLastUpdated.Validate(); err != nil { - return fmt.Errorf("field '_lastUpdated' is invalid: %w", err) - } - } - if x.XProfile != nil { - for i, item := range x.XProfile { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field '_profile[%d]' is invalid: %w", i, err) - } - } - } - } - if x.XSource != nil { - if err := x.XSource.Validate(); err != nil { - return fmt.Errorf("field '_source' is invalid: %w", err) - } - } - if x.XVersionID != nil { - if err := x.XVersionID.Validate(); err != nil { - return fmt.Errorf("field '_versionId' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.LastUpdated != nil { - if err := ValidateFhirDateTime(*x.LastUpdated); err != nil { - return fmt.Errorf("field 'lastUpdated' has invalid date-time format: %w", err) - } - } - if x.Links != nil { - } - if x.Profile != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "Meta" { - return fmt.Errorf("field 'resourceType' must be exactly 'Meta'") - } - } - if x.Security != nil { - for i, item := range x.Security { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'security[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Source != nil { - } - if x.Tag != nil { - for i, item := range x.Tag { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'tag[%d]' is invalid: %w", i, err) - } - } - } - } - if x.VersionID != nil { - if !rx_Meta_VersionID.MatchString(*x.VersionID) { - return fmt.Errorf("field 'versionId' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.VersionID) < 1 { - return fmt.Errorf("field 'versionId' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.VersionID) > 64 { - return fmt.Errorf("field 'versionId' is too long (max 64 characters)") - } - } - return nil -} - -// Validate validates a Money struct against its schema constraints. -func (x *Money) Validate() error { - if x == nil { - return nil - } - if x.XCurrency != nil { - if err := x.XCurrency.Validate(); err != nil { - return fmt.Errorf("field '_currency' is invalid: %w", err) - } - } - if x.XValue != nil { - if err := x.XValue.Validate(); err != nil { - return fmt.Errorf("field '_value' is invalid: %w", err) - } - } - if x.Currency != nil { - if !rx_Money_Currency.MatchString(*x.Currency) { - return fmt.Errorf("field 'currency' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "Money" { - return fmt.Errorf("field 'resourceType' must be exactly 'Money'") - } - } - if x.Value != nil { - } - return nil -} - -// Validate validates a Narrative struct against its schema constraints. -func (x *Narrative) Validate() error { - if x == nil { - return nil - } - if x.XDiv != nil { - if err := x.XDiv.Validate(); err != nil { - return fmt.Errorf("field '_div' is invalid: %w", err) - } - } - if x.XStatus != nil { - if err := x.XStatus.Validate(); err != nil { - return fmt.Errorf("field '_status' is invalid: %w", err) - } - } - if x.Div != nil { - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "Narrative" { - return fmt.Errorf("field 'resourceType' must be exactly 'Narrative'") - } - } - if x.Status != nil { - if !rx_Narrative_Status.MatchString(*x.Status) { - return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - return nil -} - -// Validate validates a Observation struct against its schema constraints. -func (x *Observation) Validate() error { - if x == nil { - return nil - } - if x.XEffectiveDateTime != nil { - if err := x.XEffectiveDateTime.Validate(); err != nil { - return fmt.Errorf("field '_effectiveDateTime' is invalid: %w", err) - } - } - if x.XEffectiveInstant != nil { - if err := x.XEffectiveInstant.Validate(); err != nil { - return fmt.Errorf("field '_effectiveInstant' is invalid: %w", err) - } - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XInstantiatesCanonical != nil { - if err := x.XInstantiatesCanonical.Validate(); err != nil { - return fmt.Errorf("field '_instantiatesCanonical' is invalid: %w", err) - } - } - if x.XIssued != nil { - if err := x.XIssued.Validate(); err != nil { - return fmt.Errorf("field '_issued' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.XStatus != nil { - if err := x.XStatus.Validate(); err != nil { - return fmt.Errorf("field '_status' is invalid: %w", err) - } - } - if x.XValueBoolean != nil { - if err := x.XValueBoolean.Validate(); err != nil { - return fmt.Errorf("field '_valueBoolean' is invalid: %w", err) - } - } - if x.XValueDateTime != nil { - if err := x.XValueDateTime.Validate(); err != nil { - return fmt.Errorf("field '_valueDateTime' is invalid: %w", err) - } - } - if x.XValueInteger != nil { - if err := x.XValueInteger.Validate(); err != nil { - return fmt.Errorf("field '_valueInteger' is invalid: %w", err) - } - } - if x.XValueString != nil { - if err := x.XValueString.Validate(); err != nil { - return fmt.Errorf("field '_valueString' is invalid: %w", err) - } - } - if x.XValueTime != nil { - if err := x.XValueTime.Validate(); err != nil { - return fmt.Errorf("field '_valueTime' is invalid: %w", err) - } - } - if x.BasedOn != nil { - for i, item := range x.BasedOn { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'basedOn[%d]' is invalid: %w", i, err) - } - } - } - } - if x.BodySite != nil { - if err := x.BodySite.Validate(); err != nil { - return fmt.Errorf("field 'bodySite' is invalid: %w", err) - } - } - if x.BodyStructure != nil { - if err := x.BodyStructure.Validate(); err != nil { - return fmt.Errorf("field 'bodyStructure' is invalid: %w", err) - } - } - if x.Category != nil { - for i, item := range x.Category { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'category[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Code == nil { - return fmt.Errorf("required field 'code' is missing") - } - if x.Code != nil { - if err := x.Code.Validate(); err != nil { - return fmt.Errorf("field 'code' is invalid: %w", err) - } - } - if x.Component != nil { - for i, item := range x.Component { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'component[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Contained != nil { - for i, item := range x.Contained { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) - } - } - } - } - if x.DataAbsentReason != nil { - if err := x.DataAbsentReason.Validate(); err != nil { - return fmt.Errorf("field 'dataAbsentReason' is invalid: %w", err) - } - } - if x.DerivedFrom != nil { - for i, item := range x.DerivedFrom { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'derivedFrom[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Device != nil { - if err := x.Device.Validate(); err != nil { - return fmt.Errorf("field 'device' is invalid: %w", err) - } - } - if x.EffectiveDateTime != nil { - if err := ValidateFhirDateTime(*x.EffectiveDateTime); err != nil { - return fmt.Errorf("field 'effectiveDateTime' has invalid date-time format: %w", err) - } - } - if x.EffectiveInstant != nil { - if err := ValidateFhirDateTime(*x.EffectiveInstant); err != nil { - return fmt.Errorf("field 'effectiveInstant' has invalid date-time format: %w", err) - } - } - if x.EffectivePeriod != nil { - if err := x.EffectivePeriod.Validate(); err != nil { - return fmt.Errorf("field 'effectivePeriod' is invalid: %w", err) - } - } - if x.EffectiveTiming != nil { - if err := x.EffectiveTiming.Validate(); err != nil { - return fmt.Errorf("field 'effectiveTiming' is invalid: %w", err) - } - } - if x.Encounter != nil { - if err := x.Encounter.Validate(); err != nil { - return fmt.Errorf("field 'encounter' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Focus != nil { - for i, item := range x.Focus { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'focus[%d]' is invalid: %w", i, err) - } - } - } - } - if x.HasMember != nil { - for i, item := range x.HasMember { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'hasMember[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if !rx_Observation_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ImplicitRules != nil { - } - if x.InstantiatesCanonical != nil { - } - if x.InstantiatesReference != nil { - if err := x.InstantiatesReference.Validate(); err != nil { - return fmt.Errorf("field 'instantiatesReference' is invalid: %w", err) - } - } - if x.Interpretation != nil { - for i, item := range x.Interpretation { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'interpretation[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Issued != nil { - if err := ValidateFhirDateTime(*x.Issued); err != nil { - return fmt.Errorf("field 'issued' has invalid date-time format: %w", err) - } - } - if x.Language != nil { - if !rx_Observation_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.Method != nil { - if err := x.Method.Validate(); err != nil { - return fmt.Errorf("field 'method' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Note != nil { - for i, item := range x.Note { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) - } - } - } - } - if x.PartOf != nil { - for i, item := range x.PartOf { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'partOf[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Performer != nil { - for i, item := range x.Performer { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'performer[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ReferenceRange != nil { - for i, item := range x.ReferenceRange { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'referenceRange[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "Observation" { - return fmt.Errorf("field 'resourceType' must be exactly 'Observation'") - } - } - if x.Specimen != nil { - if err := x.Specimen.Validate(); err != nil { - return fmt.Errorf("field 'specimen' is invalid: %w", err) - } - } - if x.Status != nil { - if !rx_Observation_Status.MatchString(*x.Status) { - return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Subject != nil { - if err := x.Subject.Validate(); err != nil { - return fmt.Errorf("field 'subject' is invalid: %w", err) - } - } - if x.Text != nil { - if err := x.Text.Validate(); err != nil { - return fmt.Errorf("field 'text' is invalid: %w", err) - } - } - if x.TriggeredBy != nil { - for i, item := range x.TriggeredBy { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'triggeredBy[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ValueAttachment != nil { - if err := x.ValueAttachment.Validate(); err != nil { - return fmt.Errorf("field 'valueAttachment' is invalid: %w", err) - } - } - if x.ValueBoolean != nil { - } - if x.ValueCodeableConcept != nil { - if err := x.ValueCodeableConcept.Validate(); err != nil { - return fmt.Errorf("field 'valueCodeableConcept' is invalid: %w", err) - } - } - if x.ValueDateTime != nil { - if err := ValidateFhirDateTime(*x.ValueDateTime); err != nil { - return fmt.Errorf("field 'valueDateTime' has invalid date-time format: %w", err) - } - } - if x.ValueInteger != nil { - } - if x.ValuePeriod != nil { - if err := x.ValuePeriod.Validate(); err != nil { - return fmt.Errorf("field 'valuePeriod' is invalid: %w", err) - } - } - if x.ValueQuantity != nil { - if err := x.ValueQuantity.Validate(); err != nil { - return fmt.Errorf("field 'valueQuantity' is invalid: %w", err) - } - } - if x.ValueRange != nil { - if err := x.ValueRange.Validate(); err != nil { - return fmt.Errorf("field 'valueRange' is invalid: %w", err) - } - } - if x.ValueRatio != nil { - if err := x.ValueRatio.Validate(); err != nil { - return fmt.Errorf("field 'valueRatio' is invalid: %w", err) - } - } - if x.ValueReference != nil { - if err := x.ValueReference.Validate(); err != nil { - return fmt.Errorf("field 'valueReference' is invalid: %w", err) - } - } - if x.ValueSampledData != nil { - if err := x.ValueSampledData.Validate(); err != nil { - return fmt.Errorf("field 'valueSampledData' is invalid: %w", err) - } - } - if x.ValueString != nil { - if *x.ValueString == "" { - return fmt.Errorf("field 'valueString' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.ValueTime != nil { - if err := ValidateFhirTime(*x.ValueTime); err != nil { - return fmt.Errorf("field 'valueTime' has invalid time format: %w", err) - } - } - return nil -} - -// Validate validates a ObservationComponent struct against its schema constraints. -func (x *ObservationComponent) Validate() error { - if x == nil { - return nil - } - if x.XValueBoolean != nil { - if err := x.XValueBoolean.Validate(); err != nil { - return fmt.Errorf("field '_valueBoolean' is invalid: %w", err) - } - } - if x.XValueDateTime != nil { - if err := x.XValueDateTime.Validate(); err != nil { - return fmt.Errorf("field '_valueDateTime' is invalid: %w", err) - } - } - if x.XValueInteger != nil { - if err := x.XValueInteger.Validate(); err != nil { - return fmt.Errorf("field '_valueInteger' is invalid: %w", err) - } - } - if x.XValueString != nil { - if err := x.XValueString.Validate(); err != nil { - return fmt.Errorf("field '_valueString' is invalid: %w", err) - } - } - if x.XValueTime != nil { - if err := x.XValueTime.Validate(); err != nil { - return fmt.Errorf("field '_valueTime' is invalid: %w", err) - } - } - if x.Code == nil { - return fmt.Errorf("required field 'code' is missing") - } - if x.Code != nil { - if err := x.Code.Validate(); err != nil { - return fmt.Errorf("field 'code' is invalid: %w", err) - } - } - if x.DataAbsentReason != nil { - if err := x.DataAbsentReason.Validate(); err != nil { - return fmt.Errorf("field 'dataAbsentReason' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Interpretation != nil { - for i, item := range x.Interpretation { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'interpretation[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ReferenceRange != nil { - for i, item := range x.ReferenceRange { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'referenceRange[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ObservationComponent" { - return fmt.Errorf("field 'resourceType' must be exactly 'ObservationComponent'") - } - } - if x.ValueAttachment != nil { - if err := x.ValueAttachment.Validate(); err != nil { - return fmt.Errorf("field 'valueAttachment' is invalid: %w", err) - } - } - if x.ValueBoolean != nil { - } - if x.ValueCodeableConcept != nil { - if err := x.ValueCodeableConcept.Validate(); err != nil { - return fmt.Errorf("field 'valueCodeableConcept' is invalid: %w", err) - } - } - if x.ValueDateTime != nil { - if err := ValidateFhirDateTime(*x.ValueDateTime); err != nil { - return fmt.Errorf("field 'valueDateTime' has invalid date-time format: %w", err) - } - } - if x.ValueInteger != nil { - } - if x.ValuePeriod != nil { - if err := x.ValuePeriod.Validate(); err != nil { - return fmt.Errorf("field 'valuePeriod' is invalid: %w", err) - } - } - if x.ValueQuantity != nil { - if err := x.ValueQuantity.Validate(); err != nil { - return fmt.Errorf("field 'valueQuantity' is invalid: %w", err) - } - } - if x.ValueRange != nil { - if err := x.ValueRange.Validate(); err != nil { - return fmt.Errorf("field 'valueRange' is invalid: %w", err) - } - } - if x.ValueRatio != nil { - if err := x.ValueRatio.Validate(); err != nil { - return fmt.Errorf("field 'valueRatio' is invalid: %w", err) - } - } - if x.ValueReference != nil { - if err := x.ValueReference.Validate(); err != nil { - return fmt.Errorf("field 'valueReference' is invalid: %w", err) - } - } - if x.ValueSampledData != nil { - if err := x.ValueSampledData.Validate(); err != nil { - return fmt.Errorf("field 'valueSampledData' is invalid: %w", err) - } - } - if x.ValueString != nil { - if *x.ValueString == "" { - return fmt.Errorf("field 'valueString' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.ValueTime != nil { - if err := ValidateFhirTime(*x.ValueTime); err != nil { - return fmt.Errorf("field 'valueTime' has invalid time format: %w", err) - } - } - return nil -} - -// Validate validates a ObservationReferenceRange struct against its schema constraints. -func (x *ObservationReferenceRange) Validate() error { - if x == nil { - return nil - } - if x.XText != nil { - if err := x.XText.Validate(); err != nil { - return fmt.Errorf("field '_text' is invalid: %w", err) - } - } - if x.Age != nil { - if err := x.Age.Validate(); err != nil { - return fmt.Errorf("field 'age' is invalid: %w", err) - } - } - if x.AppliesTo != nil { - for i, item := range x.AppliesTo { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'appliesTo[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.High != nil { - if err := x.High.Validate(); err != nil { - return fmt.Errorf("field 'high' is invalid: %w", err) - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Low != nil { - if err := x.Low.Validate(); err != nil { - return fmt.Errorf("field 'low' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.NormalValue != nil { - if err := x.NormalValue.Validate(); err != nil { - return fmt.Errorf("field 'normalValue' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ObservationReferenceRange" { - return fmt.Errorf("field 'resourceType' must be exactly 'ObservationReferenceRange'") - } - } - if x.Text != nil { - if !rx_ObservationReferenceRange_Text.MatchString(*x.Text) { - return fmt.Errorf("field 'text' does not match pattern '\\s*(\\S|\\s)*'") - } - } - if x.Type != nil { - if err := x.Type.Validate(); err != nil { - return fmt.Errorf("field 'type' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a ObservationTriggeredBy struct against its schema constraints. -func (x *ObservationTriggeredBy) Validate() error { - if x == nil { - return nil - } - if x.XReason != nil { - if err := x.XReason.Validate(); err != nil { - return fmt.Errorf("field '_reason' is invalid: %w", err) - } - } - if x.XType != nil { - if err := x.XType.Validate(); err != nil { - return fmt.Errorf("field '_type' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Observation == nil { - return fmt.Errorf("required field 'observation' is missing") - } - if x.Observation != nil { - if err := x.Observation.Validate(); err != nil { - return fmt.Errorf("field 'observation' is invalid: %w", err) - } - } - if x.Reason != nil { - if *x.Reason == "" { - return fmt.Errorf("field 'reason' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ObservationTriggeredBy" { - return fmt.Errorf("field 'resourceType' must be exactly 'ObservationTriggeredBy'") - } - } - if x.Type != nil { - if !rx_ObservationTriggeredBy_Type.MatchString(*x.Type) { - return fmt.Errorf("field 'type' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - return nil -} - -// Validate validates a Organization struct against its schema constraints. -func (x *Organization) Validate() error { - if x == nil { - return nil - } - if x.XActive != nil { - if err := x.XActive.Validate(); err != nil { - return fmt.Errorf("field '_active' is invalid: %w", err) - } - } - if x.XAlias != nil { - for i, item := range x.XAlias { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field '_alias[%d]' is invalid: %w", i, err) - } - } - } - } - if x.XDescription != nil { - if err := x.XDescription.Validate(); err != nil { - return fmt.Errorf("field '_description' is invalid: %w", err) - } - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.XName != nil { - if err := x.XName.Validate(); err != nil { - return fmt.Errorf("field '_name' is invalid: %w", err) - } - } - if x.Active != nil { - } - if x.Alias != nil { - for i, item := range x.Alias { - if item == "" { - return fmt.Errorf("field 'alias[%d]' does not match pattern '[ \\r\\n\\t\\S]+'", i) - } - } - } - if x.Contact != nil { - for i, item := range x.Contact { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contact[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Contained != nil { - for i, item := range x.Contained { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Description != nil { - if !rx_Organization_Description.MatchString(*x.Description) { - return fmt.Errorf("field 'description' does not match pattern '\\s*(\\S|\\s)*'") - } - } - if x.Endpoint != nil { - for i, item := range x.Endpoint { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'endpoint[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if !rx_Organization_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ImplicitRules != nil { - } - if x.Language != nil { - if !rx_Organization_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Name != nil { - if *x.Name == "" { - return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.PartOf != nil { - if err := x.PartOf.Validate(); err != nil { - return fmt.Errorf("field 'partOf' is invalid: %w", err) - } - } - if x.Qualification != nil { - for i, item := range x.Qualification { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'qualification[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "Organization" { - return fmt.Errorf("field 'resourceType' must be exactly 'Organization'") - } - } - if x.Text != nil { - if err := x.Text.Validate(); err != nil { - return fmt.Errorf("field 'text' is invalid: %w", err) - } - } - if x.Type != nil { - for i, item := range x.Type { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'type[%d]' is invalid: %w", i, err) - } - } - } - } - return nil -} - -// Validate validates a OrganizationQualification struct against its schema constraints. -func (x *OrganizationQualification) Validate() error { - if x == nil { - return nil - } - if x.Code == nil { - return fmt.Errorf("required field 'code' is missing") - } - if x.Code != nil { - if err := x.Code.Validate(); err != nil { - return fmt.Errorf("field 'code' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Issuer != nil { - if err := x.Issuer.Validate(); err != nil { - return fmt.Errorf("field 'issuer' is invalid: %w", err) - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Period != nil { - if err := x.Period.Validate(); err != nil { - return fmt.Errorf("field 'period' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "OrganizationQualification" { - return fmt.Errorf("field 'resourceType' must be exactly 'OrganizationQualification'") - } - } - return nil -} - -// Validate validates a ParameterDefinition struct against its schema constraints. -func (x *ParameterDefinition) Validate() error { - if x == nil { - return nil - } - if x.XDocumentation != nil { - if err := x.XDocumentation.Validate(); err != nil { - return fmt.Errorf("field '_documentation' is invalid: %w", err) - } - } - if x.XMax != nil { - if err := x.XMax.Validate(); err != nil { - return fmt.Errorf("field '_max' is invalid: %w", err) - } - } - if x.XMin != nil { - if err := x.XMin.Validate(); err != nil { - return fmt.Errorf("field '_min' is invalid: %w", err) - } - } - if x.XName != nil { - if err := x.XName.Validate(); err != nil { - return fmt.Errorf("field '_name' is invalid: %w", err) - } - } - if x.XProfile != nil { - if err := x.XProfile.Validate(); err != nil { - return fmt.Errorf("field '_profile' is invalid: %w", err) - } - } - if x.XType != nil { - if err := x.XType.Validate(); err != nil { - return fmt.Errorf("field '_type' is invalid: %w", err) - } - } - if x.XUse != nil { - if err := x.XUse.Validate(); err != nil { - return fmt.Errorf("field '_use' is invalid: %w", err) - } - } - if x.Documentation != nil { - if *x.Documentation == "" { - return fmt.Errorf("field 'documentation' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Max != nil { - if *x.Max == "" { - return fmt.Errorf("field 'max' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Min != nil { - } - if x.Name != nil { - if !rx_ParameterDefinition_Name.MatchString(*x.Name) { - return fmt.Errorf("field 'name' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Profile != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "ParameterDefinition" { - return fmt.Errorf("field 'resourceType' must be exactly 'ParameterDefinition'") - } - } - if x.Type != nil { - if !rx_ParameterDefinition_Type.MatchString(*x.Type) { - return fmt.Errorf("field 'type' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Use != nil { - if !rx_ParameterDefinition_Use.MatchString(*x.Use) { - return fmt.Errorf("field 'use' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - return nil -} - -// Validate validates a Patient struct against its schema constraints. -func (x *Patient) Validate() error { - if x == nil { - return nil - } - if x.XActive != nil { - if err := x.XActive.Validate(); err != nil { - return fmt.Errorf("field '_active' is invalid: %w", err) - } - } - if x.XBirthDate != nil { - if err := x.XBirthDate.Validate(); err != nil { - return fmt.Errorf("field '_birthDate' is invalid: %w", err) - } - } - if x.XDeceasedBoolean != nil { - if err := x.XDeceasedBoolean.Validate(); err != nil { - return fmt.Errorf("field '_deceasedBoolean' is invalid: %w", err) - } - } - if x.XDeceasedDateTime != nil { - if err := x.XDeceasedDateTime.Validate(); err != nil { - return fmt.Errorf("field '_deceasedDateTime' is invalid: %w", err) - } - } - if x.XGender != nil { - if err := x.XGender.Validate(); err != nil { - return fmt.Errorf("field '_gender' is invalid: %w", err) - } - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.XMultipleBirthBoolean != nil { - if err := x.XMultipleBirthBoolean.Validate(); err != nil { - return fmt.Errorf("field '_multipleBirthBoolean' is invalid: %w", err) - } - } - if x.XMultipleBirthInteger != nil { - if err := x.XMultipleBirthInteger.Validate(); err != nil { - return fmt.Errorf("field '_multipleBirthInteger' is invalid: %w", err) - } - } - if x.Active != nil { - } - if x.Address != nil { - for i, item := range x.Address { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'address[%d]' is invalid: %w", i, err) - } - } - } - } - if x.BirthDate != nil { - if err := ValidateFhirDate(*x.BirthDate); err != nil { - return fmt.Errorf("field 'birthDate' has invalid date format: %w", err) - } - } - if x.Communication != nil { - for i, item := range x.Communication { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'communication[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Contact != nil { - for i, item := range x.Contact { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contact[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Contained != nil { - for i, item := range x.Contained { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) - } - } - } - } - if x.DeceasedBoolean != nil { - } - if x.DeceasedDateTime != nil { - if err := ValidateFhirDateTime(*x.DeceasedDateTime); err != nil { - return fmt.Errorf("field 'deceasedDateTime' has invalid date-time format: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Gender != nil { - if !rx_Patient_Gender.MatchString(*x.Gender) { - return fmt.Errorf("field 'gender' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.GeneralPractitioner != nil { - for i, item := range x.GeneralPractitioner { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'generalPractitioner[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if !rx_Patient_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ImplicitRules != nil { - } - if x.Language != nil { - if !rx_Patient_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Link != nil { - for i, item := range x.Link { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'link[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Links != nil { - } - if x.ManagingOrganization != nil { - if err := x.ManagingOrganization.Validate(); err != nil { - return fmt.Errorf("field 'managingOrganization' is invalid: %w", err) - } - } - if x.MaritalStatus != nil { - if err := x.MaritalStatus.Validate(); err != nil { - return fmt.Errorf("field 'maritalStatus' is invalid: %w", err) - } - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.MultipleBirthBoolean != nil { - } - if x.MultipleBirthInteger != nil { - } - if x.Name != nil { - for i, item := range x.Name { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'name[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Photo != nil { - for i, item := range x.Photo { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'photo[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "Patient" { - return fmt.Errorf("field 'resourceType' must be exactly 'Patient'") - } - } - if x.Telecom != nil { - for i, item := range x.Telecom { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'telecom[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Text != nil { - if err := x.Text.Validate(); err != nil { - return fmt.Errorf("field 'text' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a PatientCommunication struct against its schema constraints. -func (x *PatientCommunication) Validate() error { - if x == nil { - return nil - } - if x.XPreferred != nil { - if err := x.XPreferred.Validate(); err != nil { - return fmt.Errorf("field '_preferred' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Language == nil { - return fmt.Errorf("required field 'language' is missing") - } - if x.Language != nil { - if err := x.Language.Validate(); err != nil { - return fmt.Errorf("field 'language' is invalid: %w", err) - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Preferred != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "PatientCommunication" { - return fmt.Errorf("field 'resourceType' must be exactly 'PatientCommunication'") - } - } - return nil -} - -// Validate validates a PatientContact struct against its schema constraints. -func (x *PatientContact) Validate() error { - if x == nil { - return nil - } - if x.XGender != nil { - if err := x.XGender.Validate(); err != nil { - return fmt.Errorf("field '_gender' is invalid: %w", err) - } - } - if x.Address != nil { - if err := x.Address.Validate(); err != nil { - return fmt.Errorf("field 'address' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Gender != nil { - if !rx_PatientContact_Gender.MatchString(*x.Gender) { - return fmt.Errorf("field 'gender' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Name != nil { - if err := x.Name.Validate(); err != nil { - return fmt.Errorf("field 'name' is invalid: %w", err) - } - } - if x.Organization != nil { - if err := x.Organization.Validate(); err != nil { - return fmt.Errorf("field 'organization' is invalid: %w", err) - } - } - if x.Period != nil { - if err := x.Period.Validate(); err != nil { - return fmt.Errorf("field 'period' is invalid: %w", err) - } - } - if x.Relationship != nil { - for i, item := range x.Relationship { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'relationship[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "PatientContact" { - return fmt.Errorf("field 'resourceType' must be exactly 'PatientContact'") - } - } - if x.Telecom != nil { - for i, item := range x.Telecom { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'telecom[%d]' is invalid: %w", i, err) - } - } - } - } - return nil -} - -// Validate validates a PatientLink struct against its schema constraints. -func (x *PatientLink) Validate() error { - if x == nil { - return nil - } - if x.XType != nil { - if err := x.XType.Validate(); err != nil { - return fmt.Errorf("field '_type' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Other == nil { - return fmt.Errorf("required field 'other' is missing") - } - if x.Other != nil { - if err := x.Other.Validate(); err != nil { - return fmt.Errorf("field 'other' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "PatientLink" { - return fmt.Errorf("field 'resourceType' must be exactly 'PatientLink'") - } - } - if x.Type != nil { - if !rx_PatientLink_Type.MatchString(*x.Type) { - return fmt.Errorf("field 'type' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - return nil -} - -// Validate validates a Period struct against its schema constraints. -func (x *Period) Validate() error { - if x == nil { - return nil - } - if x.XEnd != nil { - if err := x.XEnd.Validate(); err != nil { - return fmt.Errorf("field '_end' is invalid: %w", err) - } - } - if x.XStart != nil { - if err := x.XStart.Validate(); err != nil { - return fmt.Errorf("field '_start' is invalid: %w", err) - } - } - if x.End != nil { - if err := ValidateFhirDateTime(*x.End); err != nil { - return fmt.Errorf("field 'end' has invalid date-time format: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "Period" { - return fmt.Errorf("field 'resourceType' must be exactly 'Period'") - } - } - if x.Start != nil { - if err := ValidateFhirDateTime(*x.Start); err != nil { - return fmt.Errorf("field 'start' has invalid date-time format: %w", err) - } - } - return nil -} - -// Validate validates a Practitioner struct against its schema constraints. -func (x *Practitioner) Validate() error { - if x == nil { - return nil - } - if x.XActive != nil { - if err := x.XActive.Validate(); err != nil { - return fmt.Errorf("field '_active' is invalid: %w", err) - } - } - if x.XBirthDate != nil { - if err := x.XBirthDate.Validate(); err != nil { - return fmt.Errorf("field '_birthDate' is invalid: %w", err) - } - } - if x.XDeceasedBoolean != nil { - if err := x.XDeceasedBoolean.Validate(); err != nil { - return fmt.Errorf("field '_deceasedBoolean' is invalid: %w", err) - } - } - if x.XDeceasedDateTime != nil { - if err := x.XDeceasedDateTime.Validate(); err != nil { - return fmt.Errorf("field '_deceasedDateTime' is invalid: %w", err) - } - } - if x.XGender != nil { - if err := x.XGender.Validate(); err != nil { - return fmt.Errorf("field '_gender' is invalid: %w", err) - } - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.Active != nil { - } - if x.Address != nil { - for i, item := range x.Address { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'address[%d]' is invalid: %w", i, err) - } - } - } - } - if x.BirthDate != nil { - if err := ValidateFhirDate(*x.BirthDate); err != nil { - return fmt.Errorf("field 'birthDate' has invalid date format: %w", err) - } - } - if x.Communication != nil { - for i, item := range x.Communication { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'communication[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Contained != nil { - for i, item := range x.Contained { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) - } - } - } - } - if x.DeceasedBoolean != nil { - } - if x.DeceasedDateTime != nil { - if err := ValidateFhirDateTime(*x.DeceasedDateTime); err != nil { - return fmt.Errorf("field 'deceasedDateTime' has invalid date-time format: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Gender != nil { - if !rx_Practitioner_Gender.MatchString(*x.Gender) { - return fmt.Errorf("field 'gender' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.ID != nil { - if !rx_Practitioner_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ImplicitRules != nil { - } - if x.Language != nil { - if !rx_Practitioner_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Name != nil { - for i, item := range x.Name { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'name[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Photo != nil { - for i, item := range x.Photo { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'photo[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Qualification != nil { - for i, item := range x.Qualification { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'qualification[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "Practitioner" { - return fmt.Errorf("field 'resourceType' must be exactly 'Practitioner'") - } - } - if x.Telecom != nil { - for i, item := range x.Telecom { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'telecom[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Text != nil { - if err := x.Text.Validate(); err != nil { - return fmt.Errorf("field 'text' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a PractitionerCommunication struct against its schema constraints. -func (x *PractitionerCommunication) Validate() error { - if x == nil { - return nil - } - if x.XPreferred != nil { - if err := x.XPreferred.Validate(); err != nil { - return fmt.Errorf("field '_preferred' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Language == nil { - return fmt.Errorf("required field 'language' is missing") - } - if x.Language != nil { - if err := x.Language.Validate(); err != nil { - return fmt.Errorf("field 'language' is invalid: %w", err) - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Preferred != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "PractitionerCommunication" { - return fmt.Errorf("field 'resourceType' must be exactly 'PractitionerCommunication'") - } - } - return nil -} - -// Validate validates a PractitionerQualification struct against its schema constraints. -func (x *PractitionerQualification) Validate() error { - if x == nil { - return nil - } - if x.Code == nil { - return fmt.Errorf("required field 'code' is missing") - } - if x.Code != nil { - if err := x.Code.Validate(); err != nil { - return fmt.Errorf("field 'code' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Issuer != nil { - if err := x.Issuer.Validate(); err != nil { - return fmt.Errorf("field 'issuer' is invalid: %w", err) - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Period != nil { - if err := x.Period.Validate(); err != nil { - return fmt.Errorf("field 'period' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "PractitionerQualification" { - return fmt.Errorf("field 'resourceType' must be exactly 'PractitionerQualification'") - } - } - return nil -} - -// Validate validates a PractitionerRole struct against its schema constraints. -func (x *PractitionerRole) Validate() error { - if x == nil { - return nil - } - if x.XActive != nil { - if err := x.XActive.Validate(); err != nil { - return fmt.Errorf("field '_active' is invalid: %w", err) - } - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.Active != nil { - } - if x.Availability != nil { - for i, item := range x.Availability { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'availability[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Characteristic != nil { - for i, item := range x.Characteristic { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'characteristic[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Code != nil { - for i, item := range x.Code { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'code[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Communication != nil { - for i, item := range x.Communication { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'communication[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Contact != nil { - for i, item := range x.Contact { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contact[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Contained != nil { - for i, item := range x.Contained { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Endpoint != nil { - for i, item := range x.Endpoint { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'endpoint[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.HealthcareService != nil { - for i, item := range x.HealthcareService { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'healthcareService[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if !rx_PractitionerRole_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ImplicitRules != nil { - } - if x.Language != nil { - if !rx_PractitionerRole_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.Location != nil { - for i, item := range x.Location { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'location[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Organization != nil { - if err := x.Organization.Validate(); err != nil { - return fmt.Errorf("field 'organization' is invalid: %w", err) - } - } - if x.Period != nil { - if err := x.Period.Validate(); err != nil { - return fmt.Errorf("field 'period' is invalid: %w", err) - } - } - if x.Practitioner != nil { - if err := x.Practitioner.Validate(); err != nil { - return fmt.Errorf("field 'practitioner' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "PractitionerRole" { - return fmt.Errorf("field 'resourceType' must be exactly 'PractitionerRole'") - } - } - if x.Specialty != nil { - for i, item := range x.Specialty { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'specialty[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Text != nil { - if err := x.Text.Validate(); err != nil { - return fmt.Errorf("field 'text' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a Procedure struct against its schema constraints. -func (x *Procedure) Validate() error { - if x == nil { - return nil - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XInstantiatesCanonical != nil { - for i, item := range x.XInstantiatesCanonical { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field '_instantiatesCanonical[%d]' is invalid: %w", i, err) - } - } - } - } - if x.XInstantiatesURI != nil { - for i, item := range x.XInstantiatesURI { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field '_instantiatesUri[%d]' is invalid: %w", i, err) - } - } - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.XOccurrenceDateTime != nil { - if err := x.XOccurrenceDateTime.Validate(); err != nil { - return fmt.Errorf("field '_occurrenceDateTime' is invalid: %w", err) - } - } - if x.XOccurrenceString != nil { - if err := x.XOccurrenceString.Validate(); err != nil { - return fmt.Errorf("field '_occurrenceString' is invalid: %w", err) - } - } - if x.XRecorded != nil { - if err := x.XRecorded.Validate(); err != nil { - return fmt.Errorf("field '_recorded' is invalid: %w", err) - } - } - if x.XReportedBoolean != nil { - if err := x.XReportedBoolean.Validate(); err != nil { - return fmt.Errorf("field '_reportedBoolean' is invalid: %w", err) - } - } - if x.XStatus != nil { - if err := x.XStatus.Validate(); err != nil { - return fmt.Errorf("field '_status' is invalid: %w", err) - } - } - if x.BasedOn != nil { - for i, item := range x.BasedOn { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'basedOn[%d]' is invalid: %w", i, err) - } - } - } - } - if x.BodySite != nil { - for i, item := range x.BodySite { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'bodySite[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Category != nil { - for i, item := range x.Category { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'category[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Code != nil { - if err := x.Code.Validate(); err != nil { - return fmt.Errorf("field 'code' is invalid: %w", err) - } - } - if x.Complication != nil { - for i, item := range x.Complication { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'complication[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Contained != nil { - for i, item := range x.Contained { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Encounter != nil { - if err := x.Encounter.Validate(); err != nil { - return fmt.Errorf("field 'encounter' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.FocalDevice != nil { - for i, item := range x.FocalDevice { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'focalDevice[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Focus != nil { - if err := x.Focus.Validate(); err != nil { - return fmt.Errorf("field 'focus' is invalid: %w", err) - } - } - if x.FollowUp != nil { - for i, item := range x.FollowUp { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'followUp[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if !rx_Procedure_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ImplicitRules != nil { - } - if x.InstantiatesCanonical != nil { - } - if x.InstantiatesURI != nil { - } - if x.Language != nil { - if !rx_Procedure_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.Location != nil { - if err := x.Location.Validate(); err != nil { - return fmt.Errorf("field 'location' is invalid: %w", err) - } - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Note != nil { - for i, item := range x.Note { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) - } - } - } - } - if x.OccurrenceAge != nil { - if err := x.OccurrenceAge.Validate(); err != nil { - return fmt.Errorf("field 'occurrenceAge' is invalid: %w", err) - } - } - if x.OccurrenceDateTime != nil { - if err := ValidateFhirDateTime(*x.OccurrenceDateTime); err != nil { - return fmt.Errorf("field 'occurrenceDateTime' has invalid date-time format: %w", err) - } - } - if x.OccurrencePeriod != nil { - if err := x.OccurrencePeriod.Validate(); err != nil { - return fmt.Errorf("field 'occurrencePeriod' is invalid: %w", err) - } - } - if x.OccurrenceRange != nil { - if err := x.OccurrenceRange.Validate(); err != nil { - return fmt.Errorf("field 'occurrenceRange' is invalid: %w", err) - } - } - if x.OccurrenceString != nil { - if *x.OccurrenceString == "" { - return fmt.Errorf("field 'occurrenceString' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.OccurrenceTiming != nil { - if err := x.OccurrenceTiming.Validate(); err != nil { - return fmt.Errorf("field 'occurrenceTiming' is invalid: %w", err) - } - } - if x.Outcome != nil { - if err := x.Outcome.Validate(); err != nil { - return fmt.Errorf("field 'outcome' is invalid: %w", err) - } - } - if x.PartOf != nil { - for i, item := range x.PartOf { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'partOf[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Performer != nil { - for i, item := range x.Performer { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'performer[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Reason != nil { - for i, item := range x.Reason { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'reason[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Recorded != nil { - if err := ValidateFhirDateTime(*x.Recorded); err != nil { - return fmt.Errorf("field 'recorded' has invalid date-time format: %w", err) - } - } - if x.Recorder != nil { - if err := x.Recorder.Validate(); err != nil { - return fmt.Errorf("field 'recorder' is invalid: %w", err) - } - } - if x.Report != nil { - for i, item := range x.Report { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'report[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ReportedBoolean != nil { - } - if x.ReportedReference != nil { - if err := x.ReportedReference.Validate(); err != nil { - return fmt.Errorf("field 'reportedReference' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "Procedure" { - return fmt.Errorf("field 'resourceType' must be exactly 'Procedure'") - } - } - if x.Status != nil { - if !rx_Procedure_Status.MatchString(*x.Status) { - return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.StatusReason != nil { - if err := x.StatusReason.Validate(); err != nil { - return fmt.Errorf("field 'statusReason' is invalid: %w", err) - } - } - if x.Subject == nil { - return fmt.Errorf("required field 'subject' is missing") - } - if x.Subject != nil { - if err := x.Subject.Validate(); err != nil { - return fmt.Errorf("field 'subject' is invalid: %w", err) - } - } - if x.SupportingInfo != nil { - for i, item := range x.SupportingInfo { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'supportingInfo[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Text != nil { - if err := x.Text.Validate(); err != nil { - return fmt.Errorf("field 'text' is invalid: %w", err) - } - } - if x.Used != nil { - for i, item := range x.Used { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'used[%d]' is invalid: %w", i, err) - } - } - } - } - return nil -} - -// Validate validates a ProcedureFocalDevice struct against its schema constraints. -func (x *ProcedureFocalDevice) Validate() error { - if x == nil { - return nil - } - if x.Action != nil { - if err := x.Action.Validate(); err != nil { - return fmt.Errorf("field 'action' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Manipulated == nil { - return fmt.Errorf("required field 'manipulated' is missing") - } - if x.Manipulated != nil { - if err := x.Manipulated.Validate(); err != nil { - return fmt.Errorf("field 'manipulated' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ProcedureFocalDevice" { - return fmt.Errorf("field 'resourceType' must be exactly 'ProcedureFocalDevice'") - } - } - return nil -} - -// Validate validates a ProcedurePerformer struct against its schema constraints. -func (x *ProcedurePerformer) Validate() error { - if x == nil { - return nil - } - if x.Actor == nil { - return fmt.Errorf("required field 'actor' is missing") - } - if x.Actor != nil { - if err := x.Actor.Validate(); err != nil { - return fmt.Errorf("field 'actor' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Function != nil { - if err := x.Function.Validate(); err != nil { - return fmt.Errorf("field 'function' is invalid: %w", err) - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.OnBehalfOf != nil { - if err := x.OnBehalfOf.Validate(); err != nil { - return fmt.Errorf("field 'onBehalfOf' is invalid: %w", err) - } - } - if x.Period != nil { - if err := x.Period.Validate(); err != nil { - return fmt.Errorf("field 'period' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ProcedurePerformer" { - return fmt.Errorf("field 'resourceType' must be exactly 'ProcedurePerformer'") - } - } - return nil -} - -// Validate validates a Quantity struct against its schema constraints. -func (x *Quantity) Validate() error { - if x == nil { - return nil - } - if x.XCode != nil { - if err := x.XCode.Validate(); err != nil { - return fmt.Errorf("field '_code' is invalid: %w", err) - } - } - if x.XComparator != nil { - if err := x.XComparator.Validate(); err != nil { - return fmt.Errorf("field '_comparator' is invalid: %w", err) - } - } - if x.XSystem != nil { - if err := x.XSystem.Validate(); err != nil { - return fmt.Errorf("field '_system' is invalid: %w", err) - } - } - if x.XUnit != nil { - if err := x.XUnit.Validate(); err != nil { - return fmt.Errorf("field '_unit' is invalid: %w", err) - } - } - if x.XValue != nil { - if err := x.XValue.Validate(); err != nil { - return fmt.Errorf("field '_value' is invalid: %w", err) - } - } - if x.Code != nil { - if !rx_Quantity_Code.MatchString(*x.Code) { - return fmt.Errorf("field 'code' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Comparator != nil { - if !rx_Quantity_Comparator.MatchString(*x.Comparator) { - return fmt.Errorf("field 'comparator' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "Quantity" { - return fmt.Errorf("field 'resourceType' must be exactly 'Quantity'") - } - } - if x.System != nil { - } - if x.Unit != nil { - if *x.Unit == "" { - return fmt.Errorf("field 'unit' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Value != nil { - } - return nil -} - -// Validate validates a Range struct against its schema constraints. -func (x *Range) Validate() error { - if x == nil { - return nil - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.High != nil { - if err := x.High.Validate(); err != nil { - return fmt.Errorf("field 'high' is invalid: %w", err) - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Low != nil { - if err := x.Low.Validate(); err != nil { - return fmt.Errorf("field 'low' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "Range" { - return fmt.Errorf("field 'resourceType' must be exactly 'Range'") - } - } - return nil -} - -// Validate validates a Ratio struct against its schema constraints. -func (x *Ratio) Validate() error { - if x == nil { - return nil - } - if x.Denominator != nil { - if err := x.Denominator.Validate(); err != nil { - return fmt.Errorf("field 'denominator' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Numerator != nil { - if err := x.Numerator.Validate(); err != nil { - return fmt.Errorf("field 'numerator' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "Ratio" { - return fmt.Errorf("field 'resourceType' must be exactly 'Ratio'") - } - } - return nil -} - -// Validate validates a RatioRange struct against its schema constraints. -func (x *RatioRange) Validate() error { - if x == nil { - return nil - } - if x.Denominator != nil { - if err := x.Denominator.Validate(); err != nil { - return fmt.Errorf("field 'denominator' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.HighNumerator != nil { - if err := x.HighNumerator.Validate(); err != nil { - return fmt.Errorf("field 'highNumerator' is invalid: %w", err) - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.LowNumerator != nil { - if err := x.LowNumerator.Validate(); err != nil { - return fmt.Errorf("field 'lowNumerator' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "RatioRange" { - return fmt.Errorf("field 'resourceType' must be exactly 'RatioRange'") - } - } - return nil -} - -// Validate validates a Reference struct against its schema constraints. -func (x *Reference) Validate() error { - if x == nil { - return nil - } - if x.XDisplay != nil { - if err := x.XDisplay.Validate(); err != nil { - return fmt.Errorf("field '_display' is invalid: %w", err) - } - } - if x.XReference != nil { - if err := x.XReference.Validate(); err != nil { - return fmt.Errorf("field '_reference' is invalid: %w", err) - } - } - if x.XType != nil { - if err := x.XType.Validate(); err != nil { - return fmt.Errorf("field '_type' is invalid: %w", err) - } - } - if x.Display != nil { - if *x.Display == "" { - return fmt.Errorf("field 'display' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.IDentifier != nil { - if err := x.IDentifier.Validate(); err != nil { - return fmt.Errorf("field 'identifier' is invalid: %w", err) - } - } - if x.Links != nil { - } - if x.Reference != nil { - if *x.Reference == "" { - return fmt.Errorf("field 'reference' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.ResourceType != nil { - if *x.ResourceType != "Reference" { - return fmt.Errorf("field 'resourceType' must be exactly 'Reference'") - } - } - if x.Type != nil { - } - return nil -} - -// Validate validates a RelatedArtifact struct against its schema constraints. -func (x *RelatedArtifact) Validate() error { - if x == nil { - return nil - } - if x.XCitation != nil { - if err := x.XCitation.Validate(); err != nil { - return fmt.Errorf("field '_citation' is invalid: %w", err) - } - } - if x.XDisplay != nil { - if err := x.XDisplay.Validate(); err != nil { - return fmt.Errorf("field '_display' is invalid: %w", err) - } - } - if x.XLabel != nil { - if err := x.XLabel.Validate(); err != nil { - return fmt.Errorf("field '_label' is invalid: %w", err) - } - } - if x.XPublicationDate != nil { - if err := x.XPublicationDate.Validate(); err != nil { - return fmt.Errorf("field '_publicationDate' is invalid: %w", err) - } - } - if x.XPublicationStatus != nil { - if err := x.XPublicationStatus.Validate(); err != nil { - return fmt.Errorf("field '_publicationStatus' is invalid: %w", err) - } - } - if x.XResource != nil { - if err := x.XResource.Validate(); err != nil { - return fmt.Errorf("field '_resource' is invalid: %w", err) - } - } - if x.XType != nil { - if err := x.XType.Validate(); err != nil { - return fmt.Errorf("field '_type' is invalid: %w", err) - } - } - if x.Citation != nil { - if !rx_RelatedArtifact_Citation.MatchString(*x.Citation) { - return fmt.Errorf("field 'citation' does not match pattern '\\s*(\\S|\\s)*'") - } - } - if x.Classifier != nil { - for i, item := range x.Classifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'classifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Display != nil { - if *x.Display == "" { - return fmt.Errorf("field 'display' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Document != nil { - if err := x.Document.Validate(); err != nil { - return fmt.Errorf("field 'document' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Label != nil { - if *x.Label == "" { - return fmt.Errorf("field 'label' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.PublicationDate != nil { - if err := ValidateFhirDate(*x.PublicationDate); err != nil { - return fmt.Errorf("field 'publicationDate' has invalid date format: %w", err) - } - } - if x.PublicationStatus != nil { - if !rx_RelatedArtifact_PublicationStatus.MatchString(*x.PublicationStatus) { - return fmt.Errorf("field 'publicationStatus' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Resource != nil { - } - if x.ResourceReference != nil { - if err := x.ResourceReference.Validate(); err != nil { - return fmt.Errorf("field 'resourceReference' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "RelatedArtifact" { - return fmt.Errorf("field 'resourceType' must be exactly 'RelatedArtifact'") - } - } - if x.Type != nil { - if !rx_RelatedArtifact_Type.MatchString(*x.Type) { - return fmt.Errorf("field 'type' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - return nil -} - -// Validate validates a ResearchStudy struct against its schema constraints. -func (x *ResearchStudy) Validate() error { - if x == nil { - return nil - } - if x.XDate != nil { - if err := x.XDate.Validate(); err != nil { - return fmt.Errorf("field '_date' is invalid: %w", err) - } - } - if x.XDescription != nil { - if err := x.XDescription.Validate(); err != nil { - return fmt.Errorf("field '_description' is invalid: %w", err) - } - } - if x.XDescriptionSummary != nil { - if err := x.XDescriptionSummary.Validate(); err != nil { - return fmt.Errorf("field '_descriptionSummary' is invalid: %w", err) - } - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.XName != nil { - if err := x.XName.Validate(); err != nil { - return fmt.Errorf("field '_name' is invalid: %w", err) - } - } - if x.XStatus != nil { - if err := x.XStatus.Validate(); err != nil { - return fmt.Errorf("field '_status' is invalid: %w", err) - } - } - if x.XTitle != nil { - if err := x.XTitle.Validate(); err != nil { - return fmt.Errorf("field '_title' is invalid: %w", err) - } - } - if x.XURL != nil { - if err := x.XURL.Validate(); err != nil { - return fmt.Errorf("field '_url' is invalid: %w", err) - } - } - if x.XVersion != nil { - if err := x.XVersion.Validate(); err != nil { - return fmt.Errorf("field '_version' is invalid: %w", err) - } - } - if x.AssociatedParty != nil { - for i, item := range x.AssociatedParty { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'associatedParty[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Classifier != nil { - for i, item := range x.Classifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'classifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ComparisonGroup != nil { - for i, item := range x.ComparisonGroup { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'comparisonGroup[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Condition != nil { - for i, item := range x.Condition { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'condition[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Contained != nil { - for i, item := range x.Contained { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Date != nil { - if err := ValidateFhirDateTime(*x.Date); err != nil { - return fmt.Errorf("field 'date' has invalid date-time format: %w", err) - } - } - if x.Description != nil { - if !rx_ResearchStudy_Description.MatchString(*x.Description) { - return fmt.Errorf("field 'description' does not match pattern '\\s*(\\S|\\s)*'") - } - } - if x.DescriptionSummary != nil { - if !rx_ResearchStudy_DescriptionSummary.MatchString(*x.DescriptionSummary) { - return fmt.Errorf("field 'descriptionSummary' does not match pattern '\\s*(\\S|\\s)*'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Focus != nil { - for i, item := range x.Focus { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'focus[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if !rx_ResearchStudy_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ImplicitRules != nil { - } - if x.Keyword != nil { - for i, item := range x.Keyword { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'keyword[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Label != nil { - for i, item := range x.Label { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'label[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Language != nil { - if !rx_ResearchStudy_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Name != nil { - if *x.Name == "" { - return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Note != nil { - for i, item := range x.Note { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Objective != nil { - for i, item := range x.Objective { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'objective[%d]' is invalid: %w", i, err) - } - } - } - } - if x.OutcomeMeasure != nil { - for i, item := range x.OutcomeMeasure { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'outcomeMeasure[%d]' is invalid: %w", i, err) - } - } - } - } - if x.PartOf != nil { - for i, item := range x.PartOf { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'partOf[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Period != nil { - if err := x.Period.Validate(); err != nil { - return fmt.Errorf("field 'period' is invalid: %w", err) - } - } - if x.Phase != nil { - if err := x.Phase.Validate(); err != nil { - return fmt.Errorf("field 'phase' is invalid: %w", err) - } - } - if x.PrimaryPurposeType != nil { - if err := x.PrimaryPurposeType.Validate(); err != nil { - return fmt.Errorf("field 'primaryPurposeType' is invalid: %w", err) - } - } - if x.ProgressStatus != nil { - for i, item := range x.ProgressStatus { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'progressStatus[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Protocol != nil { - for i, item := range x.Protocol { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'protocol[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Recruitment != nil { - if err := x.Recruitment.Validate(); err != nil { - return fmt.Errorf("field 'recruitment' is invalid: %w", err) - } - } - if x.Region != nil { - for i, item := range x.Region { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'region[%d]' is invalid: %w", i, err) - } - } - } - } - if x.RelatedArtifact != nil { - for i, item := range x.RelatedArtifact { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'relatedArtifact[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ResearchStudy" { - return fmt.Errorf("field 'resourceType' must be exactly 'ResearchStudy'") - } - } - if x.Result != nil { - for i, item := range x.Result { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'result[%d]' is invalid: %w", i, err) - } - } - } - } - if x.RootDir != nil { - if err := x.RootDir.Validate(); err != nil { - return fmt.Errorf("field 'rootDir' is invalid: %w", err) - } - } - if x.Site != nil { - for i, item := range x.Site { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'site[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Status != nil { - if !rx_ResearchStudy_Status.MatchString(*x.Status) { - return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.StudyDesign != nil { - for i, item := range x.StudyDesign { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'studyDesign[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Text != nil { - if err := x.Text.Validate(); err != nil { - return fmt.Errorf("field 'text' is invalid: %w", err) - } - } - if x.Title != nil { - if *x.Title == "" { - return fmt.Errorf("field 'title' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.URL != nil { - } - if x.Version != nil { - if *x.Version == "" { - return fmt.Errorf("field 'version' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.WhyStopped != nil { - if err := x.WhyStopped.Validate(); err != nil { - return fmt.Errorf("field 'whyStopped' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a ResearchStudyAssociatedParty struct against its schema constraints. -func (x *ResearchStudyAssociatedParty) Validate() error { - if x == nil { - return nil - } - if x.XName != nil { - if err := x.XName.Validate(); err != nil { - return fmt.Errorf("field '_name' is invalid: %w", err) - } - } - if x.Classifier != nil { - for i, item := range x.Classifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'classifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Name != nil { - if *x.Name == "" { - return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Party != nil { - if err := x.Party.Validate(); err != nil { - return fmt.Errorf("field 'party' is invalid: %w", err) - } - } - if x.Period != nil { - for i, item := range x.Period { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'period[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ResearchStudyAssociatedParty" { - return fmt.Errorf("field 'resourceType' must be exactly 'ResearchStudyAssociatedParty'") - } - } - if x.Role == nil { - return fmt.Errorf("required field 'role' is missing") - } - if x.Role != nil { - if err := x.Role.Validate(); err != nil { - return fmt.Errorf("field 'role' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a ResearchStudyComparisonGroup struct against its schema constraints. -func (x *ResearchStudyComparisonGroup) Validate() error { - if x == nil { - return nil - } - if x.XDescription != nil { - if err := x.XDescription.Validate(); err != nil { - return fmt.Errorf("field '_description' is invalid: %w", err) - } - } - if x.XLinkID != nil { - if err := x.XLinkID.Validate(); err != nil { - return fmt.Errorf("field '_linkId' is invalid: %w", err) - } - } - if x.XName != nil { - if err := x.XName.Validate(); err != nil { - return fmt.Errorf("field '_name' is invalid: %w", err) - } - } - if x.Description != nil { - if !rx_ResearchStudyComparisonGroup_Description.MatchString(*x.Description) { - return fmt.Errorf("field 'description' does not match pattern '\\s*(\\S|\\s)*'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.IntendedExposure != nil { - for i, item := range x.IntendedExposure { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'intendedExposure[%d]' is invalid: %w", i, err) - } - } - } - } - if x.LinkID != nil { - if !rx_ResearchStudyComparisonGroup_LinkID.MatchString(*x.LinkID) { - return fmt.Errorf("field 'linkId' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.LinkID) < 1 { - return fmt.Errorf("field 'linkId' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.LinkID) > 64 { - return fmt.Errorf("field 'linkId' is too long (max 64 characters)") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Name != nil { - if *x.Name == "" { - return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.ObservedGroup != nil { - if err := x.ObservedGroup.Validate(); err != nil { - return fmt.Errorf("field 'observedGroup' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ResearchStudyComparisonGroup" { - return fmt.Errorf("field 'resourceType' must be exactly 'ResearchStudyComparisonGroup'") - } - } - if x.Type != nil { - if err := x.Type.Validate(); err != nil { - return fmt.Errorf("field 'type' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a ResearchStudyLabel struct against its schema constraints. -func (x *ResearchStudyLabel) Validate() error { - if x == nil { - return nil - } - if x.XValue != nil { - if err := x.XValue.Validate(); err != nil { - return fmt.Errorf("field '_value' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ResearchStudyLabel" { - return fmt.Errorf("field 'resourceType' must be exactly 'ResearchStudyLabel'") - } - } - if x.Type != nil { - if err := x.Type.Validate(); err != nil { - return fmt.Errorf("field 'type' is invalid: %w", err) - } - } - if x.Value != nil { - if *x.Value == "" { - return fmt.Errorf("field 'value' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - return nil -} - -// Validate validates a ResearchStudyObjective struct against its schema constraints. -func (x *ResearchStudyObjective) Validate() error { - if x == nil { - return nil - } - if x.XDescription != nil { - if err := x.XDescription.Validate(); err != nil { - return fmt.Errorf("field '_description' is invalid: %w", err) - } - } - if x.XName != nil { - if err := x.XName.Validate(); err != nil { - return fmt.Errorf("field '_name' is invalid: %w", err) - } - } - if x.Description != nil { - if !rx_ResearchStudyObjective_Description.MatchString(*x.Description) { - return fmt.Errorf("field 'description' does not match pattern '\\s*(\\S|\\s)*'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Name != nil { - if *x.Name == "" { - return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ResearchStudyObjective" { - return fmt.Errorf("field 'resourceType' must be exactly 'ResearchStudyObjective'") - } - } - if x.Type != nil { - if err := x.Type.Validate(); err != nil { - return fmt.Errorf("field 'type' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a ResearchStudyOutcomeMeasure struct against its schema constraints. -func (x *ResearchStudyOutcomeMeasure) Validate() error { - if x == nil { - return nil - } - if x.XDescription != nil { - if err := x.XDescription.Validate(); err != nil { - return fmt.Errorf("field '_description' is invalid: %w", err) - } - } - if x.XName != nil { - if err := x.XName.Validate(); err != nil { - return fmt.Errorf("field '_name' is invalid: %w", err) - } - } - if x.Description != nil { - if !rx_ResearchStudyOutcomeMeasure_Description.MatchString(*x.Description) { - return fmt.Errorf("field 'description' does not match pattern '\\s*(\\S|\\s)*'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Name != nil { - if *x.Name == "" { - return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Reference != nil { - if err := x.Reference.Validate(); err != nil { - return fmt.Errorf("field 'reference' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ResearchStudyOutcomeMeasure" { - return fmt.Errorf("field 'resourceType' must be exactly 'ResearchStudyOutcomeMeasure'") - } - } - if x.Type != nil { - for i, item := range x.Type { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'type[%d]' is invalid: %w", i, err) - } - } - } - } - return nil -} - -// Validate validates a ResearchStudyProgressStatus struct against its schema constraints. -func (x *ResearchStudyProgressStatus) Validate() error { - if x == nil { - return nil - } - if x.XActual != nil { - if err := x.XActual.Validate(); err != nil { - return fmt.Errorf("field '_actual' is invalid: %w", err) - } - } - if x.Actual != nil { - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Period != nil { - if err := x.Period.Validate(); err != nil { - return fmt.Errorf("field 'period' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ResearchStudyProgressStatus" { - return fmt.Errorf("field 'resourceType' must be exactly 'ResearchStudyProgressStatus'") - } - } - if x.State == nil { - return fmt.Errorf("required field 'state' is missing") - } - if x.State != nil { - if err := x.State.Validate(); err != nil { - return fmt.Errorf("field 'state' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a ResearchStudyRecruitment struct against its schema constraints. -func (x *ResearchStudyRecruitment) Validate() error { - if x == nil { - return nil - } - if x.XActualNumber != nil { - if err := x.XActualNumber.Validate(); err != nil { - return fmt.Errorf("field '_actualNumber' is invalid: %w", err) - } - } - if x.XTargetNumber != nil { - if err := x.XTargetNumber.Validate(); err != nil { - return fmt.Errorf("field '_targetNumber' is invalid: %w", err) - } - } - if x.ActualGroup != nil { - if err := x.ActualGroup.Validate(); err != nil { - return fmt.Errorf("field 'actualGroup' is invalid: %w", err) - } - } - if x.ActualNumber != nil { - if *x.ActualNumber < 0.000000 { - return fmt.Errorf("field 'actualNumber' is below minimum 0.000000") - } - } - if x.Eligibility != nil { - if err := x.Eligibility.Validate(); err != nil { - return fmt.Errorf("field 'eligibility' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ResearchStudyRecruitment" { - return fmt.Errorf("field 'resourceType' must be exactly 'ResearchStudyRecruitment'") - } - } - if x.TargetNumber != nil { - if *x.TargetNumber < 0.000000 { - return fmt.Errorf("field 'targetNumber' is below minimum 0.000000") - } - } - return nil -} - -// Validate validates a ResearchSubject struct against its schema constraints. -func (x *ResearchSubject) Validate() error { - if x == nil { - return nil - } - if x.XActualComparisonGroup != nil { - if err := x.XActualComparisonGroup.Validate(); err != nil { - return fmt.Errorf("field '_actualComparisonGroup' is invalid: %w", err) - } - } - if x.XAssignedComparisonGroup != nil { - if err := x.XAssignedComparisonGroup.Validate(); err != nil { - return fmt.Errorf("field '_assignedComparisonGroup' is invalid: %w", err) - } - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.XStatus != nil { - if err := x.XStatus.Validate(); err != nil { - return fmt.Errorf("field '_status' is invalid: %w", err) - } - } - if x.ActualComparisonGroup != nil { - if !rx_ResearchSubject_ActualComparisonGroup.MatchString(*x.ActualComparisonGroup) { - return fmt.Errorf("field 'actualComparisonGroup' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ActualComparisonGroup) < 1 { - return fmt.Errorf("field 'actualComparisonGroup' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ActualComparisonGroup) > 64 { - return fmt.Errorf("field 'actualComparisonGroup' is too long (max 64 characters)") - } - } - if x.AssignedComparisonGroup != nil { - if !rx_ResearchSubject_AssignedComparisonGroup.MatchString(*x.AssignedComparisonGroup) { - return fmt.Errorf("field 'assignedComparisonGroup' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.AssignedComparisonGroup) < 1 { - return fmt.Errorf("field 'assignedComparisonGroup' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.AssignedComparisonGroup) > 64 { - return fmt.Errorf("field 'assignedComparisonGroup' is too long (max 64 characters)") - } - } - if x.Consent != nil { - for i, item := range x.Consent { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'consent[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Contained != nil { - for i, item := range x.Contained { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if !rx_ResearchSubject_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ImplicitRules != nil { - } - if x.Language != nil { - if !rx_ResearchSubject_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Period != nil { - if err := x.Period.Validate(); err != nil { - return fmt.Errorf("field 'period' is invalid: %w", err) - } - } - if x.Progress != nil { - for i, item := range x.Progress { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'progress[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ResearchSubject" { - return fmt.Errorf("field 'resourceType' must be exactly 'ResearchSubject'") - } - } - if x.Status != nil { - if !rx_ResearchSubject_Status.MatchString(*x.Status) { - return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Study == nil { - return fmt.Errorf("required field 'study' is missing") - } - if x.Study != nil { - if err := x.Study.Validate(); err != nil { - return fmt.Errorf("field 'study' is invalid: %w", err) - } - } - if x.Subject == nil { - return fmt.Errorf("required field 'subject' is missing") - } - if x.Subject != nil { - if err := x.Subject.Validate(); err != nil { - return fmt.Errorf("field 'subject' is invalid: %w", err) - } - } - if x.Text != nil { - if err := x.Text.Validate(); err != nil { - return fmt.Errorf("field 'text' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a ResearchSubjectProgress struct against its schema constraints. -func (x *ResearchSubjectProgress) Validate() error { - if x == nil { - return nil - } - if x.XEndDate != nil { - if err := x.XEndDate.Validate(); err != nil { - return fmt.Errorf("field '_endDate' is invalid: %w", err) - } - } - if x.XStartDate != nil { - if err := x.XStartDate.Validate(); err != nil { - return fmt.Errorf("field '_startDate' is invalid: %w", err) - } - } - if x.EndDate != nil { - if err := ValidateFhirDateTime(*x.EndDate); err != nil { - return fmt.Errorf("field 'endDate' has invalid date-time format: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Milestone != nil { - if err := x.Milestone.Validate(); err != nil { - return fmt.Errorf("field 'milestone' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Reason != nil { - if err := x.Reason.Validate(); err != nil { - return fmt.Errorf("field 'reason' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "ResearchSubjectProgress" { - return fmt.Errorf("field 'resourceType' must be exactly 'ResearchSubjectProgress'") - } - } - if x.StartDate != nil { - if err := ValidateFhirDateTime(*x.StartDate); err != nil { - return fmt.Errorf("field 'startDate' has invalid date-time format: %w", err) - } - } - if x.SubjectState != nil { - if err := x.SubjectState.Validate(); err != nil { - return fmt.Errorf("field 'subjectState' is invalid: %w", err) - } - } - if x.Type != nil { - if err := x.Type.Validate(); err != nil { - return fmt.Errorf("field 'type' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a Resource struct against its schema constraints. -func (x *Resource) Validate() error { - if x == nil { - return nil - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.ID != nil { - if !rx_Resource_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.ImplicitRules != nil { - } - if x.Language != nil { - if !rx_Resource_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "Resource" { - return fmt.Errorf("field 'resourceType' must be exactly 'Resource'") - } - } - return nil -} - -// Validate validates a SampledData struct against its schema constraints. -func (x *SampledData) Validate() error { - if x == nil { - return nil - } - if x.XCodeMap != nil { - if err := x.XCodeMap.Validate(); err != nil { - return fmt.Errorf("field '_codeMap' is invalid: %w", err) - } - } - if x.XData != nil { - if err := x.XData.Validate(); err != nil { - return fmt.Errorf("field '_data' is invalid: %w", err) - } - } - if x.XDimensions != nil { - if err := x.XDimensions.Validate(); err != nil { - return fmt.Errorf("field '_dimensions' is invalid: %w", err) - } - } - if x.XFactor != nil { - if err := x.XFactor.Validate(); err != nil { - return fmt.Errorf("field '_factor' is invalid: %w", err) - } - } - if x.XInterval != nil { - if err := x.XInterval.Validate(); err != nil { - return fmt.Errorf("field '_interval' is invalid: %w", err) - } - } - if x.XIntervalUnit != nil { - if err := x.XIntervalUnit.Validate(); err != nil { - return fmt.Errorf("field '_intervalUnit' is invalid: %w", err) - } - } - if x.XLowerLimit != nil { - if err := x.XLowerLimit.Validate(); err != nil { - return fmt.Errorf("field '_lowerLimit' is invalid: %w", err) - } - } - if x.XOffsets != nil { - if err := x.XOffsets.Validate(); err != nil { - return fmt.Errorf("field '_offsets' is invalid: %w", err) - } - } - if x.XUpperLimit != nil { - if err := x.XUpperLimit.Validate(); err != nil { - return fmt.Errorf("field '_upperLimit' is invalid: %w", err) - } - } - if x.CodeMap != nil { - } - if x.Data != nil { - if *x.Data == "" { - return fmt.Errorf("field 'data' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Dimensions != nil { - if *x.Dimensions <= 0.000000 { - return fmt.Errorf("field 'dimensions' is below exclusive minimum 0.000000") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Factor != nil { - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Interval != nil { - } - if x.IntervalUnit != nil { - if !rx_SampledData_IntervalUnit.MatchString(*x.IntervalUnit) { - return fmt.Errorf("field 'intervalUnit' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.LowerLimit != nil { - } - if x.Offsets != nil { - if *x.Offsets == "" { - return fmt.Errorf("field 'offsets' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Origin == nil { - return fmt.Errorf("required field 'origin' is missing") - } - if x.Origin != nil { - if err := x.Origin.Validate(); err != nil { - return fmt.Errorf("field 'origin' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "SampledData" { - return fmt.Errorf("field 'resourceType' must be exactly 'SampledData'") - } - } - if x.UpperLimit != nil { - } - return nil -} - -// Validate validates a Signature struct against its schema constraints. -func (x *Signature) Validate() error { - if x == nil { - return nil - } - if x.XData != nil { - if err := x.XData.Validate(); err != nil { - return fmt.Errorf("field '_data' is invalid: %w", err) - } - } - if x.XSigFormat != nil { - if err := x.XSigFormat.Validate(); err != nil { - return fmt.Errorf("field '_sigFormat' is invalid: %w", err) - } - } - if x.XTargetFormat != nil { - if err := x.XTargetFormat.Validate(); err != nil { - return fmt.Errorf("field '_targetFormat' is invalid: %w", err) - } - } - if x.XWhen != nil { - if err := x.XWhen.Validate(); err != nil { - return fmt.Errorf("field '_when' is invalid: %w", err) - } - } - if x.Data != nil { - if err := ValidateFhirBinary(*x.Data); err != nil { - return fmt.Errorf("field 'data' has invalid binary format: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.OnBehalfOf != nil { - if err := x.OnBehalfOf.Validate(); err != nil { - return fmt.Errorf("field 'onBehalfOf' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "Signature" { - return fmt.Errorf("field 'resourceType' must be exactly 'Signature'") - } - } - if x.SigFormat != nil { - if !rx_Signature_SigFormat.MatchString(*x.SigFormat) { - return fmt.Errorf("field 'sigFormat' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.TargetFormat != nil { - if !rx_Signature_TargetFormat.MatchString(*x.TargetFormat) { - return fmt.Errorf("field 'targetFormat' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Type != nil { - for i, item := range x.Type { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'type[%d]' is invalid: %w", i, err) - } - } - } - } - if x.When != nil { - if err := ValidateFhirDateTime(*x.When); err != nil { - return fmt.Errorf("field 'when' has invalid date-time format: %w", err) - } - } - if x.Who != nil { - if err := x.Who.Validate(); err != nil { - return fmt.Errorf("field 'who' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a Specimen struct against its schema constraints. -func (x *Specimen) Validate() error { - if x == nil { - return nil - } - if x.XCombined != nil { - if err := x.XCombined.Validate(); err != nil { - return fmt.Errorf("field '_combined' is invalid: %w", err) - } - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.XReceivedTime != nil { - if err := x.XReceivedTime.Validate(); err != nil { - return fmt.Errorf("field '_receivedTime' is invalid: %w", err) - } - } - if x.XStatus != nil { - if err := x.XStatus.Validate(); err != nil { - return fmt.Errorf("field '_status' is invalid: %w", err) - } - } - if x.AccessionIDentifier != nil { - if err := x.AccessionIDentifier.Validate(); err != nil { - return fmt.Errorf("field 'accessionIdentifier' is invalid: %w", err) - } - } - if x.Collection != nil { - if err := x.Collection.Validate(); err != nil { - return fmt.Errorf("field 'collection' is invalid: %w", err) - } - } - if x.Combined != nil { - if !rx_Specimen_Combined.MatchString(*x.Combined) { - return fmt.Errorf("field 'combined' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Condition != nil { - for i, item := range x.Condition { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'condition[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Contained != nil { - for i, item := range x.Contained { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Container != nil { - for i, item := range x.Container { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'container[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Feature != nil { - for i, item := range x.Feature { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'feature[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if !rx_Specimen_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ImplicitRules != nil { - } - if x.Language != nil { - if !rx_Specimen_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Note != nil { - for i, item := range x.Note { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Parent != nil { - for i, item := range x.Parent { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'parent[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Processing != nil { - for i, item := range x.Processing { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'processing[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ReceivedTime != nil { - if err := ValidateFhirDateTime(*x.ReceivedTime); err != nil { - return fmt.Errorf("field 'receivedTime' has invalid date-time format: %w", err) - } - } - if x.Request != nil { - for i, item := range x.Request { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'request[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "Specimen" { - return fmt.Errorf("field 'resourceType' must be exactly 'Specimen'") - } - } - if x.Role != nil { - for i, item := range x.Role { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'role[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Status != nil { - if !rx_Specimen_Status.MatchString(*x.Status) { - return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Subject != nil { - if err := x.Subject.Validate(); err != nil { - return fmt.Errorf("field 'subject' is invalid: %w", err) - } - } - if x.Text != nil { - if err := x.Text.Validate(); err != nil { - return fmt.Errorf("field 'text' is invalid: %w", err) - } - } - if x.Type != nil { - if err := x.Type.Validate(); err != nil { - return fmt.Errorf("field 'type' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a SpecimenCollection struct against its schema constraints. -func (x *SpecimenCollection) Validate() error { - if x == nil { - return nil - } - if x.XCollectedDateTime != nil { - if err := x.XCollectedDateTime.Validate(); err != nil { - return fmt.Errorf("field '_collectedDateTime' is invalid: %w", err) - } - } - if x.BodySite != nil { - if err := x.BodySite.Validate(); err != nil { - return fmt.Errorf("field 'bodySite' is invalid: %w", err) - } - } - if x.CollectedDateTime != nil { - if err := ValidateFhirDateTime(*x.CollectedDateTime); err != nil { - return fmt.Errorf("field 'collectedDateTime' has invalid date-time format: %w", err) - } - } - if x.CollectedPeriod != nil { - if err := x.CollectedPeriod.Validate(); err != nil { - return fmt.Errorf("field 'collectedPeriod' is invalid: %w", err) - } - } - if x.Collector != nil { - if err := x.Collector.Validate(); err != nil { - return fmt.Errorf("field 'collector' is invalid: %w", err) - } - } - if x.Device != nil { - if err := x.Device.Validate(); err != nil { - return fmt.Errorf("field 'device' is invalid: %w", err) - } - } - if x.Duration != nil { - if err := x.Duration.Validate(); err != nil { - return fmt.Errorf("field 'duration' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.FastingStatusCodeableConcept != nil { - if err := x.FastingStatusCodeableConcept.Validate(); err != nil { - return fmt.Errorf("field 'fastingStatusCodeableConcept' is invalid: %w", err) - } - } - if x.FastingStatusDuration != nil { - if err := x.FastingStatusDuration.Validate(); err != nil { - return fmt.Errorf("field 'fastingStatusDuration' is invalid: %w", err) - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Method != nil { - if err := x.Method.Validate(); err != nil { - return fmt.Errorf("field 'method' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Procedure != nil { - if err := x.Procedure.Validate(); err != nil { - return fmt.Errorf("field 'procedure' is invalid: %w", err) - } - } - if x.Quantity != nil { - if err := x.Quantity.Validate(); err != nil { - return fmt.Errorf("field 'quantity' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "SpecimenCollection" { - return fmt.Errorf("field 'resourceType' must be exactly 'SpecimenCollection'") - } - } - return nil -} - -// Validate validates a SpecimenContainer struct against its schema constraints. -func (x *SpecimenContainer) Validate() error { - if x == nil { - return nil - } - if x.Device == nil { - return fmt.Errorf("required field 'device' is missing") - } - if x.Device != nil { - if err := x.Device.Validate(); err != nil { - return fmt.Errorf("field 'device' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Location != nil { - if err := x.Location.Validate(); err != nil { - return fmt.Errorf("field 'location' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "SpecimenContainer" { - return fmt.Errorf("field 'resourceType' must be exactly 'SpecimenContainer'") - } - } - if x.SpecimenQuantity != nil { - if err := x.SpecimenQuantity.Validate(); err != nil { - return fmt.Errorf("field 'specimenQuantity' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a SpecimenFeature struct against its schema constraints. -func (x *SpecimenFeature) Validate() error { - if x == nil { - return nil - } - if x.XDescription != nil { - if err := x.XDescription.Validate(); err != nil { - return fmt.Errorf("field '_description' is invalid: %w", err) - } - } - if x.Description != nil { - if *x.Description == "" { - return fmt.Errorf("field 'description' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "SpecimenFeature" { - return fmt.Errorf("field 'resourceType' must be exactly 'SpecimenFeature'") - } - } - if x.Type == nil { - return fmt.Errorf("required field 'type' is missing") - } - if x.Type != nil { - if err := x.Type.Validate(); err != nil { - return fmt.Errorf("field 'type' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a SpecimenProcessing struct against its schema constraints. -func (x *SpecimenProcessing) Validate() error { - if x == nil { - return nil - } - if x.XDescription != nil { - if err := x.XDescription.Validate(); err != nil { - return fmt.Errorf("field '_description' is invalid: %w", err) - } - } - if x.XTimeDateTime != nil { - if err := x.XTimeDateTime.Validate(); err != nil { - return fmt.Errorf("field '_timeDateTime' is invalid: %w", err) - } - } - if x.Additive != nil { - for i, item := range x.Additive { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'additive[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Description != nil { - if *x.Description == "" { - return fmt.Errorf("field 'description' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Method != nil { - if err := x.Method.Validate(); err != nil { - return fmt.Errorf("field 'method' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "SpecimenProcessing" { - return fmt.Errorf("field 'resourceType' must be exactly 'SpecimenProcessing'") - } - } - if x.TimeDateTime != nil { - if err := ValidateFhirDateTime(*x.TimeDateTime); err != nil { - return fmt.Errorf("field 'timeDateTime' has invalid date-time format: %w", err) - } - } - if x.TimePeriod != nil { - if err := x.TimePeriod.Validate(); err != nil { - return fmt.Errorf("field 'timePeriod' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a Substance struct against its schema constraints. -func (x *Substance) Validate() error { - if x == nil { - return nil - } - if x.XDescription != nil { - if err := x.XDescription.Validate(); err != nil { - return fmt.Errorf("field '_description' is invalid: %w", err) - } - } - if x.XExpiry != nil { - if err := x.XExpiry.Validate(); err != nil { - return fmt.Errorf("field '_expiry' is invalid: %w", err) - } - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XInstance != nil { - if err := x.XInstance.Validate(); err != nil { - return fmt.Errorf("field '_instance' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.XStatus != nil { - if err := x.XStatus.Validate(); err != nil { - return fmt.Errorf("field '_status' is invalid: %w", err) - } - } - if x.Category != nil { - for i, item := range x.Category { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'category[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Code == nil { - return fmt.Errorf("required field 'code' is missing") - } - if x.Code != nil { - if err := x.Code.Validate(); err != nil { - return fmt.Errorf("field 'code' is invalid: %w", err) - } - } - if x.Contained != nil { - for i, item := range x.Contained { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Description != nil { - if !rx_Substance_Description.MatchString(*x.Description) { - return fmt.Errorf("field 'description' does not match pattern '\\s*(\\S|\\s)*'") - } - } - if x.Expiry != nil { - if err := ValidateFhirDateTime(*x.Expiry); err != nil { - return fmt.Errorf("field 'expiry' has invalid date-time format: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if !rx_Substance_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ImplicitRules != nil { - } - if x.Ingredient != nil { - for i, item := range x.Ingredient { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'ingredient[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Instance != nil { - } - if x.Language != nil { - if !rx_Substance_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Quantity != nil { - if err := x.Quantity.Validate(); err != nil { - return fmt.Errorf("field 'quantity' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "Substance" { - return fmt.Errorf("field 'resourceType' must be exactly 'Substance'") - } - } - if x.Status != nil { - if !rx_Substance_Status.MatchString(*x.Status) { - return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Text != nil { - if err := x.Text.Validate(); err != nil { - return fmt.Errorf("field 'text' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a SubstanceDefinition struct against its schema constraints. -func (x *SubstanceDefinition) Validate() error { - if x == nil { - return nil - } - if x.XDescription != nil { - if err := x.XDescription.Validate(); err != nil { - return fmt.Errorf("field '_description' is invalid: %w", err) - } - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.XVersion != nil { - if err := x.XVersion.Validate(); err != nil { - return fmt.Errorf("field '_version' is invalid: %w", err) - } - } - if x.Characterization != nil { - for i, item := range x.Characterization { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'characterization[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Classification != nil { - for i, item := range x.Classification { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'classification[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Code != nil { - for i, item := range x.Code { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'code[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Contained != nil { - for i, item := range x.Contained { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Description != nil { - if !rx_SubstanceDefinition_Description.MatchString(*x.Description) { - return fmt.Errorf("field 'description' does not match pattern '\\s*(\\S|\\s)*'") - } - } - if x.Domain != nil { - if err := x.Domain.Validate(); err != nil { - return fmt.Errorf("field 'domain' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Grade != nil { - for i, item := range x.Grade { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'grade[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if !rx_SubstanceDefinition_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ImplicitRules != nil { - } - if x.InformationSource != nil { - for i, item := range x.InformationSource { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'informationSource[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Language != nil { - if !rx_SubstanceDefinition_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Links != nil { - } - if x.Manufacturer != nil { - for i, item := range x.Manufacturer { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'manufacturer[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Moiety != nil { - for i, item := range x.Moiety { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'moiety[%d]' is invalid: %w", i, err) - } - } - } - } - if x.MolecularWeight != nil { - for i, item := range x.MolecularWeight { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'molecularWeight[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Name != nil { - for i, item := range x.Name { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'name[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Note != nil { - for i, item := range x.Note { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) - } - } - } - } - if x.NucleicAcid != nil { - if err := x.NucleicAcid.Validate(); err != nil { - return fmt.Errorf("field 'nucleicAcid' is invalid: %w", err) - } - } - if x.Polymer != nil { - if err := x.Polymer.Validate(); err != nil { - return fmt.Errorf("field 'polymer' is invalid: %w", err) - } - } - if x.Property != nil { - for i, item := range x.Property { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'property[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Protein != nil { - if err := x.Protein.Validate(); err != nil { - return fmt.Errorf("field 'protein' is invalid: %w", err) - } - } - if x.ReferenceInformation != nil { - if err := x.ReferenceInformation.Validate(); err != nil { - return fmt.Errorf("field 'referenceInformation' is invalid: %w", err) - } - } - if x.Relationship != nil { - for i, item := range x.Relationship { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'relationship[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "SubstanceDefinition" { - return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinition'") - } - } - if x.SourceMaterial != nil { - if err := x.SourceMaterial.Validate(); err != nil { - return fmt.Errorf("field 'sourceMaterial' is invalid: %w", err) - } - } - if x.Status != nil { - if err := x.Status.Validate(); err != nil { - return fmt.Errorf("field 'status' is invalid: %w", err) - } - } - if x.Structure != nil { - if err := x.Structure.Validate(); err != nil { - return fmt.Errorf("field 'structure' is invalid: %w", err) - } - } - if x.Supplier != nil { - for i, item := range x.Supplier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'supplier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Text != nil { - if err := x.Text.Validate(); err != nil { - return fmt.Errorf("field 'text' is invalid: %w", err) - } - } - if x.Version != nil { - if *x.Version == "" { - return fmt.Errorf("field 'version' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - return nil -} - -// Validate validates a SubstanceDefinitionCharacterization struct against its schema constraints. -func (x *SubstanceDefinitionCharacterization) Validate() error { - if x == nil { - return nil - } - if x.XDescription != nil { - if err := x.XDescription.Validate(); err != nil { - return fmt.Errorf("field '_description' is invalid: %w", err) - } - } - if x.Description != nil { - if !rx_SubstanceDefinitionCharacterization_Description.MatchString(*x.Description) { - return fmt.Errorf("field 'description' does not match pattern '\\s*(\\S|\\s)*'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.File != nil { - for i, item := range x.File { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'file[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Form != nil { - if err := x.Form.Validate(); err != nil { - return fmt.Errorf("field 'form' is invalid: %w", err) - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "SubstanceDefinitionCharacterization" { - return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinitionCharacterization'") - } - } - if x.Technique != nil { - if err := x.Technique.Validate(); err != nil { - return fmt.Errorf("field 'technique' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a SubstanceDefinitionCode struct against its schema constraints. -func (x *SubstanceDefinitionCode) Validate() error { - if x == nil { - return nil - } - if x.XStatusDate != nil { - if err := x.XStatusDate.Validate(); err != nil { - return fmt.Errorf("field '_statusDate' is invalid: %w", err) - } - } - if x.Code != nil { - if err := x.Code.Validate(); err != nil { - return fmt.Errorf("field 'code' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Note != nil { - for i, item := range x.Note { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "SubstanceDefinitionCode" { - return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinitionCode'") - } - } - if x.Source != nil { - for i, item := range x.Source { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'source[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Status != nil { - if err := x.Status.Validate(); err != nil { - return fmt.Errorf("field 'status' is invalid: %w", err) - } - } - if x.StatusDate != nil { - if err := ValidateFhirDateTime(*x.StatusDate); err != nil { - return fmt.Errorf("field 'statusDate' has invalid date-time format: %w", err) - } - } - return nil -} - -// Validate validates a SubstanceDefinitionMoiety struct against its schema constraints. -func (x *SubstanceDefinitionMoiety) Validate() error { - if x == nil { - return nil - } - if x.XAmountString != nil { - if err := x.XAmountString.Validate(); err != nil { - return fmt.Errorf("field '_amountString' is invalid: %w", err) - } - } - if x.XMolecularFormula != nil { - if err := x.XMolecularFormula.Validate(); err != nil { - return fmt.Errorf("field '_molecularFormula' is invalid: %w", err) - } - } - if x.XName != nil { - if err := x.XName.Validate(); err != nil { - return fmt.Errorf("field '_name' is invalid: %w", err) - } - } - if x.AmountQuantity != nil { - if err := x.AmountQuantity.Validate(); err != nil { - return fmt.Errorf("field 'amountQuantity' is invalid: %w", err) - } - } - if x.AmountString != nil { - if *x.AmountString == "" { - return fmt.Errorf("field 'amountString' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.IDentifier != nil { - if err := x.IDentifier.Validate(); err != nil { - return fmt.Errorf("field 'identifier' is invalid: %w", err) - } - } - if x.Links != nil { - } - if x.MeasurementType != nil { - if err := x.MeasurementType.Validate(); err != nil { - return fmt.Errorf("field 'measurementType' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.MolecularFormula != nil { - if *x.MolecularFormula == "" { - return fmt.Errorf("field 'molecularFormula' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Name != nil { - if *x.Name == "" { - return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.OpticalActivity != nil { - if err := x.OpticalActivity.Validate(); err != nil { - return fmt.Errorf("field 'opticalActivity' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "SubstanceDefinitionMoiety" { - return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinitionMoiety'") - } - } - if x.Role != nil { - if err := x.Role.Validate(); err != nil { - return fmt.Errorf("field 'role' is invalid: %w", err) - } - } - if x.Stereochemistry != nil { - if err := x.Stereochemistry.Validate(); err != nil { - return fmt.Errorf("field 'stereochemistry' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a SubstanceDefinitionMolecularWeight struct against its schema constraints. -func (x *SubstanceDefinitionMolecularWeight) Validate() error { - if x == nil { - return nil - } - if x.Amount == nil { - return fmt.Errorf("required field 'amount' is missing") - } - if x.Amount != nil { - if err := x.Amount.Validate(); err != nil { - return fmt.Errorf("field 'amount' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Method != nil { - if err := x.Method.Validate(); err != nil { - return fmt.Errorf("field 'method' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "SubstanceDefinitionMolecularWeight" { - return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinitionMolecularWeight'") - } - } - if x.Type != nil { - if err := x.Type.Validate(); err != nil { - return fmt.Errorf("field 'type' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a SubstanceDefinitionName struct against its schema constraints. -func (x *SubstanceDefinitionName) Validate() error { - if x == nil { - return nil - } - if x.XName != nil { - if err := x.XName.Validate(); err != nil { - return fmt.Errorf("field '_name' is invalid: %w", err) - } - } - if x.XPreferred != nil { - if err := x.XPreferred.Validate(); err != nil { - return fmt.Errorf("field '_preferred' is invalid: %w", err) - } - } - if x.Domain != nil { - for i, item := range x.Domain { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'domain[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Jurisdiction != nil { - for i, item := range x.Jurisdiction { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'jurisdiction[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Language != nil { - for i, item := range x.Language { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'language[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Name != nil { - if *x.Name == "" { - return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Official != nil { - for i, item := range x.Official { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'official[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Preferred != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "SubstanceDefinitionName" { - return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinitionName'") - } - } - if x.Source != nil { - for i, item := range x.Source { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'source[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Status != nil { - if err := x.Status.Validate(); err != nil { - return fmt.Errorf("field 'status' is invalid: %w", err) - } - } - if x.Synonym != nil { - for i, item := range x.Synonym { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'synonym[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Translation != nil { - for i, item := range x.Translation { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'translation[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Type != nil { - if err := x.Type.Validate(); err != nil { - return fmt.Errorf("field 'type' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a SubstanceDefinitionNameOfficial struct against its schema constraints. -func (x *SubstanceDefinitionNameOfficial) Validate() error { - if x == nil { - return nil - } - if x.XDate != nil { - if err := x.XDate.Validate(); err != nil { - return fmt.Errorf("field '_date' is invalid: %w", err) - } - } - if x.Authority != nil { - if err := x.Authority.Validate(); err != nil { - return fmt.Errorf("field 'authority' is invalid: %w", err) - } - } - if x.Date != nil { - if err := ValidateFhirDateTime(*x.Date); err != nil { - return fmt.Errorf("field 'date' has invalid date-time format: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "SubstanceDefinitionNameOfficial" { - return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinitionNameOfficial'") - } - } - if x.Status != nil { - if err := x.Status.Validate(); err != nil { - return fmt.Errorf("field 'status' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a SubstanceDefinitionProperty struct against its schema constraints. -func (x *SubstanceDefinitionProperty) Validate() error { - if x == nil { - return nil - } - if x.XValueBoolean != nil { - if err := x.XValueBoolean.Validate(); err != nil { - return fmt.Errorf("field '_valueBoolean' is invalid: %w", err) - } - } - if x.XValueDate != nil { - if err := x.XValueDate.Validate(); err != nil { - return fmt.Errorf("field '_valueDate' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "SubstanceDefinitionProperty" { - return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinitionProperty'") - } - } - if x.Type == nil { - return fmt.Errorf("required field 'type' is missing") - } - if x.Type != nil { - if err := x.Type.Validate(); err != nil { - return fmt.Errorf("field 'type' is invalid: %w", err) - } - } - if x.ValueAttachment != nil { - if err := x.ValueAttachment.Validate(); err != nil { - return fmt.Errorf("field 'valueAttachment' is invalid: %w", err) - } - } - if x.ValueBoolean != nil { - } - if x.ValueCodeableConcept != nil { - if err := x.ValueCodeableConcept.Validate(); err != nil { - return fmt.Errorf("field 'valueCodeableConcept' is invalid: %w", err) - } - } - if x.ValueDate != nil { - if err := ValidateFhirDate(*x.ValueDate); err != nil { - return fmt.Errorf("field 'valueDate' has invalid date format: %w", err) - } - } - if x.ValueQuantity != nil { - if err := x.ValueQuantity.Validate(); err != nil { - return fmt.Errorf("field 'valueQuantity' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a SubstanceDefinitionRelationship struct against its schema constraints. -func (x *SubstanceDefinitionRelationship) Validate() error { - if x == nil { - return nil - } - if x.XAmountString != nil { - if err := x.XAmountString.Validate(); err != nil { - return fmt.Errorf("field '_amountString' is invalid: %w", err) - } - } - if x.XIsDefining != nil { - if err := x.XIsDefining.Validate(); err != nil { - return fmt.Errorf("field '_isDefining' is invalid: %w", err) - } - } - if x.AmountQuantity != nil { - if err := x.AmountQuantity.Validate(); err != nil { - return fmt.Errorf("field 'amountQuantity' is invalid: %w", err) - } - } - if x.AmountRatio != nil { - if err := x.AmountRatio.Validate(); err != nil { - return fmt.Errorf("field 'amountRatio' is invalid: %w", err) - } - } - if x.AmountString != nil { - if *x.AmountString == "" { - return fmt.Errorf("field 'amountString' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Comparator != nil { - if err := x.Comparator.Validate(); err != nil { - return fmt.Errorf("field 'comparator' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.IsDefining != nil { - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.RatioHighLimitAmount != nil { - if err := x.RatioHighLimitAmount.Validate(); err != nil { - return fmt.Errorf("field 'ratioHighLimitAmount' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "SubstanceDefinitionRelationship" { - return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinitionRelationship'") - } - } - if x.Source != nil { - for i, item := range x.Source { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'source[%d]' is invalid: %w", i, err) - } - } - } - } - if x.SubstanceDefinitionCodeableConcept != nil { - if err := x.SubstanceDefinitionCodeableConcept.Validate(); err != nil { - return fmt.Errorf("field 'substanceDefinitionCodeableConcept' is invalid: %w", err) - } - } - if x.SubstanceDefinitionReference != nil { - if err := x.SubstanceDefinitionReference.Validate(); err != nil { - return fmt.Errorf("field 'substanceDefinitionReference' is invalid: %w", err) - } - } - if x.Type == nil { - return fmt.Errorf("required field 'type' is missing") - } - if x.Type != nil { - if err := x.Type.Validate(); err != nil { - return fmt.Errorf("field 'type' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a SubstanceDefinitionSourceMaterial struct against its schema constraints. -func (x *SubstanceDefinitionSourceMaterial) Validate() error { - if x == nil { - return nil - } - if x.CountryOfOrigin != nil { - for i, item := range x.CountryOfOrigin { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'countryOfOrigin[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Genus != nil { - if err := x.Genus.Validate(); err != nil { - return fmt.Errorf("field 'genus' is invalid: %w", err) - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Part != nil { - if err := x.Part.Validate(); err != nil { - return fmt.Errorf("field 'part' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "SubstanceDefinitionSourceMaterial" { - return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinitionSourceMaterial'") - } - } - if x.Species != nil { - if err := x.Species.Validate(); err != nil { - return fmt.Errorf("field 'species' is invalid: %w", err) - } - } - if x.Type != nil { - if err := x.Type.Validate(); err != nil { - return fmt.Errorf("field 'type' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a SubstanceDefinitionStructure struct against its schema constraints. -func (x *SubstanceDefinitionStructure) Validate() error { - if x == nil { - return nil - } - if x.XMolecularFormula != nil { - if err := x.XMolecularFormula.Validate(); err != nil { - return fmt.Errorf("field '_molecularFormula' is invalid: %w", err) - } - } - if x.XMolecularFormulaByMoiety != nil { - if err := x.XMolecularFormulaByMoiety.Validate(); err != nil { - return fmt.Errorf("field '_molecularFormulaByMoiety' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.MolecularFormula != nil { - if *x.MolecularFormula == "" { - return fmt.Errorf("field 'molecularFormula' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.MolecularFormulaByMoiety != nil { - if *x.MolecularFormulaByMoiety == "" { - return fmt.Errorf("field 'molecularFormulaByMoiety' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.MolecularWeight != nil { - if err := x.MolecularWeight.Validate(); err != nil { - return fmt.Errorf("field 'molecularWeight' is invalid: %w", err) - } - } - if x.OpticalActivity != nil { - if err := x.OpticalActivity.Validate(); err != nil { - return fmt.Errorf("field 'opticalActivity' is invalid: %w", err) - } - } - if x.Representation != nil { - for i, item := range x.Representation { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'representation[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "SubstanceDefinitionStructure" { - return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinitionStructure'") - } - } - if x.SourceDocument != nil { - for i, item := range x.SourceDocument { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'sourceDocument[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Stereochemistry != nil { - if err := x.Stereochemistry.Validate(); err != nil { - return fmt.Errorf("field 'stereochemistry' is invalid: %w", err) - } - } - if x.Technique != nil { - for i, item := range x.Technique { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'technique[%d]' is invalid: %w", i, err) - } - } - } - } - return nil -} - -// Validate validates a SubstanceDefinitionStructureRepresentation struct against its schema constraints. -func (x *SubstanceDefinitionStructureRepresentation) Validate() error { - if x == nil { - return nil - } - if x.XRepresentation != nil { - if err := x.XRepresentation.Validate(); err != nil { - return fmt.Errorf("field '_representation' is invalid: %w", err) - } - } - if x.Document != nil { - if err := x.Document.Validate(); err != nil { - return fmt.Errorf("field 'document' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Format != nil { - if err := x.Format.Validate(); err != nil { - return fmt.Errorf("field 'format' is invalid: %w", err) - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Representation != nil { - if *x.Representation == "" { - return fmt.Errorf("field 'representation' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.ResourceType != nil { - if *x.ResourceType != "SubstanceDefinitionStructureRepresentation" { - return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinitionStructureRepresentation'") - } - } - if x.Type != nil { - if err := x.Type.Validate(); err != nil { - return fmt.Errorf("field 'type' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a SubstanceIngredient struct against its schema constraints. -func (x *SubstanceIngredient) Validate() error { - if x == nil { - return nil - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Quantity != nil { - if err := x.Quantity.Validate(); err != nil { - return fmt.Errorf("field 'quantity' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "SubstanceIngredient" { - return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceIngredient'") - } - } - if x.SubstanceCodeableConcept != nil { - if err := x.SubstanceCodeableConcept.Validate(); err != nil { - return fmt.Errorf("field 'substanceCodeableConcept' is invalid: %w", err) - } - } - if x.SubstanceReference != nil { - if err := x.SubstanceReference.Validate(); err != nil { - return fmt.Errorf("field 'substanceReference' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a Task struct against its schema constraints. -func (x *Task) Validate() error { - if x == nil { - return nil - } - if x.XAuthoredOn != nil { - if err := x.XAuthoredOn.Validate(); err != nil { - return fmt.Errorf("field '_authoredOn' is invalid: %w", err) - } - } - if x.XDescription != nil { - if err := x.XDescription.Validate(); err != nil { - return fmt.Errorf("field '_description' is invalid: %w", err) - } - } - if x.XDoNotPerform != nil { - if err := x.XDoNotPerform.Validate(); err != nil { - return fmt.Errorf("field '_doNotPerform' is invalid: %w", err) - } - } - if x.XImplicitRules != nil { - if err := x.XImplicitRules.Validate(); err != nil { - return fmt.Errorf("field '_implicitRules' is invalid: %w", err) - } - } - if x.XInstantiatesCanonical != nil { - if err := x.XInstantiatesCanonical.Validate(); err != nil { - return fmt.Errorf("field '_instantiatesCanonical' is invalid: %w", err) - } - } - if x.XInstantiatesURI != nil { - if err := x.XInstantiatesURI.Validate(); err != nil { - return fmt.Errorf("field '_instantiatesUri' is invalid: %w", err) - } - } - if x.XIntent != nil { - if err := x.XIntent.Validate(); err != nil { - return fmt.Errorf("field '_intent' is invalid: %w", err) - } - } - if x.XLanguage != nil { - if err := x.XLanguage.Validate(); err != nil { - return fmt.Errorf("field '_language' is invalid: %w", err) - } - } - if x.XLastModified != nil { - if err := x.XLastModified.Validate(); err != nil { - return fmt.Errorf("field '_lastModified' is invalid: %w", err) - } - } - if x.XPriority != nil { - if err := x.XPriority.Validate(); err != nil { - return fmt.Errorf("field '_priority' is invalid: %w", err) - } - } - if x.XStatus != nil { - if err := x.XStatus.Validate(); err != nil { - return fmt.Errorf("field '_status' is invalid: %w", err) - } - } - if x.AuthoredOn != nil { - if err := ValidateFhirDateTime(*x.AuthoredOn); err != nil { - return fmt.Errorf("field 'authoredOn' has invalid date-time format: %w", err) - } - } - if x.BasedOn != nil { - for i, item := range x.BasedOn { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'basedOn[%d]' is invalid: %w", i, err) - } - } - } - } - if x.BusinessStatus != nil { - if err := x.BusinessStatus.Validate(); err != nil { - return fmt.Errorf("field 'businessStatus' is invalid: %w", err) - } - } - if x.Code != nil { - if err := x.Code.Validate(); err != nil { - return fmt.Errorf("field 'code' is invalid: %w", err) - } - } - if x.Contained != nil { - for i, item := range x.Contained { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Description != nil { - if *x.Description == "" { - return fmt.Errorf("field 'description' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.DoNotPerform != nil { - } - if x.Encounter != nil { - if err := x.Encounter.Validate(); err != nil { - return fmt.Errorf("field 'encounter' is invalid: %w", err) - } - } - if x.ExecutionPeriod != nil { - if err := x.ExecutionPeriod.Validate(); err != nil { - return fmt.Errorf("field 'executionPeriod' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Focus != nil { - if err := x.Focus.Validate(); err != nil { - return fmt.Errorf("field 'focus' is invalid: %w", err) - } - } - if x.ForFhir != nil { - if err := x.ForFhir.Validate(); err != nil { - return fmt.Errorf("field 'for_fhir' is invalid: %w", err) - } - } - if x.GroupIDentifier != nil { - if err := x.GroupIDentifier.Validate(); err != nil { - return fmt.Errorf("field 'groupIdentifier' is invalid: %w", err) - } - } - if x.ID != nil { - if !rx_Task_ID.MatchString(*x.ID) { - return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ID) < 1 { - return fmt.Errorf("field 'id' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ID) > 64 { - return fmt.Errorf("field 'id' is too long (max 64 characters)") - } - } - if x.IDentifier != nil { - for i, item := range x.IDentifier { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ImplicitRules != nil { - } - if x.Input != nil { - for i, item := range x.Input { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'input[%d]' is invalid: %w", i, err) - } - } - } - } - if x.InstantiatesCanonical != nil { - } - if x.InstantiatesURI != nil { - } - if x.Insurance != nil { - for i, item := range x.Insurance { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'insurance[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Intent != nil { - if !rx_Task_Intent.MatchString(*x.Intent) { - return fmt.Errorf("field 'intent' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Language != nil { - if !rx_Task_Language.MatchString(*x.Language) { - return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.LastModified != nil { - if err := ValidateFhirDateTime(*x.LastModified); err != nil { - return fmt.Errorf("field 'lastModified' has invalid date-time format: %w", err) - } - } - if x.Links != nil { - } - if x.Location != nil { - if err := x.Location.Validate(); err != nil { - return fmt.Errorf("field 'location' is invalid: %w", err) - } - } - if x.Meta != nil { - if err := x.Meta.Validate(); err != nil { - return fmt.Errorf("field 'meta' is invalid: %w", err) - } - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Note != nil { - for i, item := range x.Note { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Output != nil { - for i, item := range x.Output { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'output[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Owner != nil { - if err := x.Owner.Validate(); err != nil { - return fmt.Errorf("field 'owner' is invalid: %w", err) - } - } - if x.PartOf != nil { - for i, item := range x.PartOf { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'partOf[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Performer != nil { - for i, item := range x.Performer { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'performer[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Priority != nil { - if !rx_Task_Priority.MatchString(*x.Priority) { - return fmt.Errorf("field 'priority' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Reason != nil { - for i, item := range x.Reason { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'reason[%d]' is invalid: %w", i, err) - } - } - } - } - if x.RelevantHistory != nil { - for i, item := range x.RelevantHistory { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'relevantHistory[%d]' is invalid: %w", i, err) - } - } - } - } - if x.RequestedPerformer != nil { - for i, item := range x.RequestedPerformer { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'requestedPerformer[%d]' is invalid: %w", i, err) - } - } - } - } - if x.RequestedPeriod != nil { - if err := x.RequestedPeriod.Validate(); err != nil { - return fmt.Errorf("field 'requestedPeriod' is invalid: %w", err) - } - } - if x.Requester != nil { - if err := x.Requester.Validate(); err != nil { - return fmt.Errorf("field 'requester' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "Task" { - return fmt.Errorf("field 'resourceType' must be exactly 'Task'") - } - } - if x.Restriction != nil { - if err := x.Restriction.Validate(); err != nil { - return fmt.Errorf("field 'restriction' is invalid: %w", err) - } - } - if x.Status != nil { - if !rx_Task_Status.MatchString(*x.Status) { - return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.StatusReason != nil { - if err := x.StatusReason.Validate(); err != nil { - return fmt.Errorf("field 'statusReason' is invalid: %w", err) - } - } - if x.Text != nil { - if err := x.Text.Validate(); err != nil { - return fmt.Errorf("field 'text' is invalid: %w", err) - } - } - return nil -} - -// Validate validates a TaskInput struct against its schema constraints. -func (x *TaskInput) Validate() error { - if x == nil { - return nil - } - if x.XValueBase64Binary != nil { - if err := x.XValueBase64Binary.Validate(); err != nil { - return fmt.Errorf("field '_valueBase64Binary' is invalid: %w", err) - } - } - if x.XValueBoolean != nil { - if err := x.XValueBoolean.Validate(); err != nil { - return fmt.Errorf("field '_valueBoolean' is invalid: %w", err) - } - } - if x.XValueCanonical != nil { - if err := x.XValueCanonical.Validate(); err != nil { - return fmt.Errorf("field '_valueCanonical' is invalid: %w", err) - } - } - if x.XValueCode != nil { - if err := x.XValueCode.Validate(); err != nil { - return fmt.Errorf("field '_valueCode' is invalid: %w", err) - } - } - if x.XValueDate != nil { - if err := x.XValueDate.Validate(); err != nil { - return fmt.Errorf("field '_valueDate' is invalid: %w", err) - } - } - if x.XValueDateTime != nil { - if err := x.XValueDateTime.Validate(); err != nil { - return fmt.Errorf("field '_valueDateTime' is invalid: %w", err) - } - } - if x.XValueDecimal != nil { - if err := x.XValueDecimal.Validate(); err != nil { - return fmt.Errorf("field '_valueDecimal' is invalid: %w", err) - } - } - if x.XValueID != nil { - if err := x.XValueID.Validate(); err != nil { - return fmt.Errorf("field '_valueId' is invalid: %w", err) - } - } - if x.XValueInstant != nil { - if err := x.XValueInstant.Validate(); err != nil { - return fmt.Errorf("field '_valueInstant' is invalid: %w", err) - } - } - if x.XValueInteger != nil { - if err := x.XValueInteger.Validate(); err != nil { - return fmt.Errorf("field '_valueInteger' is invalid: %w", err) - } - } - if x.XValueInteger64 != nil { - if err := x.XValueInteger64.Validate(); err != nil { - return fmt.Errorf("field '_valueInteger64' is invalid: %w", err) - } - } - if x.XValueMarkdown != nil { - if err := x.XValueMarkdown.Validate(); err != nil { - return fmt.Errorf("field '_valueMarkdown' is invalid: %w", err) - } - } - if x.XValueOid != nil { - if err := x.XValueOid.Validate(); err != nil { - return fmt.Errorf("field '_valueOid' is invalid: %w", err) - } - } - if x.XValuePositiveInt != nil { - if err := x.XValuePositiveInt.Validate(); err != nil { - return fmt.Errorf("field '_valuePositiveInt' is invalid: %w", err) - } - } - if x.XValueString != nil { - if err := x.XValueString.Validate(); err != nil { - return fmt.Errorf("field '_valueString' is invalid: %w", err) - } - } - if x.XValueTime != nil { - if err := x.XValueTime.Validate(); err != nil { - return fmt.Errorf("field '_valueTime' is invalid: %w", err) - } - } - if x.XValueUnsignedInt != nil { - if err := x.XValueUnsignedInt.Validate(); err != nil { - return fmt.Errorf("field '_valueUnsignedInt' is invalid: %w", err) - } - } - if x.XValueURI != nil { - if err := x.XValueURI.Validate(); err != nil { - return fmt.Errorf("field '_valueUri' is invalid: %w", err) - } - } - if x.XValueURL != nil { - if err := x.XValueURL.Validate(); err != nil { - return fmt.Errorf("field '_valueUrl' is invalid: %w", err) - } - } - if x.XValueUUID != nil { - if err := x.XValueUUID.Validate(); err != nil { - return fmt.Errorf("field '_valueUuid' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "TaskInput" { - return fmt.Errorf("field 'resourceType' must be exactly 'TaskInput'") - } - } - if x.Type == nil { - return fmt.Errorf("required field 'type' is missing") - } - if x.Type != nil { - if err := x.Type.Validate(); err != nil { - return fmt.Errorf("field 'type' is invalid: %w", err) - } - } - if x.ValueAddress != nil { - if err := x.ValueAddress.Validate(); err != nil { - return fmt.Errorf("field 'valueAddress' is invalid: %w", err) - } - } - if x.ValueAge != nil { - if err := x.ValueAge.Validate(); err != nil { - return fmt.Errorf("field 'valueAge' is invalid: %w", err) - } - } - if x.ValueAnnotation != nil { - if err := x.ValueAnnotation.Validate(); err != nil { - return fmt.Errorf("field 'valueAnnotation' is invalid: %w", err) - } - } - if x.ValueAttachment != nil { - if err := x.ValueAttachment.Validate(); err != nil { - return fmt.Errorf("field 'valueAttachment' is invalid: %w", err) - } - } - if x.ValueAvailability != nil { - if err := x.ValueAvailability.Validate(); err != nil { - return fmt.Errorf("field 'valueAvailability' is invalid: %w", err) - } - } - if x.ValueBase64Binary != nil { - if err := ValidateFhirBinary(*x.ValueBase64Binary); err != nil { - return fmt.Errorf("field 'valueBase64Binary' has invalid binary format: %w", err) - } - } - if x.ValueBoolean != nil { - } - if x.ValueCanonical != nil { - } - if x.ValueCode != nil { - if !rx_TaskInput_ValueCode.MatchString(*x.ValueCode) { - return fmt.Errorf("field 'valueCode' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.ValueCodeableConcept != nil { - if err := x.ValueCodeableConcept.Validate(); err != nil { - return fmt.Errorf("field 'valueCodeableConcept' is invalid: %w", err) - } - } - if x.ValueCodeableReference != nil { - if err := x.ValueCodeableReference.Validate(); err != nil { - return fmt.Errorf("field 'valueCodeableReference' is invalid: %w", err) - } - } - if x.ValueCoding != nil { - if err := x.ValueCoding.Validate(); err != nil { - return fmt.Errorf("field 'valueCoding' is invalid: %w", err) - } - } - if x.ValueContactDetail != nil { - if err := x.ValueContactDetail.Validate(); err != nil { - return fmt.Errorf("field 'valueContactDetail' is invalid: %w", err) - } - } - if x.ValueContactPoint != nil { - if err := x.ValueContactPoint.Validate(); err != nil { - return fmt.Errorf("field 'valueContactPoint' is invalid: %w", err) - } - } - if x.ValueCount != nil { - if err := x.ValueCount.Validate(); err != nil { - return fmt.Errorf("field 'valueCount' is invalid: %w", err) - } - } - if x.ValueDataRequirement != nil { - if err := x.ValueDataRequirement.Validate(); err != nil { - return fmt.Errorf("field 'valueDataRequirement' is invalid: %w", err) - } - } - if x.ValueDate != nil { - if err := ValidateFhirDate(*x.ValueDate); err != nil { - return fmt.Errorf("field 'valueDate' has invalid date format: %w", err) - } - } - if x.ValueDateTime != nil { - if err := ValidateFhirDateTime(*x.ValueDateTime); err != nil { - return fmt.Errorf("field 'valueDateTime' has invalid date-time format: %w", err) - } - } - if x.ValueDecimal != nil { - } - if x.ValueDistance != nil { - if err := x.ValueDistance.Validate(); err != nil { - return fmt.Errorf("field 'valueDistance' is invalid: %w", err) - } - } - if x.ValueDosage != nil { - if err := x.ValueDosage.Validate(); err != nil { - return fmt.Errorf("field 'valueDosage' is invalid: %w", err) - } - } - if x.ValueDuration != nil { - if err := x.ValueDuration.Validate(); err != nil { - return fmt.Errorf("field 'valueDuration' is invalid: %w", err) - } - } - if x.ValueExpression != nil { - if err := x.ValueExpression.Validate(); err != nil { - return fmt.Errorf("field 'valueExpression' is invalid: %w", err) - } - } - if x.ValueExtendedContactDetail != nil { - if err := x.ValueExtendedContactDetail.Validate(); err != nil { - return fmt.Errorf("field 'valueExtendedContactDetail' is invalid: %w", err) - } - } - if x.ValueHumanName != nil { - if err := x.ValueHumanName.Validate(); err != nil { - return fmt.Errorf("field 'valueHumanName' is invalid: %w", err) - } - } - if x.ValueID != nil { - if !rx_TaskInput_ValueID.MatchString(*x.ValueID) { - return fmt.Errorf("field 'valueId' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ValueID) < 1 { - return fmt.Errorf("field 'valueId' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ValueID) > 64 { - return fmt.Errorf("field 'valueId' is too long (max 64 characters)") - } - } - if x.ValueIDentifier != nil { - if err := x.ValueIDentifier.Validate(); err != nil { - return fmt.Errorf("field 'valueIdentifier' is invalid: %w", err) - } - } - if x.ValueInstant != nil { - if err := ValidateFhirDateTime(*x.ValueInstant); err != nil { - return fmt.Errorf("field 'valueInstant' has invalid date-time format: %w", err) - } - } - if x.ValueInteger != nil { - } - if x.ValueInteger64 != nil { - } - if x.ValueMarkdown != nil { - if !rx_TaskInput_ValueMarkdown.MatchString(*x.ValueMarkdown) { - return fmt.Errorf("field 'valueMarkdown' does not match pattern '\\s*(\\S|\\s)*'") - } - } - if x.ValueMeta != nil { - if err := x.ValueMeta.Validate(); err != nil { - return fmt.Errorf("field 'valueMeta' is invalid: %w", err) - } - } - if x.ValueMoney != nil { - if err := x.ValueMoney.Validate(); err != nil { - return fmt.Errorf("field 'valueMoney' is invalid: %w", err) - } - } - if x.ValueOid != nil { - if !rx_TaskInput_ValueOid.MatchString(*x.ValueOid) { - return fmt.Errorf("field 'valueOid' does not match pattern '^urn:oid:[0-2](\\.(0|[1-9][0-9]*))+$'") - } - } - if x.ValueParameterDefinition != nil { - if err := x.ValueParameterDefinition.Validate(); err != nil { - return fmt.Errorf("field 'valueParameterDefinition' is invalid: %w", err) - } - } - if x.ValuePeriod != nil { - if err := x.ValuePeriod.Validate(); err != nil { - return fmt.Errorf("field 'valuePeriod' is invalid: %w", err) - } - } - if x.ValuePositiveInt != nil { - if *x.ValuePositiveInt <= 0.000000 { - return fmt.Errorf("field 'valuePositiveInt' is below exclusive minimum 0.000000") - } - } - if x.ValueQuantity != nil { - if err := x.ValueQuantity.Validate(); err != nil { - return fmt.Errorf("field 'valueQuantity' is invalid: %w", err) - } - } - if x.ValueRange != nil { - if err := x.ValueRange.Validate(); err != nil { - return fmt.Errorf("field 'valueRange' is invalid: %w", err) - } - } - if x.ValueRatio != nil { - if err := x.ValueRatio.Validate(); err != nil { - return fmt.Errorf("field 'valueRatio' is invalid: %w", err) - } - } - if x.ValueRatioRange != nil { - if err := x.ValueRatioRange.Validate(); err != nil { - return fmt.Errorf("field 'valueRatioRange' is invalid: %w", err) - } - } - if x.ValueReference != nil { - if err := x.ValueReference.Validate(); err != nil { - return fmt.Errorf("field 'valueReference' is invalid: %w", err) - } - } - if x.ValueRelatedArtifact != nil { - if err := x.ValueRelatedArtifact.Validate(); err != nil { - return fmt.Errorf("field 'valueRelatedArtifact' is invalid: %w", err) - } - } - if x.ValueSampledData != nil { - if err := x.ValueSampledData.Validate(); err != nil { - return fmt.Errorf("field 'valueSampledData' is invalid: %w", err) - } - } - if x.ValueSignature != nil { - if err := x.ValueSignature.Validate(); err != nil { - return fmt.Errorf("field 'valueSignature' is invalid: %w", err) - } - } - if x.ValueString != nil { - if *x.ValueString == "" { - return fmt.Errorf("field 'valueString' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.ValueTime != nil { - if err := ValidateFhirTime(*x.ValueTime); err != nil { - return fmt.Errorf("field 'valueTime' has invalid time format: %w", err) - } - } - if x.ValueTiming != nil { - if err := x.ValueTiming.Validate(); err != nil { - return fmt.Errorf("field 'valueTiming' is invalid: %w", err) - } - } - if x.ValueTriggerDefinition != nil { - if err := x.ValueTriggerDefinition.Validate(); err != nil { - return fmt.Errorf("field 'valueTriggerDefinition' is invalid: %w", err) - } - } - if x.ValueUnsignedInt != nil { - if *x.ValueUnsignedInt < 0.000000 { - return fmt.Errorf("field 'valueUnsignedInt' is below minimum 0.000000") - } - } - if x.ValueURI != nil { - } - if x.ValueURL != nil { - if utf8.RuneCountInString(*x.ValueURL) < 1 { - return fmt.Errorf("field 'valueUrl' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ValueURL) > 65536 { - return fmt.Errorf("field 'valueUrl' is too long (max 65536 characters)") - } - if err := ValidateFhirURI(*x.ValueURL); err != nil { - return fmt.Errorf("field 'valueUrl' has invalid URI format: %w", err) - } - } - if x.ValueUsageContext != nil { - if err := x.ValueUsageContext.Validate(); err != nil { - return fmt.Errorf("field 'valueUsageContext' is invalid: %w", err) - } - } - if x.ValueUUID != nil { - if err := ValidateFhirUUID(*x.ValueUUID); err != nil { - return fmt.Errorf("field 'valueUuid' has invalid UUID format: %w", err) - } - } - return nil -} - -// Validate validates a TaskOutput struct against its schema constraints. -func (x *TaskOutput) Validate() error { - if x == nil { - return nil - } - if x.XValueBase64Binary != nil { - if err := x.XValueBase64Binary.Validate(); err != nil { - return fmt.Errorf("field '_valueBase64Binary' is invalid: %w", err) - } - } - if x.XValueBoolean != nil { - if err := x.XValueBoolean.Validate(); err != nil { - return fmt.Errorf("field '_valueBoolean' is invalid: %w", err) - } - } - if x.XValueCanonical != nil { - if err := x.XValueCanonical.Validate(); err != nil { - return fmt.Errorf("field '_valueCanonical' is invalid: %w", err) - } - } - if x.XValueCode != nil { - if err := x.XValueCode.Validate(); err != nil { - return fmt.Errorf("field '_valueCode' is invalid: %w", err) - } - } - if x.XValueDate != nil { - if err := x.XValueDate.Validate(); err != nil { - return fmt.Errorf("field '_valueDate' is invalid: %w", err) - } - } - if x.XValueDateTime != nil { - if err := x.XValueDateTime.Validate(); err != nil { - return fmt.Errorf("field '_valueDateTime' is invalid: %w", err) - } - } - if x.XValueDecimal != nil { - if err := x.XValueDecimal.Validate(); err != nil { - return fmt.Errorf("field '_valueDecimal' is invalid: %w", err) - } - } - if x.XValueID != nil { - if err := x.XValueID.Validate(); err != nil { - return fmt.Errorf("field '_valueId' is invalid: %w", err) - } - } - if x.XValueInstant != nil { - if err := x.XValueInstant.Validate(); err != nil { - return fmt.Errorf("field '_valueInstant' is invalid: %w", err) - } - } - if x.XValueInteger != nil { - if err := x.XValueInteger.Validate(); err != nil { - return fmt.Errorf("field '_valueInteger' is invalid: %w", err) - } - } - if x.XValueInteger64 != nil { - if err := x.XValueInteger64.Validate(); err != nil { - return fmt.Errorf("field '_valueInteger64' is invalid: %w", err) - } - } - if x.XValueMarkdown != nil { - if err := x.XValueMarkdown.Validate(); err != nil { - return fmt.Errorf("field '_valueMarkdown' is invalid: %w", err) - } - } - if x.XValueOid != nil { - if err := x.XValueOid.Validate(); err != nil { - return fmt.Errorf("field '_valueOid' is invalid: %w", err) - } - } - if x.XValuePositiveInt != nil { - if err := x.XValuePositiveInt.Validate(); err != nil { - return fmt.Errorf("field '_valuePositiveInt' is invalid: %w", err) - } - } - if x.XValueString != nil { - if err := x.XValueString.Validate(); err != nil { - return fmt.Errorf("field '_valueString' is invalid: %w", err) - } - } - if x.XValueTime != nil { - if err := x.XValueTime.Validate(); err != nil { - return fmt.Errorf("field '_valueTime' is invalid: %w", err) - } - } - if x.XValueUnsignedInt != nil { - if err := x.XValueUnsignedInt.Validate(); err != nil { - return fmt.Errorf("field '_valueUnsignedInt' is invalid: %w", err) - } - } - if x.XValueURI != nil { - if err := x.XValueURI.Validate(); err != nil { - return fmt.Errorf("field '_valueUri' is invalid: %w", err) - } - } - if x.XValueURL != nil { - if err := x.XValueURL.Validate(); err != nil { - return fmt.Errorf("field '_valueUrl' is invalid: %w", err) - } - } - if x.XValueUUID != nil { - if err := x.XValueUUID.Validate(); err != nil { - return fmt.Errorf("field '_valueUuid' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "TaskOutput" { - return fmt.Errorf("field 'resourceType' must be exactly 'TaskOutput'") - } - } - if x.Type == nil { - return fmt.Errorf("required field 'type' is missing") - } - if x.Type != nil { - if err := x.Type.Validate(); err != nil { - return fmt.Errorf("field 'type' is invalid: %w", err) - } - } - if x.ValueAddress != nil { - if err := x.ValueAddress.Validate(); err != nil { - return fmt.Errorf("field 'valueAddress' is invalid: %w", err) - } - } - if x.ValueAge != nil { - if err := x.ValueAge.Validate(); err != nil { - return fmt.Errorf("field 'valueAge' is invalid: %w", err) - } - } - if x.ValueAnnotation != nil { - if err := x.ValueAnnotation.Validate(); err != nil { - return fmt.Errorf("field 'valueAnnotation' is invalid: %w", err) - } - } - if x.ValueAttachment != nil { - if err := x.ValueAttachment.Validate(); err != nil { - return fmt.Errorf("field 'valueAttachment' is invalid: %w", err) - } - } - if x.ValueAvailability != nil { - if err := x.ValueAvailability.Validate(); err != nil { - return fmt.Errorf("field 'valueAvailability' is invalid: %w", err) - } - } - if x.ValueBase64Binary != nil { - if err := ValidateFhirBinary(*x.ValueBase64Binary); err != nil { - return fmt.Errorf("field 'valueBase64Binary' has invalid binary format: %w", err) - } - } - if x.ValueBoolean != nil { - } - if x.ValueCanonical != nil { - } - if x.ValueCode != nil { - if !rx_TaskOutput_ValueCode.MatchString(*x.ValueCode) { - return fmt.Errorf("field 'valueCode' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.ValueCodeableConcept != nil { - if err := x.ValueCodeableConcept.Validate(); err != nil { - return fmt.Errorf("field 'valueCodeableConcept' is invalid: %w", err) - } - } - if x.ValueCodeableReference != nil { - if err := x.ValueCodeableReference.Validate(); err != nil { - return fmt.Errorf("field 'valueCodeableReference' is invalid: %w", err) - } - } - if x.ValueCoding != nil { - if err := x.ValueCoding.Validate(); err != nil { - return fmt.Errorf("field 'valueCoding' is invalid: %w", err) - } - } - if x.ValueContactDetail != nil { - if err := x.ValueContactDetail.Validate(); err != nil { - return fmt.Errorf("field 'valueContactDetail' is invalid: %w", err) - } - } - if x.ValueContactPoint != nil { - if err := x.ValueContactPoint.Validate(); err != nil { - return fmt.Errorf("field 'valueContactPoint' is invalid: %w", err) - } - } - if x.ValueCount != nil { - if err := x.ValueCount.Validate(); err != nil { - return fmt.Errorf("field 'valueCount' is invalid: %w", err) - } - } - if x.ValueDataRequirement != nil { - if err := x.ValueDataRequirement.Validate(); err != nil { - return fmt.Errorf("field 'valueDataRequirement' is invalid: %w", err) - } - } - if x.ValueDate != nil { - if err := ValidateFhirDate(*x.ValueDate); err != nil { - return fmt.Errorf("field 'valueDate' has invalid date format: %w", err) - } - } - if x.ValueDateTime != nil { - if err := ValidateFhirDateTime(*x.ValueDateTime); err != nil { - return fmt.Errorf("field 'valueDateTime' has invalid date-time format: %w", err) - } - } - if x.ValueDecimal != nil { - } - if x.ValueDistance != nil { - if err := x.ValueDistance.Validate(); err != nil { - return fmt.Errorf("field 'valueDistance' is invalid: %w", err) - } - } - if x.ValueDosage != nil { - if err := x.ValueDosage.Validate(); err != nil { - return fmt.Errorf("field 'valueDosage' is invalid: %w", err) - } - } - if x.ValueDuration != nil { - if err := x.ValueDuration.Validate(); err != nil { - return fmt.Errorf("field 'valueDuration' is invalid: %w", err) - } - } - if x.ValueExpression != nil { - if err := x.ValueExpression.Validate(); err != nil { - return fmt.Errorf("field 'valueExpression' is invalid: %w", err) - } - } - if x.ValueExtendedContactDetail != nil { - if err := x.ValueExtendedContactDetail.Validate(); err != nil { - return fmt.Errorf("field 'valueExtendedContactDetail' is invalid: %w", err) - } - } - if x.ValueHumanName != nil { - if err := x.ValueHumanName.Validate(); err != nil { - return fmt.Errorf("field 'valueHumanName' is invalid: %w", err) - } - } - if x.ValueID != nil { - if !rx_TaskOutput_ValueID.MatchString(*x.ValueID) { - return fmt.Errorf("field 'valueId' does not match pattern '^[A-Za-z0-9\\-.]+$'") - } - if utf8.RuneCountInString(*x.ValueID) < 1 { - return fmt.Errorf("field 'valueId' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ValueID) > 64 { - return fmt.Errorf("field 'valueId' is too long (max 64 characters)") - } - } - if x.ValueIDentifier != nil { - if err := x.ValueIDentifier.Validate(); err != nil { - return fmt.Errorf("field 'valueIdentifier' is invalid: %w", err) - } - } - if x.ValueInstant != nil { - if err := ValidateFhirDateTime(*x.ValueInstant); err != nil { - return fmt.Errorf("field 'valueInstant' has invalid date-time format: %w", err) - } - } - if x.ValueInteger != nil { - } - if x.ValueInteger64 != nil { - } - if x.ValueMarkdown != nil { - if !rx_TaskOutput_ValueMarkdown.MatchString(*x.ValueMarkdown) { - return fmt.Errorf("field 'valueMarkdown' does not match pattern '\\s*(\\S|\\s)*'") - } - } - if x.ValueMeta != nil { - if err := x.ValueMeta.Validate(); err != nil { - return fmt.Errorf("field 'valueMeta' is invalid: %w", err) - } - } - if x.ValueMoney != nil { - if err := x.ValueMoney.Validate(); err != nil { - return fmt.Errorf("field 'valueMoney' is invalid: %w", err) - } - } - if x.ValueOid != nil { - if !rx_TaskOutput_ValueOid.MatchString(*x.ValueOid) { - return fmt.Errorf("field 'valueOid' does not match pattern '^urn:oid:[0-2](\\.(0|[1-9][0-9]*))+$'") - } - } - if x.ValueParameterDefinition != nil { - if err := x.ValueParameterDefinition.Validate(); err != nil { - return fmt.Errorf("field 'valueParameterDefinition' is invalid: %w", err) - } - } - if x.ValuePeriod != nil { - if err := x.ValuePeriod.Validate(); err != nil { - return fmt.Errorf("field 'valuePeriod' is invalid: %w", err) - } - } - if x.ValuePositiveInt != nil { - if *x.ValuePositiveInt <= 0.000000 { - return fmt.Errorf("field 'valuePositiveInt' is below exclusive minimum 0.000000") - } - } - if x.ValueQuantity != nil { - if err := x.ValueQuantity.Validate(); err != nil { - return fmt.Errorf("field 'valueQuantity' is invalid: %w", err) - } - } - if x.ValueRange != nil { - if err := x.ValueRange.Validate(); err != nil { - return fmt.Errorf("field 'valueRange' is invalid: %w", err) - } - } - if x.ValueRatio != nil { - if err := x.ValueRatio.Validate(); err != nil { - return fmt.Errorf("field 'valueRatio' is invalid: %w", err) - } - } - if x.ValueRatioRange != nil { - if err := x.ValueRatioRange.Validate(); err != nil { - return fmt.Errorf("field 'valueRatioRange' is invalid: %w", err) - } - } - if x.ValueReference != nil { - if err := x.ValueReference.Validate(); err != nil { - return fmt.Errorf("field 'valueReference' is invalid: %w", err) - } - } - if x.ValueRelatedArtifact != nil { - if err := x.ValueRelatedArtifact.Validate(); err != nil { - return fmt.Errorf("field 'valueRelatedArtifact' is invalid: %w", err) - } - } - if x.ValueSampledData != nil { - if err := x.ValueSampledData.Validate(); err != nil { - return fmt.Errorf("field 'valueSampledData' is invalid: %w", err) - } - } - if x.ValueSignature != nil { - if err := x.ValueSignature.Validate(); err != nil { - return fmt.Errorf("field 'valueSignature' is invalid: %w", err) - } - } - if x.ValueString != nil { - if *x.ValueString == "" { - return fmt.Errorf("field 'valueString' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.ValueTime != nil { - if err := ValidateFhirTime(*x.ValueTime); err != nil { - return fmt.Errorf("field 'valueTime' has invalid time format: %w", err) - } - } - if x.ValueTiming != nil { - if err := x.ValueTiming.Validate(); err != nil { - return fmt.Errorf("field 'valueTiming' is invalid: %w", err) - } - } - if x.ValueTriggerDefinition != nil { - if err := x.ValueTriggerDefinition.Validate(); err != nil { - return fmt.Errorf("field 'valueTriggerDefinition' is invalid: %w", err) - } - } - if x.ValueUnsignedInt != nil { - if *x.ValueUnsignedInt < 0.000000 { - return fmt.Errorf("field 'valueUnsignedInt' is below minimum 0.000000") - } - } - if x.ValueURI != nil { - } - if x.ValueURL != nil { - if utf8.RuneCountInString(*x.ValueURL) < 1 { - return fmt.Errorf("field 'valueUrl' is too short (min 1 characters)") - } - if utf8.RuneCountInString(*x.ValueURL) > 65536 { - return fmt.Errorf("field 'valueUrl' is too long (max 65536 characters)") - } - if err := ValidateFhirURI(*x.ValueURL); err != nil { - return fmt.Errorf("field 'valueUrl' has invalid URI format: %w", err) - } - } - if x.ValueUsageContext != nil { - if err := x.ValueUsageContext.Validate(); err != nil { - return fmt.Errorf("field 'valueUsageContext' is invalid: %w", err) - } - } - if x.ValueUUID != nil { - if err := ValidateFhirUUID(*x.ValueUUID); err != nil { - return fmt.Errorf("field 'valueUuid' has invalid UUID format: %w", err) - } - } - return nil -} - -// Validate validates a TaskPerformer struct against its schema constraints. -func (x *TaskPerformer) Validate() error { - if x == nil { - return nil - } - if x.Actor == nil { - return fmt.Errorf("required field 'actor' is missing") - } - if x.Actor != nil { - if err := x.Actor.Validate(); err != nil { - return fmt.Errorf("field 'actor' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Function != nil { - if err := x.Function.Validate(); err != nil { - return fmt.Errorf("field 'function' is invalid: %w", err) - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ResourceType != nil { - if *x.ResourceType != "TaskPerformer" { - return fmt.Errorf("field 'resourceType' must be exactly 'TaskPerformer'") - } - } - return nil -} - -// Validate validates a TaskRestriction struct against its schema constraints. -func (x *TaskRestriction) Validate() error { - if x == nil { - return nil - } - if x.XRepetitions != nil { - if err := x.XRepetitions.Validate(); err != nil { - return fmt.Errorf("field '_repetitions' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Period != nil { - if err := x.Period.Validate(); err != nil { - return fmt.Errorf("field 'period' is invalid: %w", err) - } - } - if x.Recipient != nil { - for i, item := range x.Recipient { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'recipient[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Repetitions != nil { - if *x.Repetitions <= 0.000000 { - return fmt.Errorf("field 'repetitions' is below exclusive minimum 0.000000") - } - } - if x.ResourceType != nil { - if *x.ResourceType != "TaskRestriction" { - return fmt.Errorf("field 'resourceType' must be exactly 'TaskRestriction'") - } - } - return nil -} - -// Validate validates a Timing struct against its schema constraints. -func (x *Timing) Validate() error { - if x == nil { - return nil - } - if x.XEvent != nil { - for i, item := range x.XEvent { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field '_event[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Code != nil { - if err := x.Code.Validate(); err != nil { - return fmt.Errorf("field 'code' is invalid: %w", err) - } - } - if x.Event != nil { - for i, item := range x.Event { - if err := ValidateFhirDateTime(item); err != nil { - return fmt.Errorf("field 'event[%d]' has invalid date-time format: %w", i, err) - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ModifierExtension != nil { - for i, item := range x.ModifierExtension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Repeat != nil { - if err := x.Repeat.Validate(); err != nil { - return fmt.Errorf("field 'repeat' is invalid: %w", err) - } - } - if x.ResourceType != nil { - if *x.ResourceType != "Timing" { - return fmt.Errorf("field 'resourceType' must be exactly 'Timing'") - } - } - return nil -} - -// Validate validates a TimingRepeat struct against its schema constraints. -func (x *TimingRepeat) Validate() error { - if x == nil { - return nil - } - if x.XCount != nil { - if err := x.XCount.Validate(); err != nil { - return fmt.Errorf("field '_count' is invalid: %w", err) - } - } - if x.XCountMax != nil { - if err := x.XCountMax.Validate(); err != nil { - return fmt.Errorf("field '_countMax' is invalid: %w", err) - } - } - if x.XDayOfWeek != nil { - for i, item := range x.XDayOfWeek { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field '_dayOfWeek[%d]' is invalid: %w", i, err) - } - } - } - } - if x.XDuration != nil { - if err := x.XDuration.Validate(); err != nil { - return fmt.Errorf("field '_duration' is invalid: %w", err) - } - } - if x.XDurationMax != nil { - if err := x.XDurationMax.Validate(); err != nil { - return fmt.Errorf("field '_durationMax' is invalid: %w", err) - } - } - if x.XDurationUnit != nil { - if err := x.XDurationUnit.Validate(); err != nil { - return fmt.Errorf("field '_durationUnit' is invalid: %w", err) - } - } - if x.XFrequency != nil { - if err := x.XFrequency.Validate(); err != nil { - return fmt.Errorf("field '_frequency' is invalid: %w", err) - } - } - if x.XFrequencyMax != nil { - if err := x.XFrequencyMax.Validate(); err != nil { - return fmt.Errorf("field '_frequencyMax' is invalid: %w", err) - } - } - if x.XOffset != nil { - if err := x.XOffset.Validate(); err != nil { - return fmt.Errorf("field '_offset' is invalid: %w", err) - } - } - if x.XPeriod != nil { - if err := x.XPeriod.Validate(); err != nil { - return fmt.Errorf("field '_period' is invalid: %w", err) - } - } - if x.XPeriodMax != nil { - if err := x.XPeriodMax.Validate(); err != nil { - return fmt.Errorf("field '_periodMax' is invalid: %w", err) - } - } - if x.XPeriodUnit != nil { - if err := x.XPeriodUnit.Validate(); err != nil { - return fmt.Errorf("field '_periodUnit' is invalid: %w", err) - } - } - if x.XTimeOfDay != nil { - for i, item := range x.XTimeOfDay { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field '_timeOfDay[%d]' is invalid: %w", i, err) - } - } - } - } - if x.XWhen != nil { - for i, item := range x.XWhen { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field '_when[%d]' is invalid: %w", i, err) - } - } - } - } - if x.BoundsDuration != nil { - if err := x.BoundsDuration.Validate(); err != nil { - return fmt.Errorf("field 'boundsDuration' is invalid: %w", err) - } - } - if x.BoundsPeriod != nil { - if err := x.BoundsPeriod.Validate(); err != nil { - return fmt.Errorf("field 'boundsPeriod' is invalid: %w", err) - } - } - if x.BoundsRange != nil { - if err := x.BoundsRange.Validate(); err != nil { - return fmt.Errorf("field 'boundsRange' is invalid: %w", err) - } - } - if x.Count != nil { - if *x.Count <= 0.000000 { - return fmt.Errorf("field 'count' is below exclusive minimum 0.000000") - } - } - if x.CountMax != nil { - if *x.CountMax <= 0.000000 { - return fmt.Errorf("field 'countMax' is below exclusive minimum 0.000000") - } - } - if x.DayOfWeek != nil { - for i, item := range x.DayOfWeek { - if !rx_TimingRepeat_DayOfWeek_items.MatchString(item) { - return fmt.Errorf("field 'dayOfWeek[%d]' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'", i) - } - } - } - if x.Duration != nil { - } - if x.DurationMax != nil { - } - if x.DurationUnit != nil { - if !rx_TimingRepeat_DurationUnit.MatchString(*x.DurationUnit) { - return fmt.Errorf("field 'durationUnit' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Frequency != nil { - if *x.Frequency <= 0.000000 { - return fmt.Errorf("field 'frequency' is below exclusive minimum 0.000000") - } - } - if x.FrequencyMax != nil { - if *x.FrequencyMax <= 0.000000 { - return fmt.Errorf("field 'frequencyMax' is below exclusive minimum 0.000000") - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Offset != nil { - if *x.Offset < 0.000000 { - return fmt.Errorf("field 'offset' is below minimum 0.000000") - } - } - if x.Period != nil { - } - if x.PeriodMax != nil { - } - if x.PeriodUnit != nil { - if !rx_TimingRepeat_PeriodUnit.MatchString(*x.PeriodUnit) { - return fmt.Errorf("field 'periodUnit' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - if x.ResourceType != nil { - if *x.ResourceType != "TimingRepeat" { - return fmt.Errorf("field 'resourceType' must be exactly 'TimingRepeat'") - } - } - if x.TimeOfDay != nil { - for i, item := range x.TimeOfDay { - if err := ValidateFhirTime(item); err != nil { - return fmt.Errorf("field 'timeOfDay[%d]' has invalid time format: %w", i, err) - } - } - } - if x.When != nil { - for i, item := range x.When { - if !rx_TimingRepeat_When_items.MatchString(item) { - return fmt.Errorf("field 'when[%d]' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'", i) - } - } - } - return nil -} - -// Validate validates a TriggerDefinition struct against its schema constraints. -func (x *TriggerDefinition) Validate() error { - if x == nil { - return nil - } - if x.XName != nil { - if err := x.XName.Validate(); err != nil { - return fmt.Errorf("field '_name' is invalid: %w", err) - } - } - if x.XSubscriptionTopic != nil { - if err := x.XSubscriptionTopic.Validate(); err != nil { - return fmt.Errorf("field '_subscriptionTopic' is invalid: %w", err) - } - } - if x.XTimingDate != nil { - if err := x.XTimingDate.Validate(); err != nil { - return fmt.Errorf("field '_timingDate' is invalid: %w", err) - } - } - if x.XTimingDateTime != nil { - if err := x.XTimingDateTime.Validate(); err != nil { - return fmt.Errorf("field '_timingDateTime' is invalid: %w", err) - } - } - if x.XType != nil { - if err := x.XType.Validate(); err != nil { - return fmt.Errorf("field '_type' is invalid: %w", err) - } - } - if x.Code != nil { - if err := x.Code.Validate(); err != nil { - return fmt.Errorf("field 'code' is invalid: %w", err) - } - } - if x.Condition != nil { - if err := x.Condition.Validate(); err != nil { - return fmt.Errorf("field 'condition' is invalid: %w", err) - } - } - if x.Data != nil { - for i, item := range x.Data { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'data[%d]' is invalid: %w", i, err) - } - } - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.Name != nil { - if *x.Name == "" { - return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.ResourceType != nil { - if *x.ResourceType != "TriggerDefinition" { - return fmt.Errorf("field 'resourceType' must be exactly 'TriggerDefinition'") - } - } - if x.SubscriptionTopic != nil { - } - if x.TimingDate != nil { - if err := ValidateFhirDate(*x.TimingDate); err != nil { - return fmt.Errorf("field 'timingDate' has invalid date format: %w", err) - } - } - if x.TimingDateTime != nil { - if err := ValidateFhirDateTime(*x.TimingDateTime); err != nil { - return fmt.Errorf("field 'timingDateTime' has invalid date-time format: %w", err) - } - } - if x.TimingReference != nil { - if err := x.TimingReference.Validate(); err != nil { - return fmt.Errorf("field 'timingReference' is invalid: %w", err) - } - } - if x.TimingTiming != nil { - if err := x.TimingTiming.Validate(); err != nil { - return fmt.Errorf("field 'timingTiming' is invalid: %w", err) - } - } - if x.Type != nil { - if !rx_TriggerDefinition_Type.MatchString(*x.Type) { - return fmt.Errorf("field 'type' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") - } - } - return nil -} - -// Validate validates a UsageContext struct against its schema constraints. -func (x *UsageContext) Validate() error { - if x == nil { - return nil - } - if x.Code == nil { - return fmt.Errorf("required field 'code' is missing") - } - if x.Code != nil { - if err := x.Code.Validate(); err != nil { - return fmt.Errorf("field 'code' is invalid: %w", err) - } - } - if x.Extension != nil { - for i, item := range x.Extension { - if item != nil { - if err := item.Validate(); err != nil { - return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) - } - } - } - } - if x.ID != nil { - if *x.ID == "" { - return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") - } - } - if x.Links != nil { - } - if x.ResourceType != nil { - if *x.ResourceType != "UsageContext" { - return fmt.Errorf("field 'resourceType' must be exactly 'UsageContext'") - } - } - if x.ValueCodeableConcept != nil { - if err := x.ValueCodeableConcept.Validate(); err != nil { - return fmt.Errorf("field 'valueCodeableConcept' is invalid: %w", err) - } - } - if x.ValueQuantity != nil { - if err := x.ValueQuantity.Validate(); err != nil { - return fmt.Errorf("field 'valueQuantity' is invalid: %w", err) - } - } - if x.ValueRange != nil { - if err := x.ValueRange.Validate(); err != nil { - return fmt.Errorf("field 'valueRange' is invalid: %w", err) - } - } - if x.ValueReference != nil { - if err := x.ValueReference.Validate(); err != nil { - return fmt.Errorf("field 'valueReference' is invalid: %w", err) - } - } - return nil -} diff --git a/internal/graphqlapi/resolver.go b/internal/graphqlapi/resolver.go deleted file mode 100644 index b03c807..0000000 --- a/internal/graphqlapi/resolver.go +++ /dev/null @@ -1,13 +0,0 @@ -package graphqlapi - -import "github.com/calypr/loom/internal/dataframebuilder" - -type Resolver struct { - service *dataframebuilder.Service -} - -type ResolverConfig = dataframebuilder.Config - -func NewResolver(cfg ResolverConfig) *Resolver { - return &Resolver{service: dataframebuilder.NewService(cfg)} -} diff --git a/internal/schemaidentity/identity.go b/internal/graphschema/identity.go similarity index 97% rename from internal/schemaidentity/identity.go rename to internal/graphschema/identity.go index 807be98..7499f58 100644 --- a/internal/schemaidentity/identity.go +++ b/internal/graphschema/identity.go @@ -1,8 +1,8 @@ -// Package schemaidentity identifies the graph schema compiled into this Loom +// Package graphschema identifies the graph schema compiled into this Loom // process. It intentionally does not decide whether a dataset is compatible // with that schema; dataset-generation persistence and comparison belong to a // later layer. -package schemaidentity +package graphschema import ( "bytes" @@ -16,7 +16,7 @@ import ( "sort" "strings" - "github.com/calypr/loom/internal/fhirschema" + "github.com/calypr/loom/fhirschema" ) var ( diff --git a/internal/schemaidentity/identity_test.go b/internal/graphschema/identity_test.go similarity index 98% rename from internal/schemaidentity/identity_test.go rename to internal/graphschema/identity_test.go index e2d389f..5287cc2 100644 --- a/internal/schemaidentity/identity_test.go +++ b/internal/graphschema/identity_test.go @@ -1,4 +1,4 @@ -package schemaidentity +package graphschema import ( "crypto/sha256" @@ -11,7 +11,7 @@ import ( "sort" "testing" - "github.com/calypr/loom/internal/fhirschema" + "github.com/calypr/loom/fhirschema" ) func TestLoadCheckedInGraphFHIRSchema(t *testing.T) { diff --git a/internal/httpapi/doc.go b/internal/httpapi/doc.go new file mode 100644 index 0000000..479ccdc --- /dev/null +++ b/internal/httpapi/doc.go @@ -0,0 +1,2 @@ +// Package httpapi owns the HTTP API surface and import ingest orchestration. +package httpapi diff --git a/internal/api/http_test.go b/internal/httpapi/http_test.go similarity index 99% rename from internal/api/http_test.go rename to internal/httpapi/http_test.go index ba97d9d..cd4a0f3 100644 --- a/internal/api/http_test.go +++ b/internal/httpapi/http_test.go @@ -1,4 +1,4 @@ -package api +package httpapi import ( "bytes" diff --git a/internal/api/import_route.go b/internal/httpapi/import_route.go similarity index 99% rename from internal/api/import_route.go rename to internal/httpapi/import_route.go index 258147a..1c41bcf 100644 --- a/internal/api/import_route.go +++ b/internal/httpapi/import_route.go @@ -1,4 +1,4 @@ -package api +package httpapi import ( "fmt" diff --git a/internal/api/middleware.go b/internal/httpapi/middleware.go similarity index 99% rename from internal/api/middleware.go rename to internal/httpapi/middleware.go index f3c0588..46e6e3f 100644 --- a/internal/api/middleware.go +++ b/internal/httpapi/middleware.go @@ -1,4 +1,4 @@ -package api +package httpapi import ( "errors" diff --git a/internal/api/routes.go b/internal/httpapi/routes.go similarity index 98% rename from internal/api/routes.go rename to internal/httpapi/routes.go index 718b81e..1e250d3 100644 --- a/internal/api/routes.go +++ b/internal/httpapi/routes.go @@ -1,4 +1,4 @@ -package api +package httpapi import ( "github.com/gofiber/fiber/v3" diff --git a/internal/api/server.go b/internal/httpapi/server.go similarity index 99% rename from internal/api/server.go rename to internal/httpapi/server.go index 9de9918..b626d91 100644 --- a/internal/api/server.go +++ b/internal/httpapi/server.go @@ -1,4 +1,4 @@ -package api +package httpapi import ( "errors" diff --git a/internal/api/service.go b/internal/httpapi/service.go similarity index 99% rename from internal/api/service.go rename to internal/httpapi/service.go index db59a71..70038a2 100644 --- a/internal/api/service.go +++ b/internal/httpapi/service.go @@ -1,4 +1,4 @@ -package api +package httpapi import ( "context" diff --git a/internal/api/service_test.go b/internal/httpapi/service_test.go similarity index 99% rename from internal/api/service_test.go rename to internal/httpapi/service_test.go index f8a0b19..c47181c 100644 --- a/internal/api/service_test.go +++ b/internal/httpapi/service_test.go @@ -1,4 +1,4 @@ -package api +package httpapi import ( "context" diff --git a/internal/ingest/backend.go b/internal/ingest/backend.go index e84fbfc..aec462e 100644 --- a/internal/ingest/backend.go +++ b/internal/ingest/backend.go @@ -4,7 +4,7 @@ import ( "context" "encoding/json" - "github.com/calypr/loom/internal/datasetstore" + datasetarango "github.com/calypr/loom/internal/dataset/arango" arangostore "github.com/calypr/loom/internal/store/arango" ) @@ -100,7 +100,7 @@ func bootstrapSpecWithReporter(resourceTypes []string, truncate bool, reporter E // caller explicitly selects immutable dataset-generation mode. func lifecycleBootstrapSpecWithReporter(reporter EventSink) arangostore.BootstrapSpec { return arangostore.BootstrapSpec{ - Collections: datasetstore.CollectionSpecs(), + Collections: datasetarango.CollectionSpecs(), Reporter: func(event string, fields map[string]any) { emitEvent(reporter, event, fields) }, diff --git a/internal/ingest/bench_test.go b/internal/ingest/bench_test.go index 8ad4580..7606a0d 100644 --- a/internal/ingest/bench_test.go +++ b/internal/ingest/bench_test.go @@ -9,7 +9,7 @@ import ( "testing" "github.com/calypr/loom/internal/catalog" - "github.com/calypr/loom/internal/fhir" + fhir "github.com/calypr/loom/fhirstructs" jsgarango "github.com/bmeg/jsonschemagraph/arango" "github.com/bmeg/jsonschemagraph/graph" diff --git a/internal/ingest/files_test.go b/internal/ingest/files_test.go index f12096e..17b91ff 100644 --- a/internal/ingest/files_test.go +++ b/internal/ingest/files_test.go @@ -2,6 +2,18 @@ package ingest import "testing" +func TestNormalizeLoadOptions(t *testing.T) { + got := normalizeLoadOptions(LoadOptions{}) + if got.BatchSize != 5000 || got.ProgressEvery != 50000 || got.WriterCount != 8 || got.WriteAPI != "import" { + t.Fatalf("normalizeLoadOptions defaults = %+v", got) + } + + got = normalizeLoadOptions(LoadOptions{BatchSize: 13, ProgressEvery: 17, WriterCount: 3, WriteAPI: "documents"}) + if got.BatchSize != 13 || got.ProgressEvery != 17 || got.WriterCount != 3 || got.WriteAPI != "documents" { + t.Fatalf("normalizeLoadOptions overwrote explicit values: %+v", got) + } +} + func TestResourceTypeFromPath(t *testing.T) { cases := map[string]string{ "/tmp/META/Patient.ndjson": "Patient", diff --git a/internal/ingest/generated_load.go b/internal/ingest/generated_load.go index 722d823..b71793a 100644 --- a/internal/ingest/generated_load.go +++ b/internal/ingest/generated_load.go @@ -5,7 +5,7 @@ import ( "fmt" "time" - "github.com/calypr/loom/internal/fhir" + fhir "github.com/calypr/loom/fhirstructs" jsgarango "github.com/bmeg/jsonschemagraph/arango" "github.com/bytedance/sonic" diff --git a/internal/ingest/generated_load_test.go b/internal/ingest/generated_load_test.go index 581f7c2..c18cdaa 100644 --- a/internal/ingest/generated_load_test.go +++ b/internal/ingest/generated_load_test.go @@ -4,7 +4,7 @@ import ( "encoding/json" "testing" - "github.com/calypr/loom/internal/fhir" + fhir "github.com/calypr/loom/fhirstructs" ) func TestGeneratedLoadCapabilityFallsBackForSchemaOnlyRoots(t *testing.T) { diff --git a/internal/ingest/generation_load.go b/internal/ingest/generation_load.go index 3892fb9..6119276 100644 --- a/internal/ingest/generation_load.go +++ b/internal/ingest/generation_load.go @@ -14,8 +14,8 @@ import ( "github.com/calypr/loom/internal/catalog" "github.com/calypr/loom/internal/dataset" - "github.com/calypr/loom/internal/datasetstore" - "github.com/calypr/loom/internal/schemaidentity" + datasetarango "github.com/calypr/loom/internal/dataset/arango" + "github.com/calypr/loom/internal/graphschema" arangostore "github.com/calypr/loom/internal/store/arango" "github.com/bmeg/jsonschemagraph/graph" @@ -32,18 +32,7 @@ func Load(ctx context.Context, opts LoadOptions) (LoadSummary, error) { } func loadGeneration(ctx context.Context, opts LoadOptions) (summary LoadSummary, err error) { - if opts.BatchSize <= 0 { - opts.BatchSize = 5000 - } - if opts.ProgressEvery <= 0 { - opts.ProgressEvery = 50000 - } - if opts.WriterCount <= 0 { - opts.WriterCount = 8 - } - if opts.WriteAPI == "" { - opts.WriteAPI = "import" - } + opts = normalizeLoadOptions(opts) start := time.Now() files, err := DiscoverNDJSON(opts.MetaDir) @@ -64,7 +53,7 @@ func loadGeneration(ctx context.Context, opts LoadOptions) (summary LoadSummary, if err != nil { return summary, err } - schemaIdentity, err := schemaidentity.Load(opts.Schema) + schemaIdentity, err := graphschema.Load(opts.Schema) if err != nil { return summary, err } @@ -153,7 +142,7 @@ func loadGeneration(ctx context.Context, opts LoadOptions) (summary LoadSummary, } summary.StageSeconds["bootstrap"] = time.Since(bootstrapStart).Seconds() - lifecycleStore, err := datasetstore.New(client) + lifecycleStore, err := datasetarango.New(client) if err != nil { return summary, err } diff --git a/internal/ingest/generation_load_test.go b/internal/ingest/generation_load_test.go index 35c7f18..942b6d2 100644 --- a/internal/ingest/generation_load_test.go +++ b/internal/ingest/generation_load_test.go @@ -10,7 +10,7 @@ import ( "github.com/calypr/loom/internal/catalog" "github.com/calypr/loom/internal/dataset" - "github.com/calypr/loom/internal/schemaidentity" + "github.com/calypr/loom/internal/graphschema" arangostore "github.com/calypr/loom/internal/store/arango" ) @@ -27,38 +27,38 @@ func TestNewGenerationLoadPlanRejectsUnsafeOrIncompleteInputs(t *testing.T) { } tests := []struct { - name string - opts LoadOptions + name string + opts LoadOptions files []string - want error + want error }{ { - name: "invalid dataset reference", - opts: LoadOptions{MetaDir: dir, Project: "project-a", Dataset: &dataset.DatasetRef{Project: "project-a"}}, + name: "invalid dataset reference", + opts: LoadOptions{MetaDir: dir, Project: "project-a", Dataset: &dataset.DatasetRef{Project: "project-a"}}, files: []string{file}, want: dataset.ErrInvalidDatasetRef, }, { - name: "project mismatch", - opts: LoadOptions{MetaDir: dir, Project: "project-b", Dataset: &validRef}, + name: "project mismatch", + opts: LoadOptions{MetaDir: dir, Project: "project-b", Dataset: &validRef}, files: []string{file}, want: ErrGenerationDatasetProjectMismatch, }, { - name: "truncate forbidden", - opts: LoadOptions{MetaDir: dir, Project: "project-a", Dataset: &validRef, Truncate: true}, + name: "truncate forbidden", + opts: LoadOptions{MetaDir: dir, Project: "project-a", Dataset: &validRef, Truncate: true}, files: []string{file}, want: ErrGenerationLoadTruncateForbidden, }, { - name: "file is not directory", - opts: LoadOptions{MetaDir: file, Project: "project-a", Dataset: &validRef}, + name: "file is not directory", + opts: LoadOptions{MetaDir: file, Project: "project-a", Dataset: &validRef}, files: []string{file}, want: ErrGenerationLoadRequiresDirectory, }, { - name: "empty staged directory", - opts: LoadOptions{MetaDir: t.TempDir(), Project: "project-a", Dataset: &validRef}, + name: "empty staged directory", + opts: LoadOptions{MetaDir: t.TempDir(), Project: "project-a", Dataset: &validRef}, files: nil, want: ErrGenerationLoadRequiresFiles, }, @@ -107,11 +107,11 @@ func TestGenerationLoadPreflightRunsBeforeOptionRejectionOrBackend(t *testing.T) } var events []string summary, err := Load(context.Background(), LoadOptions{ - Schema: repoPath(t, "schemas", "graph-fhir.json"), - MetaDir: dir, - Project: ref.Project, - Dataset: &ref, - Truncate: true, // would be rejected only after preflight succeeds. + Schema: repoPath(t, "schemas", "graph-fhir.json"), + MetaDir: dir, + Project: ref.Project, + Dataset: &ref, + Truncate: true, // would be rejected only after preflight succeeds. ConnectionOptions: arangostore.ConnectionOptions{ URL: "http://127.0.0.1:1", Database: "generation_preflight_must_not_connect", @@ -193,9 +193,9 @@ func TestSortedGenerationCatalogKeysKeepFullIdentityDistinct(t *testing.T) { } } -func loadGenerationSchemaIdentity(t *testing.T) schemaidentity.Identity { +func loadGenerationSchemaIdentity(t *testing.T) graphschema.Identity { t.Helper() - identity, err := schemaidentity.Load(repoPath(t, "schemas", "graph-fhir.json")) + identity, err := graphschema.Load(repoPath(t, "schemas", "graph-fhir.json")) if err != nil { t.Fatalf("load schema identity: %v", err) } diff --git a/internal/ingest/load.go b/internal/ingest/load.go index 186e9c5..9cf2ab6 100644 --- a/internal/ingest/load.go +++ b/internal/ingest/load.go @@ -15,7 +15,7 @@ import ( "github.com/calypr/loom/internal/catalog" "github.com/calypr/loom/internal/dataset" - "github.com/calypr/loom/internal/schemaidentity" + "github.com/calypr/loom/internal/graphschema" arangostore "github.com/calypr/loom/internal/store/arango" "github.com/bmeg/jsonschema/v6" @@ -63,13 +63,33 @@ type LoadSummary struct { // SchemaIdentity is the exact configured graph-schema evidence used for // this load. It remains nil when Loom cannot load the configured schema, so // an early failure never looks like a successful schema observation. - SchemaIdentity *schemaidentity.Identity `json:"schema_identity,omitempty"` + SchemaIdentity *graphschema.Identity `json:"schema_identity,omitempty"` // Dataset is the immutable target when this was a generation load. It is // present even on a failed generation load so callers can identify the // inactive manifest that needs operational inspection. Dataset *dataset.DatasetRef `json:"dataset,omitempty"` } +// normalizeLoadOptions applies the operational defaults shared by both loader +// modes. The immutable-generation loader deliberately has a different write +// lifecycle, but both modes must agree on batching, progress, concurrency, and +// the Arango write API before any input is examined. +func normalizeLoadOptions(opts LoadOptions) LoadOptions { + if opts.BatchSize <= 0 { + opts.BatchSize = 5000 + } + if opts.ProgressEvery <= 0 { + opts.ProgressEvery = 50000 + } + if opts.WriterCount <= 0 { + opts.WriterCount = 8 + } + if opts.WriteAPI == "" { + opts.WriteAPI = "import" + } + return opts +} + var ( // ErrGenerationLoadRequiresDirectory prevents a one-file or arbitrary-file // load from being mistaken for a complete immutable dataset snapshot. @@ -144,7 +164,7 @@ type generationLoadPlan struct { // newGenerationLoadPlan validates and snapshots all immutable information // after input preflight and before a database connection is opened. Nil keeps // the legacy loader path exactly unversioned. -func newGenerationLoadPlan(opts LoadOptions, files []string, identity schemaidentity.Identity) (*generationLoadPlan, error) { +func newGenerationLoadPlan(opts LoadOptions, files []string, identity graphschema.Identity) (*generationLoadPlan, error) { if opts.Dataset == nil { return nil, nil } @@ -185,18 +205,7 @@ func newGenerationLoadPlan(opts LoadOptions, files []string, identity schemaiden // when Dataset is nil so existing import/API behavior and physical identities // remain unchanged while generation mode evolves independently. func loadLegacy(ctx context.Context, opts LoadOptions) (LoadSummary, error) { - if opts.BatchSize <= 0 { - opts.BatchSize = 5000 - } - if opts.ProgressEvery <= 0 { - opts.ProgressEvery = 50000 - } - if opts.WriterCount <= 0 { - opts.WriterCount = 8 - } - if opts.WriteAPI == "" { - opts.WriteAPI = "import" - } + opts = normalizeLoadOptions(opts) start := time.Now() files, err := DiscoverNDJSON(opts.MetaDir) if err != nil { @@ -210,7 +219,7 @@ func loadLegacy(ctx context.Context, opts LoadOptions) (LoadSummary, error) { // Keep graph.Load as the authoritative graph parser so its established // validation and error behavior remain unchanged. Identity records evidence // for the same configured file once graph loading succeeds. - schemaIdentity, err := schemaidentity.Load(opts.Schema) + schemaIdentity, err := graphschema.Load(opts.Schema) if err != nil { return summary, err } diff --git a/internal/ingest/parity_test.go b/internal/ingest/parity_test.go index 7c2c2b1..c22f33e 100644 --- a/internal/ingest/parity_test.go +++ b/internal/ingest/parity_test.go @@ -10,7 +10,7 @@ import ( "strings" "testing" - "github.com/calypr/loom/internal/fhir" + fhir "github.com/calypr/loom/fhirstructs" jsgarango "github.com/bmeg/jsonschemagraph/arango" "github.com/bmeg/jsonschemagraph/graph" diff --git a/internal/ingest/preflight_test.go b/internal/ingest/preflight_test.go index 277bad9..b55a628 100644 --- a/internal/ingest/preflight_test.go +++ b/internal/ingest/preflight_test.go @@ -8,7 +8,7 @@ import ( "reflect" "testing" - "github.com/calypr/loom/internal/schemaidentity" + "github.com/calypr/loom/internal/graphschema" arangostore "github.com/calypr/loom/internal/store/arango" "github.com/bmeg/jsonschemagraph/graph" @@ -94,7 +94,7 @@ func TestLoadReturnsPreflightReportBeforeOpeningArango(t *testing.T) { dir := t.TempDir() writePreflightFixture(t, dir, "Unknown.ndjson", `{"resourceType":"Unknown"}`+"\n") schemaPath := repoPath(t, "schemas", "graph-fhir.json") - wantIdentity, err := schemaidentity.Load(schemaPath) + wantIdentity, err := graphschema.Load(schemaPath) if err != nil { t.Fatalf("load expected schema identity: %v", err) } diff --git a/internal/recipe/recipe_test.go b/internal/recipe/recipe_test.go deleted file mode 100644 index 3128a36..0000000 --- a/internal/recipe/recipe_test.go +++ /dev/null @@ -1,91 +0,0 @@ -package recipe - -import ( - "errors" - "reflect" - "testing" -) - -func TestNormalizeRecipeV1(t *testing.T) { - recipe := validRecipe() - recipe.Columns = append(recipe.Columns, ColumnSelection{ID: " patient.id "}) - recipe.Filters = []Filter{{ColumnID: "patient.id", Operator: " EQUALS ", Values: []string{" 123 "}}} - got, err := recipe.Normalize() - if err != nil { - t.Fatalf("Normalize: %v", err) - } - if len(got.Columns) != 2 || got.Columns[0].ID != "patient.id" || got.Filters[0].Operator != FilterEquals || got.Filters[0].Values[0] != "123" { - t.Fatalf("unexpected normalization: %#v", got) - } - if len(recipe.Columns) != 3 { - t.Fatal("Normalize mutated its input") - } -} - -func TestAllProductTemplatesValidate(t *testing.T) { - for _, template := range ListTemplates() { - r := validRecipe() - r.Template, r.Grain = template.ID, template.AllowedGrains[0] - if err := r.Validate(); err != nil { - t.Errorf("template %s: %v", template.ID, err) - } - } -} - -func TestRecipeValidationErrorsAreTyped(t *testing.T) { - r := validRecipe() - r.Grain = GrainFile - err := r.Validate() - var validation *ValidationError - if !errors.As(err, &validation) || validation.Code != "incompatible_grain" || validation.Field != "grain" { - t.Fatalf("unexpected error: %#v", err) - } -} - -func TestRecipeRejectsUnsafeOrAmbiguousIntent(t *testing.T) { - tests := []func(*Recipe){ - func(r *Recipe) { r.Version = "v2" }, - func(r *Recipe) { r.Project = "" }, - func(r *Recipe) { r.GenerationPolicy = GenerationPinned }, - func(r *Recipe) { r.Columns = nil }, - func(r *Recipe) { r.Columns[0].ID = "FOR x IN users" }, - func(r *Recipe) { r.Columns[1].OutputName = r.Columns[0].OutputName }, - func(r *Recipe) { - r.Filters = []Filter{{ColumnID: "not.selected", Operator: FilterEquals, Values: []string{"x"}}} - }, - func(r *Recipe) { - r.Filters = []Filter{{ColumnID: "patient.id", Operator: FilterBetween, Values: []string{"x"}}} - }, - func(r *Recipe) { r.Destination.Type = "shell" }, - } - for index, mutate := range tests { - r := validRecipe() - mutate(&r) - if err := r.Validate(); err == nil { - t.Errorf("case %d unexpectedly succeeded: %#v", index, r) - } - } -} - -func TestNormalizeDefensiveCopies(t *testing.T) { - r := validRecipe() - r.Filters = []Filter{{ColumnID: "patient.id", Operator: FilterIn, Values: []string{"a", "b"}}} - got, err := r.Normalize() - if err != nil { - t.Fatal(err) - } - got.Columns[0].ID = "changed" - got.Filters[0].Values[0] = "changed" - if reflect.DeepEqual(r, got) || r.Columns[0].ID == "changed" || r.Filters[0].Values[0] == "changed" { - t.Fatal("normalized recipe aliases input storage") - } -} - -func validRecipe() Recipe { - return Recipe{ - Version: VersionV1, Template: TemplatePatientCohort, TemplateVersion: 1, - Project: "demo", GenerationPolicy: GenerationLatest, Grain: GrainPatient, - Columns: []ColumnSelection{{ID: "patient.id", OutputName: "patient_id"}, {ID: "patient.gender", OutputName: "gender"}}, - Destination: Destination{Type: DestinationPreview}, - } -} diff --git a/internal/recipe/templates.go b/internal/recipe/templates.go deleted file mode 100644 index 9cf2d5f..0000000 --- a/internal/recipe/templates.go +++ /dev/null @@ -1,229 +0,0 @@ -package recipe - -import ( - "fmt" - "strings" -) - -// TemplateMetadata describes a bounded product starting point. It deliberately -// contains no FHIR paths, compiler configuration, or destination credentials: -// selected columns and filters remain opaque capability IDs in Recipe. -type TemplateMetadata struct { - ID TemplateID `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - AllowedGrains []Grain `json:"allowedGrains"` - DefaultDestination DestinationType `json:"defaultDestination"` - AllowedDestinations []DestinationType `json:"allowedDestinations"` -} - -// ListTemplates returns the six supported product starting points in stable -// product-flow order. The returned metadata and every nested slice are owned by -// the caller and may be changed without affecting subsequent calls. -func ListTemplates() []TemplateMetadata { - templates := make([]TemplateMetadata, len(templateRegistry)) - for index, template := range templateRegistry { - templates[index] = cloneTemplateMetadata(template) - } - return templates -} - -// LookupTemplate returns metadata for one supported product starting point. -// The returned metadata is a defensive copy. -func LookupTemplate(id TemplateID) (TemplateMetadata, bool) { - template, ok := templateByID[id] - if !ok { - return TemplateMetadata{}, false - } - return cloneTemplateMetadata(template), true -} - -func templateAllowsGrain(template TemplateMetadata, grain Grain) bool { - for _, allowed := range template.AllowedGrains { - if grain == allowed { - return true - } - } - return false -} - -func templateAllowsDestination(template TemplateMetadata, destination DestinationType) bool { - for _, allowed := range template.AllowedDestinations { - if destination == allowed { - return true - } - } - return false -} - -func cloneTemplateMetadata(template TemplateMetadata) TemplateMetadata { - template.AllowedGrains = append([]Grain(nil), template.AllowedGrains...) - template.AllowedDestinations = append([]DestinationType(nil), template.AllowedDestinations...) - return template -} - -var templateRegistry = []TemplateMetadata{ - { - ID: TemplatePatientCohort, - Name: "Patient cohort", - Description: "Build one row per patient for a cohort.", - AllowedGrains: []Grain{GrainPatient}, - DefaultDestination: DestinationPreview, - AllowedDestinations: allDestinations(), - }, - { - ID: TemplateSpecimenInventory, - Name: "Specimen inventory", - Description: "Build one row per specimen for an inventory.", - AllowedGrains: []Grain{GrainSpecimen}, - DefaultDestination: DestinationPreview, - AllowedDestinations: allDestinations(), - }, - { - ID: TemplateFileManifest, - Name: "File manifest", - Description: "Build one row per file for a manifest.", - AllowedGrains: []Grain{GrainFile}, - DefaultDestination: DestinationPreview, - AllowedDestinations: allDestinations(), - }, - { - ID: TemplateDiagnoses, - Name: "Diagnoses", - Description: "Build one row per diagnosis.", - AllowedGrains: []Grain{GrainDiagnosis}, - DefaultDestination: DestinationPreview, - AllowedDestinations: allDestinations(), - }, - { - ID: TemplateLabsObservations, - Name: "Labs and observations", - Description: "Build one row per lab or observation.", - AllowedGrains: []Grain{GrainObservation}, - DefaultDestination: DestinationPreview, - AllowedDestinations: allDestinations(), - }, - { - ID: TemplateStudyEnrollment, - Name: "Study enrollment", - Description: "Build one row per study enrollment.", - AllowedGrains: []Grain{GrainStudyEnrollment}, - DefaultDestination: DestinationPreview, - AllowedDestinations: allDestinations(), - }, -} - -var templateByID = mustIndexTemplates(templateRegistry) - -func mustIndexTemplates(templates []TemplateMetadata) map[TemplateID]TemplateMetadata { - if err := validateTemplateRegistry(templates); err != nil { - panic(fmt.Sprintf("invalid recipe template registry: %v", err)) - } - indexed := make(map[TemplateID]TemplateMetadata, len(templates)) - for _, template := range templates { - indexed[template.ID] = cloneTemplateMetadata(template) - } - return indexed -} - -func validateTemplateRegistry(templates []TemplateMetadata) error { - expected := map[TemplateID]struct{}{ - TemplatePatientCohort: {}, TemplateSpecimenInventory: {}, - TemplateFileManifest: {}, TemplateDiagnoses: {}, - TemplateLabsObservations: {}, TemplateStudyEnrollment: {}, - } - if len(templates) != len(expected) { - return fmt.Errorf("expected metadata for %d templates, got %d", len(expected), len(templates)) - } - seenTemplates := make(map[TemplateID]struct{}, len(templates)) - for index, template := range templates { - field := fmt.Sprintf("templates[%d]", index) - if _, known := expected[template.ID]; !known { - return fmt.Errorf("%s.id %q is not a supported template", field, template.ID) - } - if _, duplicate := seenTemplates[template.ID]; duplicate { - return fmt.Errorf("%s.id %q is duplicated", field, template.ID) - } - seenTemplates[template.ID] = struct{}{} - if strings.TrimSpace(template.Name) == "" || hasControl(template.Name) { - return fmt.Errorf("%s.name must be non-empty printable text", field) - } - if strings.TrimSpace(template.Description) == "" || hasControl(template.Description) { - return fmt.Errorf("%s.description must be non-empty printable text", field) - } - if err := validateTemplateGrains(template.AllowedGrains, field); err != nil { - return err - } - if err := validateTemplateDestinations(template, field); err != nil { - return err - } - } - for id := range expected { - if _, ok := seenTemplates[id]; !ok { - return fmt.Errorf("missing metadata for template %q", id) - } - } - return nil -} - -func validateTemplateGrains(grains []Grain, field string) error { - if len(grains) == 0 { - return fmt.Errorf("%s.allowedGrains must not be empty", field) - } - known := map[Grain]struct{}{ - GrainPatient: {}, GrainSpecimen: {}, GrainFile: {}, - GrainDiagnosis: {}, GrainObservation: {}, GrainStudyEnrollment: {}, - } - seen := make(map[Grain]struct{}, len(grains)) - for _, grain := range grains { - if _, ok := known[grain]; !ok { - return fmt.Errorf("%s.allowedGrains contains unsupported grain %q", field, grain) - } - if _, duplicate := seen[grain]; duplicate { - return fmt.Errorf("%s.allowedGrains contains duplicate grain %q", field, grain) - } - seen[grain] = struct{}{} - } - return nil -} - -func validateTemplateDestinations(template TemplateMetadata, field string) error { - if len(template.AllowedDestinations) == 0 { - return fmt.Errorf("%s.allowedDestinations must not be empty", field) - } - seen := make(map[DestinationType]struct{}, len(template.AllowedDestinations)) - for _, destination := range template.AllowedDestinations { - if !validDestination(destination) { - return fmt.Errorf("%s.allowedDestinations contains unsupported destination %q", field, destination) - } - if _, duplicate := seen[destination]; duplicate { - return fmt.Errorf("%s.allowedDestinations contains duplicate destination %q", field, destination) - } - seen[destination] = struct{}{} - } - if !validDestination(template.DefaultDestination) { - return fmt.Errorf("%s.defaultDestination %q is unsupported", field, template.DefaultDestination) - } - if _, ok := seen[template.DefaultDestination]; !ok { - return fmt.Errorf("%s.defaultDestination %q is not allowed", field, template.DefaultDestination) - } - return nil -} - -func validDestination(destination DestinationType) bool { - switch destination { - case DestinationPreview, DestinationNDJSON, DestinationCSV, DestinationElasticsearch: - return true - default: - return false - } -} - -func allDestinations() []DestinationType { - return []DestinationType{ - DestinationPreview, - DestinationNDJSON, - DestinationCSV, - DestinationElasticsearch, - } -} diff --git a/internal/recipe/templates_test.go b/internal/recipe/templates_test.go deleted file mode 100644 index 2d4e4f4..0000000 --- a/internal/recipe/templates_test.go +++ /dev/null @@ -1,109 +0,0 @@ -package recipe - -import ( - "reflect" - "strings" - "testing" -) - -func TestListTemplatesReturnsAllProductIntentsInStableOrder(t *testing.T) { - first := ListTemplates() - second := ListTemplates() - if !reflect.DeepEqual(first, second) { - t.Fatalf("ListTemplates is not deterministic:\nfirst: %#v\nsecond: %#v", first, second) - } - gotIDs := make([]TemplateID, len(first)) - for index, template := range first { - gotIDs[index] = template.ID - if template.Name == "" || template.Description == "" { - t.Fatalf("template %q has incomplete presentation metadata: %#v", template.ID, template) - } - if len(template.AllowedGrains) == 0 || len(template.AllowedDestinations) == 0 { - t.Fatalf("template %q has incomplete capabilities: %#v", template.ID, template) - } - if !templateAllowsDestination(template, template.DefaultDestination) { - t.Fatalf("template %q default destination %q is not allowed", template.ID, template.DefaultDestination) - } - } - wantIDs := []TemplateID{ - TemplatePatientCohort, - TemplateSpecimenInventory, - TemplateFileManifest, - TemplateDiagnoses, - TemplateLabsObservations, - TemplateStudyEnrollment, - } - if !reflect.DeepEqual(gotIDs, wantIDs) { - t.Fatalf("template order = %v, want %v", gotIDs, wantIDs) - } -} - -func TestTemplateMetadataAPIsAreDefensive(t *testing.T) { - listed := ListTemplates() - listed[0].Name = "changed" - listed[0].AllowedGrains[0] = GrainFile - listed[0].AllowedDestinations[0] = DestinationCSV - - lookedUp, ok := LookupTemplate(TemplatePatientCohort) - if !ok { - t.Fatal("LookupTemplate(patient_cohort) = not found") - } - lookedUp.Description = "changed" - lookedUp.AllowedGrains[0] = GrainFile - lookedUp.AllowedDestinations[0] = DestinationCSV - - freshList := ListTemplates() - freshLookup, ok := LookupTemplate(TemplatePatientCohort) - if !ok { - t.Fatal("LookupTemplate(patient_cohort) after mutation = not found") - } - if freshList[0].Name == "changed" || freshList[0].AllowedGrains[0] != GrainPatient || freshList[0].AllowedDestinations[0] != DestinationPreview { - t.Fatalf("ListTemplates leaked mutable registry data: %#v", freshList[0]) - } - if freshLookup.Description == "changed" || freshLookup.AllowedGrains[0] != GrainPatient || freshLookup.AllowedDestinations[0] != DestinationPreview { - t.Fatalf("LookupTemplate leaked mutable registry data: %#v", freshLookup) - } - if _, ok := LookupTemplate("unknown"); ok { - t.Fatal("LookupTemplate accepted unknown template") - } -} - -func TestTemplateRegistryValidationRejectsDuplicateAndMissingMetadata(t *testing.T) { - tests := []struct { - name string - templates []TemplateMetadata - contains string - }{ - { - name: "duplicate ID", - templates: func() []TemplateMetadata { - got := ListTemplates() - got[1].ID = got[0].ID - return got - }(), - contains: "duplicated", - }, - { - name: "missing metadata", - templates: ListTemplates()[:5], - contains: "expected metadata", - }, - { - name: "missing capability", - templates: func() []TemplateMetadata { - got := ListTemplates() - got[0].AllowedGrains = nil - return got - }(), - contains: "allowedGrains", - }, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - err := validateTemplateRegistry(test.templates) - if err == nil || !strings.Contains(err.Error(), test.contains) { - t.Fatalf("validateTemplateRegistry() error = %v, want message containing %q", err, test.contains) - } - }) - } -} diff --git a/internal/recipe/types.go b/internal/recipe/types.go deleted file mode 100644 index b5bac14..0000000 --- a/internal/recipe/types.go +++ /dev/null @@ -1,91 +0,0 @@ -// Package recipe defines product intent independently of FHIR and dataframe -// compiler implementation details. -package recipe - -const VersionV1 = "v1" - -type TemplateID string - -const ( - TemplatePatientCohort TemplateID = "patient_cohort" - TemplateSpecimenInventory TemplateID = "specimen_inventory" - TemplateFileManifest TemplateID = "file_manifest" - TemplateDiagnoses TemplateID = "diagnoses" - TemplateLabsObservations TemplateID = "labs_observations" - TemplateStudyEnrollment TemplateID = "study_enrollment" -) - -type Grain string - -const ( - GrainPatient Grain = "patient" - GrainSpecimen Grain = "specimen" - GrainFile Grain = "file" - GrainDiagnosis Grain = "diagnosis" - GrainObservation Grain = "observation" - GrainStudyEnrollment Grain = "study_enrollment" -) - -type GenerationPolicy string - -const ( - GenerationLatest GenerationPolicy = "latest" - GenerationPinned GenerationPolicy = "pinned" -) - -type ColumnSelection struct { - ID string `json:"id"` - OutputName string `json:"outputName,omitempty"` -} - -type FilterOperator string - -const ( - FilterEquals FilterOperator = "equals" - FilterNotEquals FilterOperator = "not_equals" - FilterIn FilterOperator = "in" - FilterNotIn FilterOperator = "not_in" - FilterExists FilterOperator = "exists" - FilterMissing FilterOperator = "missing" - FilterContains FilterOperator = "contains" - FilterGreaterThan FilterOperator = "greater_than" - FilterLessThan FilterOperator = "less_than" - FilterBetween FilterOperator = "between" -) - -type Filter struct { - ColumnID string `json:"columnId"` - Operator FilterOperator `json:"operator"` - Values []string `json:"values,omitempty"` -} - -type DestinationType string - -const ( - DestinationPreview DestinationType = "preview" - DestinationNDJSON DestinationType = "ndjson" - DestinationCSV DestinationType = "csv" - DestinationElasticsearch DestinationType = "elasticsearch" -) - -// Destination intentionally contains no credentials or backend-specific -// configuration. Those belong to a future authorized delivery adapter. -type Destination struct { - Type DestinationType `json:"type"` -} - -// Recipe is the V1 product-level intent contract. Column and filter IDs are -// opaque semantic IDs issued by Loom's future capability API, never FHIR paths -// or AQL expressions. -type Recipe struct { - Version string `json:"version"` - Template TemplateID `json:"template"` - TemplateVersion int `json:"templateVersion"` - Project string `json:"project"` - GenerationPolicy GenerationPolicy `json:"generationPolicy"` - Generation string `json:"generation,omitempty"` - Grain Grain `json:"grain"` - Columns []ColumnSelection `json:"columns"` - Filters []Filter `json:"filters,omitempty"` - Destination Destination `json:"destination"` -} diff --git a/internal/recipe/validation.go b/internal/recipe/validation.go deleted file mode 100644 index c4c0fd0..0000000 --- a/internal/recipe/validation.go +++ /dev/null @@ -1,179 +0,0 @@ -package recipe - -import ( - "fmt" - "strings" - "unicode" -) - -const ( - maxColumns = 512 - maxFilters = 128 - maxFilterValues = 1024 -) - -type ValidationError struct { - Code string - Field string - Message string -} - -func (e *ValidationError) Error() string { - return fmt.Sprintf("%s: %s", e.Field, e.Message) -} - -func invalid(code, field, message string) error { - return &ValidationError{Code: code, Field: field, Message: message} -} - -func (r Recipe) Validate() error { - _, err := r.Normalize() - return err -} - -// Normalize trims user-owned labels, canonicalizes operator spelling, removes -// duplicate column selections, and returns a defensive copy. -func (r Recipe) Normalize() (Recipe, error) { - r.Project = strings.TrimSpace(r.Project) - r.Generation = strings.TrimSpace(r.Generation) - if r.Version != VersionV1 { - return Recipe{}, invalid("unsupported_version", "version", fmt.Sprintf("must be %q", VersionV1)) - } - template, ok := templateByID[r.Template] - if !ok { - return Recipe{}, invalid("unknown_template", "template", fmt.Sprintf("unknown template %q", r.Template)) - } - if r.TemplateVersion <= 0 { - return Recipe{}, invalid("invalid_template_version", "templateVersion", "must be positive") - } - if r.Project == "" || hasControl(r.Project) { - return Recipe{}, invalid("invalid_project", "project", "must be a non-empty printable identifier") - } - if !templateAllowsGrain(template, r.Grain) { - return Recipe{}, invalid("incompatible_grain", "grain", fmt.Sprintf("template %q does not support grain %q", r.Template, r.Grain)) - } - switch r.GenerationPolicy { - case GenerationLatest: - if r.Generation != "" { - return Recipe{}, invalid("unexpected_generation", "generation", "must be empty when policy is latest") - } - case GenerationPinned: - if r.Generation == "" || hasControl(r.Generation) { - return Recipe{}, invalid("missing_generation", "generation", "is required when policy is pinned") - } - default: - return Recipe{}, invalid("invalid_generation_policy", "generationPolicy", "must be latest or pinned") - } - if len(r.Columns) == 0 { - return Recipe{}, invalid("missing_columns", "columns", "at least one column is required") - } - if len(r.Columns) > maxColumns { - return Recipe{}, invalid("too_many_columns", "columns", fmt.Sprintf("cannot exceed %d", maxColumns)) - } - columns := make([]ColumnSelection, 0, len(r.Columns)) - knownColumns := make(map[string]struct{}, len(r.Columns)) - outputNames := make(map[string]struct{}, len(r.Columns)) - for index, column := range r.Columns { - column.ID = strings.TrimSpace(column.ID) - column.OutputName = strings.TrimSpace(column.OutputName) - field := fmt.Sprintf("columns[%d]", index) - if !validSemanticID(column.ID) { - return Recipe{}, invalid("invalid_semantic_id", field+".id", "must be a stable semantic identifier") - } - if column.OutputName != "" && hasControl(column.OutputName) { - return Recipe{}, invalid("invalid_output_name", field+".outputName", "contains control characters") - } - if _, exists := knownColumns[column.ID]; exists { - continue - } - if column.OutputName != "" { - if _, exists := outputNames[column.OutputName]; exists { - return Recipe{}, invalid("duplicate_output_name", field+".outputName", fmt.Sprintf("%q is duplicated", column.OutputName)) - } - outputNames[column.OutputName] = struct{}{} - } - knownColumns[column.ID] = struct{}{} - columns = append(columns, column) - } - r.Columns = columns - if len(r.Filters) > maxFilters { - return Recipe{}, invalid("too_many_filters", "filters", fmt.Sprintf("cannot exceed %d", maxFilters)) - } - r.Filters = append([]Filter(nil), r.Filters...) - for index := range r.Filters { - filter := &r.Filters[index] - filter.ColumnID = strings.TrimSpace(filter.ColumnID) - filter.Operator = FilterOperator(strings.ToLower(strings.TrimSpace(string(filter.Operator)))) - filter.Values = append([]string(nil), filter.Values...) - field := fmt.Sprintf("filters[%d]", index) - if !validSemanticID(filter.ColumnID) { - return Recipe{}, invalid("invalid_semantic_id", field+".columnId", "must be a stable semantic identifier") - } - if _, exists := knownColumns[filter.ColumnID]; !exists { - return Recipe{}, invalid("unknown_filter_column", field+".columnId", "must reference a selected column") - } - if err := validateFilter(filter, field); err != nil { - return Recipe{}, err - } - } - if !validDestination(r.Destination.Type) { - return Recipe{}, invalid("invalid_destination", "destination.type", fmt.Sprintf("unknown destination %q", r.Destination.Type)) - } - if !templateAllowsDestination(template, r.Destination.Type) { - return Recipe{}, invalid("unsupported_destination", "destination.type", fmt.Sprintf("template %q does not support destination %q", r.Template, r.Destination.Type)) - } - return r, nil -} - -func validateFilter(filter *Filter, field string) error { - if len(filter.Values) > maxFilterValues { - return invalid("too_many_filter_values", field+".values", fmt.Sprintf("cannot exceed %d", maxFilterValues)) - } - for index := range filter.Values { - filter.Values[index] = strings.TrimSpace(filter.Values[index]) - if hasControl(filter.Values[index]) { - return invalid("invalid_filter_value", fmt.Sprintf("%s.values[%d]", field, index), "contains control characters") - } - } - want := -1 - switch filter.Operator { - case FilterExists, FilterMissing: - want = 0 - case FilterEquals, FilterNotEquals, FilterContains, FilterGreaterThan, FilterLessThan: - want = 1 - case FilterBetween: - want = 2 - case FilterIn, FilterNotIn: - if len(filter.Values) == 0 { - return invalid("missing_filter_values", field+".values", "at least one value is required") - } - return nil - default: - return invalid("invalid_filter_operator", field+".operator", fmt.Sprintf("unknown operator %q", filter.Operator)) - } - if len(filter.Values) != want { - return invalid("invalid_filter_values", field+".values", fmt.Sprintf("operator %q requires %d values", filter.Operator, want)) - } - return nil -} - -func validSemanticID(value string) bool { - if value == "" || len(value) > 256 { - return false - } - for _, r := range value { - if !(unicode.IsLetter(r) || unicode.IsDigit(r) || strings.ContainsRune("._:-", r)) { - return false - } - } - return true -} - -func hasControl(value string) bool { - for _, r := range value { - if unicode.IsControl(r) { - return true - } - } - return false -} diff --git a/internal/recipecompiler/bridge.go b/internal/recipecompiler/bridge.go deleted file mode 100644 index cfff5cc..0000000 --- a/internal/recipecompiler/bridge.go +++ /dev/null @@ -1,417 +0,0 @@ -// Package recipecompiler turns the product-level recipe contract into the -// compiler's internal Builder only after resolving its opaque capabilities -// against fresh, authorized discovery facts. -// -// This first bridge is intentionally root-only. A recipe column or filter can -// refer only to the resource represented by its named row grain; relationship -// choices, repeated-value quantifiers, pivots, aggregates, and row expansion -// need explicit product contracts before they can be lowered safely. -package recipecompiler - -import ( - "errors" - "fmt" - "math" - "strconv" - "strings" - - "github.com/calypr/loom/internal/dataframe" - "github.com/calypr/loom/internal/discovery" - "github.com/calypr/loom/internal/fhirschema" - "github.com/calypr/loom/internal/recipe" -) - -// Stable errors returned by Build. Callers should use errors.Is rather than -// parsing error text; the bridge deliberately does not disclose raw catalog -// selectors or unrecognized recipe identifiers in those errors. -var ( - ErrCatalogProjectMismatch = errors.New("recipe project does not match catalog facts") - ErrColumnCapabilityUnavailable = errors.New("recipe column capability is unavailable") - ErrRelatedResource = errors.New("recipe capability belongs to a related resource") - ErrPivotChoiceUnsupported = errors.New("recipe pivot-only capability is unsupported") - ErrRepeatedColumn = errors.New("recipe repeated column requires an explicit cardinality decision") - ErrRepeatedFilter = errors.New("recipe repeated filter requires an explicit quantifier decision") - ErrUnsupportedValueConversion = errors.New("recipe filter value cannot be converted to the resolved schema kind") - ErrUnsupportedFilter = errors.New("recipe filter is unsupported for the resolved schema capability") - ErrOutputNameCollision = errors.New("recipe output names collide after compiler normalization") - ErrGenerationBindingRequired = errors.New("pinned recipe generation requires a dataset generation binding") -) - -// Plan is the compiler-ready result of resolving a Recipe against one fresh -// authorized catalog snapshot. Recipe is normalized and Builder contains only -// selectors recovered from discovery capability resolution, never selectors -// supplied by the recipe input. -type Plan struct { - Recipe recipe.Recipe - Builder dataframe.Builder -} - -// Build normalizes input, resolves every opaque column/filter capability from -// the supplied fresh CatalogFacts, and produces a root-only dataframe Builder. -// -// A recipe BETWEEN filter is intentionally lowered as two inclusive filters: -// GTE for the first value and LTE for the second. NOT_IN is lowered as one -// scalar NOT_EQUALS filter per value. Repeated values are rejected in V1 rather -// than assuming ANY, ALL, or a projection/cardinality policy on the user's -// behalf. -// -// CatalogFacts must have been collected for the caller's current authorized -// project/scope. The returned Builder intentionally leaves AuthResourcePaths -// unset: caller authorization remains the responsibility of dataframe.Service -// or the owning request layer, which has the principal and scope identity. -// Pinned recipes return ErrGenerationBindingRequired until an owning dataset -// layer supplies facts bound to the requested generation. -func Build(input recipe.Recipe, facts discovery.CatalogFacts) (Plan, error) { - normalized, err := input.Normalize() - if err != nil { - return Plan{}, err - } - if normalized.GenerationPolicy == recipe.GenerationPinned { - // CatalogFacts deliberately has no dataset-generation identity. Accepting - // a pinned recipe here would silently compile it against whichever facts - // happen to be current, violating the recipe's reproducibility contract. - return Plan{}, ErrGenerationBindingRequired - } - if strings.TrimSpace(facts.Project) != normalized.Project { - return Plan{}, ErrCatalogProjectMismatch - } - - resolver, err := discovery.NewCapabilityResolver(facts) - if err != nil { - return Plan{}, err - } - rowGrain, rootResourceType, err := rootForRecipeGrain(normalized.Grain) - if err != nil { - return Plan{}, err - } - - resolvedColumns := make(map[string]discovery.ResolvedColumn, len(normalized.Columns)) - for _, selection := range normalized.Columns { - resolved, err := resolveRootColumn(resolver, selection.ID, rootResourceType) - if err != nil { - return Plan{}, err - } - resolvedColumns[selection.ID] = resolved - } - - builder := dataframe.Builder{ - Project: normalized.Project, - RootResourceType: rootResourceType, - RowGrain: rowGrain, - Fields: make([]dataframe.FieldSelect, 0, len(normalized.Columns)), - Filters: make([]dataframe.TypedFilter, 0, len(normalized.Filters)), - } - - // Resolve filters before materializing selections so a recipe which uses a - // repeated field as a filter receives the precise missing-quantifier error; - // a repeated selected field without a filter receives ErrRepeatedColumn. - for _, filter := range normalized.Filters { - resolved, ok := resolvedColumns[filter.ColumnID] - if !ok { - // Normalize currently proves this cannot happen, but do not turn a - // future recipe-contract regression into a selector fallback. - return Plan{}, ErrColumnCapabilityUnavailable - } - lowered, err := lowerRootFilter(rootResourceType, resolved, filter) - if err != nil { - return Plan{}, err - } - builder.Filters = append(builder.Filters, lowered...) - } - - outputNames, err := outputNames(normalized.Columns) - if err != nil { - return Plan{}, err - } - for index, selection := range normalized.Columns { - field, err := lowerRootSelection(resolvedColumns[selection.ID], outputNames[index]) - if err != nil { - return Plan{}, err - } - builder.Fields = append(builder.Fields, field) - } - - // This verifies the internal builder has a valid generated-schema semantic - // shape before it reaches later service/catalog validation or lowering. - if _, err := dataframe.BuildSemanticPlan(builder); err != nil { - return Plan{}, fmt.Errorf("recipe compiler generated invalid dataframe builder: %w", err) - } - - return Plan{Recipe: normalized, Builder: builder}, nil -} - -func rootForRecipeGrain(grain recipe.Grain) (dataframe.RowGrain, string, error) { - var rowGrain dataframe.RowGrain - switch grain { - case recipe.GrainPatient: - rowGrain = dataframe.RowGrainPatient - case recipe.GrainSpecimen: - rowGrain = dataframe.RowGrainSpecimen - case recipe.GrainFile: - rowGrain = dataframe.RowGrainFile - case recipe.GrainDiagnosis: - rowGrain = dataframe.RowGrainDiagnosis - case recipe.GrainObservation: - rowGrain = dataframe.RowGrainObservation - case recipe.GrainStudyEnrollment: - rowGrain = dataframe.RowGrainStudyEnrollment - default: - return "", "", fmt.Errorf("recipe grain %q has no named dataframe row grain", grain) - } - rootResourceType, ok := dataframe.RootResourceForGrain(rowGrain) - if !ok || rootResourceType == "" { - return "", "", fmt.Errorf("dataframe row grain %q has no named root resource", rowGrain) - } - return rowGrain, rootResourceType, nil -} - -func resolveRootColumn(resolver *discovery.CapabilityResolver, id string, rootResourceType string) (discovery.ResolvedColumn, error) { - resolved, err := resolver.ResolveColumn(discovery.ColumnID(id)) - if err != nil { - if errors.Is(err, discovery.ErrColumnUnavailable) { - return discovery.ResolvedColumn{}, fmt.Errorf("%w: %w", ErrColumnCapabilityUnavailable, discovery.ErrColumnUnavailable) - } - return discovery.ResolvedColumn{}, err - } - if resolved.ResourceType != rootResourceType { - return discovery.ResolvedColumn{}, ErrRelatedResource - } - return resolved, nil -} - -func lowerRootSelection(resolved discovery.ResolvedColumn, outputName string) (dataframe.FieldSelect, error) { - if pivotOnly(resolved) { - return dataframe.FieldSelect{}, ErrPivotChoiceUnsupported - } - if resolved.Repeated { - return dataframe.FieldSelect{}, ErrRepeatedColumn - } - if !resolved.CanSelect || resolved.Selector == nil { - return dataframe.FieldSelect{}, ErrColumnCapabilityUnavailable - } - return dataframe.FieldSelect{ - Name: outputName, - FieldRef: string(resolved.ID), - Select: fhirschema.SelectorExpression(*resolved.Selector), - ValueMode: "AUTO", - }, nil -} - -func lowerRootFilter(rootResourceType string, resolved discovery.ResolvedColumn, input recipe.Filter) ([]dataframe.TypedFilter, error) { - if pivotOnly(resolved) { - return nil, ErrPivotChoiceUnsupported - } - if resolved.Repeated { - return nil, ErrRepeatedFilter - } - if !resolved.CanFilter || resolved.Selector == nil { - return nil, ErrUnsupportedFilter - } - - kind, ok := dataframeFilterKind(resolved.ValueKind) - if !ok { - return nil, ErrUnsupportedValueConversion - } - values, err := convertFilterValues(kind, input.Values) - if err != nil { - return nil, err - } - newFilter := func(operator dataframe.FilterOperator, filterValues []dataframe.FilterValue) (dataframe.TypedFilter, error) { - filter := dataframe.TypedFilter{ - FieldRef: string(resolved.ID), - Selector: fhirschema.SelectorExpression(*resolved.Selector), - FieldKind: kind, - Operator: operator, - Values: append([]dataframe.FilterValue(nil), filterValues...), - } - if err := dataframe.ValidateTypedFilterForResource(rootResourceType, filter); err != nil { - return dataframe.TypedFilter{}, ErrUnsupportedFilter - } - return filter, nil - } - - switch input.Operator { - case recipe.FilterEquals: - filter, err := newFilter(dataframe.FilterEquals, values) - return oneFilter(filter, err) - case recipe.FilterNotEquals: - filter, err := newFilter(dataframe.FilterNotEquals, values) - return oneFilter(filter, err) - case recipe.FilterIn: - filter, err := newFilter(dataframe.FilterIn, values) - return oneFilter(filter, err) - case recipe.FilterNotIn: - filters := make([]dataframe.TypedFilter, 0, len(values)) - for _, value := range values { - filter, err := newFilter(dataframe.FilterNotEquals, []dataframe.FilterValue{value}) - if err != nil { - return nil, err - } - filters = append(filters, filter) - } - return filters, nil - case recipe.FilterExists: - filter, err := newFilter(dataframe.FilterExists, nil) - return oneFilter(filter, err) - case recipe.FilterMissing: - filter, err := newFilter(dataframe.FilterMissing, nil) - return oneFilter(filter, err) - case recipe.FilterContains: - filter, err := newFilter(dataframe.FilterContains, values) - return oneFilter(filter, err) - case recipe.FilterGreaterThan: - filter, err := newFilter(dataframe.FilterGreaterThan, values) - return oneFilter(filter, err) - case recipe.FilterLessThan: - filter, err := newFilter(dataframe.FilterLessThan, values) - return oneFilter(filter, err) - case recipe.FilterBetween: - lower, err := newFilter(dataframe.FilterGreaterEq, values[:1]) - if err != nil { - return nil, err - } - upper, err := newFilter(dataframe.FilterLessEq, values[1:]) - if err != nil { - return nil, err - } - return []dataframe.TypedFilter{lower, upper}, nil - default: - // Recipe.Normalize currently keeps this closed, but never fall through - // to a textual operator or a future unsupported enum value. - return nil, ErrUnsupportedFilter - } -} - -func oneFilter(filter dataframe.TypedFilter, err error) ([]dataframe.TypedFilter, error) { - if err != nil { - return nil, err - } - return []dataframe.TypedFilter{filter}, nil -} - -func pivotOnly(resolved discovery.ResolvedColumn) bool { - return resolved.ValueKind == discovery.ValueKindComposite || (!resolved.CanSelect && resolved.CanPivot) -} - -func dataframeFilterKind(kind discovery.ValueKind) (dataframe.FilterValueKind, bool) { - switch kind { - case discovery.ValueKindString: - return dataframe.FilterString, true - case discovery.ValueKindBoolean: - return dataframe.FilterBoolean, true - case discovery.ValueKindInteger: - return dataframe.FilterInteger, true - case discovery.ValueKindDecimal: - return dataframe.FilterDecimal, true - case discovery.ValueKindDate: - return dataframe.FilterDate, true - case discovery.ValueKindDateTime: - return dataframe.FilterDateTime, true - default: - return "", false - } -} - -func convertFilterValues(kind dataframe.FilterValueKind, values []string) ([]dataframe.FilterValue, error) { - converted := make([]dataframe.FilterValue, 0, len(values)) - for _, value := range values { - convertedValue, err := convertFilterValue(kind, value) - if err != nil { - return nil, err - } - converted = append(converted, convertedValue) - } - return converted, nil -} - -func convertFilterValue(kind dataframe.FilterValueKind, raw string) (dataframe.FilterValue, error) { - var value dataframe.FilterValue - switch kind { - case dataframe.FilterString: - value = dataframe.FilterValue{Kind: kind, String: &raw} - case dataframe.FilterBoolean: - var parsed bool - switch raw { - case "true": - parsed = true - case "false": - parsed = false - default: - return dataframe.FilterValue{}, ErrUnsupportedValueConversion - } - value = dataframe.FilterValue{Kind: kind, Boolean: &parsed} - case dataframe.FilterInteger: - parsed, err := strconv.ParseInt(raw, 10, 64) - if err != nil { - return dataframe.FilterValue{}, ErrUnsupportedValueConversion - } - value = dataframe.FilterValue{Kind: kind, Integer: &parsed} - case dataframe.FilterDecimal: - parsed, err := strconv.ParseFloat(raw, 64) - if err != nil || math.IsNaN(parsed) || math.IsInf(parsed, 0) { - return dataframe.FilterValue{}, ErrUnsupportedValueConversion - } - value = dataframe.FilterValue{Kind: kind, Decimal: &parsed} - case dataframe.FilterDate: - value = dataframe.FilterValue{Kind: kind, Date: &raw} - case dataframe.FilterDateTime: - value = dataframe.FilterValue{Kind: kind, DateTime: &raw} - default: - return dataframe.FilterValue{}, ErrUnsupportedValueConversion - } - if err := value.Validate(); err != nil { - return dataframe.FilterValue{}, ErrUnsupportedValueConversion - } - return value, nil -} - -func outputNames(columns []recipe.ColumnSelection) ([]string, error) { - // Check all explicit names first, so defaults can avoid a user-provided - // column_1 instead of creating a lower-level compiler collision. - usedCompilerNames := make(map[string]struct{}, len(columns)) - for _, column := range columns { - if column.OutputName == "" { - continue - } - name := compilerOutputName(column.OutputName) - if _, exists := usedCompilerNames[name]; exists { - return nil, ErrOutputNameCollision - } - usedCompilerNames[name] = struct{}{} - } - - names := make([]string, len(columns)) - for index, column := range columns { - if column.OutputName != "" { - names[index] = column.OutputName - continue - } - for suffix := index + 1; ; suffix++ { - candidate := fmt.Sprintf("column_%d", suffix) - compilerName := compilerOutputName(candidate) - if _, exists := usedCompilerNames[compilerName]; exists { - continue - } - usedCompilerNames[compilerName] = struct{}{} - names[index] = candidate - break - } - } - return names, nil -} - -// compilerOutputName intentionally mirrors dataframe's output-key -// normalization so recipe input cannot create duplicate compiled columns by -// using different punctuation in otherwise identical display names. -func compilerOutputName(name string) string { - var builder strings.Builder - for _, r := range name { - switch { - case r >= 'a' && r <= 'z', r >= 'A' && r <= 'Z', r >= '0' && r <= '9': - builder.WriteRune(r) - default: - builder.WriteRune('_') - } - } - return builder.String() -} diff --git a/internal/recipecompiler/bridge_test.go b/internal/recipecompiler/bridge_test.go deleted file mode 100644 index f08ac47..0000000 --- a/internal/recipecompiler/bridge_test.go +++ /dev/null @@ -1,336 +0,0 @@ -package recipecompiler - -import ( - "errors" - "fmt" - "reflect" - "strings" - "testing" - - "github.com/calypr/loom/internal/catalog" - "github.com/calypr/loom/internal/dataframe" - "github.com/calypr/loom/internal/discovery" - "github.com/calypr/loom/internal/fhirschema" - "github.com/calypr/loom/internal/recipe" -) - -func TestBuildPatientCohortProducesCompilerReadyTypedFilters(t *testing.T) { - facts := bridgeFacts() - genderID := capabilityID(t, facts, "Patient", "gender") - birthDateID := capabilityID(t, facts, "Patient", "birthDate") - - input := patientRecipe(genderID, birthDateID) - input.Columns[0].OutputName = "Sex" - input.Columns[1].OutputName = "Birth date" - input.Filters = []recipe.Filter{ - {ColumnID: genderID, Operator: recipe.FilterEquals, Values: []string{"female"}}, - {ColumnID: birthDateID, Operator: recipe.FilterBetween, Values: []string{"1970-01-01", "2000-12-31"}}, - {ColumnID: genderID, Operator: recipe.FilterNotIn, Values: []string{"unknown", "other"}}, - } - - plan, err := Build(input, facts) - if err != nil { - t.Fatalf("Build() error = %v", err) - } - if plan.Recipe.Project != "project-a" || plan.Builder.Project != "project-a" { - t.Errorf("project normalization = recipe %q builder %q, want project-a", plan.Recipe.Project, plan.Builder.Project) - } - if plan.Builder.RootResourceType != "Patient" || plan.Builder.RowGrain != dataframe.RowGrainPatient { - t.Errorf("root builder = %+v, want Patient/patient", plan.Builder) - } - if plan.Builder.AuthResourcePaths != nil { - t.Errorf("bridge unexpectedly invented authorization paths: %#v", plan.Builder.AuthResourcePaths) - } - if got, want := len(plan.Builder.Fields), 2; got != want { - t.Fatalf("field count = %d, want %d", got, want) - } - if got := plan.Builder.Fields[0]; got.Name != "Sex" || got.FieldRef != genderID || got.Select != "gender" || got.ValueMode != "AUTO" { - t.Errorf("gender field = %+v", got) - } - if got := plan.Builder.Fields[1]; got.Name != "Birth date" || got.FieldRef != birthDateID || got.Select != "birthDate" || got.ValueMode != "AUTO" { - t.Errorf("birth date field = %+v", got) - } - - // BETWEEN is an inclusive range: the lower and upper endpoints are - // explicitly represented as GTE and LTE rather than a string expression. - wantOperators := []dataframe.FilterOperator{ - dataframe.FilterEquals, - dataframe.FilterGreaterEq, - dataframe.FilterLessEq, - dataframe.FilterNotEquals, - dataframe.FilterNotEquals, - } - if got := filterOperators(plan.Builder.Filters); !reflect.DeepEqual(got, wantOperators) { - t.Errorf("filter operators = %v, want %v", got, wantOperators) - } - if got := plan.Builder.Filters[0]; got.FieldKind != dataframe.FilterString || got.Values[0].String == nil || *got.Values[0].String != "female" { - t.Errorf("gender typed filter = %+v", got) - } - for index, want := range []string{"1970-01-01", "2000-12-31"} { - filter := plan.Builder.Filters[index+1] - if filter.FieldKind != dataframe.FilterDate || len(filter.Values) != 1 || filter.Values[0].Date == nil || *filter.Values[0].Date != want { - t.Errorf("between filter %d = %+v, want DATE %q", index, filter, want) - } - } - - compiled, err := dataframe.CompileRequest(plan.Builder, 25) - if err != nil { - t.Fatalf("CompileRequest(recipe builder) error = %v", err) - } - if compiled.RootResourceType != "Patient" || compiled.RowIdentity == nil || compiled.RowIdentity.Grain != dataframe.RowGrainPatient { - t.Errorf("compiled query metadata = %+v", compiled) - } - if !strings.Contains(compiled.Query, " >= ") || !strings.Contains(compiled.Query, " <= ") { - t.Errorf("compiled inclusive BETWEEN predicates missing from query:\n%s", compiled.Query) - } -} - -func TestBuildMapsEverySupportedRootFilterOperator(t *testing.T) { - facts := bridgeFacts() - genderID := capabilityID(t, facts, "Patient", "gender") - birthDateID := capabilityID(t, facts, "Patient", "birthDate") - - tests := []struct { - name string - columnID string - operator recipe.FilterOperator - values []string - want []dataframe.FilterOperator - wantKind dataframe.FilterValueKind - }{ - {name: "equals", columnID: genderID, operator: recipe.FilterEquals, values: []string{"female"}, want: []dataframe.FilterOperator{dataframe.FilterEquals}, wantKind: dataframe.FilterString}, - {name: "not equals", columnID: genderID, operator: recipe.FilterNotEquals, values: []string{"male"}, want: []dataframe.FilterOperator{dataframe.FilterNotEquals}, wantKind: dataframe.FilterString}, - {name: "in", columnID: genderID, operator: recipe.FilterIn, values: []string{"female", "male"}, want: []dataframe.FilterOperator{dataframe.FilterIn}, wantKind: dataframe.FilterString}, - {name: "not in", columnID: genderID, operator: recipe.FilterNotIn, values: []string{"unknown", "other"}, want: []dataframe.FilterOperator{dataframe.FilterNotEquals, dataframe.FilterNotEquals}, wantKind: dataframe.FilterString}, - {name: "exists", columnID: genderID, operator: recipe.FilterExists, want: []dataframe.FilterOperator{dataframe.FilterExists}, wantKind: dataframe.FilterString}, - {name: "missing", columnID: genderID, operator: recipe.FilterMissing, want: []dataframe.FilterOperator{dataframe.FilterMissing}, wantKind: dataframe.FilterString}, - {name: "contains", columnID: genderID, operator: recipe.FilterContains, values: []string{"em"}, want: []dataframe.FilterOperator{dataframe.FilterContains}, wantKind: dataframe.FilterString}, - {name: "greater than", columnID: birthDateID, operator: recipe.FilterGreaterThan, values: []string{"1970-01-01"}, want: []dataframe.FilterOperator{dataframe.FilterGreaterThan}, wantKind: dataframe.FilterDate}, - {name: "less than", columnID: birthDateID, operator: recipe.FilterLessThan, values: []string{"2000-12-31"}, want: []dataframe.FilterOperator{dataframe.FilterLessThan}, wantKind: dataframe.FilterDate}, - {name: "between inclusive", columnID: birthDateID, operator: recipe.FilterBetween, values: []string{"1970-01-01", "2000-12-31"}, want: []dataframe.FilterOperator{dataframe.FilterGreaterEq, dataframe.FilterLessEq}, wantKind: dataframe.FilterDate}, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - input := patientRecipe(test.columnID) - input.Filters = []recipe.Filter{{ColumnID: test.columnID, Operator: test.operator, Values: test.values}} - plan, err := Build(input, facts) - if err != nil { - t.Fatalf("Build() error = %v", err) - } - if got := filterOperators(plan.Builder.Filters); !reflect.DeepEqual(got, test.want) { - t.Errorf("operators = %v, want %v", got, test.want) - } - for _, filter := range plan.Builder.Filters { - if filter.FieldKind != test.wantKind { - t.Errorf("filter kind = %q, want %q", filter.FieldKind, test.wantKind) - } - } - }) - } -} - -func TestBuildRejectsStaleUnknownAndRawFHIRPathCapabilities(t *testing.T) { - facts := bridgeFacts() - genderID := capabilityID(t, facts, "Patient", "gender") - freshFacts := discovery.CatalogFacts{ - Project: "project-a", - Fields: []catalog.PopulatedField{{ - Project: "project-a", ResourceType: "Patient", Path: "birthDate", Kind: "scalar", DocCount: 1, - }}, - } - - tests := []struct { - name string - id string - facts discovery.CatalogFacts - }{ - {name: "stale opaque ID", id: genderID, facts: freshFacts}, - {name: "raw FHIR path", id: "gender", facts: facts}, - {name: "unknown opaque shaped ID", id: "col_" + strings.Repeat("0", 64), facts: facts}, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - input := patientRecipe(test.id) - plan, err := Build(input, test.facts) - if !errors.Is(err, ErrColumnCapabilityUnavailable) { - t.Fatalf("Build() error = %v, want ErrColumnCapabilityUnavailable", err) - } - if !errors.Is(err, discovery.ErrColumnUnavailable) { - t.Errorf("Build() error = %v, want discovery.ErrColumnUnavailable cause", err) - } - if len(plan.Builder.Fields) != 0 || len(plan.Builder.Filters) != 0 { - t.Errorf("failed bridge returned a usable builder: %+v", plan.Builder) - } - if strings.Contains(fmt.Sprintf("%#v", plan), "gender") { - t.Errorf("raw recipe path leaked into failed plan: %#v", plan) - } - }) - } -} - -func TestBuildRejectsRelatedPivotAndRepeatedChoices(t *testing.T) { - facts := bridgeFacts() - genderID := capabilityID(t, facts, "Patient", "gender") - observationValueID := capabilityID(t, facts, "Observation", "valueInteger") - observationCodeID := capabilityID(t, facts, "Observation", "code") - repeatedNameID := capabilityID(t, facts, "Patient", "name[].family") - - t.Run("related root column", func(t *testing.T) { - _, err := Build(patientRecipe(genderID, observationValueID), facts) - if !errors.Is(err, ErrRelatedResource) { - t.Fatalf("Build() error = %v, want ErrRelatedResource", err) - } - }) - - t.Run("composite pivot only choice", func(t *testing.T) { - input := observationRecipe(observationCodeID) - _, err := Build(input, facts) - if !errors.Is(err, ErrPivotChoiceUnsupported) { - t.Fatalf("Build() error = %v, want ErrPivotChoiceUnsupported", err) - } - }) - - t.Run("repeated root column", func(t *testing.T) { - _, err := Build(patientRecipe(repeatedNameID), facts) - if !errors.Is(err, ErrRepeatedColumn) { - t.Fatalf("Build() error = %v, want ErrRepeatedColumn", err) - } - }) - - t.Run("repeated root filter needs quantifier", func(t *testing.T) { - input := patientRecipe(repeatedNameID) - input.Filters = []recipe.Filter{{ColumnID: repeatedNameID, Operator: recipe.FilterExists}} - _, err := Build(input, facts) - if !errors.Is(err, ErrRepeatedFilter) { - t.Fatalf("Build() error = %v, want ErrRepeatedFilter", err) - } - }) -} - -func TestBuildRejectsInvalidTypedFilterValues(t *testing.T) { - facts := bridgeFacts() - booleanID := capabilityID(t, facts, "Patient", "deceasedBoolean") - integerID := capabilityID(t, facts, "Patient", "multipleBirthInteger") - dateID := capabilityID(t, facts, "Patient", "birthDate") - - tests := []struct { - name string - id string - value string - }{ - {name: "boolean", id: booleanID, value: "yes"}, - {name: "integer", id: integerID, value: "twelve"}, - {name: "date", id: dateID, value: "2024-99-99"}, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - input := patientRecipe(test.id) - input.Filters = []recipe.Filter{{ColumnID: test.id, Operator: recipe.FilterEquals, Values: []string{test.value}}} - _, err := Build(input, facts) - if !errors.Is(err, ErrUnsupportedValueConversion) { - t.Fatalf("Build() error = %v, want ErrUnsupportedValueConversion", err) - } - }) - } -} - -func TestBuildRejectsPinnedRecipeWithoutGenerationBinding(t *testing.T) { - facts := bridgeFacts() - genderID := capabilityID(t, facts, "Patient", "gender") - input := patientRecipe(genderID) - input.GenerationPolicy = recipe.GenerationPinned - input.Generation = "generation-42" - - _, err := Build(input, facts) - if !errors.Is(err, ErrGenerationBindingRequired) { - t.Fatalf("Build() error = %v, want ErrGenerationBindingRequired", err) - } -} - -func TestBuildRejectsProjectMismatchedCatalogFacts(t *testing.T) { - facts := bridgeFacts() - genderID := capabilityID(t, facts, "Patient", "gender") - input := patientRecipe(genderID) - input.Project = "another-project" - - _, err := Build(input, facts) - if !errors.Is(err, ErrCatalogProjectMismatch) { - t.Fatalf("Build() error = %v, want ErrCatalogProjectMismatch", err) - } -} - -func patientRecipe(columnIDs ...string) recipe.Recipe { - return productRecipe(recipe.TemplatePatientCohort, recipe.GrainPatient, columnIDs...) -} - -func observationRecipe(columnIDs ...string) recipe.Recipe { - return productRecipe(recipe.TemplateLabsObservations, recipe.GrainObservation, columnIDs...) -} - -func productRecipe(template recipe.TemplateID, grain recipe.Grain, columnIDs ...string) recipe.Recipe { - columns := make([]recipe.ColumnSelection, 0, len(columnIDs)) - for _, id := range columnIDs { - columns = append(columns, recipe.ColumnSelection{ID: id}) - } - return recipe.Recipe{ - Version: recipe.VersionV1, - Template: template, - TemplateVersion: 1, - Project: "project-a", - GenerationPolicy: recipe.GenerationLatest, - Grain: grain, - Columns: columns, - Destination: recipe.Destination{Type: recipe.DestinationPreview}, - } -} - -func bridgeFacts() discovery.CatalogFacts { - return discovery.CatalogFacts{ - Project: "project-a", - Fields: []catalog.PopulatedField{ - {Project: "project-a", ResourceType: "Patient", Path: "gender", Kind: "scalar", DocCount: 3, DistinctValues: []string{"female", "male"}}, - {Project: "project-a", ResourceType: "Patient", Path: "birthDate", Kind: "scalar", DocCount: 3, DistinctValues: []string{"1970-01-01", "2000-12-31"}}, - {Project: "project-a", ResourceType: "Patient", Path: "name[].family", Kind: "scalar", DocCount: 3, DistinctValues: []string{"Ng", "Smith"}}, - {Project: "project-a", ResourceType: "Patient", Path: "deceasedBoolean", Kind: "scalar", DocCount: 3, DistinctValues: []string{"false", "true"}}, - {Project: "project-a", ResourceType: "Patient", Path: "multipleBirthInteger", Kind: "scalar", DocCount: 3, DistinctValues: []string{"1", "2"}}, - { - Project: "project-a", ResourceType: "Observation", Path: "code", Kind: "codeable_concept", DocCount: 3, - PivotCandidate: true, PivotFamily: fhirschema.PivotFamilyObservationCodeValue, - PivotColumnSelect: "code.coding[].display", PivotValueSelect: "valueInteger", PivotColumns: []string{"Hemoglobin"}, - }, - {Project: "project-a", ResourceType: "Observation", Path: "valueInteger", Kind: "scalar", DocCount: 3, DistinctValues: []string{"12", "13"}}, - }, - } -} - -func capabilityID(t *testing.T, facts discovery.CatalogFacts, resourceType, canonicalPath string) string { - t.Helper() - snapshot, err := discovery.BuildSnapshot(facts) - if err != nil { - t.Fatalf("BuildSnapshot() error = %v", err) - } - resolver, err := discovery.NewCapabilityResolver(facts) - if err != nil { - t.Fatalf("NewCapabilityResolver() error = %v", err) - } - for _, column := range snapshot.Columns { - resolved, err := resolver.ResolveColumn(column.ID) - if err != nil { - t.Fatalf("ResolveColumn(%q) error = %v", column.ID, err) - } - if resolved.ResourceType == resourceType && resolved.CanonicalPath == canonicalPath { - return string(column.ID) - } - } - t.Fatalf("no capability for %s.%s", resourceType, canonicalPath) - return "" -} - -func filterOperators(filters []dataframe.TypedFilter) []dataframe.FilterOperator { - operators := make([]dataframe.FilterOperator, 0, len(filters)) - for _, filter := range filters { - operators = append(operators, filter.Operator) - } - return operators -} diff --git a/internal/store/arango/profile.go b/internal/store/arango/profile.go new file mode 100644 index 0000000..8630b0a --- /dev/null +++ b/internal/store/arango/profile.go @@ -0,0 +1,188 @@ +package arango + +import ( + "bytes" + "encoding/json" + "fmt" + "sort" +) + +// ProfileRequest is the parameterized body accepted by ArangoDB's cursor +// endpoint. Profile is intentionally opt-in because profiling adds execution +// overhead and is not appropriate for normal dataframe requests. +type ProfileRequest struct { + Query string `json:"query"` + BindVars map[string]any `json:"bindVars,omitempty"` + BatchSize int `json:"batchSize,omitempty"` + Count bool `json:"count,omitempty"` + Options ProfileOptions `json:"options,omitempty"` +} + +type ProfileOptions struct { + Profile int `json:"profile,omitempty"` + Optimizer OptimizerOptions `json:"optimizer,omitempty"` +} + +// ProfileResult is the first cursor response returned by a profiled query. +// ArangoDB places profiling information under extra. Result is retained as +// raw JSON because profile is a diagnostic API and must support arbitrary row +// shapes without coupling this package to dataframe models. +type ProfileResult struct { + Result []json.RawMessage `json:"result,omitempty"` + HasMore bool `json:"hasMore,omitempty"` + ID string `json:"id,omitempty"` + Count int `json:"count,omitempty"` + Cached bool `json:"cached,omitempty"` + Extra ProfileExtra `json:"extra,omitempty"` + Error bool `json:"error,omitempty"` + ErrorNum int `json:"errorNum,omitempty"` + ErrorMessage string `json:"errorMessage,omitempty"` + Code int `json:"code,omitempty"` +} + +type ProfileExtra struct { + Warnings []ExplainWarning `json:"warnings,omitempty"` + Stats ProfileStats `json:"stats,omitempty"` + Profile ProfilePhases `json:"profile,omitempty"` + Plan *ExplainPlan `json:"plan,omitempty"` +} + +type ProfileStats struct { + WritesExecuted int `json:"writesExecuted,omitempty"` + WritesIgnored int `json:"writesIgnored,omitempty"` + DocumentLookups int `json:"documentLookups,omitempty"` + Seeks int `json:"seeks,omitempty"` + ScannedFull int `json:"scannedFull,omitempty"` + ScannedIndex int `json:"scannedIndex,omitempty"` + CursorsCreated int `json:"cursorsCreated,omitempty"` + CursorsRearmed int `json:"cursorsRearmed,omitempty"` + CacheHits int `json:"cacheHits,omitempty"` + HTTPRequests int `json:"httpRequests,omitempty"` + PeakMemoryUsage uint64 `json:"peakMemoryUsage,omitempty"` + Nodes []ProfileNode `json:"nodes,omitempty"` +} + +type ProfileNode struct { + ID int64 `json:"id,omitempty"` + Calls int `json:"calls,omitempty"` + Items int `json:"items,omitempty"` + Filtered int `json:"filtered,omitempty"` + Runtime float64 `json:"runtime,omitempty"` +} + +// ProfilePhases contains the stable phase names emitted by ArangoDB. New +// server versions may add phases; unknown fields are intentionally ignored. +type ProfilePhases struct { + Initializing float64 `json:"initializing,omitempty"` + Parsing float64 `json:"parsing,omitempty"` + OptimizingAST float64 `json:"optimizing ast,omitempty"` + LoadingCollections float64 `json:"loading collections,omitempty"` + InstantiatingPlan float64 `json:"instantiating plan,omitempty"` + InstantiatingExecutors float64 `json:"instantiating executors,omitempty"` + Executing float64 `json:"executing,omitempty"` + Finalizing float64 `json:"finalizing,omitempty"` +} + +// ProfileNodeSummary is a deterministic compact view suitable for logs and +// benchmark artifacts. Node type comes from the profiled execution plan. +type ProfileNodeSummary struct { + ID int64 + Type string + Calls int + Items int + Filtered int + Runtime float64 +} + +type ProfileSummary struct { + RuntimeSeconds float64 + Nodes []ProfileNodeSummary + ByType []ProfileNodeGroup + ScannedFull int + ScannedIndex int + PeakMemory uint64 +} + +type ProfileNodeGroup struct { + Type string + NodeIDs []int64 + Calls int + Items int + Filtered int + Runtime float64 +} + +// ParseProfileResult decodes an Arango cursor response and rejects malformed +// or error envelopes. It accepts profile level 1 (phase timings) and level 2 +// (plan plus per-node timings). +func ParseProfileResult(data []byte) (ProfileResult, error) { + decoder := json.NewDecoder(bytes.NewReader(data)) + var result ProfileResult + if err := decoder.Decode(&result); err != nil { + return ProfileResult{}, fmt.Errorf("decode Arango profile response: %w", err) + } + if err := rejectTrailingJSON(decoder); err != nil { + return ProfileResult{}, err + } + if result.Error { + return ProfileResult{}, fmt.Errorf("Arango profile error %d (HTTP %d): %s", result.ErrorNum, result.Code, result.ErrorMessage) + } + return result, nil +} + +// SummarizeProfile joins runtime node statistics to the returned execution +// plan and groups them by node type. Ordering is stable: nodes and groups are +// sorted by descending runtime and then by ID/type. +func SummarizeProfile(result ProfileResult) ProfileSummary { + summary := ProfileSummary{ + ScannedFull: result.Extra.Stats.ScannedFull, + ScannedIndex: result.Extra.Stats.ScannedIndex, + PeakMemory: result.Extra.Stats.PeakMemoryUsage, + } + for _, node := range result.Extra.Stats.Nodes { + typ := "" + if result.Extra.Plan != nil { + for _, planNode := range result.Extra.Plan.Nodes { + if planNode.ID == node.ID { + typ = planNode.Type + break + } + } + } + summary.Nodes = append(summary.Nodes, ProfileNodeSummary{ID: node.ID, Type: typ, Calls: node.Calls, Items: node.Items, Filtered: node.Filtered, Runtime: node.Runtime}) + group := -1 + for i := range summary.ByType { + if summary.ByType[i].Type == typ { + group = i + break + } + } + if group < 0 { + summary.ByType = append(summary.ByType, ProfileNodeGroup{Type: typ}) + group = len(summary.ByType) - 1 + } + g := &summary.ByType[group] + g.NodeIDs = append(g.NodeIDs, node.ID) + g.Calls += node.Calls + g.Items += node.Items + g.Filtered += node.Filtered + g.Runtime += node.Runtime + summary.RuntimeSeconds += node.Runtime + } + sort.SliceStable(summary.Nodes, func(i, j int) bool { + if summary.Nodes[i].Runtime != summary.Nodes[j].Runtime { + return summary.Nodes[i].Runtime > summary.Nodes[j].Runtime + } + return summary.Nodes[i].ID < summary.Nodes[j].ID + }) + sort.SliceStable(summary.ByType, func(i, j int) bool { + if summary.ByType[i].Runtime != summary.ByType[j].Runtime { + return summary.ByType[i].Runtime > summary.ByType[j].Runtime + } + return summary.ByType[i].Type < summary.ByType[j].Type + }) + for i := range summary.ByType { + sort.Slice(summary.ByType[i].NodeIDs, func(a, b int) bool { return summary.ByType[i].NodeIDs[a] < summary.ByType[i].NodeIDs[b] }) + } + return summary +} diff --git a/internal/store/arango/profile_client.go b/internal/store/arango/profile_client.go new file mode 100644 index 0000000..c79fb76 --- /dev/null +++ b/internal/store/arango/profile_client.go @@ -0,0 +1,56 @@ +package arango + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "strings" +) + +// Profile submits a parameterized AQL query to ArangoDB's cursor endpoint +// with profiling enabled. It returns the first cursor response, which contains +// the complete profile metadata under extra. Callers should use a sufficiently +// large BatchSize when they need to profile a complete result export; normal +// dataframe execution remains on QueryRows and is never profiled implicitly. +func (c *Client) Profile(ctx context.Context, request ProfileRequest) (ProfileResult, error) { + if strings.TrimSpace(request.Query) == "" { + return ProfileResult{}, fmt.Errorf("AQL profile query is required") + } + if request.Options.Profile == 0 { + request.Options.Profile = 2 + } + body, err := json.Marshal(request) + if err != nil { + return ProfileResult{}, fmt.Errorf("encode AQL profile request: %w", err) + } + endpoint := fmt.Sprintf("%s/_db/%s/_api/cursor", strings.TrimRight(c.rawURL, "/"), url.PathEscape(c.dbName)) + httpRequest, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint, bytes.NewReader(body)) + if err != nil { + return ProfileResult{}, fmt.Errorf("create AQL profile request: %w", err) + } + httpRequest.Header.Set("Content-Type", "application/json") + response, err := c.client.Do(httpRequest) + if err != nil { + return ProfileResult{}, fmt.Errorf("send AQL profile request: %w", err) + } + defer func() { + _, _ = io.Copy(io.Discard, response.Body) + _ = response.Body.Close() + }() + responseBody, err := io.ReadAll(response.Body) + if err != nil { + return ProfileResult{}, fmt.Errorf("read AQL profile response: %w", err) + } + if response.StatusCode >= http.StatusBadRequest { + return ProfileResult{}, fmt.Errorf("AQL profile HTTP %d: %s", response.StatusCode, strings.TrimSpace(string(responseBody))) + } + result, err := ParseProfileResult(responseBody) + if err != nil { + return ProfileResult{}, err + } + return result, nil +} diff --git a/internal/store/arango/profile_client_test.go b/internal/store/arango/profile_client_test.go new file mode 100644 index 0000000..9484770 --- /dev/null +++ b/internal/store/arango/profile_client_test.go @@ -0,0 +1,59 @@ +package arango + +import ( + "bytes" + "context" + "io" + "net/http" + "strings" + "testing" +) + +func TestClientProfilePostsParameterizedCursorRequest(t *testing.T) { + client := &Client{ + rawURL: "http://arango.test", + dbName: "fhir_proto", + client: &http.Client{Transport: roundTripFunc(func(r *http.Request) (*http.Response, error) { + if r.Method != http.MethodPost || r.URL.Path != "/_db/fhir_proto/_api/cursor" { + t.Fatalf("unexpected request: %s %s", r.Method, r.URL.Path) + } + body, err := io.ReadAll(r.Body) + if err != nil { + t.Fatal(err) + } + text := string(body) + for _, fragment := range []string{`"query":"FOR p IN Patient RETURN p"`, `"bindVars":{"project":"demo"}`, `"profile":2`} { + if !strings.Contains(text, fragment) { + t.Fatalf("request body %s does not contain %s", text, fragment) + } + } + return &http.Response{ + StatusCode: http.StatusCreated, + Header: make(http.Header), + Body: io.NopCloser(bytes.NewBufferString(`{"result":[{"_key":"p1"}],"hasMore":false,"extra":{"stats":{"nodes":[{"id":1,"calls":1,"items":1,"runtime":0.01}]},"plan":{"nodes":[{"id":1,"type":"ReturnNode"}]}}}`)), + Request: r, + }, nil + })}, + } + result, err := client.Profile(context.Background(), ProfileRequest{Query: "FOR p IN Patient RETURN p", BindVars: map[string]any{"project": "demo"}}) + if err != nil { + t.Fatal(err) + } + if len(result.Result) != 1 || len(result.Extra.Stats.Nodes) != 1 { + t.Fatalf("unexpected result: %#v", result) + } +} + +func TestClientProfileRejectsHTTPError(t *testing.T) { + client := &Client{ + rawURL: "http://arango.test", + dbName: "fhir_proto", + client: &http.Client{Transport: roundTripFunc(func(r *http.Request) (*http.Response, error) { + return &http.Response{StatusCode: http.StatusBadRequest, Header: make(http.Header), Body: io.NopCloser(strings.NewReader("bad query")), Request: r}, nil + })}, + } + _, err := client.Profile(context.Background(), ProfileRequest{Query: "FOR p IN Patient RETURN p"}) + if err == nil || !strings.Contains(err.Error(), "HTTP 400") { + t.Fatalf("expected HTTP error, got %v", err) + } +} diff --git a/internal/store/arango/profile_integration_test.go b/internal/store/arango/profile_integration_test.go new file mode 100644 index 0000000..88d3324 --- /dev/null +++ b/internal/store/arango/profile_integration_test.go @@ -0,0 +1,189 @@ +package arango + +import ( + "context" + "os" + "strconv" + "strings" + "testing" + "time" +) + +// TestProfileCorpusAgainstArango is opt-in because it reads a provisioned +// Arango/META database. The queries are deliberately generic physical shapes, +// not compiler or GDC fixtures: each protects a class of AQL operation that a +// FHIR dataframe compiler must be able to emit for any schema route. +func TestProfileCorpusAgainstArango(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run Arango profile corpus") + } + url := os.Getenv("LOOM_ARANGO_URL") + if url == "" { + url = "http://127.0.0.1:8529" + } + database := os.Getenv("LOOM_ARANGO_DATABASE") + if database == "" { + database = "fhir_proto" + } + project := os.Getenv("LOOM_ARANGO_PROJECT") + if project == "" { + project = "ARANGODB_PROTO" + } + + client, err := Open(context.Background(), url, database) + if err != nil { + t.Fatalf("open Arango: %v", err) + } + defer client.Close(context.Background()) + + corpus := profileCorpus(project) + for _, shape := range corpus { + shape := shape + t.Run(shape.name, func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 90*time.Second) + defer cancel() + explain, err := client.Explain(ctx, ExplainRequest{Query: shape.query, BindVars: shape.bindVars}) + if err != nil { + t.Fatalf("EXPLAIN %s: %v\nAQL:\n%s", shape.name, err, shape.query) + } + if explain.Plan == nil && len(explain.Plans) == 0 { + t.Fatalf("EXPLAIN %s returned no plan", shape.name) + } + assessment := AssessExplainResult(explain) + t.Logf("%s explain: plans=%d full_scans=%d indexes=%d", shape.name, len(assessment.Plans), len(assessment.FullCollectionScans), len(assessment.Indexes)) + if shape.name == "root" && !assessmentHasIndexField(assessment, "Patient", "project") { + t.Fatalf("root profile corpus did not select a project index: %#v", assessment.Indexes) + } + if shape.name != "root" && !assessmentHasIndexCollection(assessment, "fhir_edge") { + t.Fatalf("%s profile corpus did not report an edge index: %#v", shape.name, assessment.Indexes) + } + + profile, err := client.Profile(ctx, ProfileRequest{ + Query: shape.query, + BindVars: shape.bindVars, + BatchSize: 1000, + Count: true, + Options: ProfileOptions{Profile: 2}, + }) + if err != nil { + t.Fatalf("PROFILE %s: %v\nAQL:\n%s", shape.name, err, shape.query) + } + if len(profile.Extra.Stats.Nodes) == 0 { + t.Fatalf("PROFILE %s returned no execution-node statistics", shape.name) + } + summary := SummarizeProfile(profile) + t.Logf("%s profile: rows=%d runtime=%0.6fs scanned_full=%d scanned_index=%d top=%s", shape.name, len(profile.Result), summary.RuntimeSeconds, summary.ScannedFull, summary.ScannedIndex, profileTopNode(summary)) + }) + } +} + +func assessmentHasIndexCollection(assessment ExplainAssessment, collection string) bool { + for _, index := range assessment.Indexes { + if index.Collection == collection { + return true + } + } + return false +} + +func assessmentHasIndexField(assessment ExplainAssessment, collection, field string) bool { + for _, index := range assessment.Indexes { + if index.Collection != collection { + continue + } + for _, candidate := range index.Fields { + if candidate == field { + return true + } + } + } + return false +} + +type profileCorpusShape struct { + name string + query string + bindVars map[string]any +} + +func profileCorpus(project string) []profileCorpusShape { + bind := func(root string) map[string]any { + return map[string]any{ + "@root_collection": root, + "project": project, + "dataset_generation": "", + "auth_resource_paths_unrestricted": true, + "auth_resource_paths": []string{}, + "limit": 5, + "label": "subject_Patient", + } + } + root := `FOR root IN @@root_collection + FILTER root.project == @project + FILTER @dataset_generation == "" OR root.dataset_generation == @dataset_generation + FILTER @auth_resource_paths_unrestricted == true OR root.auth_resource_path IN @auth_resource_paths + SORT root._key + LIMIT @limit + RETURN {"_key": root._key}` + sibling := `FOR root IN @@root_collection + FILTER root.project == @project + SORT root._key + LIMIT @limit + LET conditions = (FOR node, edge IN 1..1 INBOUND root fhir_edge + FILTER edge.project == @project AND node.project == @project + FILTER edge.label == @label AND node.resourceType == "Condition" + RETURN node._key) + LET specimens = (FOR node, edge IN 1..1 INBOUND root fhir_edge + FILTER edge.project == @project AND node.project == @project + FILTER edge.label == @label AND node.resourceType == "Specimen" + RETURN node._key) + LET observations = (FOR node, edge IN 1..1 INBOUND root fhir_edge + FILTER edge.project == @project AND node.project == @project + FILTER edge.label == @label AND node.resourceType == "Observation" + RETURN node._key) + RETURN {"_key": root._key, "conditions": conditions, "specimens": specimens, "observations": observations}` + deep := `FOR root IN @@root_collection + FILTER root.project == @project + SORT root._key + LIMIT @limit + LET descendants = (FOR first, firstEdge IN 1..1 INBOUND root fhir_edge + FILTER firstEdge.project == @project AND first.project == @project + FOR second, secondEdge IN 1..1 INBOUND first fhir_edge + FILTER secondEdge.project == @project AND second.project == @project + RETURN second._key) + RETURN {"_key": root._key, "descendants": UNIQUE(descendants)}` + required := `FOR root IN @@root_collection + FILTER root.project == @project + FILTER LENGTH(FOR node, edge IN 1..1 INBOUND root fhir_edge + FILTER edge.project == @project AND node.project == @project + FILTER edge.label == @label + LIMIT 1 + RETURN 1) > 0 + SORT root._key + LIMIT @limit + RETURN {"_key": root._key}` + pivot := `FOR root IN @@root_collection + FILTER root.project == @project + SORT root._key + LIMIT @limit + LET coding = root.payload.code.coding ? root.payload.code.coding : [] + LET pivot = (FOR value IN coding + COLLECT key = value.system INTO grouped + RETURN {"key": key, "value": FIRST(grouped).value.code}) + RETURN {"_key": root._key, "pivot": pivot}` + return []profileCorpusShape{ + {name: "root", query: root, bindVars: bind("Patient")}, + {name: "sibling", query: sibling, bindVars: bind("Patient")}, + {name: "deep", query: deep, bindVars: bind("Patient")}, + {name: "required", query: required, bindVars: bind("Patient")}, + {name: "pivot", query: pivot, bindVars: bind("Observation")}, + } +} + +func profileTopNode(summary ProfileSummary) string { + if len(summary.Nodes) == 0 { + return "none" + } + node := summary.Nodes[0] + return strings.Join([]string{node.Type, "id=" + strconv.FormatInt(node.ID, 10), "runtime=" + strconv.FormatFloat(node.Runtime, 'f', 6, 64)}, " ") +} diff --git a/internal/store/arango/profile_test.go b/internal/store/arango/profile_test.go new file mode 100644 index 0000000..32678fd --- /dev/null +++ b/internal/store/arango/profile_test.go @@ -0,0 +1,70 @@ +package arango + +import ( + "encoding/json" + "strings" + "testing" +) + +func TestProfileRequestJSONKeepsBindVarsAndProfileLevel(t *testing.T) { + request := ProfileRequest{ + Query: "FOR p IN @@collection FILTER p.project == @project RETURN p", + BindVars: map[string]any{"@collection": "Patient", "project": "demo"}, + BatchSize: 1000, + Options: ProfileOptions{Profile: 2}, + } + data, err := json.Marshal(request) + if err != nil { + t.Fatal(err) + } + for _, fragment := range []string{`"query"`, `"bindVars"`, `"batchSize":1000`, `"profile":2`} { + if !strings.Contains(string(data), fragment) { + t.Errorf("request JSON %s does not contain %s", data, fragment) + } + } +} + +func TestParseProfileResultAndSummarizeNodes(t *testing.T) { + result, err := ParseProfileResult([]byte(`{ + "result":[{"_key":"p1"}], "hasMore":false, "count":1, + "extra": { + "profile": {"initializing":0.001,"executing":1.25,"finalizing":0.002}, + "stats": {"scannedFull":3,"scannedIndex":11,"peakMemoryUsage":4096, + "nodes":[{"id":2,"calls":4,"items":100,"filtered":7,"runtime":0.75}, + {"id":3,"calls":4,"items":50,"filtered":2,"runtime":0.25}]}, + "plan": {"nodes":[{"id":1,"type":"SingletonNode"},{"id":2,"type":"TraversalNode"},{"id":3,"type":"FilterNode"}]} + } +}`)) + if err != nil { + t.Fatal(err) + } + if len(result.Result) != 1 || result.Extra.Profile.Executing != 1.25 || len(result.Extra.Stats.Nodes) != 2 { + t.Fatalf("unexpected profile fixture: %#v", result) + } + summary := SummarizeProfile(result) + if summary.RuntimeSeconds != 1.0 || summary.ScannedFull != 3 || summary.ScannedIndex != 11 || len(summary.Nodes) != 2 { + t.Fatalf("unexpected summary: %#v", summary) + } + if summary.Nodes[0].Type != "TraversalNode" || summary.Nodes[0].Runtime != 0.75 { + t.Fatalf("nodes not sorted or correlated with plan: %#v", summary.Nodes) + } + if len(summary.ByType) != 2 || summary.ByType[0].Type != "TraversalNode" { + t.Fatalf("groups not stable: %#v", summary.ByType) + } +} + +func TestParseProfileResultRejectsErrorsAndTrailingJSON(t *testing.T) { + for _, test := range []struct { + body string + want string + }{ + {`{"error":true,"errorNum":1501,"errorMessage":"parse error","code":400}`, "1501"}, + {`{"result":[]} {}`, "trailing JSON"}, + {`{`, "decode Arango"}, + } { + _, err := ParseProfileResult([]byte(test.body)) + if err == nil || !strings.Contains(err.Error(), test.want) { + t.Errorf("error = %v; want %q", err, test.want) + } + } +} From bbd1ad07090f9912533654acee1da2db6d6007dd Mon Sep 17 00:00:00 2001 From: matthewpeterkort Date: Sun, 12 Jul 2026 14:12:56 -0700 Subject: [PATCH 04/15] add confomrance fixtures --- conformance/compiler/benchmark_test.go | 112 + conformance/compiler/corpus_coverage_test.go | 48 + .../compiler/fixtures/gdc-case-matrix.json | 102 + .../fixtures/observation-pivot-filter.json | 31 + .../fixtures/patient-deep-filter.json | 37 + .../fixtures/patient-sibling-targets.json | 23 + .../fixtures/patient-temporal-filter.json | 27 + .../fixtures/patient_observation_pivot.json | 29 + .../fixtures/patient_specimen_file.json | 31 + .../research-subject-study-required.json | 25 + .../fixtures/specimen-aggregate-slice.json | 31 + .../specimen-file-filter-aggregate.json | 34 + .../unsupported_simple_projection.json | 19 + .../fixtures/unsupported_specimen_root.json | 19 + .../fixtures/unsupported_unknown_root.json | 16 + conformance/compiler/gdc_fixture_test.go | 87 + .../generated_semantics_coverage_test.go | 182 + .../compiler/physical_plan_cost_test.go | 39 + conformance/compiler/run.go | 72 + conformance/compiler/run_test.go | 20 + conformance/compiler/schema_roots_test.go | 46 + conformance/compiler/test_helpers_test.go | 7 + conformance/compiler/types.go | 105 + conformance/compiler/types_test.go | 57 + fhirstructs/extract.go | 80173 ++++++++++++++++ fhirstructs/helpers.go | 143 + fhirstructs/model.go | 3044 + fhirstructs/validate.go | 14864 +++ 28 files changed, 99423 insertions(+) create mode 100644 conformance/compiler/benchmark_test.go create mode 100644 conformance/compiler/corpus_coverage_test.go create mode 100644 conformance/compiler/fixtures/gdc-case-matrix.json create mode 100644 conformance/compiler/fixtures/observation-pivot-filter.json create mode 100644 conformance/compiler/fixtures/patient-deep-filter.json create mode 100644 conformance/compiler/fixtures/patient-sibling-targets.json create mode 100644 conformance/compiler/fixtures/patient-temporal-filter.json create mode 100644 conformance/compiler/fixtures/patient_observation_pivot.json create mode 100644 conformance/compiler/fixtures/patient_specimen_file.json create mode 100644 conformance/compiler/fixtures/research-subject-study-required.json create mode 100644 conformance/compiler/fixtures/specimen-aggregate-slice.json create mode 100644 conformance/compiler/fixtures/specimen-file-filter-aggregate.json create mode 100644 conformance/compiler/fixtures/unsupported_simple_projection.json create mode 100644 conformance/compiler/fixtures/unsupported_specimen_root.json create mode 100644 conformance/compiler/fixtures/unsupported_unknown_root.json create mode 100644 conformance/compiler/gdc_fixture_test.go create mode 100644 conformance/compiler/generated_semantics_coverage_test.go create mode 100644 conformance/compiler/physical_plan_cost_test.go create mode 100644 conformance/compiler/run.go create mode 100644 conformance/compiler/run_test.go create mode 100644 conformance/compiler/schema_roots_test.go create mode 100644 conformance/compiler/test_helpers_test.go create mode 100644 conformance/compiler/types.go create mode 100644 conformance/compiler/types_test.go create mode 100644 fhirstructs/extract.go create mode 100644 fhirstructs/helpers.go create mode 100644 fhirstructs/model.go create mode 100644 fhirstructs/validate.go diff --git a/conformance/compiler/benchmark_test.go b/conformance/compiler/benchmark_test.go new file mode 100644 index 0000000..590d8d0 --- /dev/null +++ b/conformance/compiler/benchmark_test.go @@ -0,0 +1,112 @@ +package compilerfixture + +import ( + "fmt" + "path/filepath" + "slices" + "testing" + + "github.com/calypr/loom/internal/dataframe" + "github.com/calypr/loom/fhirschema" +) + +type compilerBenchmarkCase struct { + name string + builder dataframe.Builder + limit int +} + +var ( + benchmarkCompiled dataframe.CompiledQuery + benchmarkErr error +) + +// BenchmarkCompilerOracle measures pure lowering and AQL rendering for the +// checked-in oracle requests and every root advertised by generated metadata. +// Unsupported oracle cases are intentionally included: deterministic rejection +// is part of compiler cost and conformance behavior. +func BenchmarkCompilerOracle(b *testing.B) { + cases := loadCompilerBenchmarkCases(b) + for _, testCase := range cases { + testCase := testCase + b.Run(testCase.name, func(b *testing.B) { + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + benchmarkCompiled, benchmarkErr = dataframe.CompileRequest(testCase.builder, testCase.limit) + } + }) + } +} + +func TestCompilerBenchmarkEnumerationIsStable(t *testing.T) { + first := loadCompilerBenchmarkCases(t) + second := loadCompilerBenchmarkCases(t) + firstNames := benchmarkCaseNames(first) + secondNames := benchmarkCaseNames(second) + if !slices.Equal(firstNames, secondNames) { + t.Fatalf("benchmark enumeration changed between reads:\nfirst: %v\nsecond: %v", firstNames, secondNames) + } + if len(firstNames) == 0 { + t.Fatal("benchmark enumeration is empty") + } + seen := make(map[string]struct{}, len(firstNames)) + for _, name := range firstNames { + if _, duplicate := seen[name]; duplicate { + t.Fatalf("duplicate benchmark case %q", name) + } + seen[name] = struct{}{} + } + + fixtures, err := LoadDir(filepath.Join("fixtures")) + if err != nil { + t.Fatal(err) + } + wantCount := len(fixtures) + len(fhirschema.ResourceTypes()) + if len(firstNames) != wantCount { + t.Fatalf("benchmark case count = %d, want %d fixtures plus generated roots", len(firstNames), wantCount) + } +} + +type benchmarkTestingT interface { + Helper() + Fatal(args ...any) +} + +func loadCompilerBenchmarkCases(t benchmarkTestingT) []compilerBenchmarkCase { + t.Helper() + fixtures, err := LoadDir(filepath.Join("fixtures")) + if err != nil { + t.Fatal(err) + } + cases := make([]compilerBenchmarkCase, 0, len(fixtures)+len(fhirschema.ResourceTypes())) + for _, fixture := range fixtures { + cases = append(cases, compilerBenchmarkCase{ + name: "fixture/" + fixture.ID, + builder: fixture.Builder, + limit: fixture.Limit, + }) + } + for _, resourceType := range fhirschema.ResourceTypes() { + cases = append(cases, compilerBenchmarkCase{ + name: "generated-root/" + resourceType, + builder: dataframe.Builder{ + Project: "compiler-benchmark", + RootResourceType: resourceType, + }, + limit: 1, + }) + } + return cases +} + +func benchmarkCaseNames(cases []compilerBenchmarkCase) []string { + names := make([]string, len(cases)) + for index, testCase := range cases { + if testCase.name == "" { + panic(fmt.Sprintf("benchmark case %d has no name", index)) + } + names[index] = testCase.name + } + return names +} diff --git a/conformance/compiler/corpus_coverage_test.go b/conformance/compiler/corpus_coverage_test.go new file mode 100644 index 0000000..12e7c9f --- /dev/null +++ b/conformance/compiler/corpus_coverage_test.go @@ -0,0 +1,48 @@ +package compilerfixture + +import ( + "path/filepath" + "testing" +) + +// TestGenericFHIRCorpusCoverage keeps the optimization benchmark honest. The +// GDC request is intentionally only one mixed-shape case; each independent +// semantic feature must also have a small fixture that can be compiled and +// profiled in isolation. +func TestGenericFHIRCorpusCoverage(t *testing.T) { + fixtures, err := LoadDir(filepath.Join("fixtures")) + if err != nil { + t.Fatal(err) + } + want := map[string]string{ + "patient-sibling-targets": "sibling", + "research-subject-study-required": "outbound", + "patient-deep-filter": "deep", + "specimen-aggregate-slice": "reuse", + "observation-pivot-filter": "pivot", + } + byID := make(map[string]Fixture, len(fixtures)) + for _, fixture := range fixtures { + byID[fixture.ID] = fixture + } + for id, tag := range want { + fixture, ok := byID[id] + if !ok { + t.Errorf("required generic corpus fixture %q is missing", id) + continue + } + found := false + for _, candidate := range fixture.Tags { + if candidate == tag { + found = true + break + } + } + if !found { + t.Errorf("fixture %q does not declare coverage tag %q (tags=%v)", id, tag, fixture.Tags) + } + if !fixture.Expected.Supported { + t.Errorf("generic corpus fixture %q must be a supported compile case", id) + } + } +} diff --git a/conformance/compiler/fixtures/gdc-case-matrix.json b/conformance/compiler/fixtures/gdc-case-matrix.json new file mode 100644 index 0000000..d1edec3 --- /dev/null +++ b/conformance/compiler/fixtures/gdc-case-matrix.json @@ -0,0 +1,102 @@ +{ + "schema": "loom.compiler-oracle/v1", + "id": "gdc-case-matrix", + "description": "GDC-style patient dataframe with diagnoses, samples, files, groups, observations, pivots, slices, and nested traversal sets", + "tags": ["supported", "gdc", "patient", "nested", "aggregate", "pivot", "slice"], + "limit": 25, + "builder": { + "Project": "ARANGODB_PROTO", + "RootResourceType": "Patient", + "Fields": [ + {"Name": "patient_id", "Select": "id", "ValueMode": "AUTO"}, + {"Name": "case_identifier", "Select": "identifier[].value", "ValueMode": "AUTO"}, + {"Name": "gender", "Select": "gender", "ValueMode": "AUTO"} + ], + "Traversals": [ + { + "Label": "subject_Patient", + "ToResourceType": "Condition", + "Alias": "diagnosis", + "Aggregates": [ + {"Name": "diagnosis_count", "Operation": "COUNT"}, + {"Name": "diagnosis_values", "Operation": "DISTINCT_VALUES", "Select": "code.coding[].display", "ValueMode": "AUTO"} + ], + "Slices": [ + {"Name": "representative_diagnoses", "Limit": 3, "Fields": [ + {"Name": "diagnosis_id", "Select": "id", "ValueMode": "AUTO"}, + {"Name": "diagnosis", "Select": "code.coding[].display", "ValueMode": "AUTO"} + ]} + ] + }, + { + "Label": "subject_Patient", + "ToResourceType": "Specimen", + "Alias": "sample", + "Aggregates": [ + {"Name": "sample_count", "Operation": "COUNT"}, + {"Name": "sample_types", "Operation": "DISTINCT_VALUES", "Select": "type.coding[].display", "ValueMode": "AUTO"} + ], + "Slices": [ + {"Name": "representative_samples", "Limit": 5, "Fields": [ + {"Name": "sample_id", "Select": "id", "ValueMode": "AUTO"}, + {"Name": "sample_type", "Select": "type.coding[].display", "ValueMode": "AUTO"} + ]} + ], + "Traversals": [ + { + "Label": "subject_Specimen", + "ToResourceType": "DocumentReference", + "Alias": "file", + "Aggregates": [ + {"Name": "file_count", "Operation": "COUNT"}, + {"Name": "file_names", "Operation": "DISTINCT_VALUES", "Select": "content[].attachment.title", "ValueMode": "AUTO"}, + {"Name": "file_formats", "Operation": "DISTINCT_VALUES", "Select": "type.coding[].display", "ValueMode": "AUTO"} + ], + "Slices": [ + {"Name": "representative_files", "Limit": 10, "Fields": [ + {"Name": "file_id", "Select": "id", "ValueMode": "AUTO"}, + {"Name": "file_name", "Select": "content[].attachment.title", "ValueMode": "AUTO"}, + {"Name": "file_url", "Select": "content[].attachment.url", "ValueMode": "AUTO"}, + {"Name": "file_size", "Select": "content[].attachment.size", "ValueMode": "AUTO"}, + {"Name": "file_format", "Select": "type.coding[].display", "ValueMode": "AUTO"} + ]} + ] + }, + { + "Label": "member_entity_Specimen", + "ToResourceType": "Group", + "Alias": "sample_group", + "Aggregates": [{"Name": "sample_group_count", "Operation": "COUNT"}], + "Traversals": [{ + "Label": "subject_Group", + "ToResourceType": "DocumentReference", + "Alias": "group_file", + "Aggregates": [{"Name": "group_file_count", "Operation": "COUNT"}] + }] + } + ] + }, + { + "Label": "subject_Patient", + "ToResourceType": "Observation", + "Alias": "observation", + "Aggregates": [ + {"Name": "observation_count", "Operation": "COUNT"}, + {"Name": "observation_codes", "Operation": "DISTINCT_VALUES", "Select": "code.coding[].display", "ValueMode": "AUTO"} + ], + "Pivots": [{ + "Name": "observation_values", + "ColumnSelect": "code.coding[].display", + "ValueSelect": "valueQuantity.value", + "Columns": ["Tumor Purity", "Hemoglobin", "Platelet Count", "White Blood Cell Count"] + }] + } + ] + }, + "expected": { + "supported": true, + "planProfile": "generic_fhir_graph", + "bindVars": {"project": "ARANGODB_PROTO", "limit": 25}, + "outputColumns": ["patient_id", "case_identifier", "gender", "sample__sample_count", "observation__observation_count"] + } +} diff --git a/conformance/compiler/fixtures/observation-pivot-filter.json b/conformance/compiler/fixtures/observation-pivot-filter.json new file mode 100644 index 0000000..826b242 --- /dev/null +++ b/conformance/compiler/fixtures/observation-pivot-filter.json @@ -0,0 +1,31 @@ +{ + "schema": "loom.compiler-oracle/v1", + "id": "observation-pivot-filter", + "description": "Observation-root pivot with a typed status filter and sparse value columns", + "tags": ["supported", "observation", "pivot", "filter"], + "limit": 100, + "builder": { + "Project": "oracle-project", + "RootResourceType": "Observation", + "Fields": [{"Name": "observation_id", "Select": "id"}], + "Filters": [{ + "fieldRef": "Observation.status", + "selector": "status", + "fieldKind": "STRING", + "operator": "EQUALS", + "values": [{"kind": "STRING", "string": "final"}] + }], + "Pivots": [{ + "Name": "lab_values", + "ColumnSelect": "code.coding[].display", + "ValueSelect": "valueQuantity.value", + "Columns": ["Hemoglobin", "Platelet Count", "White Blood Cell Count"] + }] + }, + "expected": { + "supported": true, + "planProfile": "generic_fhir_graph", + "bindVars": {"project": "oracle-project", "limit": 100}, + "outputColumns": ["observation_id"] + } +} diff --git a/conformance/compiler/fixtures/patient-deep-filter.json b/conformance/compiler/fixtures/patient-deep-filter.json new file mode 100644 index 0000000..395d706 --- /dev/null +++ b/conformance/compiler/fixtures/patient-deep-filter.json @@ -0,0 +1,37 @@ +{ + "schema": "loom.compiler-oracle/v1", + "id": "patient-deep-filter", + "description": "Three-hop Patient to Specimen to DocumentReference traversal with a typed child filter", + "tags": ["supported", "patient", "deep", "filter", "nested"], + "limit": 50, + "builder": { + "Project": "oracle-project", + "RootResourceType": "Patient", + "Fields": [{"Name": "patient_id", "Select": "id"}], + "Traversals": [{ + "Label": "subject_Patient", + "ToResourceType": "Specimen", + "Alias": "specimen", + "Traversals": [{ + "Label": "subject_Specimen", + "ToResourceType": "DocumentReference", + "Alias": "file", + "Filters": [{ + "fieldRef": "DocumentReference.file_name", + "selector": "content[].attachment.title", + "fieldKind": "STRING", + "repeated": true, + "quantifier": "ANY", + "operator": "EXISTS" + }], + "Fields": [{"Name": "file_name", "Select": "content[].attachment.title"}] + }] + }] + }, + "expected": { + "supported": true, + "planProfile": "generic_fhir_graph", + "bindVars": {"project": "oracle-project", "limit": 50}, + "outputColumns": ["patient_id"] + } +} diff --git a/conformance/compiler/fixtures/patient-sibling-targets.json b/conformance/compiler/fixtures/patient-sibling-targets.json new file mode 100644 index 0000000..6812077 --- /dev/null +++ b/conformance/compiler/fixtures/patient-sibling-targets.json @@ -0,0 +1,23 @@ +{ + "schema": "loom.compiler-oracle/v1", + "id": "patient-sibling-targets", + "description": "Patient dataframe with sibling Condition, Specimen, and Observation routes sharing one edge label", + "tags": ["supported", "patient", "sibling", "sharing", "aggregate"], + "limit": 100, + "builder": { + "Project": "oracle-project", + "RootResourceType": "Patient", + "Fields": [{"Name": "patient_id", "Select": "id"}], + "Traversals": [ + {"Label": "subject_Patient", "ToResourceType": "Condition", "Alias": "condition", "Aggregates": [{"Name": "condition_count", "Operation": "COUNT"}]}, + {"Label": "subject_Patient", "ToResourceType": "Specimen", "Alias": "specimen", "Aggregates": [{"Name": "specimen_count", "Operation": "COUNT"}]}, + {"Label": "subject_Patient", "ToResourceType": "Observation", "Alias": "observation", "Aggregates": [{"Name": "observation_count", "Operation": "COUNT"}]} + ] + }, + "expected": { + "supported": true, + "planProfile": "generic_fhir_graph", + "bindVars": {"project": "oracle-project", "limit": 100}, + "outputColumns": ["patient_id", "condition__condition_count", "specimen__specimen_count", "observation__observation_count"] + } +} diff --git a/conformance/compiler/fixtures/patient-temporal-filter.json b/conformance/compiler/fixtures/patient-temporal-filter.json new file mode 100644 index 0000000..6130381 --- /dev/null +++ b/conformance/compiler/fixtures/patient-temporal-filter.json @@ -0,0 +1,27 @@ +{ + "schema": "loom.compiler-oracle/v1", + "id": "patient-temporal-filter", + "description": "Patient date filtering is type checked from generated FHIR metadata and normalized for ordered comparison", + "tags": ["supported", "patient", "filter", "date"], + "limit": 25, + "builder": { + "Project": "oracle-project", + "RootResourceType": "Patient", + "Fields": [{"Name": "birth_date", "Select": "birthDate"}], + "Filters": [{ + "fieldRef": "Patient.birth_date", + "selector": "birthDate", + "fieldKind": "DATE", + "operator": "GTE", + "values": [{"kind": "DATE", "date": "1980-01-01"}] + }] + }, + "expected": { + "supported": true, + "planProfile": "generic_fhir_graph", + "optimizerRules": ["push_down_typed_filters"], + "queryContains": ["DATE_TIMESTAMP(", "DATE_TIMESTAMP(@"], + "bindVars": {"project": "oracle-project", "limit": 25}, + "outputColumns": ["birth_date"] + } +} diff --git a/conformance/compiler/fixtures/patient_observation_pivot.json b/conformance/compiler/fixtures/patient_observation_pivot.json new file mode 100644 index 0000000..deafc1a --- /dev/null +++ b/conformance/compiler/fixtures/patient_observation_pivot.json @@ -0,0 +1,29 @@ +{ + "schema": "loom.compiler-oracle/v1", + "id": "patient-observation-pivot", + "description": "Patient-grain sparse Observation pivot", + "tags": ["supported", "patient", "observation", "pivot"], + "limit": 10, + "builder": { + "Project": "oracle-project", + "RootResourceType": "Patient", + "Traversals": [{ + "Label": "subject_Patient", + "ToResourceType": "Observation", + "Alias": "observation", + "Pivots": [{ + "Name": "lab_values", + "ColumnSelect": "code.coding[].display", + "ValueSelect": "valueQuantity.value", + "Columns": ["Tumor Purity", "Hemoglobin"] + }] + }] + }, + "expected": { + "supported": true, + "planProfile": "generic_fhir_graph", + "queryContains": ["MERGE(", "FILTER LENGTH(__pivot_values) > 0"], + "bindVars": {"project": "oracle-project", "limit": 10}, + "expectedTraversalSets": 1 + } +} diff --git a/conformance/compiler/fixtures/patient_specimen_file.json b/conformance/compiler/fixtures/patient_specimen_file.json new file mode 100644 index 0000000..4ca181a --- /dev/null +++ b/conformance/compiler/fixtures/patient_specimen_file.json @@ -0,0 +1,31 @@ +{ + "schema": "loom.compiler-oracle/v1", + "id": "patient-specimen-file", + "description": "Patient-grain projection through specimen to DocumentReference", + "tags": ["supported", "patient", "specimen", "document-reference"], + "limit": 25, + "builder": { + "Project": "oracle-project", + "RootResourceType": "Patient", + "Fields": [{"Name": "gender", "Select": "gender"}], + "Traversals": [{ + "Label": "subject_Patient", + "ToResourceType": "Specimen", + "Alias": "specimen", + "Fields": [{"Name": "specimen_type", "Select": "type.coding[].display"}], + "Traversals": [{ + "Label": "subject_Specimen", + "ToResourceType": "DocumentReference", + "Alias": "file", + "Fields": [{"Name": "file_name", "Select": "content[].attachment.title"}] + }] + }] + }, + "expected": { + "supported": true, + "planProfile": "generic_fhir_graph", + "queryContains": ["FOR root IN @@root_collection", "LIMIT @limit"], + "bindVars": {"project": "oracle-project", "limit": 25}, + "expectedTraversalSets": 2 + } +} diff --git a/conformance/compiler/fixtures/research-subject-study-required.json b/conformance/compiler/fixtures/research-subject-study-required.json new file mode 100644 index 0000000..b6f49c0 --- /dev/null +++ b/conformance/compiler/fixtures/research-subject-study-required.json @@ -0,0 +1,25 @@ +{ + "schema": "loom.compiler-oracle/v1", + "id": "research-subject-study-required", + "description": "Required outbound ResearchSubject to ResearchStudy relationship", + "tags": ["supported", "research-subject", "outbound", "required"], + "limit": 25, + "builder": { + "Project": "oracle-project", + "RootResourceType": "ResearchSubject", + "Fields": [{"Name": "status", "Select": "status"}], + "Traversals": [{ + "Label": "study", + "ToResourceType": "ResearchStudy", + "Alias": "study", + "MatchMode": "REQUIRED", + "Fields": [{"Name": "study_title", "Select": "title"}] + }] + }, + "expected": { + "supported": true, + "planProfile": "generic_fhir_graph", + "bindVars": {"project": "oracle-project", "limit": 25}, + "outputColumns": ["status", "study__study_title"] + } +} diff --git a/conformance/compiler/fixtures/specimen-aggregate-slice.json b/conformance/compiler/fixtures/specimen-aggregate-slice.json new file mode 100644 index 0000000..622d588 --- /dev/null +++ b/conformance/compiler/fixtures/specimen-aggregate-slice.json @@ -0,0 +1,31 @@ +{ + "schema": "loom.compiler-oracle/v1", + "id": "specimen-aggregate-slice", + "description": "Specimen dataframe combining child count, distinct values, and a bounded representative file slice", + "tags": ["supported", "specimen", "aggregate", "slice", "reuse"], + "limit": 100, + "builder": { + "Project": "oracle-project", + "RootResourceType": "Specimen", + "Fields": [{"Name": "specimen_id", "Select": "id"}], + "Traversals": [{ + "Label": "subject_Specimen", + "ToResourceType": "DocumentReference", + "Alias": "file", + "Aggregates": [ + {"Name": "file_count", "Operation": "COUNT"}, + {"Name": "file_formats", "Operation": "DISTINCT_VALUES", "Select": "type.coding[].display", "ValueMode": "AUTO"} + ], + "Slices": [{"Name": "representative_files", "Limit": 3, "Fields": [ + {"Name": "file_id", "Select": "id"}, + {"Name": "file_name", "Select": "content[].attachment.title"} + ]}] + }] + }, + "expected": { + "supported": true, + "planProfile": "generic_fhir_graph", + "bindVars": {"project": "oracle-project", "limit": 100}, + "outputColumns": ["specimen_id", "file__file_count", "file__file_formats"] + } +} diff --git a/conformance/compiler/fixtures/specimen-file-filter-aggregate.json b/conformance/compiler/fixtures/specimen-file-filter-aggregate.json new file mode 100644 index 0000000..0b52ae4 --- /dev/null +++ b/conformance/compiler/fixtures/specimen-file-filter-aggregate.json @@ -0,0 +1,34 @@ +{ + "schema": "loom.compiler-oracle/v1", + "id": "specimen-file-filter-aggregate", + "description": "Generic Specimen traversal pushes a child existence filter into the DocumentReference set before counting it", + "tags": ["supported", "specimen", "document-reference", "filter", "aggregate"], + "limit": 25, + "builder": { + "Project": "oracle-project", + "RootResourceType": "Specimen", + "Traversals": [{ + "Label": "subject_Specimen", + "ToResourceType": "DocumentReference", + "Alias": "file", + "Filters": [{ + "fieldRef": "DocumentReference.file_name", + "selector": "content[].attachment.title", + "fieldKind": "STRING", + "repeated": true, + "quantifier": "ANY", + "operator": "EXISTS" + }], + "Aggregates": [{"Name": "file_count", "Operation": "COUNT"}] + }] + }, + "expected": { + "supported": true, + "planProfile": "generic_fhir_graph", + "optimizerRules": ["push_down_typed_filters"], + "queryContains": ["LET child_set_1 = UNIQUE(", "FILTER LENGTH(("], + "bindVars": {"project": "oracle-project", "limit": 25}, + "outputColumns": ["file__file_count"], + "expectedTraversalSets": 1 + } +} diff --git a/conformance/compiler/fixtures/unsupported_simple_projection.json b/conformance/compiler/fixtures/unsupported_simple_projection.json new file mode 100644 index 0000000..80952ca --- /dev/null +++ b/conformance/compiler/fixtures/unsupported_simple_projection.json @@ -0,0 +1,19 @@ +{ + "schema": "loom.compiler-oracle/v1", + "id": "patient-simple-projection", + "description": "Patient root-only projection uses the generic FHIR graph plan", + "tags": ["supported", "patient", "root-only"], + "limit": 25, + "builder": { + "Project": "oracle-project", + "RootResourceType": "Patient", + "Fields": [{"Name": "gender", "Select": "gender"}] + }, + "expected": { + "supported": true, + "planProfile": "generic_fhir_graph", + "queryContains": ["FOR root IN @@root_collection", "root.payload.gender"], + "bindVars": {"project": "oracle-project", "limit": 25}, + "outputColumns": ["gender"] + } +} diff --git a/conformance/compiler/fixtures/unsupported_specimen_root.json b/conformance/compiler/fixtures/unsupported_specimen_root.json new file mode 100644 index 0000000..934a675 --- /dev/null +++ b/conformance/compiler/fixtures/unsupported_specimen_root.json @@ -0,0 +1,19 @@ +{ + "schema": "loom.compiler-oracle/v1", + "id": "specimen-root-projection", + "description": "Specimen root-only projection uses the generic FHIR graph plan", + "tags": ["supported", "specimen", "root-only"], + "limit": 25, + "builder": { + "Project": "oracle-project", + "RootResourceType": "Specimen", + "Fields": [{"Name": "specimen_type", "Select": "type.coding[].display"}] + }, + "expected": { + "supported": true, + "planProfile": "generic_fhir_graph", + "queryContains": ["FOR root IN @@root_collection"], + "bindVars": {"project": "oracle-project", "limit": 25}, + "outputColumns": ["specimen_type"] + } +} diff --git a/conformance/compiler/fixtures/unsupported_unknown_root.json b/conformance/compiler/fixtures/unsupported_unknown_root.json new file mode 100644 index 0000000..556da6d --- /dev/null +++ b/conformance/compiler/fixtures/unsupported_unknown_root.json @@ -0,0 +1,16 @@ +{ + "schema": "loom.compiler-oracle/v1", + "id": "unsupported-unknown-root", + "description": "Unknown roots fail before AQL collection interpolation", + "tags": ["unsupported", "safety"], + "limit": 25, + "builder": { + "Project": "oracle-project", + "RootResourceType": "NotAResource", + "Fields": [{"Name": "anything", "Select": "anything"}] + }, + "expected": { + "supported": false, + "errorContains": "not represented by the active generated FHIR schema" + } +} diff --git a/conformance/compiler/gdc_fixture_test.go b/conformance/compiler/gdc_fixture_test.go new file mode 100644 index 0000000..9a7cadc --- /dev/null +++ b/conformance/compiler/gdc_fixture_test.go @@ -0,0 +1,87 @@ +package compilerfixture + +import ( + "path/filepath" + "strings" + "testing" + + "github.com/calypr/loom/internal/dataframe" +) + +// TestGDCFixtureCoversRichShape keeps the checked-in benchmark representative +// of the dataframe users actually want to build. It is intentionally a corpus +// test, not a compiler test: as physical feature families land, the same +// request remains the parity and Arango-cost benchmark target. +func TestGDCFixtureCoversRichShape(t *testing.T) { + fixtures, err := LoadDir(filepath.Join("fixtures")) + if err != nil { + t.Fatal(err) + } + var fixture Fixture + for _, candidate := range fixtures { + if candidate.ID == "gdc-case-matrix" { + fixture = candidate + break + } + } + if fixture.ID == "" { + t.Fatal("gdc-case-matrix fixture is missing") + } + if !hasField(fixture.Builder.Fields, "patient_id") || !hasField(fixture.Builder.Fields, "case_identifier") { + t.Fatal("GDC fixture must retain patient identity and case identifier fields") + } + var hasPivot, hasSlice, hasAggregate bool + maxDepth := 0 + var walk func([]dataframe.TraversalStep, int) + walk = func(steps []dataframe.TraversalStep, depth int) { + if depth > maxDepth { + maxDepth = depth + } + for _, step := range steps { + if len(step.Pivots) != 0 { + hasPivot = true + } + if len(step.Slices) != 0 { + hasSlice = true + } + if len(step.Aggregates) != 0 { + hasAggregate = true + } + walk(step.Traversals, depth+1) + } + } + walk(fixture.Builder.Traversals, 1) + if !hasPivot || !hasSlice || !hasAggregate { + t.Fatalf("GDC fixture coverage pivot=%t slice=%t aggregate=%t", hasPivot, hasSlice, hasAggregate) + } + if maxDepth < 3 { + t.Fatalf("GDC fixture max traversal depth = %d, want at least 3", maxDepth) + } + if !strings.Contains(fixture.Description, "nested") { + t.Fatal("GDC fixture description should identify nested shaping") + } + compiled, err := dataframe.CompileRequest(fixture.Builder, 1000) + if err != nil { + t.Fatalf("compile rich GDC fixture: %v", err) + } + diagnostics := compiled.PlanDiagnostics + t.Logf("GDC compiler plan: traversal_sets=%d shared=%d scope_safe_sharing_groups=%d scope_safe_sharing_sets=%d potential_sharing_groups=%d potential_sharing_sets=%d rich_reuse=%#v", diagnostics.TraversalSets, diagnostics.SharedTraversalCount, diagnostics.ScopedSharingCandidateGroups, diagnostics.ScopedSharingCandidateSets, diagnostics.PotentialSharingOpportunityGroups, diagnostics.PotentialSharingOpportunitySets, diagnostics.RichSourceReuse) + if diagnostics.TraversalSets == 0 { + t.Fatal("rich GDC fixture produced no physical traversal sets") + } + if diagnostics.SharedTraversalCount == 0 && diagnostics.PotentialSharingOpportunityGroups == 0 { + t.Fatal("rich GDC fixture should expose traversal-sharing work") + } + if len(diagnostics.RichSourceReuse) == 0 { + t.Fatal("rich GDC fixture should expose repeated rich source consumers") + } +} + +func hasField(fields []dataframe.FieldSelect, name string) bool { + for _, field := range fields { + if field.Name == name { + return true + } + } + return false +} diff --git a/conformance/compiler/generated_semantics_coverage_test.go b/conformance/compiler/generated_semantics_coverage_test.go new file mode 100644 index 0000000..c6bc32e --- /dev/null +++ b/conformance/compiler/generated_semantics_coverage_test.go @@ -0,0 +1,182 @@ +package compilerfixture + +import ( + "encoding/json" + "fmt" + "os" + "path/filepath" + "regexp" + "sort" + "strings" + "testing" + + "github.com/calypr/loom/internal/dataframe" + "github.com/calypr/loom/fhirschema" +) + +func TestPublicCompilerAcceptsEveryGeneratedFHIRRoot(t *testing.T) { + resourceTypes := fhirschema.ResourceTypes() + if len(resourceTypes) == 0 { + t.Fatal("generated FHIR schema advertises no resource roots") + } + for _, resourceType := range resourceTypes { + t.Run(resourceType, func(t *testing.T) { + compiled, err := dataframe.CompileRequest(dataframe.Builder{ + Project: "compiler-oracle", + RootResourceType: resourceType, + }, 1) + if err != nil { + t.Fatalf("CompileRequest(%s): %v", resourceType, err) + } + assertOnlyValidatedRootCollection(t, compiled, resourceType) + if compiled.PlanProfile != "generic_fhir_graph" { + t.Fatalf("plan profile = %q, want generic_fhir_graph", compiled.PlanProfile) + } + }) + } +} + +func TestPublicCompilerAcceptsEveryGeneratedBuilderTraversal(t *testing.T) { + traversals := loadGeneratedBuilderTraversals(t) + if len(traversals) == 0 { + t.Fatal("no compiler-visible generated catalog traversals found") + } + for _, traversal := range traversals { + name := traversal.FromType + "__" + traversal.EdgeLabel + "__" + traversal.ToType + t.Run(name, func(t *testing.T) { + compiled, err := dataframe.CompileRequest(dataframe.Builder{ + Project: "compiler-oracle", + RootResourceType: traversal.FromType, + Traversals: []dataframe.TraversalStep{{ + Label: traversal.EdgeLabel, + ToResourceType: traversal.ToType, + Alias: "related", + }}, + }, 1) + if err != nil { + t.Fatalf("CompileRequest(%s -> %s via %s): %v", traversal.FromType, traversal.ToType, traversal.EdgeLabel, err) + } + assertOnlyValidatedRootCollection(t, compiled, traversal.FromType) + if compiled.PlanProfile != "generic_fhir_graph" { + t.Fatalf("plan profile = %q, want generic_fhir_graph", compiled.PlanProfile) + } + if !bindVarsContain(compiled.BindVars, traversal.ToType) { + t.Fatalf("target resource type %q is not represented as a bind value: %#v", traversal.ToType, compiled.BindVars) + } + }) + } +} + +func TestPublicCompilerRejectsUnadvertisedRootBeforeRenderingAQL(t *testing.T) { + malicious := "Patient REMOVE root IN Patient" + if fhirschema.HasResource(malicious) { + t.Fatal("test root unexpectedly advertised by schema") + } + compiled, err := dataframe.CompileRequest(dataframe.Builder{ + Project: "compiler-oracle", + RootResourceType: malicious, + }, 1) + if err == nil || !strings.Contains(err.Error(), "not represented by the active generated FHIR schema") { + t.Fatalf("error = %v, want generated-schema rejection", err) + } + if compiled.Query != "" { + t.Fatalf("unsafe root produced AQL: %s", compiled.Query) + } +} + +type graphSchemaDocument struct { + Definitions map[string]struct { + Links []struct { + Relation string `json:"rel"` + Target struct { + Reference string `json:"$ref"` + } `json:"targetSchema"` + } `json:"links"` + } `json:"$defs"` +} + +// loadGeneratedBuilderTraversals derives the same parent -> related-child +// orientation exposed by Loom's populated-reference catalog. A graph-schema +// link describes the stored forward FHIR reference (child -> parent), while +// the dataframe builder intentionally follows its generated reverse route +// (parent -> child) through INBOUND fhir_edge traversal. This coverage stays +// on that broad route family; the one separately proven forward contract +// (ResearchSubject --study--> ResearchStudy) has focused storage-route and +// extractor regressions. Other forward links remain unproven and must not be +// blessed by this generic coverage loop. +func loadGeneratedBuilderTraversals(t *testing.T) []fhirschema.CompilerTraversal { + t.Helper() + path := filepath.Join("..", "..", "schemas", "graph-fhir.json") + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("read active graph schema %s: %v", path, err) + } + var document graphSchemaDocument + if err := json.Unmarshal(data, &document); err != nil { + t.Fatalf("decode active graph schema: %v", err) + } + + seen := map[string]fhirschema.CompilerTraversal{} + for childType, definition := range document.Definitions { + if !fhirschema.HasResource(childType) { + continue + } + for _, link := range definition.Links { + parentType := referenceName(link.Target.Reference) + if !fhirschema.HasResource(parentType) { + continue + } + traversal, found, err := fhirschema.ResolveCompilerTraversal(parentType, link.Relation, childType) + if err != nil { + t.Fatalf("normalize generated builder traversal %s -> %s (%s): %v", parentType, childType, link.Relation, err) + } + if !found { + t.Fatalf("generated builder traversal missing from compiler API: %s -> %s (%s)", parentType, childType, link.Relation) + } + key := fmt.Sprintf("%s\x00%s\x00%s", traversal.FromType, traversal.EdgeLabel, traversal.ToType) + seen[key] = traversal + } + } + keys := make([]string, 0, len(seen)) + for key := range seen { + keys = append(keys, key) + } + sort.Strings(keys) + out := make([]fhirschema.CompilerTraversal, 0, len(keys)) + for _, key := range keys { + out = append(out, seen[key]) + } + return out +} + +func referenceName(reference string) string { + if index := strings.LastIndex(reference, "/"); index >= 0 { + return reference[index+1:] + } + return reference +} + +var collectionIteration = regexp.MustCompile(`(?m)^FOR\s+[A-Za-z_][A-Za-z0-9_]*\s+IN\s+([A-Za-z_][A-Za-z0-9_]*)\s*$`) + +func assertOnlyValidatedRootCollection(t *testing.T, compiled dataframe.CompiledQuery, rootResourceType string) { + t.Helper() + matches := collectionIteration.FindAllStringSubmatch(compiled.Query, -1) + if strings.Contains(compiled.Query, "FOR root IN @@root_collection") { + if len(matches) != 0 || compiled.BindVars["@root_collection"] != rootResourceType { + t.Fatalf("physical root collection = %#v / direct iterations %#v, want only validated root %q\nquery:\n%s", compiled.BindVars["@root_collection"], matches, rootResourceType, compiled.Query) + } + return + } + if len(matches) != 1 || matches[0][1] != rootResourceType { + t.Fatalf("direct collection iterations = %#v, want only validated root %q\nquery:\n%s", matches, rootResourceType, compiled.Query) + } +} + +func bindVarsContain(bindVars map[string]any, expected string) bool { + for _, value := range bindVars { + if value == expected { + return true + } + } + return false +} diff --git a/conformance/compiler/physical_plan_cost_test.go b/conformance/compiler/physical_plan_cost_test.go new file mode 100644 index 0000000..909466a --- /dev/null +++ b/conformance/compiler/physical_plan_cost_test.go @@ -0,0 +1,39 @@ +package compilerfixture + +import ( + "path/filepath" + "testing" + + "github.com/calypr/loom/internal/dataframe" +) + +// TestPhysicalPlanOptimizationCorpus is a structural regression gate. It does +// not pretend to replace live Arango PROFILE; it prevents future compiler +// changes from silently removing the generic rewrites that PROFILE is meant +// to measure. +func TestPhysicalPlanOptimizationCorpus(t *testing.T) { + fixtures, err := LoadDir(filepath.Join("fixtures")) + if err != nil { + t.Fatal(err) + } + for _, fixture := range fixtures { + if !fixture.Expected.Supported { + continue + } + fixture := fixture + t.Run(fixture.ID, func(t *testing.T) { + compiled, err := dataframe.CompileRequest(fixture.Builder, fixture.Limit) + if err != nil { + t.Fatalf("CompileRequest() error = %v", err) + } + diagnostics := compiled.PlanDiagnostics + t.Logf("plan traversal_sets=%d shared=%d required_reuse=%d rich_sources=%d", diagnostics.TraversalSets, diagnostics.SharedTraversalCount, diagnostics.RequiredMatchReuseCount, len(diagnostics.RichSourceReuse)) + if fixture.ID == "patient-sibling-targets" && diagnostics.SharedTraversalCount == 0 { + t.Fatal("generic sibling fixture lost traversal sharing") + } + if fixture.ID == "specimen-aggregate-slice" && len(diagnostics.RichSourceReuse) == 0 { + t.Fatal("aggregate/slice fixture lost rich-source reuse diagnostics") + } + }) + } +} diff --git a/conformance/compiler/run.go b/conformance/compiler/run.go new file mode 100644 index 0000000..82e42dd --- /dev/null +++ b/conformance/compiler/run.go @@ -0,0 +1,72 @@ +package compilerfixture + +import ( + "fmt" + "slices" + "strings" + + "github.com/calypr/loom/internal/dataframe" +) + +// Result is the pure-compiler outcome for one oracle fixture. It intentionally +// stops before execution; result-row parity against META belongs to the Arango +// integration corpus. +type Result struct { + FixtureID string + Compiled dataframe.CompiledQuery + Err error +} + +func Run(fixture Fixture) Result { + // Conformance exercises the production compiler entrypoint directly. + compiled, err := dataframe.CompileRequest(fixture.Builder, fixture.Limit) + return Result{FixtureID: fixture.ID, Compiled: compiled, Err: err} +} + +func Verify(fixture Fixture) error { + result := Run(fixture) + if !fixture.Expected.Supported { + if result.Err == nil { + return fmt.Errorf("expected compiler failure containing %q, got success", fixture.Expected.ErrorContains) + } + if !strings.Contains(result.Err.Error(), fixture.Expected.ErrorContains) { + return fmt.Errorf("compiler error %q does not contain %q", result.Err, fixture.Expected.ErrorContains) + } + return nil + } + if result.Err != nil { + return result.Err + } + if profile := fixture.Expected.PlanProfile; profile != "" && result.Compiled.PlanProfile != profile { + return fmt.Errorf("plan profile = %q, want %q", result.Compiled.PlanProfile, profile) + } + for _, want := range fixture.Expected.OptimizerRules { + if !slices.Contains(result.Compiled.OptimizationRules, want) { + return fmt.Errorf("compiled optimizer rules %v do not contain %q", result.Compiled.OptimizationRules, want) + } + } + for _, fragment := range fixture.Expected.QueryContains { + if !strings.Contains(result.Compiled.Query, fragment) { + return fmt.Errorf("compiled query does not contain %q", fragment) + } + } + for _, fragment := range fixture.Expected.QueryNotContains { + if strings.Contains(result.Compiled.Query, fragment) { + return fmt.Errorf("compiled query unexpectedly contains %q", fragment) + } + } + for key, want := range fixture.Expected.BindVars { + if got, ok := result.Compiled.BindVars[key]; !ok || fmt.Sprint(got) != fmt.Sprint(want) { + return fmt.Errorf("bind variable %q = %#v, want %#v", key, got, want) + } + } + for _, want := range fixture.Expected.OutputColumns { + if !slices.Contains(result.Compiled.Columns, want) { + return fmt.Errorf("compiled output columns %v do not contain %q", result.Compiled.Columns, want) + } + } + if fixture.Expected.ExpectedTraversalSets != nil && result.Compiled.PlanDiagnostics.TraversalSets != *fixture.Expected.ExpectedTraversalSets { + return fmt.Errorf("physical traversal sets = %d, want %d", result.Compiled.PlanDiagnostics.TraversalSets, *fixture.Expected.ExpectedTraversalSets) + } + return nil +} diff --git a/conformance/compiler/run_test.go b/conformance/compiler/run_test.go new file mode 100644 index 0000000..e8c2a79 --- /dev/null +++ b/conformance/compiler/run_test.go @@ -0,0 +1,20 @@ +package compilerfixture + +import ( + "path/filepath" + "testing" +) + +func TestCompilerOracleFixtures(t *testing.T) { + fixtures, err := LoadDir(filepath.Join("fixtures")) + if err != nil { + t.Fatal(err) + } + for _, fixture := range fixtures { + t.Run(fixture.ID, func(t *testing.T) { + if err := Verify(fixture); err != nil { + t.Fatal(err) + } + }) + } +} diff --git a/conformance/compiler/schema_roots_test.go b/conformance/compiler/schema_roots_test.go new file mode 100644 index 0000000..773fd1e --- /dev/null +++ b/conformance/compiler/schema_roots_test.go @@ -0,0 +1,46 @@ +package compilerfixture + +import ( + "strings" + "testing" + + "github.com/calypr/loom/internal/dataframe" +) + +func TestPublicCompilerAcceptsExpandedSchemaRootExamples(t *testing.T) { + for _, resourceType := range []string{ + "DiagnosticReport", + "MedicationRequest", + "MedicationStatement", + "Procedure", + "Task", + } { + t.Run(resourceType, func(t *testing.T) { + compiled, err := dataframe.CompileRequest(dataframe.Builder{ + Project: "compiler-oracle", + RootResourceType: resourceType, + }, 1) + if err != nil { + t.Fatalf("CompileRequest(%q): %v", resourceType, err) + } + assertOnlyValidatedRootCollection(t, compiled, resourceType) + }) + } +} + +func TestPublicCompilerRejectsSchemaBackboneAndAbstractRoots(t *testing.T) { + for _, resourceType := range []string{"Address", "PatientContact", "Resource"} { + t.Run(resourceType, func(t *testing.T) { + compiled, err := dataframe.CompileRequest(dataframe.Builder{ + Project: "compiler-oracle", + RootResourceType: resourceType, + }, 1) + if err == nil || !strings.Contains(err.Error(), "not represented by the active generated FHIR schema") { + t.Fatalf("CompileRequest(%q) error = %v, want generated-schema rejection", resourceType, err) + } + if compiled.Query != "" { + t.Fatalf("CompileRequest(%q) rendered AQL for a rejected root:\n%s", resourceType, compiled.Query) + } + }) + } +} diff --git a/conformance/compiler/test_helpers_test.go b/conformance/compiler/test_helpers_test.go new file mode 100644 index 0000000..7a83ba3 --- /dev/null +++ b/conformance/compiler/test_helpers_test.go @@ -0,0 +1,7 @@ +package compilerfixture + +import "github.com/calypr/loom/internal/dataframe" + +func validBuilder() dataframe.Builder { + return dataframe.Builder{Project: "p", RootResourceType: "Patient"} +} diff --git a/conformance/compiler/types.go b/conformance/compiler/types.go new file mode 100644 index 0000000..3897468 --- /dev/null +++ b/conformance/compiler/types.go @@ -0,0 +1,105 @@ +// Package compilerfixture loads the machine-readable compiler oracle corpus. +package compilerfixture + +import ( + "encoding/json" + "errors" + "fmt" + "os" + "path/filepath" + "sort" + "strings" + + "github.com/calypr/loom/internal/dataframe" +) + +const SchemaVersion = "loom.compiler-oracle/v1" + +type Expected struct { + Supported bool `json:"supported"` + PlanProfile string `json:"planProfile,omitempty"` + OptimizerRules []string `json:"optimizerRules,omitempty"` + ErrorContains string `json:"errorContains,omitempty"` + QueryContains []string `json:"queryContains,omitempty"` + QueryNotContains []string `json:"queryNotContains,omitempty"` + BindVars map[string]any `json:"bindVars,omitempty"` + OutputColumns []string `json:"outputColumns,omitempty"` + // ExpectedTraversalSets describes the physical traversal count. + ExpectedTraversalSets *int `json:"expectedTraversalSets,omitempty"` +} + +type Fixture struct { + Schema string `json:"schema"` + ID string `json:"id"` + Description string `json:"description"` + Tags []string `json:"tags,omitempty"` + Limit int `json:"limit"` + Builder dataframe.Builder `json:"builder"` + Expected Expected `json:"expected"` + SourceFile string `json:"-"` +} + +func LoadDir(dir string) ([]Fixture, error) { + entries, err := os.ReadDir(dir) + if err != nil { + return nil, err + } + var fixtures []Fixture + seen := map[string]string{} + for _, entry := range entries { + if entry.IsDir() || filepath.Ext(entry.Name()) != ".json" { + continue + } + path := filepath.Join(dir, entry.Name()) + data, err := os.ReadFile(path) + if err != nil { + return nil, err + } + var fixture Fixture + decoder := json.NewDecoder(strings.NewReader(string(data))) + decoder.DisallowUnknownFields() + if err := decoder.Decode(&fixture); err != nil { + return nil, fmt.Errorf("decode %s: %w", path, err) + } + fixture.SourceFile = path + if err := fixture.Validate(); err != nil { + return nil, fmt.Errorf("validate %s: %w", path, err) + } + if prior, ok := seen[fixture.ID]; ok { + return nil, fmt.Errorf("duplicate fixture id %q in %s and %s", fixture.ID, prior, path) + } + seen[fixture.ID] = path + fixtures = append(fixtures, fixture) + } + if len(fixtures) == 0 { + return nil, errors.New("compiler fixture directory contains no JSON fixtures") + } + sort.Slice(fixtures, func(i, j int) bool { return fixtures[i].ID < fixtures[j].ID }) + return fixtures, nil +} + +func (f Fixture) Validate() error { + if f.Schema != SchemaVersion { + return fmt.Errorf("schema must be %q", SchemaVersion) + } + if strings.TrimSpace(f.ID) == "" || strings.ContainsAny(f.ID, " /\\") { + return errors.New("id must be a non-empty path-safe identifier") + } + if strings.TrimSpace(f.Description) == "" { + return errors.New("description is required") + } + if f.Limit <= 0 { + return errors.New("limit must be positive") + } + if strings.TrimSpace(f.Builder.Project) == "" || strings.TrimSpace(f.Builder.RootResourceType) == "" { + return errors.New("builder project and rootResourceType are required") + } + if f.Expected.Supported { + if f.Expected.ErrorContains != "" { + return errors.New("supported fixture cannot declare errorContains") + } + } else if strings.TrimSpace(f.Expected.ErrorContains) == "" { + return errors.New("unsupported fixture must declare errorContains") + } + return nil +} diff --git a/conformance/compiler/types_test.go b/conformance/compiler/types_test.go new file mode 100644 index 0000000..b624941 --- /dev/null +++ b/conformance/compiler/types_test.go @@ -0,0 +1,57 @@ +package compilerfixture + +import ( + "path/filepath" + "testing" +) + +func TestLoadFixtureCorpus(t *testing.T) { + fixtures, err := LoadDir(filepath.Join("fixtures")) + if err != nil { + t.Fatal(err) + } + if len(fixtures) < 4 { + t.Fatalf("fixture count = %d, want at least 4", len(fixtures)) + } + + supported, unsupported := 0, 0 + for _, fixture := range fixtures { + if fixture.Expected.Supported { + supported++ + } else { + unsupported++ + } + } + if supported == 0 || unsupported == 0 { + t.Fatalf("corpus must contain supported and unsupported shapes; got %d and %d", supported, unsupported) + } +} + +func TestFixturesAreSortedByID(t *testing.T) { + fixtures, err := LoadDir(filepath.Join("fixtures")) + if err != nil { + t.Fatal(err) + } + for i := 1; i < len(fixtures); i++ { + if fixtures[i-1].ID >= fixtures[i].ID { + t.Fatalf("fixtures not sorted: %q before %q", fixtures[i-1].ID, fixtures[i].ID) + } + } +} + +func TestFixtureValidationRejectsContradictoryExpectation(t *testing.T) { + fixture := Fixture{ + Schema: SchemaVersion, + ID: "contradictory", + Description: "invalid fixture", + Limit: 1, + Builder: validBuilder(), + Expected: Expected{ + Supported: true, + ErrorContains: "failure", + }, + } + if err := fixture.Validate(); err == nil { + t.Fatal("expected validation error") + } +} diff --git a/fhirstructs/extract.go b/fhirstructs/extract.go new file mode 100644 index 0000000..be07e4a --- /dev/null +++ b/fhirstructs/extract.go @@ -0,0 +1,80173 @@ +// Code generated by cmd/generate/main.go. DO NOT EDIT. +package fhirstructs + +import ( + "bytes" + "crypto/sha1" + "encoding/hex" + "encoding/json" + "fmt" + "github.com/bytedance/sonic" + "github.com/google/uuid" + "hash" + "strconv" + "strings" + "sync" +) + +// EdgeDocument represents an edge in ArangoDB. +type EdgeDocument struct { + Key string `json:"_key"` + From string `json:"_from"` + To string `json:"_to"` + Label string `json:"label"` + Project string `json:"project"` + FromType string `json:"from_type"` + ToType string `json:"to_type"` +} + +// Result of validation and edge extraction. +type Result struct { + ObjectID string + ResourceType string + Vertex any + Edges []json.RawMessage +} + +// Global namespace UUID constant computed from "calypr-public.ohsu.edu" +var namespaceUUID = uuid.NewMD5(uuid.NameSpaceDNS, []byte("calypr-public.ohsu.edu")) + +var sha1Pool = sync.Pool{ + New: func() any { + return sha1.New() + }, +} + +var bufferPool = sync.Pool{ + New: func() any { + return &bytes.Buffer{} + }, +} + +func fastUUIDSHA1(space uuid.UUID, data []byte) string { + h := sha1Pool.Get().(hash.Hash) + h.Reset() + h.Write(space[:]) + h.Write(data) + var hashBytes [20]byte + h.Sum(hashBytes[:0]) + sha1Pool.Put(h) + + // format uuid v5: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + // version 5 (SHA-1) + hashBytes[6] = (hashBytes[6] & 0x0f) | 0x50 + hashBytes[8] = (hashBytes[8] & 0x3f) | 0x80 + + var buf [36]byte + hex.Encode(buf[0:8], hashBytes[0:4]) + buf[8] = '-' + hex.Encode(buf[9:13], hashBytes[4:6]) + buf[13] = '-' + hex.Encode(buf[14:18], hashBytes[6:8]) + buf[18] = '-' + hex.Encode(buf[19:23], hashBytes[8:10]) + buf[23] = '-' + hex.Encode(buf[24:36], hashBytes[10:16]) + + return string(buf[:]) +} + +func getEdgeUUID(a, b, c string) string { + buf := bufferPool.Get().(*bytes.Buffer) + buf.Reset() + buf.WriteString(a) + buf.WriteByte('-') + buf.WriteString(b) + buf.WriteByte('-') + buf.WriteString(c) + uuidStr := fastUUIDSHA1(namespaceUUID, buf.Bytes()) + bufferPool.Put(buf) + return uuidStr +} + +func collectionID(resourceType, id string) string { + return sanitizeKey(resourceType) + "/" + sanitizeKey(id) +} + +func sanitizeKey(value string) string { + value = strings.TrimSpace(value) + if value == "" { + return "_" + } + needsSanitization := false + for i := 0; i < len(value); i++ { + r := value[i] + if (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || + r == '_' || r == '-' || r == ':' || r == '.' || r == '@' || r == '(' || r == ')' || + r == '+' || r == ',' || r == '=' || r == ';' || r == '$' || r == '!' || r == '*' || + r == '\'' || r == '%' { + // clean character + } else { + needsSanitization = true + break + } + } + if !needsSanitization { + return value + } + + var sb strings.Builder + sb.Grow(len(value)) + for _, r := range value { + if (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || + r == '_' || r == '-' || r == ':' || r == '.' || r == '@' || r == '(' || r == ')' || + r == '+' || r == ',' || r == '=' || r == ';' || r == '$' || r == '!' || r == '*' || + r == '\'' || r == '%' { + sb.WriteRune(r) + } else { + sb.WriteRune('_') + } + } + return sb.String() +} + +func splitFHIRReference(ref string) (string, string, bool) { + firstSlash := strings.IndexByte(ref, '/') + if firstSlash <= 0 || firstSlash == len(ref)-1 { + return "", "", false + } + targetType := ref[:firstSlash] + targetID := ref[firstSlash+1:] + if secondSlash := strings.IndexByte(targetID, '/'); secondSlash != -1 { + targetID = targetID[:secondSlash] + } + if targetID == "" { + return "", "", false + } + return targetType, targetID, true +} + +func targetTypeFromLabel(label string) string { + parts := strings.Split(label, "_") + if len(parts) == 0 { + return "" + } + return parts[len(parts)-1] +} + +func buildEdgeRawJSON(key, from, to, label, projectJSON, fromType, toType string) json.RawMessage { + var buf bytes.Buffer + buf.Grow(256) + buf.WriteString("{\"_key\":\"") + buf.WriteString(key) + buf.WriteString("\",\"_from\":\"") + buf.WriteString(from) + buf.WriteString("\",\"_to\":\"") + buf.WriteString(to) + buf.WriteString("\",\"label\":\"") + buf.WriteString(label) + buf.WriteString("\",\"project\":") + buf.WriteString(projectJSON) + buf.WriteString(",\"from_type\":\"") + buf.WriteString(fromType) + buf.WriteString("\",\"to_type\":\"") + buf.WriteString(toType) + buf.WriteString("\"}") + return json.RawMessage(buf.Bytes()) +} + +// ExtractEdges extracts graph links from Address. +func (x *Address) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Address" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from Age. +func (x *Age) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Age" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from Annotation. +func (x *Annotation) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Annotation" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.AuthorReference != nil { + if x.AuthorReference.Reference != nil { + refVal := *x.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "authorReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "authorReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + if x.AuthorReference != nil { + if x.AuthorReference.Reference != nil { + refVal := *x.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "authorReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "authorReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + if x.AuthorReference != nil { + if x.AuthorReference.Reference != nil { + refVal := *x.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "authorReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "authorReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + if x.AuthorReference != nil { + if x.AuthorReference.Reference != nil { + refVal := *x.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "authorReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "authorReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from Attachment. +func (x *Attachment) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Attachment" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from Availability. +func (x *Availability) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Availability" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from AvailabilityAvailableTime. +func (x *AvailabilityAvailableTime) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "AvailabilityAvailableTime" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from AvailabilityNotAvailableTime. +func (x *AvailabilityNotAvailableTime) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "AvailabilityNotAvailableTime" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from BodyStructure. +func (x *BodyStructure) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "BodyStructure" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Patient != nil { + if x.Patient.Reference != nil { + refVal := *x.Patient.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("patient", targetID), + "patient", + projectJSON, + sourceType, + "patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "body_structure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("structure", id), + "body_structure", + projectJSON, + sourceType, + "structure", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from BodyStructureIncludedStructure. +func (x *BodyStructureIncludedStructure) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "BodyStructureIncludedStructure" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from BodyStructureIncludedStructureBodyLandmarkOrientation. +func (x *BodyStructureIncludedStructureBodyLandmarkOrientation) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "BodyStructureIncludedStructureBodyLandmarkOrientation" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark. +func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "device_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "device_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "device_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "device_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "device_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "device_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "device_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "device_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "device_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "device_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "device_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "device_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "device_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "device_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "device_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "device_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "device_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "device_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "device_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "device_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "device_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "device_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "device_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from CodeableConcept. +func (x *CodeableConcept) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "CodeableConcept" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from CodeableReference. +func (x *CodeableReference) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "CodeableReference" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from Coding. +func (x *Coding) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Coding" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from Condition. +func (x *Condition) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Condition" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "subject_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "subject_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("condition", id), + "condition", + projectJSON, + sourceType, + "condition", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "subject_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "subject_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("condition", id), + "condition", + projectJSON, + sourceType, + "condition", + )) + } + } + } + } + } + if x.Evidence != nil { + for _, item_3_x_Evidence := range x.Evidence { + if item_3_x_Evidence != nil { + if item_3_x_Evidence.Reference != nil { + if item_3_x_Evidence.Reference.Reference != nil { + refVal := *item_3_x_Evidence.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "evidence_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "evidence_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Evidence != nil { + for _, item_3_x_Evidence := range x.Evidence { + if item_3_x_Evidence != nil { + if item_3_x_Evidence.Reference != nil { + if item_3_x_Evidence.Reference.Reference != nil { + refVal := *item_3_x_Evidence.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "evidence_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "evidence_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Evidence != nil { + for _, item_3_x_Evidence := range x.Evidence { + if item_3_x_Evidence != nil { + if item_3_x_Evidence.Reference != nil { + if item_3_x_Evidence.Reference.Reference != nil { + refVal := *item_3_x_Evidence.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "evidence_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "evidence_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Evidence != nil { + for _, item_3_x_Evidence := range x.Evidence { + if item_3_x_Evidence != nil { + if item_3_x_Evidence.Reference != nil { + if item_3_x_Evidence.Reference.Reference != nil { + refVal := *item_3_x_Evidence.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "evidence_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "evidence_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Evidence != nil { + for _, item_3_x_Evidence := range x.Evidence { + if item_3_x_Evidence != nil { + if item_3_x_Evidence.Reference != nil { + if item_3_x_Evidence.Reference.Reference != nil { + refVal := *item_3_x_Evidence.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "evidence_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "evidence_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Evidence != nil { + for _, item_3_x_Evidence := range x.Evidence { + if item_3_x_Evidence != nil { + if item_3_x_Evidence.Reference != nil { + if item_3_x_Evidence.Reference.Reference != nil { + refVal := *item_3_x_Evidence.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "evidence_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "evidence_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Evidence != nil { + for _, item_3_x_Evidence := range x.Evidence { + if item_3_x_Evidence != nil { + if item_3_x_Evidence.Reference != nil { + if item_3_x_Evidence.Reference.Reference != nil { + refVal := *item_3_x_Evidence.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "evidence_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "evidence_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Evidence != nil { + for _, item_3_x_Evidence := range x.Evidence { + if item_3_x_Evidence != nil { + if item_3_x_Evidence.Reference != nil { + if item_3_x_Evidence.Reference.Reference != nil { + refVal := *item_3_x_Evidence.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "evidence_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "evidence_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Evidence != nil { + for _, item_3_x_Evidence := range x.Evidence { + if item_3_x_Evidence != nil { + if item_3_x_Evidence.Reference != nil { + if item_3_x_Evidence.Reference.Reference != nil { + refVal := *item_3_x_Evidence.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "evidence_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "evidence_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Evidence != nil { + for _, item_3_x_Evidence := range x.Evidence { + if item_3_x_Evidence != nil { + if item_3_x_Evidence.Reference != nil { + if item_3_x_Evidence.Reference.Reference != nil { + refVal := *item_3_x_Evidence.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "evidence_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "evidence_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Evidence != nil { + for _, item_3_x_Evidence := range x.Evidence { + if item_3_x_Evidence != nil { + if item_3_x_Evidence.Reference != nil { + if item_3_x_Evidence.Reference.Reference != nil { + refVal := *item_3_x_Evidence.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "evidence_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "evidence_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Evidence != nil { + for _, item_3_x_Evidence := range x.Evidence { + if item_3_x_Evidence != nil { + if item_3_x_Evidence.Reference != nil { + if item_3_x_Evidence.Reference.Reference != nil { + refVal := *item_3_x_Evidence.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "evidence_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "evidence_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Evidence != nil { + for _, item_3_x_Evidence := range x.Evidence { + if item_3_x_Evidence != nil { + if item_3_x_Evidence.Reference != nil { + if item_3_x_Evidence.Reference.Reference != nil { + refVal := *item_3_x_Evidence.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "evidence_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "evidence_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Evidence != nil { + for _, item_3_x_Evidence := range x.Evidence { + if item_3_x_Evidence != nil { + if item_3_x_Evidence.Reference != nil { + if item_3_x_Evidence.Reference.Reference != nil { + refVal := *item_3_x_Evidence.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "evidence_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "evidence_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Evidence != nil { + for _, item_3_x_Evidence := range x.Evidence { + if item_3_x_Evidence != nil { + if item_3_x_Evidence.Reference != nil { + if item_3_x_Evidence.Reference.Reference != nil { + refVal := *item_3_x_Evidence.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "evidence_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "evidence_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Evidence != nil { + for _, item_3_x_Evidence := range x.Evidence { + if item_3_x_Evidence != nil { + if item_3_x_Evidence.Reference != nil { + if item_3_x_Evidence.Reference.Reference != nil { + refVal := *item_3_x_Evidence.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "evidence_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "evidence_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Evidence != nil { + for _, item_3_x_Evidence := range x.Evidence { + if item_3_x_Evidence != nil { + if item_3_x_Evidence.Reference != nil { + if item_3_x_Evidence.Reference.Reference != nil { + refVal := *item_3_x_Evidence.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "evidence_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "evidence_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Evidence != nil { + for _, item_3_x_Evidence := range x.Evidence { + if item_3_x_Evidence != nil { + if item_3_x_Evidence.Reference != nil { + if item_3_x_Evidence.Reference.Reference != nil { + refVal := *item_3_x_Evidence.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "evidence_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "evidence_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Evidence != nil { + for _, item_3_x_Evidence := range x.Evidence { + if item_3_x_Evidence != nil { + if item_3_x_Evidence.Reference != nil { + if item_3_x_Evidence.Reference.Reference != nil { + refVal := *item_3_x_Evidence.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "evidence_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "evidence_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Evidence != nil { + for _, item_3_x_Evidence := range x.Evidence { + if item_3_x_Evidence != nil { + if item_3_x_Evidence.Reference != nil { + if item_3_x_Evidence.Reference.Reference != nil { + refVal := *item_3_x_Evidence.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "evidence_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "evidence_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Evidence != nil { + for _, item_3_x_Evidence := range x.Evidence { + if item_3_x_Evidence != nil { + if item_3_x_Evidence.Reference != nil { + if item_3_x_Evidence.Reference.Reference != nil { + refVal := *item_3_x_Evidence.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "evidence_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "evidence_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Evidence != nil { + for _, item_3_x_Evidence := range x.Evidence { + if item_3_x_Evidence != nil { + if item_3_x_Evidence.Reference != nil { + if item_3_x_Evidence.Reference.Reference != nil { + refVal := *item_3_x_Evidence.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "evidence_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "evidence_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Evidence != nil { + for _, item_3_x_Evidence := range x.Evidence { + if item_3_x_Evidence != nil { + if item_3_x_Evidence.Reference != nil { + if item_3_x_Evidence.Reference.Reference != nil { + refVal := *item_3_x_Evidence.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "evidence_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "evidence_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "note_authorReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "note_authorReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "note_authorReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "note_authorReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Participant != nil { + for _, item_3_x_Participant := range x.Participant { + if item_3_x_Participant != nil { + if item_3_x_Participant.Actor != nil { + if item_3_x_Participant.Actor.Reference != nil { + refVal := *item_3_x_Participant.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "participant_actor_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "participant_actor_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "condition_participant") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("participant", id), + "condition_participant", + projectJSON, + sourceType, + "participant", + )) + } + } + } + } + } + } + } + } + if x.Participant != nil { + for _, item_3_x_Participant := range x.Participant { + if item_3_x_Participant != nil { + if item_3_x_Participant.Actor != nil { + if item_3_x_Participant.Actor.Reference != nil { + refVal := *item_3_x_Participant.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "participant_actor_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "participant_actor_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "condition_participant") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("participant", id), + "condition_participant", + projectJSON, + sourceType, + "participant", + )) + } + } + } + } + } + } + } + } + if x.Participant != nil { + for _, item_3_x_Participant := range x.Participant { + if item_3_x_Participant != nil { + if item_3_x_Participant.Actor != nil { + if item_3_x_Participant.Actor.Reference != nil { + refVal := *item_3_x_Participant.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "participant_actor_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "participant_actor_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "condition_participant") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("participant", id), + "condition_participant", + projectJSON, + sourceType, + "participant", + )) + } + } + } + } + } + } + } + } + if x.Participant != nil { + for _, item_3_x_Participant := range x.Participant { + if item_3_x_Participant != nil { + if item_3_x_Participant.Actor != nil { + if item_3_x_Participant.Actor.Reference != nil { + refVal := *item_3_x_Participant.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "participant_actor_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "participant_actor_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "condition_participant") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("participant", id), + "condition_participant", + projectJSON, + sourceType, + "participant", + )) + } + } + } + } + } + } + } + } + if x.Stage != nil { + for _, item_4_x_Stage := range x.Stage { + if item_4_x_Stage != nil { + if item_4_x_Stage.Assessment != nil { + for _, item_2_item_4_x_Stage_Assessment := range item_4_x_Stage.Assessment { + if item_2_item_4_x_Stage_Assessment != nil { + if item_2_item_4_x_Stage_Assessment.Reference != nil { + refVal := *item_2_item_4_x_Stage_Assessment.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "stage_assessment_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "stage_assessment_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "assessment_condition_stage") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("stage", id), + "assessment_condition_stage", + projectJSON, + sourceType, + "stage", + )) + } + } + } + } + } + } + } + } + } + } + if x.Stage != nil { + for _, item_4_x_Stage := range x.Stage { + if item_4_x_Stage != nil { + if item_4_x_Stage.Assessment != nil { + for _, item_2_item_4_x_Stage_Assessment := range item_4_x_Stage.Assessment { + if item_2_item_4_x_Stage_Assessment != nil { + if item_2_item_4_x_Stage_Assessment.Reference != nil { + refVal := *item_2_item_4_x_Stage_Assessment.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "stage_assessment_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "stage_assessment_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "assessment_condition_stage") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("stage", id), + "assessment_condition_stage", + projectJSON, + sourceType, + "stage", + )) + } + } + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from ConditionParticipant. +func (x *ConditionParticipant) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ConditionParticipant" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Actor != nil { + if x.Actor.Reference != nil { + refVal := *x.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "actor_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "actor_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "condition_participant") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("participant", id), + "condition_participant", + projectJSON, + sourceType, + "participant", + )) + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + refVal := *x.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "actor_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "actor_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "condition_participant") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("participant", id), + "condition_participant", + projectJSON, + sourceType, + "participant", + )) + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + refVal := *x.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "actor_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "actor_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "condition_participant") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("participant", id), + "condition_participant", + projectJSON, + sourceType, + "participant", + )) + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + refVal := *x.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "actor_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "actor_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "condition_participant") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("participant", id), + "condition_participant", + projectJSON, + sourceType, + "participant", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from ConditionStage. +func (x *ConditionStage) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ConditionStage" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Assessment != nil { + for _, item_2_x_Assessment := range x.Assessment { + if item_2_x_Assessment != nil { + if item_2_x_Assessment.Reference != nil { + refVal := *item_2_x_Assessment.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "assessment_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "assessment_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "assessment_condition_stage") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("stage", id), + "assessment_condition_stage", + projectJSON, + sourceType, + "stage", + )) + } + } + } + } + } + } + } + if x.Assessment != nil { + for _, item_2_x_Assessment := range x.Assessment { + if item_2_x_Assessment != nil { + if item_2_x_Assessment.Reference != nil { + refVal := *item_2_x_Assessment.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "assessment_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "assessment_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "assessment_condition_stage") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("stage", id), + "assessment_condition_stage", + projectJSON, + sourceType, + "stage", + )) + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from ContactDetail. +func (x *ContactDetail) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ContactDetail" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from ContactPoint. +func (x *ContactPoint) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ContactPoint" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from Count. +func (x *Count) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Count" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from DataRequirement. +func (x *DataRequirement) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "DataRequirement" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.SubjectReference != nil { + if x.SubjectReference.Reference != nil { + refVal := *x.SubjectReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "subjectReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("subjectReference", targetID), + "subjectReference", + projectJSON, + sourceType, + "subjectReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "data_requirement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("requirement", id), + "data_requirement", + projectJSON, + sourceType, + "requirement", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from DataRequirementCodeFilter. +func (x *DataRequirementCodeFilter) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "DataRequirementCodeFilter" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from DataRequirementDateFilter. +func (x *DataRequirementDateFilter) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "DataRequirementDateFilter" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from DataRequirementSort. +func (x *DataRequirementSort) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "DataRequirementSort" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from DataRequirementValueFilter. +func (x *DataRequirementValueFilter) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "DataRequirementValueFilter" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from DiagnosticReport. +func (x *DiagnosticReport) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "DiagnosticReport" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "basedOn_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_diagnostic_report") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("report", id), + "basedOn_diagnostic_report", + projectJSON, + sourceType, + "report", + )) + } + } + } + } + } + } + } + if x.Performer != nil { + for _, item_2_x_Performer := range x.Performer { + if item_2_x_Performer != nil { + if item_2_x_Performer.Reference != nil { + refVal := *item_2_x_Performer.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "performer_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "performer_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "performer_diagnostic_report") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("report", id), + "performer_diagnostic_report", + projectJSON, + sourceType, + "report", + )) + } + } + } + } + } + } + } + if x.Performer != nil { + for _, item_2_x_Performer := range x.Performer { + if item_2_x_Performer != nil { + if item_2_x_Performer.Reference != nil { + refVal := *item_2_x_Performer.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "performer_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "performer_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "performer_diagnostic_report") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("report", id), + "performer_diagnostic_report", + projectJSON, + sourceType, + "report", + )) + } + } + } + } + } + } + } + if x.Performer != nil { + for _, item_2_x_Performer := range x.Performer { + if item_2_x_Performer != nil { + if item_2_x_Performer.Reference != nil { + refVal := *item_2_x_Performer.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "performer_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "performer_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "performer_diagnostic_report") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("report", id), + "performer_diagnostic_report", + projectJSON, + sourceType, + "report", + )) + } + } + } + } + } + } + } + if x.Result != nil { + for _, item_2_x_Result := range x.Result { + if item_2_x_Result != nil { + if item_2_x_Result.Reference != nil { + refVal := *item_2_x_Result.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "result") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("result", targetID), + "result", + projectJSON, + sourceType, + "result", + )) + } + backrefKey := getEdgeUUID(id, targetID, "result_diagnostic_report") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("report", id), + "result_diagnostic_report", + projectJSON, + sourceType, + "report", + )) + } + } + } + } + } + } + } + if x.ResultsInterpreter != nil { + for _, item_2_x_ResultsInterpreter := range x.ResultsInterpreter { + if item_2_x_ResultsInterpreter != nil { + if item_2_x_ResultsInterpreter.Reference != nil { + refVal := *item_2_x_ResultsInterpreter.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "resultsInterpreter_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "resultsInterpreter_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "resultsInterpreter_diagnostic_report") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("report", id), + "resultsInterpreter_diagnostic_report", + projectJSON, + sourceType, + "report", + )) + } + } + } + } + } + } + } + if x.ResultsInterpreter != nil { + for _, item_2_x_ResultsInterpreter := range x.ResultsInterpreter { + if item_2_x_ResultsInterpreter != nil { + if item_2_x_ResultsInterpreter.Reference != nil { + refVal := *item_2_x_ResultsInterpreter.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "resultsInterpreter_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "resultsInterpreter_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "resultsInterpreter_diagnostic_report") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("report", id), + "resultsInterpreter_diagnostic_report", + projectJSON, + sourceType, + "report", + )) + } + } + } + } + } + } + } + if x.ResultsInterpreter != nil { + for _, item_2_x_ResultsInterpreter := range x.ResultsInterpreter { + if item_2_x_ResultsInterpreter != nil { + if item_2_x_ResultsInterpreter.Reference != nil { + refVal := *item_2_x_ResultsInterpreter.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "resultsInterpreter_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "resultsInterpreter_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "resultsInterpreter_diagnostic_report") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("report", id), + "resultsInterpreter_diagnostic_report", + projectJSON, + sourceType, + "report", + )) + } + } + } + } + } + } + } + if x.Specimen != nil { + for _, item_2_x_Specimen := range x.Specimen { + if item_2_x_Specimen != nil { + if item_2_x_Specimen.Reference != nil { + refVal := *item_2_x_Specimen.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("specimen", targetID), + "specimen", + projectJSON, + sourceType, + "specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "specimen_diagnostic_report") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("report", id), + "specimen_diagnostic_report", + projectJSON, + sourceType, + "report", + )) + } + } + } + } + } + } + } + if x.Study != nil { + for _, item_2_x_Study := range x.Study { + if item_2_x_Study != nil { + if item_2_x_Study.Reference != nil { + refVal := *item_2_x_Study.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "study_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "study_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "study_diagnostic_report") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("report", id), + "study_diagnostic_report", + projectJSON, + sourceType, + "report", + )) + } + } + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "subject_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "subject_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "subject_diagnostic_report") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("report", id), + "subject_diagnostic_report", + projectJSON, + sourceType, + "report", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "subject_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "subject_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "subject_diagnostic_report") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("report", id), + "subject_diagnostic_report", + projectJSON, + sourceType, + "report", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "subject_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "subject_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "subject_diagnostic_report") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("report", id), + "subject_diagnostic_report", + projectJSON, + sourceType, + "report", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "subject_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "subject_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "subject_diagnostic_report") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("report", id), + "subject_diagnostic_report", + projectJSON, + sourceType, + "report", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "subject_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "subject_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "subject_diagnostic_report") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("report", id), + "subject_diagnostic_report", + projectJSON, + sourceType, + "report", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "subject_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "subject_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "subject_diagnostic_report") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("report", id), + "subject_diagnostic_report", + projectJSON, + sourceType, + "report", + )) + } + } + } + } + } + if x.Media != nil { + for _, item_3_x_Media := range x.Media { + if item_3_x_Media != nil { + if item_3_x_Media.Link != nil { + if item_3_x_Media.Link.Reference != nil { + refVal := *item_3_x_Media.Link.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "media_link") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("link", targetID), + "media_link", + projectJSON, + sourceType, + "link", + )) + } + backrefKey := getEdgeUUID(id, targetID, "diagnostic_report_media") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("media", id), + "diagnostic_report_media", + projectJSON, + sourceType, + "media", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "note_authorReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "note_authorReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "note_authorReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "note_authorReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_3_x_SupportingInfo := range x.SupportingInfo { + if item_3_x_SupportingInfo != nil { + if item_3_x_SupportingInfo.Reference != nil { + if item_3_x_SupportingInfo.Reference.Reference != nil { + refVal := *item_3_x_SupportingInfo.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "supportingInfo_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "diagnostic_report_supporting_info") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("info", id), + "diagnostic_report_supporting_info", + projectJSON, + sourceType, + "info", + )) + } + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_3_x_SupportingInfo := range x.SupportingInfo { + if item_3_x_SupportingInfo != nil { + if item_3_x_SupportingInfo.Reference != nil { + if item_3_x_SupportingInfo.Reference.Reference != nil { + refVal := *item_3_x_SupportingInfo.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "supportingInfo_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "diagnostic_report_supporting_info") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("info", id), + "diagnostic_report_supporting_info", + projectJSON, + sourceType, + "info", + )) + } + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_3_x_SupportingInfo := range x.SupportingInfo { + if item_3_x_SupportingInfo != nil { + if item_3_x_SupportingInfo.Reference != nil { + if item_3_x_SupportingInfo.Reference.Reference != nil { + refVal := *item_3_x_SupportingInfo.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "supportingInfo_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "diagnostic_report_supporting_info") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("info", id), + "diagnostic_report_supporting_info", + projectJSON, + sourceType, + "info", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from DiagnosticReportMedia. +func (x *DiagnosticReportMedia) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "DiagnosticReportMedia" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Link != nil { + if x.Link.Reference != nil { + refVal := *x.Link.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "link") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("link", targetID), + "link", + projectJSON, + sourceType, + "link", + )) + } + backrefKey := getEdgeUUID(id, targetID, "diagnostic_report_media") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("media", id), + "diagnostic_report_media", + projectJSON, + sourceType, + "media", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from DiagnosticReportSupportingInfo. +func (x *DiagnosticReportSupportingInfo) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "DiagnosticReportSupportingInfo" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "diagnostic_report_supporting_info") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("info", id), + "diagnostic_report_supporting_info", + projectJSON, + sourceType, + "info", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "diagnostic_report_supporting_info") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("info", id), + "diagnostic_report_supporting_info", + projectJSON, + sourceType, + "info", + )) + } + } + } + } + } + if x.Reference != nil { + if x.Reference.Reference != nil { + refVal := *x.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "diagnostic_report_supporting_info") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("info", id), + "diagnostic_report_supporting_info", + projectJSON, + sourceType, + "info", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from Directory. +func (x *Directory) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Directory" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Child != nil { + for _, item_2_x_Child := range x.Child { + if item_2_x_Child != nil { + if item_2_x_Child.Reference != nil { + refVal := *item_2_x_Child.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Directory" { + forwardKey := getEdgeUUID(targetID, id, "child_Directory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Directory", targetID), + "child_Directory", + projectJSON, + sourceType, + "Directory", + )) + } + } + } + } + } + } + } + if x.Child != nil { + for _, item_2_x_Child := range x.Child { + if item_2_x_Child != nil { + if item_2_x_Child.Reference != nil { + refVal := *item_2_x_Child.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "child_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "child_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from Distance. +func (x *Distance) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Distance" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from DocumentReference. +func (x *DocumentReference) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "DocumentReference" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Author != nil { + for _, item_2_x_Author := range x.Author { + if item_2_x_Author != nil { + if item_2_x_Author.Reference != nil { + refVal := *item_2_x_Author.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "author_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "author_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "author_document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "author_document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + if x.Author != nil { + for _, item_2_x_Author := range x.Author { + if item_2_x_Author != nil { + if item_2_x_Author.Reference != nil { + refVal := *item_2_x_Author.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "author_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "author_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "author_document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "author_document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + if x.Author != nil { + for _, item_2_x_Author := range x.Author { + if item_2_x_Author != nil { + if item_2_x_Author.Reference != nil { + refVal := *item_2_x_Author.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "author_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "author_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "author_document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "author_document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + if x.Author != nil { + for _, item_2_x_Author := range x.Author { + if item_2_x_Author != nil { + if item_2_x_Author.Reference != nil { + refVal := *item_2_x_Author.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "author_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "author_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "author_document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "author_document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "basedOn_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "basedOn_document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + if x.Custodian != nil { + if x.Custodian.Reference != nil { + refVal := *x.Custodian.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "custodian") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("custodian", targetID), + "custodian", + projectJSON, + sourceType, + "custodian", + )) + } + backrefKey := getEdgeUUID(id, targetID, "custodian_document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "custodian_document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "subject_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "subject_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "subject_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "subject_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "subject_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "subject_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "subject_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "subject_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "subject_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "subject_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "subject_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "subject_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "subject_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "subject_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "subject_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "subject_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "subject_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "subject_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "subject_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "subject_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "subject_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "subject_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "subject_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "subject_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "subject_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "subject_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "subject_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "subject_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "subject_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "subject_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "subject_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "subject_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "subject_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "subject_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "subject_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "subject_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "subject_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "subject_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "subject_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "subject_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "subject_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "subject_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "subject_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "subject_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "subject_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "subject_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "document_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + if x.Attester != nil { + for _, item_3_x_Attester := range x.Attester { + if item_3_x_Attester != nil { + if item_3_x_Attester.Party != nil { + if item_3_x_Attester.Party.Reference != nil { + refVal := *item_3_x_Attester.Party.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "attester_party_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "attester_party_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference_attester") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("attester", id), + "document_reference_attester", + projectJSON, + sourceType, + "attester", + )) + } + } + } + } + } + } + } + } + if x.Attester != nil { + for _, item_3_x_Attester := range x.Attester { + if item_3_x_Attester != nil { + if item_3_x_Attester.Party != nil { + if item_3_x_Attester.Party.Reference != nil { + refVal := *item_3_x_Attester.Party.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "attester_party_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "attester_party_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference_attester") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("attester", id), + "document_reference_attester", + projectJSON, + sourceType, + "attester", + )) + } + } + } + } + } + } + } + } + if x.Attester != nil { + for _, item_3_x_Attester := range x.Attester { + if item_3_x_Attester != nil { + if item_3_x_Attester.Party != nil { + if item_3_x_Attester.Party.Reference != nil { + refVal := *item_3_x_Attester.Party.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "attester_party_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "attester_party_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference_attester") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("attester", id), + "document_reference_attester", + projectJSON, + sourceType, + "attester", + )) + } + } + } + } + } + } + } + } + if x.Attester != nil { + for _, item_3_x_Attester := range x.Attester { + if item_3_x_Attester != nil { + if item_3_x_Attester.Party != nil { + if item_3_x_Attester.Party.Reference != nil { + refVal := *item_3_x_Attester.Party.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "attester_party_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "attester_party_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference_attester") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("attester", id), + "document_reference_attester", + projectJSON, + sourceType, + "attester", + )) + } + } + } + } + } + } + } + } + if x.BodySite != nil { + for _, item_3_x_BodySite := range x.BodySite { + if item_3_x_BodySite != nil { + if item_3_x_BodySite.Reference != nil { + if item_3_x_BodySite.Reference.Reference != nil { + refVal := *item_3_x_BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "bodySite_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.BodySite != nil { + for _, item_3_x_BodySite := range x.BodySite { + if item_3_x_BodySite != nil { + if item_3_x_BodySite.Reference != nil { + if item_3_x_BodySite.Reference.Reference != nil { + refVal := *item_3_x_BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "bodySite_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.BodySite != nil { + for _, item_3_x_BodySite := range x.BodySite { + if item_3_x_BodySite != nil { + if item_3_x_BodySite.Reference != nil { + if item_3_x_BodySite.Reference.Reference != nil { + refVal := *item_3_x_BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "bodySite_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.BodySite != nil { + for _, item_3_x_BodySite := range x.BodySite { + if item_3_x_BodySite != nil { + if item_3_x_BodySite.Reference != nil { + if item_3_x_BodySite.Reference.Reference != nil { + refVal := *item_3_x_BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "bodySite_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.BodySite != nil { + for _, item_3_x_BodySite := range x.BodySite { + if item_3_x_BodySite != nil { + if item_3_x_BodySite.Reference != nil { + if item_3_x_BodySite.Reference.Reference != nil { + refVal := *item_3_x_BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "bodySite_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.BodySite != nil { + for _, item_3_x_BodySite := range x.BodySite { + if item_3_x_BodySite != nil { + if item_3_x_BodySite.Reference != nil { + if item_3_x_BodySite.Reference.Reference != nil { + refVal := *item_3_x_BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "bodySite_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.BodySite != nil { + for _, item_3_x_BodySite := range x.BodySite { + if item_3_x_BodySite != nil { + if item_3_x_BodySite.Reference != nil { + if item_3_x_BodySite.Reference.Reference != nil { + refVal := *item_3_x_BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "bodySite_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.BodySite != nil { + for _, item_3_x_BodySite := range x.BodySite { + if item_3_x_BodySite != nil { + if item_3_x_BodySite.Reference != nil { + if item_3_x_BodySite.Reference.Reference != nil { + refVal := *item_3_x_BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "bodySite_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.BodySite != nil { + for _, item_3_x_BodySite := range x.BodySite { + if item_3_x_BodySite != nil { + if item_3_x_BodySite.Reference != nil { + if item_3_x_BodySite.Reference.Reference != nil { + refVal := *item_3_x_BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "bodySite_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.BodySite != nil { + for _, item_3_x_BodySite := range x.BodySite { + if item_3_x_BodySite != nil { + if item_3_x_BodySite.Reference != nil { + if item_3_x_BodySite.Reference.Reference != nil { + refVal := *item_3_x_BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "bodySite_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.BodySite != nil { + for _, item_3_x_BodySite := range x.BodySite { + if item_3_x_BodySite != nil { + if item_3_x_BodySite.Reference != nil { + if item_3_x_BodySite.Reference.Reference != nil { + refVal := *item_3_x_BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "bodySite_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.BodySite != nil { + for _, item_3_x_BodySite := range x.BodySite { + if item_3_x_BodySite != nil { + if item_3_x_BodySite.Reference != nil { + if item_3_x_BodySite.Reference.Reference != nil { + refVal := *item_3_x_BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "bodySite_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.BodySite != nil { + for _, item_3_x_BodySite := range x.BodySite { + if item_3_x_BodySite != nil { + if item_3_x_BodySite.Reference != nil { + if item_3_x_BodySite.Reference.Reference != nil { + refVal := *item_3_x_BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "bodySite_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.BodySite != nil { + for _, item_3_x_BodySite := range x.BodySite { + if item_3_x_BodySite != nil { + if item_3_x_BodySite.Reference != nil { + if item_3_x_BodySite.Reference.Reference != nil { + refVal := *item_3_x_BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "bodySite_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.BodySite != nil { + for _, item_3_x_BodySite := range x.BodySite { + if item_3_x_BodySite != nil { + if item_3_x_BodySite.Reference != nil { + if item_3_x_BodySite.Reference.Reference != nil { + refVal := *item_3_x_BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "bodySite_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.BodySite != nil { + for _, item_3_x_BodySite := range x.BodySite { + if item_3_x_BodySite != nil { + if item_3_x_BodySite.Reference != nil { + if item_3_x_BodySite.Reference.Reference != nil { + refVal := *item_3_x_BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "bodySite_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.BodySite != nil { + for _, item_3_x_BodySite := range x.BodySite { + if item_3_x_BodySite != nil { + if item_3_x_BodySite.Reference != nil { + if item_3_x_BodySite.Reference.Reference != nil { + refVal := *item_3_x_BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "bodySite_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.BodySite != nil { + for _, item_3_x_BodySite := range x.BodySite { + if item_3_x_BodySite != nil { + if item_3_x_BodySite.Reference != nil { + if item_3_x_BodySite.Reference.Reference != nil { + refVal := *item_3_x_BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "bodySite_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.BodySite != nil { + for _, item_3_x_BodySite := range x.BodySite { + if item_3_x_BodySite != nil { + if item_3_x_BodySite.Reference != nil { + if item_3_x_BodySite.Reference.Reference != nil { + refVal := *item_3_x_BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "bodySite_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.BodySite != nil { + for _, item_3_x_BodySite := range x.BodySite { + if item_3_x_BodySite != nil { + if item_3_x_BodySite.Reference != nil { + if item_3_x_BodySite.Reference.Reference != nil { + refVal := *item_3_x_BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "bodySite_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.BodySite != nil { + for _, item_3_x_BodySite := range x.BodySite { + if item_3_x_BodySite != nil { + if item_3_x_BodySite.Reference != nil { + if item_3_x_BodySite.Reference.Reference != nil { + refVal := *item_3_x_BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "bodySite_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.BodySite != nil { + for _, item_3_x_BodySite := range x.BodySite { + if item_3_x_BodySite != nil { + if item_3_x_BodySite.Reference != nil { + if item_3_x_BodySite.Reference.Reference != nil { + refVal := *item_3_x_BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "bodySite_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.BodySite != nil { + for _, item_3_x_BodySite := range x.BodySite { + if item_3_x_BodySite != nil { + if item_3_x_BodySite.Reference != nil { + if item_3_x_BodySite.Reference.Reference != nil { + refVal := *item_3_x_BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "bodySite_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Event != nil { + for _, item_3_x_Event := range x.Event { + if item_3_x_Event != nil { + if item_3_x_Event.Reference != nil { + if item_3_x_Event.Reference.Reference != nil { + refVal := *item_3_x_Event.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "event_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "event_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Event != nil { + for _, item_3_x_Event := range x.Event { + if item_3_x_Event != nil { + if item_3_x_Event.Reference != nil { + if item_3_x_Event.Reference.Reference != nil { + refVal := *item_3_x_Event.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "event_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "event_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Event != nil { + for _, item_3_x_Event := range x.Event { + if item_3_x_Event != nil { + if item_3_x_Event.Reference != nil { + if item_3_x_Event.Reference.Reference != nil { + refVal := *item_3_x_Event.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "event_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "event_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Event != nil { + for _, item_3_x_Event := range x.Event { + if item_3_x_Event != nil { + if item_3_x_Event.Reference != nil { + if item_3_x_Event.Reference.Reference != nil { + refVal := *item_3_x_Event.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "event_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "event_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Event != nil { + for _, item_3_x_Event := range x.Event { + if item_3_x_Event != nil { + if item_3_x_Event.Reference != nil { + if item_3_x_Event.Reference.Reference != nil { + refVal := *item_3_x_Event.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "event_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "event_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Event != nil { + for _, item_3_x_Event := range x.Event { + if item_3_x_Event != nil { + if item_3_x_Event.Reference != nil { + if item_3_x_Event.Reference.Reference != nil { + refVal := *item_3_x_Event.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "event_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "event_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Event != nil { + for _, item_3_x_Event := range x.Event { + if item_3_x_Event != nil { + if item_3_x_Event.Reference != nil { + if item_3_x_Event.Reference.Reference != nil { + refVal := *item_3_x_Event.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "event_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "event_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Event != nil { + for _, item_3_x_Event := range x.Event { + if item_3_x_Event != nil { + if item_3_x_Event.Reference != nil { + if item_3_x_Event.Reference.Reference != nil { + refVal := *item_3_x_Event.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "event_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "event_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Event != nil { + for _, item_3_x_Event := range x.Event { + if item_3_x_Event != nil { + if item_3_x_Event.Reference != nil { + if item_3_x_Event.Reference.Reference != nil { + refVal := *item_3_x_Event.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "event_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "event_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Event != nil { + for _, item_3_x_Event := range x.Event { + if item_3_x_Event != nil { + if item_3_x_Event.Reference != nil { + if item_3_x_Event.Reference.Reference != nil { + refVal := *item_3_x_Event.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "event_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "event_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Event != nil { + for _, item_3_x_Event := range x.Event { + if item_3_x_Event != nil { + if item_3_x_Event.Reference != nil { + if item_3_x_Event.Reference.Reference != nil { + refVal := *item_3_x_Event.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "event_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "event_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Event != nil { + for _, item_3_x_Event := range x.Event { + if item_3_x_Event != nil { + if item_3_x_Event.Reference != nil { + if item_3_x_Event.Reference.Reference != nil { + refVal := *item_3_x_Event.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "event_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "event_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Event != nil { + for _, item_3_x_Event := range x.Event { + if item_3_x_Event != nil { + if item_3_x_Event.Reference != nil { + if item_3_x_Event.Reference.Reference != nil { + refVal := *item_3_x_Event.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "event_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "event_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Event != nil { + for _, item_3_x_Event := range x.Event { + if item_3_x_Event != nil { + if item_3_x_Event.Reference != nil { + if item_3_x_Event.Reference.Reference != nil { + refVal := *item_3_x_Event.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "event_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "event_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Event != nil { + for _, item_3_x_Event := range x.Event { + if item_3_x_Event != nil { + if item_3_x_Event.Reference != nil { + if item_3_x_Event.Reference.Reference != nil { + refVal := *item_3_x_Event.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "event_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "event_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Event != nil { + for _, item_3_x_Event := range x.Event { + if item_3_x_Event != nil { + if item_3_x_Event.Reference != nil { + if item_3_x_Event.Reference.Reference != nil { + refVal := *item_3_x_Event.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "event_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "event_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Event != nil { + for _, item_3_x_Event := range x.Event { + if item_3_x_Event != nil { + if item_3_x_Event.Reference != nil { + if item_3_x_Event.Reference.Reference != nil { + refVal := *item_3_x_Event.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "event_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "event_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Event != nil { + for _, item_3_x_Event := range x.Event { + if item_3_x_Event != nil { + if item_3_x_Event.Reference != nil { + if item_3_x_Event.Reference.Reference != nil { + refVal := *item_3_x_Event.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "event_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "event_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Event != nil { + for _, item_3_x_Event := range x.Event { + if item_3_x_Event != nil { + if item_3_x_Event.Reference != nil { + if item_3_x_Event.Reference.Reference != nil { + refVal := *item_3_x_Event.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "event_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "event_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Event != nil { + for _, item_3_x_Event := range x.Event { + if item_3_x_Event != nil { + if item_3_x_Event.Reference != nil { + if item_3_x_Event.Reference.Reference != nil { + refVal := *item_3_x_Event.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "event_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "event_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Event != nil { + for _, item_3_x_Event := range x.Event { + if item_3_x_Event != nil { + if item_3_x_Event.Reference != nil { + if item_3_x_Event.Reference.Reference != nil { + refVal := *item_3_x_Event.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "event_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "event_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Event != nil { + for _, item_3_x_Event := range x.Event { + if item_3_x_Event != nil { + if item_3_x_Event.Reference != nil { + if item_3_x_Event.Reference.Reference != nil { + refVal := *item_3_x_Event.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "event_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "event_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Event != nil { + for _, item_3_x_Event := range x.Event { + if item_3_x_Event != nil { + if item_3_x_Event.Reference != nil { + if item_3_x_Event.Reference.Reference != nil { + refVal := *item_3_x_Event.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "event_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "event_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RelatesTo != nil { + for _, item_3_x_RelatesTo := range x.RelatesTo { + if item_3_x_RelatesTo != nil { + if item_3_x_RelatesTo.Target != nil { + if item_3_x_RelatesTo.Target.Reference != nil { + refVal := *item_3_x_RelatesTo.Target.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "relatesTo_target") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("target", targetID), + "relatesTo_target", + projectJSON, + sourceType, + "target", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference_relates_to") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("to", id), + "document_reference_relates_to", + projectJSON, + sourceType, + "to", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from DocumentReferenceAttester. +func (x *DocumentReferenceAttester) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "DocumentReferenceAttester" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Party != nil { + if x.Party.Reference != nil { + refVal := *x.Party.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "party_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "party_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference_attester") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("attester", id), + "document_reference_attester", + projectJSON, + sourceType, + "attester", + )) + } + } + } + } + } + if x.Party != nil { + if x.Party.Reference != nil { + refVal := *x.Party.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "party_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "party_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference_attester") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("attester", id), + "document_reference_attester", + projectJSON, + sourceType, + "attester", + )) + } + } + } + } + } + if x.Party != nil { + if x.Party.Reference != nil { + refVal := *x.Party.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "party_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "party_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference_attester") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("attester", id), + "document_reference_attester", + projectJSON, + sourceType, + "attester", + )) + } + } + } + } + } + if x.Party != nil { + if x.Party.Reference != nil { + refVal := *x.Party.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "party_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "party_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference_attester") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("attester", id), + "document_reference_attester", + projectJSON, + sourceType, + "attester", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from DocumentReferenceContent. +func (x *DocumentReferenceContent) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "DocumentReferenceContent" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from DocumentReferenceContentProfile. +func (x *DocumentReferenceContentProfile) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "DocumentReferenceContentProfile" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from DocumentReferenceRelatesTo. +func (x *DocumentReferenceRelatesTo) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "DocumentReferenceRelatesTo" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Target != nil { + if x.Target.Reference != nil { + refVal := *x.Target.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "target") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("target", targetID), + "target", + projectJSON, + sourceType, + "target", + )) + } + backrefKey := getEdgeUUID(id, targetID, "document_reference_relates_to") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("to", id), + "document_reference_relates_to", + projectJSON, + sourceType, + "to", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from Dosage. +func (x *Dosage) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Dosage" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from DosageDoseAndRate. +func (x *DosageDoseAndRate) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "DosageDoseAndRate" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from Duration. +func (x *Duration) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Duration" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from Expression. +func (x *Expression) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Expression" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from ExtendedContactDetail. +func (x *ExtendedContactDetail) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ExtendedContactDetail" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Organization != nil { + if x.Organization.Reference != nil { + refVal := *x.Organization.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("organization", targetID), + "organization", + projectJSON, + sourceType, + "organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extended_contact_detail") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("detail", id), + "extended_contact_detail", + projectJSON, + sourceType, + "detail", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from Extension. +func (x *Extension) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Extension" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "valueReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extension") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("extension", id), + "extension", + projectJSON, + sourceType, + "extension", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "valueReference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extension") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("extension", id), + "extension", + projectJSON, + sourceType, + "extension", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "valueReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extension") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("extension", id), + "extension", + projectJSON, + sourceType, + "extension", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "valueReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extension") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("extension", id), + "extension", + projectJSON, + sourceType, + "extension", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "valueReference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extension") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("extension", id), + "extension", + projectJSON, + sourceType, + "extension", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "valueReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extension") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("extension", id), + "extension", + projectJSON, + sourceType, + "extension", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "valueReference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extension") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("extension", id), + "extension", + projectJSON, + sourceType, + "extension", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "valueReference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extension") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("extension", id), + "extension", + projectJSON, + sourceType, + "extension", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "valueReference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extension") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("extension", id), + "extension", + projectJSON, + sourceType, + "extension", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "valueReference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extension") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("extension", id), + "extension", + projectJSON, + sourceType, + "extension", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "valueReference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extension") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("extension", id), + "extension", + projectJSON, + sourceType, + "extension", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "valueReference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extension") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("extension", id), + "extension", + projectJSON, + sourceType, + "extension", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "valueReference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extension") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("extension", id), + "extension", + projectJSON, + sourceType, + "extension", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "valueReference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extension") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("extension", id), + "extension", + projectJSON, + sourceType, + "extension", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "valueReference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extension") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("extension", id), + "extension", + projectJSON, + sourceType, + "extension", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "valueReference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extension") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("extension", id), + "extension", + projectJSON, + sourceType, + "extension", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "valueReference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extension") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("extension", id), + "extension", + projectJSON, + sourceType, + "extension", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "valueReference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extension") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("extension", id), + "extension", + projectJSON, + sourceType, + "extension", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "valueReference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extension") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("extension", id), + "extension", + projectJSON, + sourceType, + "extension", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "valueReference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extension") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("extension", id), + "extension", + projectJSON, + sourceType, + "extension", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "valueReference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extension") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("extension", id), + "extension", + projectJSON, + sourceType, + "extension", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "valueReference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extension") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("extension", id), + "extension", + projectJSON, + sourceType, + "extension", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "valueReference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extension") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("extension", id), + "extension", + projectJSON, + sourceType, + "extension", + )) + } + } + } + } + } + if x.ValueAnnotation != nil { + if x.ValueAnnotation.AuthorReference != nil { + if x.ValueAnnotation.AuthorReference.Reference != nil { + refVal := *x.ValueAnnotation.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "valueAnnotation_authorReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + if x.ValueAnnotation != nil { + if x.ValueAnnotation.AuthorReference != nil { + if x.ValueAnnotation.AuthorReference.Reference != nil { + refVal := *x.ValueAnnotation.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "valueAnnotation_authorReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + if x.ValueAnnotation != nil { + if x.ValueAnnotation.AuthorReference != nil { + if x.ValueAnnotation.AuthorReference.Reference != nil { + refVal := *x.ValueAnnotation.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "valueAnnotation_authorReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + if x.ValueAnnotation != nil { + if x.ValueAnnotation.AuthorReference != nil { + if x.ValueAnnotation.AuthorReference.Reference != nil { + refVal := *x.ValueAnnotation.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "valueAnnotation_authorReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "valueCodeableReference_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "valueCodeableReference_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "valueCodeableReference_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "valueCodeableReference_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "valueCodeableReference_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "valueCodeableReference_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "valueCodeableReference_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "valueCodeableReference_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "valueCodeableReference_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "valueCodeableReference_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "valueCodeableReference_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "valueCodeableReference_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "valueCodeableReference_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "valueCodeableReference_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "valueCodeableReference_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "valueCodeableReference_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "valueCodeableReference_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "valueCodeableReference_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "valueCodeableReference_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "valueCodeableReference_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "valueCodeableReference_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "valueCodeableReference_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "valueCodeableReference_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueDataRequirement != nil { + if x.ValueDataRequirement.SubjectReference != nil { + if x.ValueDataRequirement.SubjectReference.Reference != nil { + refVal := *x.ValueDataRequirement.SubjectReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "valueDataRequirement_subjectReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("subjectReference", targetID), + "valueDataRequirement_subjectReference", + projectJSON, + sourceType, + "subjectReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "data_requirement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("requirement", id), + "data_requirement", + projectJSON, + sourceType, + "requirement", + )) + } + } + } + } + } + } + if x.ValueExtendedContactDetail != nil { + if x.ValueExtendedContactDetail.Organization != nil { + if x.ValueExtendedContactDetail.Organization.Reference != nil { + refVal := *x.ValueExtendedContactDetail.Organization.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueExtendedContactDetail_organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("organization", targetID), + "valueExtendedContactDetail_organization", + projectJSON, + sourceType, + "organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extended_contact_detail") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("detail", id), + "extended_contact_detail", + projectJSON, + sourceType, + "detail", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "valueRelatedArtifact_resourceReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "valueRelatedArtifact_resourceReference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "valueRelatedArtifact_resourceReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "valueRelatedArtifact_resourceReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "valueRelatedArtifact_resourceReference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "valueRelatedArtifact_resourceReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "valueRelatedArtifact_resourceReference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "valueRelatedArtifact_resourceReference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "valueRelatedArtifact_resourceReference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "valueRelatedArtifact_resourceReference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "valueRelatedArtifact_resourceReference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "valueRelatedArtifact_resourceReference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "valueRelatedArtifact_resourceReference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "valueRelatedArtifact_resourceReference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "valueRelatedArtifact_resourceReference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "valueRelatedArtifact_resourceReference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "valueRelatedArtifact_resourceReference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "valueRelatedArtifact_resourceReference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "valueRelatedArtifact_resourceReference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "valueRelatedArtifact_resourceReference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "valueRelatedArtifact_resourceReference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "valueRelatedArtifact_resourceReference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "valueRelatedArtifact_resourceReference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.OnBehalfOf != nil { + if x.ValueSignature.OnBehalfOf.Reference != nil { + refVal := *x.ValueSignature.OnBehalfOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "valueSignature_onBehalfOf_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "onBehalfOf_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.OnBehalfOf != nil { + if x.ValueSignature.OnBehalfOf.Reference != nil { + refVal := *x.ValueSignature.OnBehalfOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "valueSignature_onBehalfOf_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "onBehalfOf_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.OnBehalfOf != nil { + if x.ValueSignature.OnBehalfOf.Reference != nil { + refVal := *x.ValueSignature.OnBehalfOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "valueSignature_onBehalfOf_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "onBehalfOf_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.OnBehalfOf != nil { + if x.ValueSignature.OnBehalfOf.Reference != nil { + refVal := *x.ValueSignature.OnBehalfOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "valueSignature_onBehalfOf_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "onBehalfOf_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.Who != nil { + if x.ValueSignature.Who.Reference != nil { + refVal := *x.ValueSignature.Who.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "valueSignature_who_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "who_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "who_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.Who != nil { + if x.ValueSignature.Who.Reference != nil { + refVal := *x.ValueSignature.Who.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "valueSignature_who_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "who_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "who_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.Who != nil { + if x.ValueSignature.Who.Reference != nil { + refVal := *x.ValueSignature.Who.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "valueSignature_who_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "who_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "who_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.Who != nil { + if x.ValueSignature.Who.Reference != nil { + refVal := *x.ValueSignature.Who.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "valueSignature_who_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "who_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "who_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueUsageContext != nil { + if x.ValueUsageContext.ValueReference != nil { + if x.ValueUsageContext.ValueReference.Reference != nil { + refVal := *x.ValueUsageContext.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueUsageContext_valueReference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "valueUsageContext_valueReference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "usage_context") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("context", id), + "usage_context", + projectJSON, + sourceType, + "context", + )) + } + } + } + } + } + } + if x.ValueUsageContext != nil { + if x.ValueUsageContext.ValueReference != nil { + if x.ValueUsageContext.ValueReference.Reference != nil { + refVal := *x.ValueUsageContext.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "valueUsageContext_valueReference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "valueUsageContext_valueReference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "usage_context") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("context", id), + "usage_context", + projectJSON, + sourceType, + "context", + )) + } + } + } + } + } + } + if x.ValueUsageContext != nil { + if x.ValueUsageContext.ValueReference != nil { + if x.ValueUsageContext.ValueReference.Reference != nil { + refVal := *x.ValueUsageContext.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueUsageContext_valueReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "valueUsageContext_valueReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "usage_context") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("context", id), + "usage_context", + projectJSON, + sourceType, + "context", + )) + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from FHIRPrimitiveExtension. +func (x *FHIRPrimitiveExtension) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "FHIRPrimitiveExtension" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from FamilyMemberHistory. +func (x *FamilyMemberHistory) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "FamilyMemberHistory" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Patient != nil { + if x.Patient.Reference != nil { + refVal := *x.Patient.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("patient", targetID), + "patient", + projectJSON, + sourceType, + "patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "family_member_history") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("history", id), + "family_member_history", + projectJSON, + sourceType, + "history", + )) + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "note_authorReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "note_authorReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "note_authorReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "note_authorReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Participant != nil { + for _, item_3_x_Participant := range x.Participant { + if item_3_x_Participant != nil { + if item_3_x_Participant.Actor != nil { + if item_3_x_Participant.Actor.Reference != nil { + refVal := *item_3_x_Participant.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "participant_actor_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "participant_actor_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "family_member_history_participant") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("participant", id), + "family_member_history_participant", + projectJSON, + sourceType, + "participant", + )) + } + } + } + } + } + } + } + } + if x.Participant != nil { + for _, item_3_x_Participant := range x.Participant { + if item_3_x_Participant != nil { + if item_3_x_Participant.Actor != nil { + if item_3_x_Participant.Actor.Reference != nil { + refVal := *item_3_x_Participant.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "participant_actor_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "participant_actor_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "family_member_history_participant") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("participant", id), + "family_member_history_participant", + projectJSON, + sourceType, + "participant", + )) + } + } + } + } + } + } + } + } + if x.Participant != nil { + for _, item_3_x_Participant := range x.Participant { + if item_3_x_Participant != nil { + if item_3_x_Participant.Actor != nil { + if item_3_x_Participant.Actor.Reference != nil { + refVal := *item_3_x_Participant.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "participant_actor_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "participant_actor_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "family_member_history_participant") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("participant", id), + "family_member_history_participant", + projectJSON, + sourceType, + "participant", + )) + } + } + } + } + } + } + } + } + if x.Participant != nil { + for _, item_3_x_Participant := range x.Participant { + if item_3_x_Participant != nil { + if item_3_x_Participant.Actor != nil { + if item_3_x_Participant.Actor.Reference != nil { + refVal := *item_3_x_Participant.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "participant_actor_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "participant_actor_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "family_member_history_participant") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("participant", id), + "family_member_history_participant", + projectJSON, + sourceType, + "participant", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "reason_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "reason_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "reason_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "reason_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "reason_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "reason_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "reason_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "reason_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "reason_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "reason_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "reason_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "reason_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "reason_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "reason_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "reason_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "reason_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "reason_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "reason_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "reason_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "reason_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "reason_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "reason_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "reason_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from FamilyMemberHistoryCondition. +func (x *FamilyMemberHistoryCondition) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "FamilyMemberHistoryCondition" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "note_authorReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "note_authorReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "note_authorReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "note_authorReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from FamilyMemberHistoryParticipant. +func (x *FamilyMemberHistoryParticipant) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "FamilyMemberHistoryParticipant" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Actor != nil { + if x.Actor.Reference != nil { + refVal := *x.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "actor_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "actor_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "family_member_history_participant") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("participant", id), + "family_member_history_participant", + projectJSON, + sourceType, + "participant", + )) + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + refVal := *x.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "actor_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "actor_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "family_member_history_participant") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("participant", id), + "family_member_history_participant", + projectJSON, + sourceType, + "participant", + )) + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + refVal := *x.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "actor_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "actor_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "family_member_history_participant") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("participant", id), + "family_member_history_participant", + projectJSON, + sourceType, + "participant", + )) + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + refVal := *x.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "actor_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "actor_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "family_member_history_participant") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("participant", id), + "family_member_history_participant", + projectJSON, + sourceType, + "participant", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from FamilyMemberHistoryProcedure. +func (x *FamilyMemberHistoryProcedure) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "FamilyMemberHistoryProcedure" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "note_authorReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "note_authorReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "note_authorReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "note_authorReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from Group. +func (x *Group) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Group" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.ManagingEntity != nil { + if x.ManagingEntity.Reference != nil { + refVal := *x.ManagingEntity.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "managingEntity_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "managingEntity_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("group", id), + "group", + projectJSON, + sourceType, + "group", + )) + } + } + } + } + } + if x.ManagingEntity != nil { + if x.ManagingEntity.Reference != nil { + refVal := *x.ManagingEntity.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "managingEntity_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "managingEntity_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("group", id), + "group", + projectJSON, + sourceType, + "group", + )) + } + } + } + } + } + if x.ManagingEntity != nil { + if x.ManagingEntity.Reference != nil { + refVal := *x.ManagingEntity.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "managingEntity_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "managingEntity_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("group", id), + "group", + projectJSON, + sourceType, + "group", + )) + } + } + } + } + } + if x.Characteristic != nil { + for _, item_3_x_Characteristic := range x.Characteristic { + if item_3_x_Characteristic != nil { + if item_3_x_Characteristic.ValueReference != nil { + if item_3_x_Characteristic.ValueReference.Reference != nil { + refVal := *item_3_x_Characteristic.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "characteristic_valueReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + } + } + } + if x.Characteristic != nil { + for _, item_3_x_Characteristic := range x.Characteristic { + if item_3_x_Characteristic != nil { + if item_3_x_Characteristic.ValueReference != nil { + if item_3_x_Characteristic.ValueReference.Reference != nil { + refVal := *item_3_x_Characteristic.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "characteristic_valueReference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + } + } + } + if x.Characteristic != nil { + for _, item_3_x_Characteristic := range x.Characteristic { + if item_3_x_Characteristic != nil { + if item_3_x_Characteristic.ValueReference != nil { + if item_3_x_Characteristic.ValueReference.Reference != nil { + refVal := *item_3_x_Characteristic.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "characteristic_valueReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + } + } + } + if x.Characteristic != nil { + for _, item_3_x_Characteristic := range x.Characteristic { + if item_3_x_Characteristic != nil { + if item_3_x_Characteristic.ValueReference != nil { + if item_3_x_Characteristic.ValueReference.Reference != nil { + refVal := *item_3_x_Characteristic.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "characteristic_valueReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + } + } + } + if x.Characteristic != nil { + for _, item_3_x_Characteristic := range x.Characteristic { + if item_3_x_Characteristic != nil { + if item_3_x_Characteristic.ValueReference != nil { + if item_3_x_Characteristic.ValueReference.Reference != nil { + refVal := *item_3_x_Characteristic.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "characteristic_valueReference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + } + } + } + if x.Characteristic != nil { + for _, item_3_x_Characteristic := range x.Characteristic { + if item_3_x_Characteristic != nil { + if item_3_x_Characteristic.ValueReference != nil { + if item_3_x_Characteristic.ValueReference.Reference != nil { + refVal := *item_3_x_Characteristic.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "characteristic_valueReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + } + } + } + if x.Characteristic != nil { + for _, item_3_x_Characteristic := range x.Characteristic { + if item_3_x_Characteristic != nil { + if item_3_x_Characteristic.ValueReference != nil { + if item_3_x_Characteristic.ValueReference.Reference != nil { + refVal := *item_3_x_Characteristic.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "characteristic_valueReference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + } + } + } + if x.Characteristic != nil { + for _, item_3_x_Characteristic := range x.Characteristic { + if item_3_x_Characteristic != nil { + if item_3_x_Characteristic.ValueReference != nil { + if item_3_x_Characteristic.ValueReference.Reference != nil { + refVal := *item_3_x_Characteristic.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "characteristic_valueReference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + } + } + } + if x.Characteristic != nil { + for _, item_3_x_Characteristic := range x.Characteristic { + if item_3_x_Characteristic != nil { + if item_3_x_Characteristic.ValueReference != nil { + if item_3_x_Characteristic.ValueReference.Reference != nil { + refVal := *item_3_x_Characteristic.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "characteristic_valueReference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + } + } + } + if x.Characteristic != nil { + for _, item_3_x_Characteristic := range x.Characteristic { + if item_3_x_Characteristic != nil { + if item_3_x_Characteristic.ValueReference != nil { + if item_3_x_Characteristic.ValueReference.Reference != nil { + refVal := *item_3_x_Characteristic.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "characteristic_valueReference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + } + } + } + if x.Characteristic != nil { + for _, item_3_x_Characteristic := range x.Characteristic { + if item_3_x_Characteristic != nil { + if item_3_x_Characteristic.ValueReference != nil { + if item_3_x_Characteristic.ValueReference.Reference != nil { + refVal := *item_3_x_Characteristic.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "characteristic_valueReference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + } + } + } + if x.Characteristic != nil { + for _, item_3_x_Characteristic := range x.Characteristic { + if item_3_x_Characteristic != nil { + if item_3_x_Characteristic.ValueReference != nil { + if item_3_x_Characteristic.ValueReference.Reference != nil { + refVal := *item_3_x_Characteristic.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "characteristic_valueReference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + } + } + } + if x.Characteristic != nil { + for _, item_3_x_Characteristic := range x.Characteristic { + if item_3_x_Characteristic != nil { + if item_3_x_Characteristic.ValueReference != nil { + if item_3_x_Characteristic.ValueReference.Reference != nil { + refVal := *item_3_x_Characteristic.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "characteristic_valueReference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + } + } + } + if x.Characteristic != nil { + for _, item_3_x_Characteristic := range x.Characteristic { + if item_3_x_Characteristic != nil { + if item_3_x_Characteristic.ValueReference != nil { + if item_3_x_Characteristic.ValueReference.Reference != nil { + refVal := *item_3_x_Characteristic.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "characteristic_valueReference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + } + } + } + if x.Characteristic != nil { + for _, item_3_x_Characteristic := range x.Characteristic { + if item_3_x_Characteristic != nil { + if item_3_x_Characteristic.ValueReference != nil { + if item_3_x_Characteristic.ValueReference.Reference != nil { + refVal := *item_3_x_Characteristic.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "characteristic_valueReference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + } + } + } + if x.Characteristic != nil { + for _, item_3_x_Characteristic := range x.Characteristic { + if item_3_x_Characteristic != nil { + if item_3_x_Characteristic.ValueReference != nil { + if item_3_x_Characteristic.ValueReference.Reference != nil { + refVal := *item_3_x_Characteristic.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "characteristic_valueReference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + } + } + } + if x.Characteristic != nil { + for _, item_3_x_Characteristic := range x.Characteristic { + if item_3_x_Characteristic != nil { + if item_3_x_Characteristic.ValueReference != nil { + if item_3_x_Characteristic.ValueReference.Reference != nil { + refVal := *item_3_x_Characteristic.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "characteristic_valueReference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + } + } + } + if x.Characteristic != nil { + for _, item_3_x_Characteristic := range x.Characteristic { + if item_3_x_Characteristic != nil { + if item_3_x_Characteristic.ValueReference != nil { + if item_3_x_Characteristic.ValueReference.Reference != nil { + refVal := *item_3_x_Characteristic.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "characteristic_valueReference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + } + } + } + if x.Characteristic != nil { + for _, item_3_x_Characteristic := range x.Characteristic { + if item_3_x_Characteristic != nil { + if item_3_x_Characteristic.ValueReference != nil { + if item_3_x_Characteristic.ValueReference.Reference != nil { + refVal := *item_3_x_Characteristic.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "characteristic_valueReference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + } + } + } + if x.Characteristic != nil { + for _, item_3_x_Characteristic := range x.Characteristic { + if item_3_x_Characteristic != nil { + if item_3_x_Characteristic.ValueReference != nil { + if item_3_x_Characteristic.ValueReference.Reference != nil { + refVal := *item_3_x_Characteristic.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "characteristic_valueReference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + } + } + } + if x.Characteristic != nil { + for _, item_3_x_Characteristic := range x.Characteristic { + if item_3_x_Characteristic != nil { + if item_3_x_Characteristic.ValueReference != nil { + if item_3_x_Characteristic.ValueReference.Reference != nil { + refVal := *item_3_x_Characteristic.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "characteristic_valueReference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + } + } + } + if x.Characteristic != nil { + for _, item_3_x_Characteristic := range x.Characteristic { + if item_3_x_Characteristic != nil { + if item_3_x_Characteristic.ValueReference != nil { + if item_3_x_Characteristic.ValueReference.Reference != nil { + refVal := *item_3_x_Characteristic.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "characteristic_valueReference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + } + } + } + if x.Characteristic != nil { + for _, item_3_x_Characteristic := range x.Characteristic { + if item_3_x_Characteristic != nil { + if item_3_x_Characteristic.ValueReference != nil { + if item_3_x_Characteristic.ValueReference.Reference != nil { + refVal := *item_3_x_Characteristic.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "characteristic_valueReference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "characteristic_valueReference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + } + } + } + if x.Member != nil { + for _, item_3_x_Member := range x.Member { + if item_3_x_Member != nil { + if item_3_x_Member.Entity != nil { + if item_3_x_Member.Entity.Reference != nil { + refVal := *item_3_x_Member.Entity.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "member_entity_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "member_entity_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_member") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("member", id), + "group_member", + projectJSON, + sourceType, + "member", + )) + } + } + } + } + } + } + } + } + if x.Member != nil { + for _, item_3_x_Member := range x.Member { + if item_3_x_Member != nil { + if item_3_x_Member.Entity != nil { + if item_3_x_Member.Entity.Reference != nil { + refVal := *item_3_x_Member.Entity.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "member_entity_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "member_entity_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_member") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("member", id), + "group_member", + projectJSON, + sourceType, + "member", + )) + } + } + } + } + } + } + } + } + if x.Member != nil { + for _, item_3_x_Member := range x.Member { + if item_3_x_Member != nil { + if item_3_x_Member.Entity != nil { + if item_3_x_Member.Entity.Reference != nil { + refVal := *item_3_x_Member.Entity.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "member_entity_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "member_entity_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_member") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("member", id), + "group_member", + projectJSON, + sourceType, + "member", + )) + } + } + } + } + } + } + } + } + if x.Member != nil { + for _, item_3_x_Member := range x.Member { + if item_3_x_Member != nil { + if item_3_x_Member.Entity != nil { + if item_3_x_Member.Entity.Reference != nil { + refVal := *item_3_x_Member.Entity.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "member_entity_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "member_entity_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_member") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("member", id), + "group_member", + projectJSON, + sourceType, + "member", + )) + } + } + } + } + } + } + } + } + if x.Member != nil { + for _, item_3_x_Member := range x.Member { + if item_3_x_Member != nil { + if item_3_x_Member.Entity != nil { + if item_3_x_Member.Entity.Reference != nil { + refVal := *item_3_x_Member.Entity.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "member_entity_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "member_entity_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_member") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("member", id), + "group_member", + projectJSON, + sourceType, + "member", + )) + } + } + } + } + } + } + } + } + if x.Member != nil { + for _, item_3_x_Member := range x.Member { + if item_3_x_Member != nil { + if item_3_x_Member.Entity != nil { + if item_3_x_Member.Entity.Reference != nil { + refVal := *item_3_x_Member.Entity.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "member_entity_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "member_entity_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_member") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("member", id), + "group_member", + projectJSON, + sourceType, + "member", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from GroupCharacteristic. +func (x *GroupCharacteristic) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "GroupCharacteristic" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "valueReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "valueReference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "valueReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "valueReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "valueReference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "valueReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "valueReference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "valueReference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "valueReference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "valueReference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "valueReference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "valueReference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "valueReference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "valueReference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "valueReference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "valueReference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "valueReference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "valueReference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "valueReference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "valueReference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "valueReference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "valueReference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "valueReference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_characteristic") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("characteristic", id), + "group_characteristic", + projectJSON, + sourceType, + "characteristic", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from GroupMember. +func (x *GroupMember) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "GroupMember" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Entity != nil { + if x.Entity.Reference != nil { + refVal := *x.Entity.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "entity_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "entity_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_member") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("member", id), + "group_member", + projectJSON, + sourceType, + "member", + )) + } + } + } + } + } + if x.Entity != nil { + if x.Entity.Reference != nil { + refVal := *x.Entity.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "entity_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "entity_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_member") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("member", id), + "group_member", + projectJSON, + sourceType, + "member", + )) + } + } + } + } + } + if x.Entity != nil { + if x.Entity.Reference != nil { + refVal := *x.Entity.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "entity_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "entity_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_member") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("member", id), + "group_member", + projectJSON, + sourceType, + "member", + )) + } + } + } + } + } + if x.Entity != nil { + if x.Entity.Reference != nil { + refVal := *x.Entity.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "entity_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "entity_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_member") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("member", id), + "group_member", + projectJSON, + sourceType, + "member", + )) + } + } + } + } + } + if x.Entity != nil { + if x.Entity.Reference != nil { + refVal := *x.Entity.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "entity_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "entity_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_member") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("member", id), + "group_member", + projectJSON, + sourceType, + "member", + )) + } + } + } + } + } + if x.Entity != nil { + if x.Entity.Reference != nil { + refVal := *x.Entity.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "entity_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "entity_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "group_member") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("member", id), + "group_member", + projectJSON, + sourceType, + "member", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from HumanName. +func (x *HumanName) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "HumanName" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from Identifier. +func (x *Identifier) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Identifier" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Assigner != nil { + if x.Assigner.Reference != nil { + refVal := *x.Assigner.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "assigner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("assigner", targetID), + "assigner", + projectJSON, + sourceType, + "assigner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "identifier") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("identifier", id), + "identifier", + projectJSON, + sourceType, + "identifier", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from ImagingStudy. +func (x *ImagingStudy) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ImagingStudy" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "basedOn_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_imaging_study") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("study", id), + "basedOn_imaging_study", + projectJSON, + sourceType, + "study", + )) + } + } + } + } + } + } + } + if x.PartOf != nil { + for _, item_2_x_PartOf := range x.PartOf { + if item_2_x_PartOf != nil { + if item_2_x_PartOf.Reference != nil { + refVal := *item_2_x_PartOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "partOf") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("partOf", targetID), + "partOf", + projectJSON, + sourceType, + "partOf", + )) + } + backrefKey := getEdgeUUID(id, targetID, "partOf_imaging_study") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("study", id), + "partOf_imaging_study", + projectJSON, + sourceType, + "study", + )) + } + } + } + } + } + } + } + if x.Referrer != nil { + if x.Referrer.Reference != nil { + refVal := *x.Referrer.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "referrer_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "referrer_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "imaging_study") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("study", id), + "imaging_study", + projectJSON, + sourceType, + "study", + )) + } + } + } + } + } + if x.Referrer != nil { + if x.Referrer.Reference != nil { + refVal := *x.Referrer.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "referrer_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "referrer_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "imaging_study") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("study", id), + "imaging_study", + projectJSON, + sourceType, + "study", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "subject_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "subject_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "imaging_study") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("study", id), + "imaging_study", + projectJSON, + sourceType, + "study", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "subject_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "subject_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "imaging_study") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("study", id), + "imaging_study", + projectJSON, + sourceType, + "study", + )) + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "note_authorReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "note_authorReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "note_authorReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "note_authorReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Procedure != nil { + for _, item_3_x_Procedure := range x.Procedure { + if item_3_x_Procedure != nil { + if item_3_x_Procedure.Reference != nil { + if item_3_x_Procedure.Reference.Reference != nil { + refVal := *item_3_x_Procedure.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "procedure_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "procedure_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Procedure != nil { + for _, item_3_x_Procedure := range x.Procedure { + if item_3_x_Procedure != nil { + if item_3_x_Procedure.Reference != nil { + if item_3_x_Procedure.Reference.Reference != nil { + refVal := *item_3_x_Procedure.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "procedure_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "procedure_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Procedure != nil { + for _, item_3_x_Procedure := range x.Procedure { + if item_3_x_Procedure != nil { + if item_3_x_Procedure.Reference != nil { + if item_3_x_Procedure.Reference.Reference != nil { + refVal := *item_3_x_Procedure.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "procedure_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "procedure_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Procedure != nil { + for _, item_3_x_Procedure := range x.Procedure { + if item_3_x_Procedure != nil { + if item_3_x_Procedure.Reference != nil { + if item_3_x_Procedure.Reference.Reference != nil { + refVal := *item_3_x_Procedure.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "procedure_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "procedure_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Procedure != nil { + for _, item_3_x_Procedure := range x.Procedure { + if item_3_x_Procedure != nil { + if item_3_x_Procedure.Reference != nil { + if item_3_x_Procedure.Reference.Reference != nil { + refVal := *item_3_x_Procedure.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "procedure_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "procedure_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Procedure != nil { + for _, item_3_x_Procedure := range x.Procedure { + if item_3_x_Procedure != nil { + if item_3_x_Procedure.Reference != nil { + if item_3_x_Procedure.Reference.Reference != nil { + refVal := *item_3_x_Procedure.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "procedure_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "procedure_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Procedure != nil { + for _, item_3_x_Procedure := range x.Procedure { + if item_3_x_Procedure != nil { + if item_3_x_Procedure.Reference != nil { + if item_3_x_Procedure.Reference.Reference != nil { + refVal := *item_3_x_Procedure.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "procedure_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "procedure_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Procedure != nil { + for _, item_3_x_Procedure := range x.Procedure { + if item_3_x_Procedure != nil { + if item_3_x_Procedure.Reference != nil { + if item_3_x_Procedure.Reference.Reference != nil { + refVal := *item_3_x_Procedure.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "procedure_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "procedure_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Procedure != nil { + for _, item_3_x_Procedure := range x.Procedure { + if item_3_x_Procedure != nil { + if item_3_x_Procedure.Reference != nil { + if item_3_x_Procedure.Reference.Reference != nil { + refVal := *item_3_x_Procedure.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "procedure_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "procedure_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Procedure != nil { + for _, item_3_x_Procedure := range x.Procedure { + if item_3_x_Procedure != nil { + if item_3_x_Procedure.Reference != nil { + if item_3_x_Procedure.Reference.Reference != nil { + refVal := *item_3_x_Procedure.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "procedure_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "procedure_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Procedure != nil { + for _, item_3_x_Procedure := range x.Procedure { + if item_3_x_Procedure != nil { + if item_3_x_Procedure.Reference != nil { + if item_3_x_Procedure.Reference.Reference != nil { + refVal := *item_3_x_Procedure.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "procedure_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "procedure_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Procedure != nil { + for _, item_3_x_Procedure := range x.Procedure { + if item_3_x_Procedure != nil { + if item_3_x_Procedure.Reference != nil { + if item_3_x_Procedure.Reference.Reference != nil { + refVal := *item_3_x_Procedure.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "procedure_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "procedure_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Procedure != nil { + for _, item_3_x_Procedure := range x.Procedure { + if item_3_x_Procedure != nil { + if item_3_x_Procedure.Reference != nil { + if item_3_x_Procedure.Reference.Reference != nil { + refVal := *item_3_x_Procedure.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "procedure_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "procedure_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Procedure != nil { + for _, item_3_x_Procedure := range x.Procedure { + if item_3_x_Procedure != nil { + if item_3_x_Procedure.Reference != nil { + if item_3_x_Procedure.Reference.Reference != nil { + refVal := *item_3_x_Procedure.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "procedure_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "procedure_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Procedure != nil { + for _, item_3_x_Procedure := range x.Procedure { + if item_3_x_Procedure != nil { + if item_3_x_Procedure.Reference != nil { + if item_3_x_Procedure.Reference.Reference != nil { + refVal := *item_3_x_Procedure.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "procedure_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "procedure_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Procedure != nil { + for _, item_3_x_Procedure := range x.Procedure { + if item_3_x_Procedure != nil { + if item_3_x_Procedure.Reference != nil { + if item_3_x_Procedure.Reference.Reference != nil { + refVal := *item_3_x_Procedure.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "procedure_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "procedure_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Procedure != nil { + for _, item_3_x_Procedure := range x.Procedure { + if item_3_x_Procedure != nil { + if item_3_x_Procedure.Reference != nil { + if item_3_x_Procedure.Reference.Reference != nil { + refVal := *item_3_x_Procedure.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "procedure_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "procedure_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Procedure != nil { + for _, item_3_x_Procedure := range x.Procedure { + if item_3_x_Procedure != nil { + if item_3_x_Procedure.Reference != nil { + if item_3_x_Procedure.Reference.Reference != nil { + refVal := *item_3_x_Procedure.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "procedure_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "procedure_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Procedure != nil { + for _, item_3_x_Procedure := range x.Procedure { + if item_3_x_Procedure != nil { + if item_3_x_Procedure.Reference != nil { + if item_3_x_Procedure.Reference.Reference != nil { + refVal := *item_3_x_Procedure.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "procedure_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "procedure_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Procedure != nil { + for _, item_3_x_Procedure := range x.Procedure { + if item_3_x_Procedure != nil { + if item_3_x_Procedure.Reference != nil { + if item_3_x_Procedure.Reference.Reference != nil { + refVal := *item_3_x_Procedure.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "procedure_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "procedure_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Procedure != nil { + for _, item_3_x_Procedure := range x.Procedure { + if item_3_x_Procedure != nil { + if item_3_x_Procedure.Reference != nil { + if item_3_x_Procedure.Reference.Reference != nil { + refVal := *item_3_x_Procedure.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "procedure_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "procedure_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Procedure != nil { + for _, item_3_x_Procedure := range x.Procedure { + if item_3_x_Procedure != nil { + if item_3_x_Procedure.Reference != nil { + if item_3_x_Procedure.Reference.Reference != nil { + refVal := *item_3_x_Procedure.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "procedure_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "procedure_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Procedure != nil { + for _, item_3_x_Procedure := range x.Procedure { + if item_3_x_Procedure != nil { + if item_3_x_Procedure.Reference != nil { + if item_3_x_Procedure.Reference.Reference != nil { + refVal := *item_3_x_Procedure.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "procedure_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "procedure_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "reason_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "reason_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "reason_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "reason_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "reason_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "reason_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "reason_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "reason_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "reason_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "reason_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "reason_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "reason_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "reason_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "reason_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "reason_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "reason_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "reason_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "reason_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "reason_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "reason_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "reason_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "reason_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "reason_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Series != nil { + for _, item_4_x_Series := range x.Series { + if item_4_x_Series != nil { + if item_4_x_Series.Specimen != nil { + for _, item_2_item_4_x_Series_Specimen := range item_4_x_Series.Specimen { + if item_2_item_4_x_Series_Specimen != nil { + if item_2_item_4_x_Series_Specimen.Reference != nil { + refVal := *item_2_item_4_x_Series_Specimen.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "series_specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("specimen", targetID), + "series_specimen", + projectJSON, + sourceType, + "specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "specimen_imaging_study_series") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("series", id), + "specimen_imaging_study_series", + projectJSON, + sourceType, + "series", + )) + } + } + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from ImagingStudySeries. +func (x *ImagingStudySeries) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ImagingStudySeries" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Specimen != nil { + for _, item_2_x_Specimen := range x.Specimen { + if item_2_x_Specimen != nil { + if item_2_x_Specimen.Reference != nil { + refVal := *item_2_x_Specimen.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("specimen", targetID), + "specimen", + projectJSON, + sourceType, + "specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "specimen_imaging_study_series") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("series", id), + "specimen_imaging_study_series", + projectJSON, + sourceType, + "series", + )) + } + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "bodySite_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "bodySite_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "bodySite_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "bodySite_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "bodySite_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "bodySite_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "bodySite_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "bodySite_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "bodySite_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "bodySite_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "bodySite_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "bodySite_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "bodySite_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "bodySite_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "bodySite_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "bodySite_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "bodySite_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "bodySite_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "bodySite_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "bodySite_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "bodySite_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "bodySite_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "bodySite_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Performer != nil { + for _, item_3_x_Performer := range x.Performer { + if item_3_x_Performer != nil { + if item_3_x_Performer.Actor != nil { + if item_3_x_Performer.Actor.Reference != nil { + refVal := *item_3_x_Performer.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "performer_actor_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "performer_actor_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "imaging_study_series_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "imaging_study_series_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + } + } + } + if x.Performer != nil { + for _, item_3_x_Performer := range x.Performer { + if item_3_x_Performer != nil { + if item_3_x_Performer.Actor != nil { + if item_3_x_Performer.Actor.Reference != nil { + refVal := *item_3_x_Performer.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "performer_actor_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "performer_actor_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "imaging_study_series_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "imaging_study_series_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + } + } + } + if x.Performer != nil { + for _, item_3_x_Performer := range x.Performer { + if item_3_x_Performer != nil { + if item_3_x_Performer.Actor != nil { + if item_3_x_Performer.Actor.Reference != nil { + refVal := *item_3_x_Performer.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "performer_actor_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "performer_actor_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "imaging_study_series_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "imaging_study_series_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + } + } + } + if x.Performer != nil { + for _, item_3_x_Performer := range x.Performer { + if item_3_x_Performer != nil { + if item_3_x_Performer.Actor != nil { + if item_3_x_Performer.Actor.Reference != nil { + refVal := *item_3_x_Performer.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "performer_actor_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "performer_actor_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "imaging_study_series_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "imaging_study_series_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from ImagingStudySeriesInstance. +func (x *ImagingStudySeriesInstance) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ImagingStudySeriesInstance" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from ImagingStudySeriesPerformer. +func (x *ImagingStudySeriesPerformer) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ImagingStudySeriesPerformer" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Actor != nil { + if x.Actor.Reference != nil { + refVal := *x.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "actor_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "actor_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "imaging_study_series_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "imaging_study_series_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + refVal := *x.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "actor_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "actor_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "imaging_study_series_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "imaging_study_series_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + refVal := *x.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "actor_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "actor_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "imaging_study_series_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "imaging_study_series_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + refVal := *x.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "actor_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "actor_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "imaging_study_series_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "imaging_study_series_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from Medication. +func (x *Medication) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Medication" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.MarketingAuthorizationHolder != nil { + if x.MarketingAuthorizationHolder.Reference != nil { + refVal := *x.MarketingAuthorizationHolder.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "marketingAuthorizationHolder") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("marketingAuthorizationHolder", targetID), + "marketingAuthorizationHolder", + projectJSON, + sourceType, + "marketingAuthorizationHolder", + )) + } + backrefKey := getEdgeUUID(id, targetID, "medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("medication", id), + "medication", + projectJSON, + sourceType, + "medication", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from MedicationAdministration. +func (x *MedicationAdministration) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "MedicationAdministration" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.PartOf != nil { + for _, item_2_x_PartOf := range x.PartOf { + if item_2_x_PartOf != nil { + if item_2_x_PartOf.Reference != nil { + refVal := *item_2_x_PartOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "partOf_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "partOf_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "partOf_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "partOf_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.PartOf != nil { + for _, item_2_x_PartOf := range x.PartOf { + if item_2_x_PartOf != nil { + if item_2_x_PartOf.Reference != nil { + refVal := *item_2_x_PartOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "partOf_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "partOf_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "partOf_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "partOf_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.Request != nil { + if x.Request.Reference != nil { + refVal := *x.Request.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("request", targetID), + "request", + projectJSON, + sourceType, + "request", + )) + } + backrefKey := getEdgeUUID(id, targetID, "medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "subject_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "subject_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "subject_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "subject_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "supportingInformation_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "supportingInformation_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "supportingInformation_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "supportingInformation_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "supportingInformation_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "supportingInformation_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "supportingInformation_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "supportingInformation_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "supportingInformation_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "supportingInformation_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "supportingInformation_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "supportingInformation_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "supportingInformation_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "supportingInformation_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "supportingInformation_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "supportingInformation_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "supportingInformation_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "supportingInformation_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "supportingInformation_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "supportingInformation_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "supportingInformation_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "supportingInformation_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "supportingInformation_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "supportingInformation_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "supportingInformation_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "supportingInformation_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "supportingInformation_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "supportingInformation_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "supportingInformation_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "supportingInformation_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "supportingInformation_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "supportingInformation_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "supportingInformation_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "supportingInformation_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "supportingInformation_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "supportingInformation_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "supportingInformation_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "supportingInformation_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "supportingInformation_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "supportingInformation_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "supportingInformation_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "supportingInformation_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "supportingInformation_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "supportingInformation_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "supportingInformation_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_administration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("administration", id), + "supportingInformation_medication_administration", + projectJSON, + sourceType, + "administration", + )) + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "device_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "device_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "device_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "device_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "device_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "device_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "device_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "device_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "device_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "device_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "device_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "device_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "device_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "device_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "device_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "device_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "device_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "device_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "device_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "device_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "device_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "device_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "device_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "medication_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "medication_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "medication_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "medication_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "medication_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "medication_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "medication_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "medication_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "medication_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "medication_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "medication_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "medication_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "medication_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "medication_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "medication_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "medication_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "medication_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "medication_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "medication_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "medication_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "medication_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "medication_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "medication_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "note_authorReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "note_authorReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "note_authorReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "note_authorReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "reason_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "reason_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "reason_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "reason_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "reason_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "reason_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "reason_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "reason_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "reason_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "reason_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "reason_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "reason_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "reason_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "reason_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "reason_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "reason_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "reason_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "reason_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "reason_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "reason_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "reason_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "reason_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "reason_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from MedicationAdministrationDosage. +func (x *MedicationAdministrationDosage) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "MedicationAdministrationDosage" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from MedicationAdministrationPerformer. +func (x *MedicationAdministrationPerformer) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "MedicationAdministrationPerformer" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Actor != nil { + if x.Actor.Reference != nil { + if x.Actor.Reference.Reference != nil { + refVal := *x.Actor.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "actor_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "actor_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + if x.Actor.Reference.Reference != nil { + refVal := *x.Actor.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "actor_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "actor_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + if x.Actor.Reference.Reference != nil { + refVal := *x.Actor.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "actor_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "actor_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + if x.Actor.Reference.Reference != nil { + refVal := *x.Actor.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "actor_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "actor_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + if x.Actor.Reference.Reference != nil { + refVal := *x.Actor.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "actor_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "actor_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + if x.Actor.Reference.Reference != nil { + refVal := *x.Actor.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "actor_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "actor_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + if x.Actor.Reference.Reference != nil { + refVal := *x.Actor.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "actor_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "actor_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + if x.Actor.Reference.Reference != nil { + refVal := *x.Actor.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "actor_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "actor_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + if x.Actor.Reference.Reference != nil { + refVal := *x.Actor.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "actor_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "actor_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + if x.Actor.Reference.Reference != nil { + refVal := *x.Actor.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "actor_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "actor_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + if x.Actor.Reference.Reference != nil { + refVal := *x.Actor.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "actor_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "actor_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + if x.Actor.Reference.Reference != nil { + refVal := *x.Actor.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "actor_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "actor_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + if x.Actor.Reference.Reference != nil { + refVal := *x.Actor.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "actor_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "actor_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + if x.Actor.Reference.Reference != nil { + refVal := *x.Actor.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "actor_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "actor_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + if x.Actor.Reference.Reference != nil { + refVal := *x.Actor.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "actor_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "actor_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + if x.Actor.Reference.Reference != nil { + refVal := *x.Actor.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "actor_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "actor_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + if x.Actor.Reference.Reference != nil { + refVal := *x.Actor.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "actor_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "actor_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + if x.Actor.Reference.Reference != nil { + refVal := *x.Actor.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "actor_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "actor_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + if x.Actor.Reference.Reference != nil { + refVal := *x.Actor.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "actor_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "actor_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + if x.Actor.Reference.Reference != nil { + refVal := *x.Actor.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "actor_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "actor_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + if x.Actor.Reference.Reference != nil { + refVal := *x.Actor.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "actor_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "actor_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + if x.Actor.Reference.Reference != nil { + refVal := *x.Actor.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "actor_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "actor_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + if x.Actor.Reference.Reference != nil { + refVal := *x.Actor.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "actor_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "actor_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from MedicationBatch. +func (x *MedicationBatch) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "MedicationBatch" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from MedicationIngredient. +func (x *MedicationIngredient) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "MedicationIngredient" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Item != nil { + if x.Item.Reference != nil { + if x.Item.Reference.Reference != nil { + refVal := *x.Item.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "item_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "item_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Item != nil { + if x.Item.Reference != nil { + if x.Item.Reference.Reference != nil { + refVal := *x.Item.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "item_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "item_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Item != nil { + if x.Item.Reference != nil { + if x.Item.Reference.Reference != nil { + refVal := *x.Item.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "item_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "item_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Item != nil { + if x.Item.Reference != nil { + if x.Item.Reference.Reference != nil { + refVal := *x.Item.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "item_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "item_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Item != nil { + if x.Item.Reference != nil { + if x.Item.Reference.Reference != nil { + refVal := *x.Item.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "item_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "item_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Item != nil { + if x.Item.Reference != nil { + if x.Item.Reference.Reference != nil { + refVal := *x.Item.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "item_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "item_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Item != nil { + if x.Item.Reference != nil { + if x.Item.Reference.Reference != nil { + refVal := *x.Item.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "item_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "item_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Item != nil { + if x.Item.Reference != nil { + if x.Item.Reference.Reference != nil { + refVal := *x.Item.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "item_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "item_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Item != nil { + if x.Item.Reference != nil { + if x.Item.Reference.Reference != nil { + refVal := *x.Item.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "item_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "item_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Item != nil { + if x.Item.Reference != nil { + if x.Item.Reference.Reference != nil { + refVal := *x.Item.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "item_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "item_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Item != nil { + if x.Item.Reference != nil { + if x.Item.Reference.Reference != nil { + refVal := *x.Item.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "item_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "item_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Item != nil { + if x.Item.Reference != nil { + if x.Item.Reference.Reference != nil { + refVal := *x.Item.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "item_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "item_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Item != nil { + if x.Item.Reference != nil { + if x.Item.Reference.Reference != nil { + refVal := *x.Item.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "item_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "item_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Item != nil { + if x.Item.Reference != nil { + if x.Item.Reference.Reference != nil { + refVal := *x.Item.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "item_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "item_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Item != nil { + if x.Item.Reference != nil { + if x.Item.Reference.Reference != nil { + refVal := *x.Item.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "item_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "item_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Item != nil { + if x.Item.Reference != nil { + if x.Item.Reference.Reference != nil { + refVal := *x.Item.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "item_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "item_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Item != nil { + if x.Item.Reference != nil { + if x.Item.Reference.Reference != nil { + refVal := *x.Item.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "item_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "item_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Item != nil { + if x.Item.Reference != nil { + if x.Item.Reference.Reference != nil { + refVal := *x.Item.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "item_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "item_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Item != nil { + if x.Item.Reference != nil { + if x.Item.Reference.Reference != nil { + refVal := *x.Item.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "item_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "item_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Item != nil { + if x.Item.Reference != nil { + if x.Item.Reference.Reference != nil { + refVal := *x.Item.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "item_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "item_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Item != nil { + if x.Item.Reference != nil { + if x.Item.Reference.Reference != nil { + refVal := *x.Item.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "item_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "item_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Item != nil { + if x.Item.Reference != nil { + if x.Item.Reference.Reference != nil { + refVal := *x.Item.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "item_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "item_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Item != nil { + if x.Item.Reference != nil { + if x.Item.Reference.Reference != nil { + refVal := *x.Item.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "item_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "item_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from MedicationRequest. +func (x *MedicationRequest) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "MedicationRequest" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "basedOn_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "basedOn_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.InformationSource != nil { + for _, item_2_x_InformationSource := range x.InformationSource { + if item_2_x_InformationSource != nil { + if item_2_x_InformationSource.Reference != nil { + refVal := *item_2_x_InformationSource.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "informationSource_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "informationSource_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "informationSource_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "informationSource_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.InformationSource != nil { + for _, item_2_x_InformationSource := range x.InformationSource { + if item_2_x_InformationSource != nil { + if item_2_x_InformationSource.Reference != nil { + refVal := *item_2_x_InformationSource.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "informationSource_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "informationSource_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "informationSource_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "informationSource_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.InformationSource != nil { + for _, item_2_x_InformationSource := range x.InformationSource { + if item_2_x_InformationSource != nil { + if item_2_x_InformationSource.Reference != nil { + refVal := *item_2_x_InformationSource.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "informationSource_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "informationSource_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "informationSource_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "informationSource_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.InformationSource != nil { + for _, item_2_x_InformationSource := range x.InformationSource { + if item_2_x_InformationSource != nil { + if item_2_x_InformationSource.Reference != nil { + refVal := *item_2_x_InformationSource.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "informationSource_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "informationSource_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "informationSource_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "informationSource_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.Performer != nil { + for _, item_2_x_Performer := range x.Performer { + if item_2_x_Performer != nil { + if item_2_x_Performer.Reference != nil { + refVal := *item_2_x_Performer.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "performer_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "performer_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "performer_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "performer_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.Performer != nil { + for _, item_2_x_Performer := range x.Performer { + if item_2_x_Performer != nil { + if item_2_x_Performer.Reference != nil { + refVal := *item_2_x_Performer.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "performer_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "performer_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "performer_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "performer_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.Performer != nil { + for _, item_2_x_Performer := range x.Performer { + if item_2_x_Performer != nil { + if item_2_x_Performer.Reference != nil { + refVal := *item_2_x_Performer.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "performer_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "performer_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "performer_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "performer_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.Performer != nil { + for _, item_2_x_Performer := range x.Performer { + if item_2_x_Performer != nil { + if item_2_x_Performer.Reference != nil { + refVal := *item_2_x_Performer.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "performer_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "performer_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "performer_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "performer_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.PriorPrescription != nil { + if x.PriorPrescription.Reference != nil { + refVal := *x.PriorPrescription.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "priorPrescription") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("priorPrescription", targetID), + "priorPrescription", + projectJSON, + sourceType, + "priorPrescription", + )) + } + backrefKey := getEdgeUUID(id, targetID, "priorPrescription_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "priorPrescription_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + if x.Recorder != nil { + if x.Recorder.Reference != nil { + refVal := *x.Recorder.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "recorder_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "recorder_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "recorder_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "recorder_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + if x.Recorder != nil { + if x.Recorder.Reference != nil { + refVal := *x.Recorder.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "recorder_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "recorder_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "recorder_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "recorder_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + if x.Requester != nil { + if x.Requester.Reference != nil { + refVal := *x.Requester.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "requester_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "requester_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "requester_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "requester_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + if x.Requester != nil { + if x.Requester.Reference != nil { + refVal := *x.Requester.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "requester_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "requester_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "requester_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "requester_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + if x.Requester != nil { + if x.Requester.Reference != nil { + refVal := *x.Requester.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "requester_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "requester_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "requester_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "requester_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + if x.Requester != nil { + if x.Requester.Reference != nil { + refVal := *x.Requester.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "requester_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "requester_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "requester_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "requester_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "subject_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "subject_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "subject_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "subject_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "subject_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "subject_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "subject_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "subject_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "supportingInformation_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "supportingInformation_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "supportingInformation_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "supportingInformation_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "supportingInformation_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "supportingInformation_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "supportingInformation_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "supportingInformation_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "supportingInformation_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "supportingInformation_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "supportingInformation_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "supportingInformation_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "supportingInformation_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "supportingInformation_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "supportingInformation_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "supportingInformation_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "supportingInformation_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "supportingInformation_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "supportingInformation_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "supportingInformation_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "supportingInformation_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "supportingInformation_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "supportingInformation_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "supportingInformation_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "supportingInformation_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "supportingInformation_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "supportingInformation_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "supportingInformation_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "supportingInformation_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "supportingInformation_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "supportingInformation_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "supportingInformation_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "supportingInformation_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "supportingInformation_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "supportingInformation_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "supportingInformation_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "supportingInformation_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "supportingInformation_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "supportingInformation_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "supportingInformation_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "supportingInformation_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "supportingInformation_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "supportingInformation_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "supportingInformation_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.SupportingInformation != nil { + for _, item_2_x_SupportingInformation := range x.SupportingInformation { + if item_2_x_SupportingInformation != nil { + if item_2_x_SupportingInformation.Reference != nil { + refVal := *item_2_x_SupportingInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "supportingInformation_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "supportingInformation_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInformation_medication_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "supportingInformation_medication_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "device_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "device_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "device_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "device_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "device_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "device_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "device_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "device_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "device_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "device_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "device_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "device_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "device_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "device_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "device_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "device_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "device_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "device_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "device_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "device_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "device_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "device_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Device != nil { + for _, item_3_x_Device := range x.Device { + if item_3_x_Device != nil { + if item_3_x_Device.Reference != nil { + if item_3_x_Device.Reference.Reference != nil { + refVal := *item_3_x_Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "device_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.DispenseRequest != nil { + if x.DispenseRequest.Dispenser != nil { + if x.DispenseRequest.Dispenser.Reference != nil { + refVal := *x.DispenseRequest.Dispenser.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "dispenseRequest_dispenser") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("dispenser", targetID), + "dispenseRequest_dispenser", + projectJSON, + sourceType, + "dispenser", + )) + } + backrefKey := getEdgeUUID(id, targetID, "medication_request_dispense_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "medication_request_dispense_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "medication_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "medication_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "medication_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "medication_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "medication_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "medication_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "medication_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "medication_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "medication_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "medication_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "medication_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "medication_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "medication_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "medication_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "medication_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "medication_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "medication_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "medication_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "medication_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "medication_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "medication_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "medication_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "medication_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "note_authorReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "note_authorReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "note_authorReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "note_authorReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "reason_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "reason_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "reason_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "reason_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "reason_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "reason_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "reason_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "reason_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "reason_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "reason_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "reason_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "reason_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "reason_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "reason_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "reason_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "reason_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "reason_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "reason_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "reason_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "reason_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "reason_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "reason_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "reason_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from MedicationRequestDispenseRequest. +func (x *MedicationRequestDispenseRequest) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "MedicationRequestDispenseRequest" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Dispenser != nil { + if x.Dispenser.Reference != nil { + refVal := *x.Dispenser.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "dispenser") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("dispenser", targetID), + "dispenser", + projectJSON, + sourceType, + "dispenser", + )) + } + backrefKey := getEdgeUUID(id, targetID, "medication_request_dispense_request") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("request", id), + "medication_request_dispense_request", + projectJSON, + sourceType, + "request", + )) + } + } + } + } + } + if x.DispenserInstruction != nil { + for _, item_3_x_DispenserInstruction := range x.DispenserInstruction { + if item_3_x_DispenserInstruction != nil { + if item_3_x_DispenserInstruction.AuthorReference != nil { + if item_3_x_DispenserInstruction.AuthorReference.Reference != nil { + refVal := *item_3_x_DispenserInstruction.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "dispenserInstruction_authorReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "dispenserInstruction_authorReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.DispenserInstruction != nil { + for _, item_3_x_DispenserInstruction := range x.DispenserInstruction { + if item_3_x_DispenserInstruction != nil { + if item_3_x_DispenserInstruction.AuthorReference != nil { + if item_3_x_DispenserInstruction.AuthorReference.Reference != nil { + refVal := *item_3_x_DispenserInstruction.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "dispenserInstruction_authorReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "dispenserInstruction_authorReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.DispenserInstruction != nil { + for _, item_3_x_DispenserInstruction := range x.DispenserInstruction { + if item_3_x_DispenserInstruction != nil { + if item_3_x_DispenserInstruction.AuthorReference != nil { + if item_3_x_DispenserInstruction.AuthorReference.Reference != nil { + refVal := *item_3_x_DispenserInstruction.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "dispenserInstruction_authorReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "dispenserInstruction_authorReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.DispenserInstruction != nil { + for _, item_3_x_DispenserInstruction := range x.DispenserInstruction { + if item_3_x_DispenserInstruction != nil { + if item_3_x_DispenserInstruction.AuthorReference != nil { + if item_3_x_DispenserInstruction.AuthorReference.Reference != nil { + refVal := *item_3_x_DispenserInstruction.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "dispenserInstruction_authorReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "dispenserInstruction_authorReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from MedicationRequestDispenseRequestInitialFill. +func (x *MedicationRequestDispenseRequestInitialFill) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "MedicationRequestDispenseRequestInitialFill" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from MedicationRequestSubstitution. +func (x *MedicationRequestSubstitution) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "MedicationRequestSubstitution" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from MedicationStatement. +func (x *MedicationStatement) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "MedicationStatement" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "derivedFrom_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "derivedFrom_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "derivedFrom_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "derivedFrom_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "derivedFrom_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "derivedFrom_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "derivedFrom_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "derivedFrom_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "derivedFrom_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "derivedFrom_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "derivedFrom_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "derivedFrom_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "derivedFrom_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "derivedFrom_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "derivedFrom_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "derivedFrom_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "derivedFrom_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "derivedFrom_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "derivedFrom_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "derivedFrom_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "derivedFrom_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "derivedFrom_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "derivedFrom_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "derivedFrom_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "derivedFrom_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "derivedFrom_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "derivedFrom_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "derivedFrom_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "derivedFrom_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "derivedFrom_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "derivedFrom_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "derivedFrom_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "derivedFrom_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "derivedFrom_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "derivedFrom_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "derivedFrom_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "derivedFrom_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "derivedFrom_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "derivedFrom_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "derivedFrom_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "derivedFrom_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "derivedFrom_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "derivedFrom_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "derivedFrom_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "derivedFrom_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "derivedFrom_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.InformationSource != nil { + for _, item_2_x_InformationSource := range x.InformationSource { + if item_2_x_InformationSource != nil { + if item_2_x_InformationSource.Reference != nil { + refVal := *item_2_x_InformationSource.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "informationSource_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "informationSource_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "informationSource_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "informationSource_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.InformationSource != nil { + for _, item_2_x_InformationSource := range x.InformationSource { + if item_2_x_InformationSource != nil { + if item_2_x_InformationSource.Reference != nil { + refVal := *item_2_x_InformationSource.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "informationSource_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "informationSource_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "informationSource_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "informationSource_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.InformationSource != nil { + for _, item_2_x_InformationSource := range x.InformationSource { + if item_2_x_InformationSource != nil { + if item_2_x_InformationSource.Reference != nil { + refVal := *item_2_x_InformationSource.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "informationSource_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "informationSource_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "informationSource_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "informationSource_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.InformationSource != nil { + for _, item_2_x_InformationSource := range x.InformationSource { + if item_2_x_InformationSource != nil { + if item_2_x_InformationSource.Reference != nil { + refVal := *item_2_x_InformationSource.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "informationSource_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "informationSource_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "informationSource_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "informationSource_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.PartOf != nil { + for _, item_2_x_PartOf := range x.PartOf { + if item_2_x_PartOf != nil { + if item_2_x_PartOf.Reference != nil { + refVal := *item_2_x_PartOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "partOf_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "partOf_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "partOf_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "partOf_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.PartOf != nil { + for _, item_2_x_PartOf := range x.PartOf { + if item_2_x_PartOf != nil { + if item_2_x_PartOf.Reference != nil { + refVal := *item_2_x_PartOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "partOf_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "partOf_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "partOf_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "partOf_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.RelatedClinicalInformation != nil { + for _, item_2_x_RelatedClinicalInformation := range x.RelatedClinicalInformation { + if item_2_x_RelatedClinicalInformation != nil { + if item_2_x_RelatedClinicalInformation.Reference != nil { + refVal := *item_2_x_RelatedClinicalInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "relatedClinicalInformation_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "relatedClinicalInformation_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "relatedClinicalInformation_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "relatedClinicalInformation_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.RelatedClinicalInformation != nil { + for _, item_2_x_RelatedClinicalInformation := range x.RelatedClinicalInformation { + if item_2_x_RelatedClinicalInformation != nil { + if item_2_x_RelatedClinicalInformation.Reference != nil { + refVal := *item_2_x_RelatedClinicalInformation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "relatedClinicalInformation_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "relatedClinicalInformation_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "relatedClinicalInformation_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "relatedClinicalInformation_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "subject_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "subject_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "subject_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "subject_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "subject_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "subject_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "subject_medication_statement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("statement", id), + "subject_medication_statement", + projectJSON, + sourceType, + "statement", + )) + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "medication_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "medication_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "medication_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "medication_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "medication_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "medication_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "medication_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "medication_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "medication_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "medication_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "medication_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "medication_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "medication_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "medication_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "medication_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "medication_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "medication_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "medication_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "medication_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "medication_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "medication_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "medication_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Medication != nil { + if x.Medication.Reference != nil { + if x.Medication.Reference.Reference != nil { + refVal := *x.Medication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "medication_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "medication_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "note_authorReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "note_authorReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "note_authorReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "note_authorReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "reason_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "reason_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "reason_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "reason_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "reason_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "reason_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "reason_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "reason_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "reason_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "reason_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "reason_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "reason_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "reason_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "reason_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "reason_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "reason_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "reason_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "reason_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "reason_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "reason_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "reason_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "reason_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "reason_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from MedicationStatementAdherence. +func (x *MedicationStatementAdherence) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "MedicationStatementAdherence" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from Meta. +func (x *Meta) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Meta" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from Money. +func (x *Money) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Money" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from Narrative. +func (x *Narrative) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Narrative" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from Observation. +func (x *Observation) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Observation" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "basedOn_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "basedOn_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.BodyStructure != nil { + if x.BodyStructure.Reference != nil { + refVal := *x.BodyStructure.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "bodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("bodyStructure", targetID), + "bodyStructure", + projectJSON, + sourceType, + "bodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "derivedFrom_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "derivedFrom_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "derivedFrom_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "derivedFrom_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.DerivedFrom != nil { + for _, item_2_x_DerivedFrom := range x.DerivedFrom { + if item_2_x_DerivedFrom != nil { + if item_2_x_DerivedFrom.Reference != nil { + refVal := *item_2_x_DerivedFrom.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "derivedFrom_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "derivedFrom_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "derivedFrom_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "derivedFrom_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_2_x_Focus := range x.Focus { + if item_2_x_Focus != nil { + if item_2_x_Focus.Reference != nil { + refVal := *item_2_x_Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "focus_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "focus_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "focus_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_2_x_Focus := range x.Focus { + if item_2_x_Focus != nil { + if item_2_x_Focus.Reference != nil { + refVal := *item_2_x_Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "focus_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "focus_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "focus_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_2_x_Focus := range x.Focus { + if item_2_x_Focus != nil { + if item_2_x_Focus.Reference != nil { + refVal := *item_2_x_Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "focus_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "focus_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "focus_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_2_x_Focus := range x.Focus { + if item_2_x_Focus != nil { + if item_2_x_Focus.Reference != nil { + refVal := *item_2_x_Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "focus_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "focus_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "focus_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_2_x_Focus := range x.Focus { + if item_2_x_Focus != nil { + if item_2_x_Focus.Reference != nil { + refVal := *item_2_x_Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "focus_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "focus_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "focus_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_2_x_Focus := range x.Focus { + if item_2_x_Focus != nil { + if item_2_x_Focus.Reference != nil { + refVal := *item_2_x_Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "focus_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "focus_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "focus_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_2_x_Focus := range x.Focus { + if item_2_x_Focus != nil { + if item_2_x_Focus.Reference != nil { + refVal := *item_2_x_Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "focus_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "focus_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "focus_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_2_x_Focus := range x.Focus { + if item_2_x_Focus != nil { + if item_2_x_Focus.Reference != nil { + refVal := *item_2_x_Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "focus_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "focus_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "focus_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_2_x_Focus := range x.Focus { + if item_2_x_Focus != nil { + if item_2_x_Focus.Reference != nil { + refVal := *item_2_x_Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "focus_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "focus_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "focus_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_2_x_Focus := range x.Focus { + if item_2_x_Focus != nil { + if item_2_x_Focus.Reference != nil { + refVal := *item_2_x_Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "focus_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "focus_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "focus_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_2_x_Focus := range x.Focus { + if item_2_x_Focus != nil { + if item_2_x_Focus.Reference != nil { + refVal := *item_2_x_Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "focus_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "focus_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "focus_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_2_x_Focus := range x.Focus { + if item_2_x_Focus != nil { + if item_2_x_Focus.Reference != nil { + refVal := *item_2_x_Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "focus_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "focus_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "focus_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_2_x_Focus := range x.Focus { + if item_2_x_Focus != nil { + if item_2_x_Focus.Reference != nil { + refVal := *item_2_x_Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "focus_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "focus_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "focus_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_2_x_Focus := range x.Focus { + if item_2_x_Focus != nil { + if item_2_x_Focus.Reference != nil { + refVal := *item_2_x_Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "focus_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "focus_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "focus_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_2_x_Focus := range x.Focus { + if item_2_x_Focus != nil { + if item_2_x_Focus.Reference != nil { + refVal := *item_2_x_Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "focus_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "focus_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "focus_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_2_x_Focus := range x.Focus { + if item_2_x_Focus != nil { + if item_2_x_Focus.Reference != nil { + refVal := *item_2_x_Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "focus_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "focus_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "focus_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_2_x_Focus := range x.Focus { + if item_2_x_Focus != nil { + if item_2_x_Focus.Reference != nil { + refVal := *item_2_x_Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "focus_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "focus_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "focus_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_2_x_Focus := range x.Focus { + if item_2_x_Focus != nil { + if item_2_x_Focus.Reference != nil { + refVal := *item_2_x_Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "focus_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "focus_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "focus_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_2_x_Focus := range x.Focus { + if item_2_x_Focus != nil { + if item_2_x_Focus.Reference != nil { + refVal := *item_2_x_Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "focus_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "focus_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "focus_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_2_x_Focus := range x.Focus { + if item_2_x_Focus != nil { + if item_2_x_Focus.Reference != nil { + refVal := *item_2_x_Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "focus_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "focus_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "focus_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_2_x_Focus := range x.Focus { + if item_2_x_Focus != nil { + if item_2_x_Focus.Reference != nil { + refVal := *item_2_x_Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "focus_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "focus_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "focus_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_2_x_Focus := range x.Focus { + if item_2_x_Focus != nil { + if item_2_x_Focus.Reference != nil { + refVal := *item_2_x_Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "focus_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "focus_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "focus_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_2_x_Focus := range x.Focus { + if item_2_x_Focus != nil { + if item_2_x_Focus.Reference != nil { + refVal := *item_2_x_Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "focus_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "focus_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "focus_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.HasMember != nil { + for _, item_2_x_HasMember := range x.HasMember { + if item_2_x_HasMember != nil { + if item_2_x_HasMember.Reference != nil { + refVal := *item_2_x_HasMember.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "hasMember_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "hasMember_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "hasMember_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "hasMember_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.PartOf != nil { + for _, item_2_x_PartOf := range x.PartOf { + if item_2_x_PartOf != nil { + if item_2_x_PartOf.Reference != nil { + refVal := *item_2_x_PartOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "partOf_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "partOf_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "partOf_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "partOf_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.PartOf != nil { + for _, item_2_x_PartOf := range x.PartOf { + if item_2_x_PartOf != nil { + if item_2_x_PartOf.Reference != nil { + refVal := *item_2_x_PartOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "partOf_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "partOf_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "partOf_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "partOf_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.PartOf != nil { + for _, item_2_x_PartOf := range x.PartOf { + if item_2_x_PartOf != nil { + if item_2_x_PartOf.Reference != nil { + refVal := *item_2_x_PartOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "partOf_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "partOf_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "partOf_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "partOf_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.PartOf != nil { + for _, item_2_x_PartOf := range x.PartOf { + if item_2_x_PartOf != nil { + if item_2_x_PartOf.Reference != nil { + refVal := *item_2_x_PartOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "partOf_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "partOf_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "partOf_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "partOf_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Performer != nil { + for _, item_2_x_Performer := range x.Performer { + if item_2_x_Performer != nil { + if item_2_x_Performer.Reference != nil { + refVal := *item_2_x_Performer.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "performer_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "performer_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "performer_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "performer_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Performer != nil { + for _, item_2_x_Performer := range x.Performer { + if item_2_x_Performer != nil { + if item_2_x_Performer.Reference != nil { + refVal := *item_2_x_Performer.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "performer_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "performer_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "performer_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "performer_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Performer != nil { + for _, item_2_x_Performer := range x.Performer { + if item_2_x_Performer != nil { + if item_2_x_Performer.Reference != nil { + refVal := *item_2_x_Performer.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "performer_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "performer_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "performer_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "performer_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Performer != nil { + for _, item_2_x_Performer := range x.Performer { + if item_2_x_Performer != nil { + if item_2_x_Performer.Reference != nil { + refVal := *item_2_x_Performer.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "performer_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "performer_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "performer_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "performer_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + } + } + if x.Specimen != nil { + if x.Specimen.Reference != nil { + refVal := *x.Specimen.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "specimen_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "specimen_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "specimen_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "specimen_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + if x.Specimen != nil { + if x.Specimen.Reference != nil { + refVal := *x.Specimen.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "specimen_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "specimen_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "specimen_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "specimen_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "subject_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "subject_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "subject_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "subject_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "subject_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "subject_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "subject_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "subject_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "subject_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "subject_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "subject_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "subject_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "subject_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "subject_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "subject_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "subject_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "subject_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "subject_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "subject_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "subject_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "subject_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "subject_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "subject_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "subject_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "subject_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "subject_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "subject_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("observation", id), + "subject_observation", + projectJSON, + sourceType, + "observation", + )) + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "note_authorReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "note_authorReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "note_authorReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "note_authorReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.TriggeredBy != nil { + for _, item_3_x_TriggeredBy := range x.TriggeredBy { + if item_3_x_TriggeredBy != nil { + if item_3_x_TriggeredBy.Observation != nil { + if item_3_x_TriggeredBy.Observation.Reference != nil { + refVal := *item_3_x_TriggeredBy.Observation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "triggeredBy_observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("observation", targetID), + "triggeredBy_observation", + projectJSON, + sourceType, + "observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "observation_triggered_by") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("by", id), + "observation_triggered_by", + projectJSON, + sourceType, + "by", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from ObservationComponent. +func (x *ObservationComponent) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ObservationComponent" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from ObservationReferenceRange. +func (x *ObservationReferenceRange) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ObservationReferenceRange" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from ObservationTriggeredBy. +func (x *ObservationTriggeredBy) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ObservationTriggeredBy" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Observation != nil { + if x.Observation.Reference != nil { + refVal := *x.Observation.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("observation", targetID), + "observation", + projectJSON, + sourceType, + "observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "observation_triggered_by") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("by", id), + "observation_triggered_by", + projectJSON, + sourceType, + "by", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from Organization. +func (x *Organization) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Organization" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.PartOf != nil { + if x.PartOf.Reference != nil { + refVal := *x.PartOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "partOf") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("partOf", targetID), + "partOf", + projectJSON, + sourceType, + "partOf", + )) + } + backrefKey := getEdgeUUID(id, targetID, "organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("organization", id), + "organization", + projectJSON, + sourceType, + "organization", + )) + } + } + } + } + } + if x.Contact != nil { + for _, item_3_x_Contact := range x.Contact { + if item_3_x_Contact != nil { + if item_3_x_Contact.Organization != nil { + if item_3_x_Contact.Organization.Reference != nil { + refVal := *item_3_x_Contact.Organization.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "contact_organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("organization", targetID), + "contact_organization", + projectJSON, + sourceType, + "organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extended_contact_detail") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("detail", id), + "extended_contact_detail", + projectJSON, + sourceType, + "detail", + )) + } + } + } + } + } + } + } + } + if x.Qualification != nil { + for _, item_3_x_Qualification := range x.Qualification { + if item_3_x_Qualification != nil { + if item_3_x_Qualification.Issuer != nil { + if item_3_x_Qualification.Issuer.Reference != nil { + refVal := *item_3_x_Qualification.Issuer.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "qualification_issuer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("issuer", targetID), + "qualification_issuer", + projectJSON, + sourceType, + "issuer", + )) + } + backrefKey := getEdgeUUID(id, targetID, "organization_qualification") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("qualification", id), + "organization_qualification", + projectJSON, + sourceType, + "qualification", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from OrganizationQualification. +func (x *OrganizationQualification) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "OrganizationQualification" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Issuer != nil { + if x.Issuer.Reference != nil { + refVal := *x.Issuer.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "issuer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("issuer", targetID), + "issuer", + projectJSON, + sourceType, + "issuer", + )) + } + backrefKey := getEdgeUUID(id, targetID, "organization_qualification") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("qualification", id), + "organization_qualification", + projectJSON, + sourceType, + "qualification", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from ParameterDefinition. +func (x *ParameterDefinition) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ParameterDefinition" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from Patient. +func (x *Patient) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Patient" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.GeneralPractitioner != nil { + for _, item_2_x_GeneralPractitioner := range x.GeneralPractitioner { + if item_2_x_GeneralPractitioner != nil { + if item_2_x_GeneralPractitioner.Reference != nil { + refVal := *item_2_x_GeneralPractitioner.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "generalPractitioner_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "generalPractitioner_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "generalPractitioner_patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("patient", id), + "generalPractitioner_patient", + projectJSON, + sourceType, + "patient", + )) + } + } + } + } + } + } + } + if x.GeneralPractitioner != nil { + for _, item_2_x_GeneralPractitioner := range x.GeneralPractitioner { + if item_2_x_GeneralPractitioner != nil { + if item_2_x_GeneralPractitioner.Reference != nil { + refVal := *item_2_x_GeneralPractitioner.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "generalPractitioner_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "generalPractitioner_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "generalPractitioner_patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("patient", id), + "generalPractitioner_patient", + projectJSON, + sourceType, + "patient", + )) + } + } + } + } + } + } + } + if x.GeneralPractitioner != nil { + for _, item_2_x_GeneralPractitioner := range x.GeneralPractitioner { + if item_2_x_GeneralPractitioner != nil { + if item_2_x_GeneralPractitioner.Reference != nil { + refVal := *item_2_x_GeneralPractitioner.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "generalPractitioner_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "generalPractitioner_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "generalPractitioner_patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("patient", id), + "generalPractitioner_patient", + projectJSON, + sourceType, + "patient", + )) + } + } + } + } + } + } + } + if x.ManagingOrganization != nil { + if x.ManagingOrganization.Reference != nil { + refVal := *x.ManagingOrganization.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "managingOrganization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("managingOrganization", targetID), + "managingOrganization", + projectJSON, + sourceType, + "managingOrganization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "managingOrganization_patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("patient", id), + "managingOrganization_patient", + projectJSON, + sourceType, + "patient", + )) + } + } + } + } + } + if x.Contact != nil { + for _, item_3_x_Contact := range x.Contact { + if item_3_x_Contact != nil { + if item_3_x_Contact.Organization != nil { + if item_3_x_Contact.Organization.Reference != nil { + refVal := *item_3_x_Contact.Organization.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "contact_organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("organization", targetID), + "contact_organization", + projectJSON, + sourceType, + "organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "patient_contact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("contact", id), + "patient_contact", + projectJSON, + sourceType, + "contact", + )) + } + } + } + } + } + } + } + } + if x.Link != nil { + for _, item_3_x_Link := range x.Link { + if item_3_x_Link != nil { + if item_3_x_Link.Other != nil { + if item_3_x_Link.Other.Reference != nil { + refVal := *item_3_x_Link.Other.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "link_other_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "link_other_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "patient_link") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("link", id), + "patient_link", + projectJSON, + sourceType, + "link", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from PatientCommunication. +func (x *PatientCommunication) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "PatientCommunication" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from PatientContact. +func (x *PatientContact) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "PatientContact" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Organization != nil { + if x.Organization.Reference != nil { + refVal := *x.Organization.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("organization", targetID), + "organization", + projectJSON, + sourceType, + "organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "patient_contact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("contact", id), + "patient_contact", + projectJSON, + sourceType, + "contact", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from PatientLink. +func (x *PatientLink) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "PatientLink" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Other != nil { + if x.Other.Reference != nil { + refVal := *x.Other.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "other_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "other_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "patient_link") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("link", id), + "patient_link", + projectJSON, + sourceType, + "link", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from Period. +func (x *Period) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Period" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from Practitioner. +func (x *Practitioner) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Practitioner" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Qualification != nil { + for _, item_3_x_Qualification := range x.Qualification { + if item_3_x_Qualification != nil { + if item_3_x_Qualification.Issuer != nil { + if item_3_x_Qualification.Issuer.Reference != nil { + refVal := *item_3_x_Qualification.Issuer.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "qualification_issuer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("issuer", targetID), + "qualification_issuer", + projectJSON, + sourceType, + "issuer", + )) + } + backrefKey := getEdgeUUID(id, targetID, "practitioner_qualification") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("qualification", id), + "practitioner_qualification", + projectJSON, + sourceType, + "qualification", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from PractitionerCommunication. +func (x *PractitionerCommunication) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "PractitionerCommunication" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from PractitionerQualification. +func (x *PractitionerQualification) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "PractitionerQualification" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Issuer != nil { + if x.Issuer.Reference != nil { + refVal := *x.Issuer.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "issuer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("issuer", targetID), + "issuer", + projectJSON, + sourceType, + "issuer", + )) + } + backrefKey := getEdgeUUID(id, targetID, "practitioner_qualification") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("qualification", id), + "practitioner_qualification", + projectJSON, + sourceType, + "qualification", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from PractitionerRole. +func (x *PractitionerRole) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "PractitionerRole" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Organization != nil { + if x.Organization.Reference != nil { + refVal := *x.Organization.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("organization", targetID), + "organization", + projectJSON, + sourceType, + "organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "practitioner_role") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("role", id), + "practitioner_role", + projectJSON, + sourceType, + "role", + )) + } + } + } + } + } + if x.Practitioner != nil { + if x.Practitioner.Reference != nil { + refVal := *x.Practitioner.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("practitioner", targetID), + "practitioner", + projectJSON, + sourceType, + "practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "practitioner_role") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("role", id), + "practitioner_role", + projectJSON, + sourceType, + "role", + )) + } + } + } + } + } + if x.Contact != nil { + for _, item_3_x_Contact := range x.Contact { + if item_3_x_Contact != nil { + if item_3_x_Contact.Organization != nil { + if item_3_x_Contact.Organization.Reference != nil { + refVal := *item_3_x_Contact.Organization.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "contact_organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("organization", targetID), + "contact_organization", + projectJSON, + sourceType, + "organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extended_contact_detail") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("detail", id), + "extended_contact_detail", + projectJSON, + sourceType, + "detail", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from Procedure. +func (x *Procedure) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Procedure" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "focus_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "focus_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "focus_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "focus_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "focus_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "focus_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "focus_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "focus_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "focus_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "focus_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "focus_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "focus_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "focus_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "focus_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "focus_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "focus_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "focus_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "focus_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + if x.PartOf != nil { + for _, item_2_x_PartOf := range x.PartOf { + if item_2_x_PartOf != nil { + if item_2_x_PartOf.Reference != nil { + refVal := *item_2_x_PartOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "partOf_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "partOf_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "partOf_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "partOf_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.PartOf != nil { + for _, item_2_x_PartOf := range x.PartOf { + if item_2_x_PartOf != nil { + if item_2_x_PartOf.Reference != nil { + refVal := *item_2_x_PartOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "partOf_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "partOf_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "partOf_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "partOf_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.PartOf != nil { + for _, item_2_x_PartOf := range x.PartOf { + if item_2_x_PartOf != nil { + if item_2_x_PartOf.Reference != nil { + refVal := *item_2_x_PartOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "partOf_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "partOf_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "partOf_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "partOf_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.Recorder != nil { + if x.Recorder.Reference != nil { + refVal := *x.Recorder.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "recorder_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "recorder_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "recorder_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "recorder_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + if x.Recorder != nil { + if x.Recorder.Reference != nil { + refVal := *x.Recorder.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "recorder_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "recorder_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "recorder_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "recorder_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + if x.Recorder != nil { + if x.Recorder.Reference != nil { + refVal := *x.Recorder.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "recorder_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "recorder_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "recorder_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "recorder_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + if x.Report != nil { + for _, item_2_x_Report := range x.Report { + if item_2_x_Report != nil { + if item_2_x_Report.Reference != nil { + refVal := *item_2_x_Report.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "report_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "report_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "report_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "report_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.Report != nil { + for _, item_2_x_Report := range x.Report { + if item_2_x_Report != nil { + if item_2_x_Report.Reference != nil { + refVal := *item_2_x_Report.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "report_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "report_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "report_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "report_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.ReportedReference != nil { + if x.ReportedReference.Reference != nil { + refVal := *x.ReportedReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "reportedReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "reportedReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "reportedReference_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "reportedReference_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + if x.ReportedReference != nil { + if x.ReportedReference.Reference != nil { + refVal := *x.ReportedReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "reportedReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "reportedReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "reportedReference_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "reportedReference_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + if x.ReportedReference != nil { + if x.ReportedReference.Reference != nil { + refVal := *x.ReportedReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "reportedReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "reportedReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "reportedReference_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "reportedReference_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + if x.ReportedReference != nil { + if x.ReportedReference.Reference != nil { + refVal := *x.ReportedReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "reportedReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "reportedReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "reportedReference_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "reportedReference_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "subject_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "subject_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "subject_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "subject_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "subject_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "subject_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "subject_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "subject_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "subject_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "subject_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "subject_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "subject_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "subject_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "subject_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "subject_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "subject_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_2_x_SupportingInfo := range x.SupportingInfo { + if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo.Reference != nil { + refVal := *item_2_x_SupportingInfo.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "supportingInfo_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "supportingInfo_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_2_x_SupportingInfo := range x.SupportingInfo { + if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo.Reference != nil { + refVal := *item_2_x_SupportingInfo.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "supportingInfo_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "supportingInfo_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_2_x_SupportingInfo := range x.SupportingInfo { + if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo.Reference != nil { + refVal := *item_2_x_SupportingInfo.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "supportingInfo_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "supportingInfo_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_2_x_SupportingInfo := range x.SupportingInfo { + if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo.Reference != nil { + refVal := *item_2_x_SupportingInfo.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "supportingInfo_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "supportingInfo_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_2_x_SupportingInfo := range x.SupportingInfo { + if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo.Reference != nil { + refVal := *item_2_x_SupportingInfo.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "supportingInfo_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "supportingInfo_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_2_x_SupportingInfo := range x.SupportingInfo { + if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo.Reference != nil { + refVal := *item_2_x_SupportingInfo.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "supportingInfo_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "supportingInfo_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_2_x_SupportingInfo := range x.SupportingInfo { + if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo.Reference != nil { + refVal := *item_2_x_SupportingInfo.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "supportingInfo_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "supportingInfo_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_2_x_SupportingInfo := range x.SupportingInfo { + if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo.Reference != nil { + refVal := *item_2_x_SupportingInfo.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "supportingInfo_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "supportingInfo_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_2_x_SupportingInfo := range x.SupportingInfo { + if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo.Reference != nil { + refVal := *item_2_x_SupportingInfo.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "supportingInfo_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "supportingInfo_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_2_x_SupportingInfo := range x.SupportingInfo { + if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo.Reference != nil { + refVal := *item_2_x_SupportingInfo.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "supportingInfo_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "supportingInfo_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_2_x_SupportingInfo := range x.SupportingInfo { + if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo.Reference != nil { + refVal := *item_2_x_SupportingInfo.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "supportingInfo_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "supportingInfo_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_2_x_SupportingInfo := range x.SupportingInfo { + if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo.Reference != nil { + refVal := *item_2_x_SupportingInfo.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "supportingInfo_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "supportingInfo_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_2_x_SupportingInfo := range x.SupportingInfo { + if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo.Reference != nil { + refVal := *item_2_x_SupportingInfo.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "supportingInfo_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "supportingInfo_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_2_x_SupportingInfo := range x.SupportingInfo { + if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo.Reference != nil { + refVal := *item_2_x_SupportingInfo.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "supportingInfo_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "supportingInfo_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_2_x_SupportingInfo := range x.SupportingInfo { + if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo.Reference != nil { + refVal := *item_2_x_SupportingInfo.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "supportingInfo_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "supportingInfo_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_2_x_SupportingInfo := range x.SupportingInfo { + if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo.Reference != nil { + refVal := *item_2_x_SupportingInfo.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "supportingInfo_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "supportingInfo_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_2_x_SupportingInfo := range x.SupportingInfo { + if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo.Reference != nil { + refVal := *item_2_x_SupportingInfo.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "supportingInfo_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "supportingInfo_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_2_x_SupportingInfo := range x.SupportingInfo { + if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo.Reference != nil { + refVal := *item_2_x_SupportingInfo.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "supportingInfo_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "supportingInfo_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_2_x_SupportingInfo := range x.SupportingInfo { + if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo.Reference != nil { + refVal := *item_2_x_SupportingInfo.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "supportingInfo_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "supportingInfo_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_2_x_SupportingInfo := range x.SupportingInfo { + if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo.Reference != nil { + refVal := *item_2_x_SupportingInfo.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "supportingInfo_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "supportingInfo_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_2_x_SupportingInfo := range x.SupportingInfo { + if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo.Reference != nil { + refVal := *item_2_x_SupportingInfo.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "supportingInfo_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "supportingInfo_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_2_x_SupportingInfo := range x.SupportingInfo { + if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo.Reference != nil { + refVal := *item_2_x_SupportingInfo.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "supportingInfo_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "supportingInfo_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.SupportingInfo != nil { + for _, item_2_x_SupportingInfo := range x.SupportingInfo { + if item_2_x_SupportingInfo != nil { + if item_2_x_SupportingInfo.Reference != nil { + refVal := *item_2_x_SupportingInfo.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "supportingInfo_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "supportingInfo_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supportingInfo_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("procedure", id), + "supportingInfo_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + } + } + } + } + } + } + if x.Complication != nil { + for _, item_3_x_Complication := range x.Complication { + if item_3_x_Complication != nil { + if item_3_x_Complication.Reference != nil { + if item_3_x_Complication.Reference.Reference != nil { + refVal := *item_3_x_Complication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "complication_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "complication_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Complication != nil { + for _, item_3_x_Complication := range x.Complication { + if item_3_x_Complication != nil { + if item_3_x_Complication.Reference != nil { + if item_3_x_Complication.Reference.Reference != nil { + refVal := *item_3_x_Complication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "complication_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "complication_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Complication != nil { + for _, item_3_x_Complication := range x.Complication { + if item_3_x_Complication != nil { + if item_3_x_Complication.Reference != nil { + if item_3_x_Complication.Reference.Reference != nil { + refVal := *item_3_x_Complication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "complication_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "complication_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Complication != nil { + for _, item_3_x_Complication := range x.Complication { + if item_3_x_Complication != nil { + if item_3_x_Complication.Reference != nil { + if item_3_x_Complication.Reference.Reference != nil { + refVal := *item_3_x_Complication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "complication_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "complication_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Complication != nil { + for _, item_3_x_Complication := range x.Complication { + if item_3_x_Complication != nil { + if item_3_x_Complication.Reference != nil { + if item_3_x_Complication.Reference.Reference != nil { + refVal := *item_3_x_Complication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "complication_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "complication_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Complication != nil { + for _, item_3_x_Complication := range x.Complication { + if item_3_x_Complication != nil { + if item_3_x_Complication.Reference != nil { + if item_3_x_Complication.Reference.Reference != nil { + refVal := *item_3_x_Complication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "complication_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "complication_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Complication != nil { + for _, item_3_x_Complication := range x.Complication { + if item_3_x_Complication != nil { + if item_3_x_Complication.Reference != nil { + if item_3_x_Complication.Reference.Reference != nil { + refVal := *item_3_x_Complication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "complication_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "complication_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Complication != nil { + for _, item_3_x_Complication := range x.Complication { + if item_3_x_Complication != nil { + if item_3_x_Complication.Reference != nil { + if item_3_x_Complication.Reference.Reference != nil { + refVal := *item_3_x_Complication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "complication_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "complication_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Complication != nil { + for _, item_3_x_Complication := range x.Complication { + if item_3_x_Complication != nil { + if item_3_x_Complication.Reference != nil { + if item_3_x_Complication.Reference.Reference != nil { + refVal := *item_3_x_Complication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "complication_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "complication_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Complication != nil { + for _, item_3_x_Complication := range x.Complication { + if item_3_x_Complication != nil { + if item_3_x_Complication.Reference != nil { + if item_3_x_Complication.Reference.Reference != nil { + refVal := *item_3_x_Complication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "complication_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "complication_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Complication != nil { + for _, item_3_x_Complication := range x.Complication { + if item_3_x_Complication != nil { + if item_3_x_Complication.Reference != nil { + if item_3_x_Complication.Reference.Reference != nil { + refVal := *item_3_x_Complication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "complication_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "complication_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Complication != nil { + for _, item_3_x_Complication := range x.Complication { + if item_3_x_Complication != nil { + if item_3_x_Complication.Reference != nil { + if item_3_x_Complication.Reference.Reference != nil { + refVal := *item_3_x_Complication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "complication_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "complication_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Complication != nil { + for _, item_3_x_Complication := range x.Complication { + if item_3_x_Complication != nil { + if item_3_x_Complication.Reference != nil { + if item_3_x_Complication.Reference.Reference != nil { + refVal := *item_3_x_Complication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "complication_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "complication_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Complication != nil { + for _, item_3_x_Complication := range x.Complication { + if item_3_x_Complication != nil { + if item_3_x_Complication.Reference != nil { + if item_3_x_Complication.Reference.Reference != nil { + refVal := *item_3_x_Complication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "complication_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "complication_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Complication != nil { + for _, item_3_x_Complication := range x.Complication { + if item_3_x_Complication != nil { + if item_3_x_Complication.Reference != nil { + if item_3_x_Complication.Reference.Reference != nil { + refVal := *item_3_x_Complication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "complication_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "complication_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Complication != nil { + for _, item_3_x_Complication := range x.Complication { + if item_3_x_Complication != nil { + if item_3_x_Complication.Reference != nil { + if item_3_x_Complication.Reference.Reference != nil { + refVal := *item_3_x_Complication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "complication_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "complication_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Complication != nil { + for _, item_3_x_Complication := range x.Complication { + if item_3_x_Complication != nil { + if item_3_x_Complication.Reference != nil { + if item_3_x_Complication.Reference.Reference != nil { + refVal := *item_3_x_Complication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "complication_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "complication_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Complication != nil { + for _, item_3_x_Complication := range x.Complication { + if item_3_x_Complication != nil { + if item_3_x_Complication.Reference != nil { + if item_3_x_Complication.Reference.Reference != nil { + refVal := *item_3_x_Complication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "complication_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "complication_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Complication != nil { + for _, item_3_x_Complication := range x.Complication { + if item_3_x_Complication != nil { + if item_3_x_Complication.Reference != nil { + if item_3_x_Complication.Reference.Reference != nil { + refVal := *item_3_x_Complication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "complication_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "complication_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Complication != nil { + for _, item_3_x_Complication := range x.Complication { + if item_3_x_Complication != nil { + if item_3_x_Complication.Reference != nil { + if item_3_x_Complication.Reference.Reference != nil { + refVal := *item_3_x_Complication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "complication_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "complication_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Complication != nil { + for _, item_3_x_Complication := range x.Complication { + if item_3_x_Complication != nil { + if item_3_x_Complication.Reference != nil { + if item_3_x_Complication.Reference.Reference != nil { + refVal := *item_3_x_Complication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "complication_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "complication_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Complication != nil { + for _, item_3_x_Complication := range x.Complication { + if item_3_x_Complication != nil { + if item_3_x_Complication.Reference != nil { + if item_3_x_Complication.Reference.Reference != nil { + refVal := *item_3_x_Complication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "complication_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "complication_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Complication != nil { + for _, item_3_x_Complication := range x.Complication { + if item_3_x_Complication != nil { + if item_3_x_Complication.Reference != nil { + if item_3_x_Complication.Reference.Reference != nil { + refVal := *item_3_x_Complication.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "complication_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "complication_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "note_authorReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "note_authorReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "note_authorReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "note_authorReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Performer != nil { + for _, item_3_x_Performer := range x.Performer { + if item_3_x_Performer != nil { + if item_3_x_Performer.Actor != nil { + if item_3_x_Performer.Actor.Reference != nil { + refVal := *item_3_x_Performer.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "performer_actor_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "performer_actor_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "actor_procedure_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "actor_procedure_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + } + } + } + if x.Performer != nil { + for _, item_3_x_Performer := range x.Performer { + if item_3_x_Performer != nil { + if item_3_x_Performer.Actor != nil { + if item_3_x_Performer.Actor.Reference != nil { + refVal := *item_3_x_Performer.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "performer_actor_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "performer_actor_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "actor_procedure_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "actor_procedure_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + } + } + } + if x.Performer != nil { + for _, item_3_x_Performer := range x.Performer { + if item_3_x_Performer != nil { + if item_3_x_Performer.Actor != nil { + if item_3_x_Performer.Actor.Reference != nil { + refVal := *item_3_x_Performer.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "performer_actor_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "performer_actor_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "actor_procedure_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "actor_procedure_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + } + } + } + if x.Performer != nil { + for _, item_3_x_Performer := range x.Performer { + if item_3_x_Performer != nil { + if item_3_x_Performer.Actor != nil { + if item_3_x_Performer.Actor.Reference != nil { + refVal := *item_3_x_Performer.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "performer_actor_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "performer_actor_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "actor_procedure_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "actor_procedure_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + } + } + } + if x.Performer != nil { + for _, item_3_x_Performer := range x.Performer { + if item_3_x_Performer != nil { + if item_3_x_Performer.OnBehalfOf != nil { + if item_3_x_Performer.OnBehalfOf.Reference != nil { + refVal := *item_3_x_Performer.OnBehalfOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "performer_onBehalfOf") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("onBehalfOf", targetID), + "performer_onBehalfOf", + projectJSON, + sourceType, + "onBehalfOf", + )) + } + backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_procedure_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "onBehalfOf_procedure_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "reason_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "reason_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "reason_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "reason_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "reason_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "reason_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "reason_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "reason_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "reason_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "reason_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "reason_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "reason_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "reason_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "reason_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "reason_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "reason_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "reason_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "reason_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "reason_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "reason_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "reason_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "reason_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "reason_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Used != nil { + for _, item_3_x_Used := range x.Used { + if item_3_x_Used != nil { + if item_3_x_Used.Reference != nil { + if item_3_x_Used.Reference.Reference != nil { + refVal := *item_3_x_Used.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "used_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "used_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Used != nil { + for _, item_3_x_Used := range x.Used { + if item_3_x_Used != nil { + if item_3_x_Used.Reference != nil { + if item_3_x_Used.Reference.Reference != nil { + refVal := *item_3_x_Used.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "used_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "used_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Used != nil { + for _, item_3_x_Used := range x.Used { + if item_3_x_Used != nil { + if item_3_x_Used.Reference != nil { + if item_3_x_Used.Reference.Reference != nil { + refVal := *item_3_x_Used.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "used_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "used_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Used != nil { + for _, item_3_x_Used := range x.Used { + if item_3_x_Used != nil { + if item_3_x_Used.Reference != nil { + if item_3_x_Used.Reference.Reference != nil { + refVal := *item_3_x_Used.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "used_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "used_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Used != nil { + for _, item_3_x_Used := range x.Used { + if item_3_x_Used != nil { + if item_3_x_Used.Reference != nil { + if item_3_x_Used.Reference.Reference != nil { + refVal := *item_3_x_Used.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "used_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "used_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Used != nil { + for _, item_3_x_Used := range x.Used { + if item_3_x_Used != nil { + if item_3_x_Used.Reference != nil { + if item_3_x_Used.Reference.Reference != nil { + refVal := *item_3_x_Used.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "used_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "used_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Used != nil { + for _, item_3_x_Used := range x.Used { + if item_3_x_Used != nil { + if item_3_x_Used.Reference != nil { + if item_3_x_Used.Reference.Reference != nil { + refVal := *item_3_x_Used.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "used_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "used_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Used != nil { + for _, item_3_x_Used := range x.Used { + if item_3_x_Used != nil { + if item_3_x_Used.Reference != nil { + if item_3_x_Used.Reference.Reference != nil { + refVal := *item_3_x_Used.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "used_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "used_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Used != nil { + for _, item_3_x_Used := range x.Used { + if item_3_x_Used != nil { + if item_3_x_Used.Reference != nil { + if item_3_x_Used.Reference.Reference != nil { + refVal := *item_3_x_Used.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "used_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "used_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Used != nil { + for _, item_3_x_Used := range x.Used { + if item_3_x_Used != nil { + if item_3_x_Used.Reference != nil { + if item_3_x_Used.Reference.Reference != nil { + refVal := *item_3_x_Used.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "used_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "used_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Used != nil { + for _, item_3_x_Used := range x.Used { + if item_3_x_Used != nil { + if item_3_x_Used.Reference != nil { + if item_3_x_Used.Reference.Reference != nil { + refVal := *item_3_x_Used.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "used_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "used_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Used != nil { + for _, item_3_x_Used := range x.Used { + if item_3_x_Used != nil { + if item_3_x_Used.Reference != nil { + if item_3_x_Used.Reference.Reference != nil { + refVal := *item_3_x_Used.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "used_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "used_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Used != nil { + for _, item_3_x_Used := range x.Used { + if item_3_x_Used != nil { + if item_3_x_Used.Reference != nil { + if item_3_x_Used.Reference.Reference != nil { + refVal := *item_3_x_Used.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "used_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "used_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Used != nil { + for _, item_3_x_Used := range x.Used { + if item_3_x_Used != nil { + if item_3_x_Used.Reference != nil { + if item_3_x_Used.Reference.Reference != nil { + refVal := *item_3_x_Used.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "used_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "used_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Used != nil { + for _, item_3_x_Used := range x.Used { + if item_3_x_Used != nil { + if item_3_x_Used.Reference != nil { + if item_3_x_Used.Reference.Reference != nil { + refVal := *item_3_x_Used.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "used_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "used_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Used != nil { + for _, item_3_x_Used := range x.Used { + if item_3_x_Used != nil { + if item_3_x_Used.Reference != nil { + if item_3_x_Used.Reference.Reference != nil { + refVal := *item_3_x_Used.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "used_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "used_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Used != nil { + for _, item_3_x_Used := range x.Used { + if item_3_x_Used != nil { + if item_3_x_Used.Reference != nil { + if item_3_x_Used.Reference.Reference != nil { + refVal := *item_3_x_Used.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "used_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "used_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Used != nil { + for _, item_3_x_Used := range x.Used { + if item_3_x_Used != nil { + if item_3_x_Used.Reference != nil { + if item_3_x_Used.Reference.Reference != nil { + refVal := *item_3_x_Used.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "used_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "used_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Used != nil { + for _, item_3_x_Used := range x.Used { + if item_3_x_Used != nil { + if item_3_x_Used.Reference != nil { + if item_3_x_Used.Reference.Reference != nil { + refVal := *item_3_x_Used.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "used_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "used_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Used != nil { + for _, item_3_x_Used := range x.Used { + if item_3_x_Used != nil { + if item_3_x_Used.Reference != nil { + if item_3_x_Used.Reference.Reference != nil { + refVal := *item_3_x_Used.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "used_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "used_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Used != nil { + for _, item_3_x_Used := range x.Used { + if item_3_x_Used != nil { + if item_3_x_Used.Reference != nil { + if item_3_x_Used.Reference.Reference != nil { + refVal := *item_3_x_Used.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "used_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "used_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Used != nil { + for _, item_3_x_Used := range x.Used { + if item_3_x_Used != nil { + if item_3_x_Used.Reference != nil { + if item_3_x_Used.Reference.Reference != nil { + refVal := *item_3_x_Used.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "used_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "used_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Used != nil { + for _, item_3_x_Used := range x.Used { + if item_3_x_Used != nil { + if item_3_x_Used.Reference != nil { + if item_3_x_Used.Reference.Reference != nil { + refVal := *item_3_x_Used.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "used_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "used_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from ProcedureFocalDevice. +func (x *ProcedureFocalDevice) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ProcedureFocalDevice" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from ProcedurePerformer. +func (x *ProcedurePerformer) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ProcedurePerformer" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Actor != nil { + if x.Actor.Reference != nil { + refVal := *x.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "actor_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "actor_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "actor_procedure_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "actor_procedure_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + refVal := *x.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "actor_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "actor_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "actor_procedure_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "actor_procedure_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + refVal := *x.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "actor_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "actor_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "actor_procedure_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "actor_procedure_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + refVal := *x.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "actor_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "actor_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "actor_procedure_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "actor_procedure_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + if x.OnBehalfOf != nil { + if x.OnBehalfOf.Reference != nil { + refVal := *x.OnBehalfOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "onBehalfOf") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("onBehalfOf", targetID), + "onBehalfOf", + projectJSON, + sourceType, + "onBehalfOf", + )) + } + backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_procedure_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "onBehalfOf_procedure_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from Quantity. +func (x *Quantity) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Quantity" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from Range. +func (x *Range) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Range" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from Ratio. +func (x *Ratio) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Ratio" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from RatioRange. +func (x *RatioRange) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "RatioRange" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from Reference. +func (x *Reference) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Reference" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from RelatedArtifact. +func (x *RelatedArtifact) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "RelatedArtifact" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.ResourceReference != nil { + if x.ResourceReference.Reference != nil { + refVal := *x.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "resourceReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "resourceReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + if x.ResourceReference != nil { + if x.ResourceReference.Reference != nil { + refVal := *x.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "resourceReference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "resourceReference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + if x.ResourceReference != nil { + if x.ResourceReference.Reference != nil { + refVal := *x.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "resourceReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "resourceReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + if x.ResourceReference != nil { + if x.ResourceReference.Reference != nil { + refVal := *x.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "resourceReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "resourceReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + if x.ResourceReference != nil { + if x.ResourceReference.Reference != nil { + refVal := *x.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "resourceReference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "resourceReference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + if x.ResourceReference != nil { + if x.ResourceReference.Reference != nil { + refVal := *x.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "resourceReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "resourceReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + if x.ResourceReference != nil { + if x.ResourceReference.Reference != nil { + refVal := *x.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "resourceReference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "resourceReference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + if x.ResourceReference != nil { + if x.ResourceReference.Reference != nil { + refVal := *x.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "resourceReference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "resourceReference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + if x.ResourceReference != nil { + if x.ResourceReference.Reference != nil { + refVal := *x.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "resourceReference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "resourceReference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + if x.ResourceReference != nil { + if x.ResourceReference.Reference != nil { + refVal := *x.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "resourceReference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "resourceReference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + if x.ResourceReference != nil { + if x.ResourceReference.Reference != nil { + refVal := *x.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "resourceReference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "resourceReference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + if x.ResourceReference != nil { + if x.ResourceReference.Reference != nil { + refVal := *x.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "resourceReference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "resourceReference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + if x.ResourceReference != nil { + if x.ResourceReference.Reference != nil { + refVal := *x.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "resourceReference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "resourceReference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + if x.ResourceReference != nil { + if x.ResourceReference.Reference != nil { + refVal := *x.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "resourceReference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "resourceReference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + if x.ResourceReference != nil { + if x.ResourceReference.Reference != nil { + refVal := *x.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "resourceReference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "resourceReference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + if x.ResourceReference != nil { + if x.ResourceReference.Reference != nil { + refVal := *x.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "resourceReference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "resourceReference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + if x.ResourceReference != nil { + if x.ResourceReference.Reference != nil { + refVal := *x.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "resourceReference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "resourceReference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + if x.ResourceReference != nil { + if x.ResourceReference.Reference != nil { + refVal := *x.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "resourceReference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "resourceReference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + if x.ResourceReference != nil { + if x.ResourceReference.Reference != nil { + refVal := *x.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "resourceReference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "resourceReference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + if x.ResourceReference != nil { + if x.ResourceReference.Reference != nil { + refVal := *x.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "resourceReference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "resourceReference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + if x.ResourceReference != nil { + if x.ResourceReference.Reference != nil { + refVal := *x.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "resourceReference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "resourceReference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + if x.ResourceReference != nil { + if x.ResourceReference.Reference != nil { + refVal := *x.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "resourceReference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "resourceReference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + if x.ResourceReference != nil { + if x.ResourceReference.Reference != nil { + refVal := *x.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "resourceReference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "resourceReference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from ResearchStudy. +func (x *ResearchStudy) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ResearchStudy" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.RootDir != nil { + if x.RootDir.Reference != nil { + refVal := *x.RootDir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Directory" { + forwardKey := getEdgeUUID(targetID, id, "rootDir_Directory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Directory", targetID), + "rootDir_Directory", + projectJSON, + sourceType, + "Directory", + )) + } + } + } + } + } + if x.PartOf != nil { + for _, item_2_x_PartOf := range x.PartOf { + if item_2_x_PartOf != nil { + if item_2_x_PartOf.Reference != nil { + refVal := *item_2_x_PartOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "partOf") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("partOf", targetID), + "partOf", + projectJSON, + sourceType, + "partOf", + )) + } + backrefKey := getEdgeUUID(id, targetID, "partOf_research_study") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("study", id), + "partOf_research_study", + projectJSON, + sourceType, + "study", + )) + } + } + } + } + } + } + } + if x.Result != nil { + for _, item_2_x_Result := range x.Result { + if item_2_x_Result != nil { + if item_2_x_Result.Reference != nil { + refVal := *item_2_x_Result.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "result_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "result_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "result_research_study") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("study", id), + "result_research_study", + projectJSON, + sourceType, + "study", + )) + } + } + } + } + } + } + } + if x.Site != nil { + for _, item_2_x_Site := range x.Site { + if item_2_x_Site != nil { + if item_2_x_Site.Reference != nil { + refVal := *item_2_x_Site.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "site_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "site_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "site_research_study") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("study", id), + "site_research_study", + projectJSON, + sourceType, + "study", + )) + } + } + } + } + } + } + } + if x.Site != nil { + for _, item_2_x_Site := range x.Site { + if item_2_x_Site != nil { + if item_2_x_Site.Reference != nil { + refVal := *item_2_x_Site.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "site_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "site_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "site_research_study") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("study", id), + "site_research_study", + projectJSON, + sourceType, + "study", + )) + } + } + } + } + } + } + } + if x.AssociatedParty != nil { + for _, item_3_x_AssociatedParty := range x.AssociatedParty { + if item_3_x_AssociatedParty != nil { + if item_3_x_AssociatedParty.Party != nil { + if item_3_x_AssociatedParty.Party.Reference != nil { + refVal := *item_3_x_AssociatedParty.Party.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "associatedParty_party_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "associatedParty_party_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "research_study_associated_party") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("party", id), + "research_study_associated_party", + projectJSON, + sourceType, + "party", + )) + } + } + } + } + } + } + } + } + if x.AssociatedParty != nil { + for _, item_3_x_AssociatedParty := range x.AssociatedParty { + if item_3_x_AssociatedParty != nil { + if item_3_x_AssociatedParty.Party != nil { + if item_3_x_AssociatedParty.Party.Reference != nil { + refVal := *item_3_x_AssociatedParty.Party.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "associatedParty_party_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "associatedParty_party_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "research_study_associated_party") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("party", id), + "research_study_associated_party", + projectJSON, + sourceType, + "party", + )) + } + } + } + } + } + } + } + } + if x.AssociatedParty != nil { + for _, item_3_x_AssociatedParty := range x.AssociatedParty { + if item_3_x_AssociatedParty != nil { + if item_3_x_AssociatedParty.Party != nil { + if item_3_x_AssociatedParty.Party.Reference != nil { + refVal := *item_3_x_AssociatedParty.Party.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "associatedParty_party_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "associatedParty_party_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "research_study_associated_party") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("party", id), + "research_study_associated_party", + projectJSON, + sourceType, + "party", + )) + } + } + } + } + } + } + } + } + if x.ComparisonGroup != nil { + for _, item_3_x_ComparisonGroup := range x.ComparisonGroup { + if item_3_x_ComparisonGroup != nil { + if item_3_x_ComparisonGroup.ObservedGroup != nil { + if item_3_x_ComparisonGroup.ObservedGroup.Reference != nil { + refVal := *item_3_x_ComparisonGroup.ObservedGroup.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "comparisonGroup_observedGroup") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("observedGroup", targetID), + "comparisonGroup_observedGroup", + projectJSON, + sourceType, + "observedGroup", + )) + } + backrefKey := getEdgeUUID(id, targetID, "research_study_comparison_group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("group", id), + "research_study_comparison_group", + projectJSON, + sourceType, + "group", + )) + } + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_3_x_Focus := range x.Focus { + if item_3_x_Focus != nil { + if item_3_x_Focus.Reference != nil { + if item_3_x_Focus.Reference.Reference != nil { + refVal := *item_3_x_Focus.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "focus_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "focus_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_3_x_Focus := range x.Focus { + if item_3_x_Focus != nil { + if item_3_x_Focus.Reference != nil { + if item_3_x_Focus.Reference.Reference != nil { + refVal := *item_3_x_Focus.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "focus_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "focus_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_3_x_Focus := range x.Focus { + if item_3_x_Focus != nil { + if item_3_x_Focus.Reference != nil { + if item_3_x_Focus.Reference.Reference != nil { + refVal := *item_3_x_Focus.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "focus_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "focus_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_3_x_Focus := range x.Focus { + if item_3_x_Focus != nil { + if item_3_x_Focus.Reference != nil { + if item_3_x_Focus.Reference.Reference != nil { + refVal := *item_3_x_Focus.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "focus_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "focus_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_3_x_Focus := range x.Focus { + if item_3_x_Focus != nil { + if item_3_x_Focus.Reference != nil { + if item_3_x_Focus.Reference.Reference != nil { + refVal := *item_3_x_Focus.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "focus_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "focus_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_3_x_Focus := range x.Focus { + if item_3_x_Focus != nil { + if item_3_x_Focus.Reference != nil { + if item_3_x_Focus.Reference.Reference != nil { + refVal := *item_3_x_Focus.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "focus_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "focus_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_3_x_Focus := range x.Focus { + if item_3_x_Focus != nil { + if item_3_x_Focus.Reference != nil { + if item_3_x_Focus.Reference.Reference != nil { + refVal := *item_3_x_Focus.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "focus_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "focus_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_3_x_Focus := range x.Focus { + if item_3_x_Focus != nil { + if item_3_x_Focus.Reference != nil { + if item_3_x_Focus.Reference.Reference != nil { + refVal := *item_3_x_Focus.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "focus_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "focus_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_3_x_Focus := range x.Focus { + if item_3_x_Focus != nil { + if item_3_x_Focus.Reference != nil { + if item_3_x_Focus.Reference.Reference != nil { + refVal := *item_3_x_Focus.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "focus_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "focus_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_3_x_Focus := range x.Focus { + if item_3_x_Focus != nil { + if item_3_x_Focus.Reference != nil { + if item_3_x_Focus.Reference.Reference != nil { + refVal := *item_3_x_Focus.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "focus_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "focus_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_3_x_Focus := range x.Focus { + if item_3_x_Focus != nil { + if item_3_x_Focus.Reference != nil { + if item_3_x_Focus.Reference.Reference != nil { + refVal := *item_3_x_Focus.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "focus_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "focus_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_3_x_Focus := range x.Focus { + if item_3_x_Focus != nil { + if item_3_x_Focus.Reference != nil { + if item_3_x_Focus.Reference.Reference != nil { + refVal := *item_3_x_Focus.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "focus_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "focus_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_3_x_Focus := range x.Focus { + if item_3_x_Focus != nil { + if item_3_x_Focus.Reference != nil { + if item_3_x_Focus.Reference.Reference != nil { + refVal := *item_3_x_Focus.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "focus_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "focus_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_3_x_Focus := range x.Focus { + if item_3_x_Focus != nil { + if item_3_x_Focus.Reference != nil { + if item_3_x_Focus.Reference.Reference != nil { + refVal := *item_3_x_Focus.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "focus_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "focus_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_3_x_Focus := range x.Focus { + if item_3_x_Focus != nil { + if item_3_x_Focus.Reference != nil { + if item_3_x_Focus.Reference.Reference != nil { + refVal := *item_3_x_Focus.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "focus_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "focus_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_3_x_Focus := range x.Focus { + if item_3_x_Focus != nil { + if item_3_x_Focus.Reference != nil { + if item_3_x_Focus.Reference.Reference != nil { + refVal := *item_3_x_Focus.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "focus_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "focus_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_3_x_Focus := range x.Focus { + if item_3_x_Focus != nil { + if item_3_x_Focus.Reference != nil { + if item_3_x_Focus.Reference.Reference != nil { + refVal := *item_3_x_Focus.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "focus_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "focus_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_3_x_Focus := range x.Focus { + if item_3_x_Focus != nil { + if item_3_x_Focus.Reference != nil { + if item_3_x_Focus.Reference.Reference != nil { + refVal := *item_3_x_Focus.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "focus_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "focus_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_3_x_Focus := range x.Focus { + if item_3_x_Focus != nil { + if item_3_x_Focus.Reference != nil { + if item_3_x_Focus.Reference.Reference != nil { + refVal := *item_3_x_Focus.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "focus_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "focus_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_3_x_Focus := range x.Focus { + if item_3_x_Focus != nil { + if item_3_x_Focus.Reference != nil { + if item_3_x_Focus.Reference.Reference != nil { + refVal := *item_3_x_Focus.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "focus_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "focus_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_3_x_Focus := range x.Focus { + if item_3_x_Focus != nil { + if item_3_x_Focus.Reference != nil { + if item_3_x_Focus.Reference.Reference != nil { + refVal := *item_3_x_Focus.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "focus_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "focus_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_3_x_Focus := range x.Focus { + if item_3_x_Focus != nil { + if item_3_x_Focus.Reference != nil { + if item_3_x_Focus.Reference.Reference != nil { + refVal := *item_3_x_Focus.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "focus_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "focus_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Focus != nil { + for _, item_3_x_Focus := range x.Focus { + if item_3_x_Focus != nil { + if item_3_x_Focus.Reference != nil { + if item_3_x_Focus.Reference.Reference != nil { + refVal := *item_3_x_Focus.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "focus_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "focus_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "note_authorReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "note_authorReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "note_authorReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "note_authorReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Recruitment != nil { + if x.Recruitment.ActualGroup != nil { + if x.Recruitment.ActualGroup.Reference != nil { + refVal := *x.Recruitment.ActualGroup.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "recruitment_actualGroup") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("actualGroup", targetID), + "recruitment_actualGroup", + projectJSON, + sourceType, + "actualGroup", + )) + } + backrefKey := getEdgeUUID(id, targetID, "actualGroup_research_study_recruitment") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("recruitment", id), + "actualGroup_research_study_recruitment", + projectJSON, + sourceType, + "recruitment", + )) + } + } + } + } + } + } + if x.Recruitment != nil { + if x.Recruitment.Eligibility != nil { + if x.Recruitment.Eligibility.Reference != nil { + refVal := *x.Recruitment.Eligibility.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "recruitment_eligibility_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "recruitment_eligibility_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "eligibility_research_study_recruitment") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("recruitment", id), + "eligibility_research_study_recruitment", + projectJSON, + sourceType, + "recruitment", + )) + } + } + } + } + } + } + if x.RelatedArtifact != nil { + for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { + if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact.ResourceReference != nil { + if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { + refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "relatedArtifact_resourceReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + } + } + if x.RelatedArtifact != nil { + for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { + if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact.ResourceReference != nil { + if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { + refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "relatedArtifact_resourceReference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + } + } + if x.RelatedArtifact != nil { + for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { + if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact.ResourceReference != nil { + if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { + refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "relatedArtifact_resourceReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + } + } + if x.RelatedArtifact != nil { + for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { + if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact.ResourceReference != nil { + if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { + refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "relatedArtifact_resourceReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + } + } + if x.RelatedArtifact != nil { + for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { + if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact.ResourceReference != nil { + if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { + refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "relatedArtifact_resourceReference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + } + } + if x.RelatedArtifact != nil { + for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { + if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact.ResourceReference != nil { + if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { + refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "relatedArtifact_resourceReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + } + } + if x.RelatedArtifact != nil { + for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { + if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact.ResourceReference != nil { + if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { + refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "relatedArtifact_resourceReference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + } + } + if x.RelatedArtifact != nil { + for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { + if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact.ResourceReference != nil { + if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { + refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "relatedArtifact_resourceReference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + } + } + if x.RelatedArtifact != nil { + for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { + if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact.ResourceReference != nil { + if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { + refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "relatedArtifact_resourceReference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + } + } + if x.RelatedArtifact != nil { + for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { + if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact.ResourceReference != nil { + if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { + refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "relatedArtifact_resourceReference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + } + } + if x.RelatedArtifact != nil { + for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { + if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact.ResourceReference != nil { + if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { + refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "relatedArtifact_resourceReference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + } + } + if x.RelatedArtifact != nil { + for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { + if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact.ResourceReference != nil { + if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { + refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "relatedArtifact_resourceReference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + } + } + if x.RelatedArtifact != nil { + for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { + if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact.ResourceReference != nil { + if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { + refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "relatedArtifact_resourceReference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + } + } + if x.RelatedArtifact != nil { + for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { + if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact.ResourceReference != nil { + if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { + refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "relatedArtifact_resourceReference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + } + } + if x.RelatedArtifact != nil { + for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { + if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact.ResourceReference != nil { + if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { + refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "relatedArtifact_resourceReference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + } + } + if x.RelatedArtifact != nil { + for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { + if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact.ResourceReference != nil { + if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { + refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "relatedArtifact_resourceReference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + } + } + if x.RelatedArtifact != nil { + for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { + if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact.ResourceReference != nil { + if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { + refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "relatedArtifact_resourceReference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + } + } + if x.RelatedArtifact != nil { + for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { + if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact.ResourceReference != nil { + if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { + refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "relatedArtifact_resourceReference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + } + } + if x.RelatedArtifact != nil { + for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { + if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact.ResourceReference != nil { + if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { + refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "relatedArtifact_resourceReference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + } + } + if x.RelatedArtifact != nil { + for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { + if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact.ResourceReference != nil { + if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { + refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "relatedArtifact_resourceReference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + } + } + if x.RelatedArtifact != nil { + for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { + if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact.ResourceReference != nil { + if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { + refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "relatedArtifact_resourceReference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + } + } + if x.RelatedArtifact != nil { + for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { + if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact.ResourceReference != nil { + if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { + refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "relatedArtifact_resourceReference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + } + } + if x.RelatedArtifact != nil { + for _, item_3_x_RelatedArtifact := range x.RelatedArtifact { + if item_3_x_RelatedArtifact != nil { + if item_3_x_RelatedArtifact.ResourceReference != nil { + if item_3_x_RelatedArtifact.ResourceReference.Reference != nil { + refVal := *item_3_x_RelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "relatedArtifact_resourceReference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "relatedArtifact_resourceReference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from ResearchStudyAssociatedParty. +func (x *ResearchStudyAssociatedParty) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ResearchStudyAssociatedParty" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Party != nil { + if x.Party.Reference != nil { + refVal := *x.Party.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "party_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "party_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "research_study_associated_party") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("party", id), + "research_study_associated_party", + projectJSON, + sourceType, + "party", + )) + } + } + } + } + } + if x.Party != nil { + if x.Party.Reference != nil { + refVal := *x.Party.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "party_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "party_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "research_study_associated_party") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("party", id), + "research_study_associated_party", + projectJSON, + sourceType, + "party", + )) + } + } + } + } + } + if x.Party != nil { + if x.Party.Reference != nil { + refVal := *x.Party.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "party_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "party_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "research_study_associated_party") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("party", id), + "research_study_associated_party", + projectJSON, + sourceType, + "party", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from ResearchStudyComparisonGroup. +func (x *ResearchStudyComparisonGroup) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ResearchStudyComparisonGroup" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.ObservedGroup != nil { + if x.ObservedGroup.Reference != nil { + refVal := *x.ObservedGroup.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "observedGroup") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("observedGroup", targetID), + "observedGroup", + projectJSON, + sourceType, + "observedGroup", + )) + } + backrefKey := getEdgeUUID(id, targetID, "research_study_comparison_group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("group", id), + "research_study_comparison_group", + projectJSON, + sourceType, + "group", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from ResearchStudyLabel. +func (x *ResearchStudyLabel) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ResearchStudyLabel" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from ResearchStudyObjective. +func (x *ResearchStudyObjective) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ResearchStudyObjective" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from ResearchStudyOutcomeMeasure. +func (x *ResearchStudyOutcomeMeasure) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ResearchStudyOutcomeMeasure" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from ResearchStudyProgressStatus. +func (x *ResearchStudyProgressStatus) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ResearchStudyProgressStatus" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from ResearchStudyRecruitment. +func (x *ResearchStudyRecruitment) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ResearchStudyRecruitment" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.ActualGroup != nil { + if x.ActualGroup.Reference != nil { + refVal := *x.ActualGroup.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "actualGroup") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("actualGroup", targetID), + "actualGroup", + projectJSON, + sourceType, + "actualGroup", + )) + } + backrefKey := getEdgeUUID(id, targetID, "actualGroup_research_study_recruitment") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("recruitment", id), + "actualGroup_research_study_recruitment", + projectJSON, + sourceType, + "recruitment", + )) + } + } + } + } + } + if x.Eligibility != nil { + if x.Eligibility.Reference != nil { + refVal := *x.Eligibility.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "eligibility_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "eligibility_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "eligibility_research_study_recruitment") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("recruitment", id), + "eligibility_research_study_recruitment", + projectJSON, + sourceType, + "recruitment", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from ResearchSubject. +func (x *ResearchSubject) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ResearchSubject" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Study != nil { + if x.Study.Reference != nil { + refVal := *x.Study.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "study") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "study", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "research_subject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("subject", id), + "research_subject", + projectJSON, + sourceType, + "subject", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "subject_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "subject_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "research_subject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("subject", id), + "research_subject", + projectJSON, + sourceType, + "subject", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "subject_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "subject_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "research_subject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("subject", id), + "research_subject", + projectJSON, + sourceType, + "subject", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "subject_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "subject_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "research_subject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("subject", id), + "research_subject", + projectJSON, + sourceType, + "subject", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "subject_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "subject_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "research_subject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("subject", id), + "research_subject", + projectJSON, + sourceType, + "subject", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "subject_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "subject_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "research_subject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("subject", id), + "research_subject", + projectJSON, + sourceType, + "subject", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from ResearchSubjectProgress. +func (x *ResearchSubjectProgress) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "ResearchSubjectProgress" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from Resource. +func (x *Resource) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Resource" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from SampledData. +func (x *SampledData) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "SampledData" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from Signature. +func (x *Signature) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Signature" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.OnBehalfOf != nil { + if x.OnBehalfOf.Reference != nil { + refVal := *x.OnBehalfOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "onBehalfOf_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "onBehalfOf_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "onBehalfOf_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + if x.OnBehalfOf != nil { + if x.OnBehalfOf.Reference != nil { + refVal := *x.OnBehalfOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "onBehalfOf_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "onBehalfOf_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "onBehalfOf_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + if x.OnBehalfOf != nil { + if x.OnBehalfOf.Reference != nil { + refVal := *x.OnBehalfOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "onBehalfOf_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "onBehalfOf_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "onBehalfOf_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + if x.OnBehalfOf != nil { + if x.OnBehalfOf.Reference != nil { + refVal := *x.OnBehalfOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "onBehalfOf_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "onBehalfOf_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "onBehalfOf_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + if x.Who != nil { + if x.Who.Reference != nil { + refVal := *x.Who.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "who_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "who_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "who_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "who_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + if x.Who != nil { + if x.Who.Reference != nil { + refVal := *x.Who.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "who_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "who_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "who_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "who_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + if x.Who != nil { + if x.Who.Reference != nil { + refVal := *x.Who.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "who_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "who_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "who_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "who_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + if x.Who != nil { + if x.Who.Reference != nil { + refVal := *x.Who.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "who_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "who_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "who_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "who_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from Specimen. +func (x *Specimen) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Specimen" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Parent != nil { + for _, item_2_x_Parent := range x.Parent { + if item_2_x_Parent != nil { + if item_2_x_Parent.Reference != nil { + refVal := *item_2_x_Parent.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "parent") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("parent", targetID), + "parent", + projectJSON, + sourceType, + "parent", + )) + } + backrefKey := getEdgeUUID(id, targetID, "parent_specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("specimen", id), + "parent_specimen", + projectJSON, + sourceType, + "specimen", + )) + } + } + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "subject_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "subject_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("specimen", id), + "specimen", + projectJSON, + sourceType, + "specimen", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "subject_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "subject_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("specimen", id), + "specimen", + projectJSON, + sourceType, + "specimen", + )) + } + } + } + } + } + if x.Subject != nil { + if x.Subject.Reference != nil { + refVal := *x.Subject.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "subject_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "subject_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("specimen", id), + "specimen", + projectJSON, + sourceType, + "specimen", + )) + } + } + } + } + } + if x.Collection != nil { + if x.Collection.Collector != nil { + if x.Collection.Collector.Reference != nil { + refVal := *x.Collection.Collector.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "collection_collector_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "collection_collector_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "specimen_collection") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("collection", id), + "specimen_collection", + projectJSON, + sourceType, + "collection", + )) + } + } + } + } + } + } + if x.Collection != nil { + if x.Collection.Collector != nil { + if x.Collection.Collector.Reference != nil { + refVal := *x.Collection.Collector.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "collection_collector_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "collection_collector_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "specimen_collection") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("collection", id), + "specimen_collection", + projectJSON, + sourceType, + "collection", + )) + } + } + } + } + } + } + if x.Collection != nil { + if x.Collection.Collector != nil { + if x.Collection.Collector.Reference != nil { + refVal := *x.Collection.Collector.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "collection_collector_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "collection_collector_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "specimen_collection") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("collection", id), + "specimen_collection", + projectJSON, + sourceType, + "collection", + )) + } + } + } + } + } + } + if x.Collection != nil { + if x.Collection.Procedure != nil { + if x.Collection.Procedure.Reference != nil { + refVal := *x.Collection.Procedure.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "collection_procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("procedure", targetID), + "collection_procedure", + projectJSON, + sourceType, + "procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "specimen_collection") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("collection", id), + "specimen_collection", + projectJSON, + sourceType, + "collection", + )) + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "note_authorReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "note_authorReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "note_authorReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "note_authorReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Processing != nil { + for _, item_4_x_Processing := range x.Processing { + if item_4_x_Processing != nil { + if item_4_x_Processing.Additive != nil { + for _, item_2_item_4_x_Processing_Additive := range item_4_x_Processing.Additive { + if item_2_item_4_x_Processing_Additive != nil { + if item_2_item_4_x_Processing_Additive.Reference != nil { + refVal := *item_2_item_4_x_Processing_Additive.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "processing_additive") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("additive", targetID), + "processing_additive", + projectJSON, + sourceType, + "additive", + )) + } + backrefKey := getEdgeUUID(id, targetID, "additive_specimen_processing") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("processing", id), + "additive_specimen_processing", + projectJSON, + sourceType, + "processing", + )) + } + } + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from SpecimenCollection. +func (x *SpecimenCollection) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "SpecimenCollection" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Collector != nil { + if x.Collector.Reference != nil { + refVal := *x.Collector.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "collector_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "collector_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "specimen_collection") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("collection", id), + "specimen_collection", + projectJSON, + sourceType, + "collection", + )) + } + } + } + } + } + if x.Collector != nil { + if x.Collector.Reference != nil { + refVal := *x.Collector.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "collector_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "collector_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "specimen_collection") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("collection", id), + "specimen_collection", + projectJSON, + sourceType, + "collection", + )) + } + } + } + } + } + if x.Collector != nil { + if x.Collector.Reference != nil { + refVal := *x.Collector.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "collector_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "collector_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "specimen_collection") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("collection", id), + "specimen_collection", + projectJSON, + sourceType, + "collection", + )) + } + } + } + } + } + if x.Procedure != nil { + if x.Procedure.Reference != nil { + refVal := *x.Procedure.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("procedure", targetID), + "procedure", + projectJSON, + sourceType, + "procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "specimen_collection") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("collection", id), + "specimen_collection", + projectJSON, + sourceType, + "collection", + )) + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "bodySite_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "bodySite_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "bodySite_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "bodySite_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "bodySite_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "bodySite_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "bodySite_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "bodySite_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "bodySite_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "bodySite_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "bodySite_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "bodySite_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "bodySite_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "bodySite_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "bodySite_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "bodySite_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "bodySite_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "bodySite_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "bodySite_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "bodySite_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "bodySite_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "bodySite_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.BodySite != nil { + if x.BodySite.Reference != nil { + if x.BodySite.Reference.Reference != nil { + refVal := *x.BodySite.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "bodySite_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "bodySite_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Device != nil { + if x.Device.Reference != nil { + if x.Device.Reference.Reference != nil { + refVal := *x.Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "device_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Device != nil { + if x.Device.Reference != nil { + if x.Device.Reference.Reference != nil { + refVal := *x.Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "device_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Device != nil { + if x.Device.Reference != nil { + if x.Device.Reference.Reference != nil { + refVal := *x.Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "device_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Device != nil { + if x.Device.Reference != nil { + if x.Device.Reference.Reference != nil { + refVal := *x.Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "device_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Device != nil { + if x.Device.Reference != nil { + if x.Device.Reference.Reference != nil { + refVal := *x.Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "device_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Device != nil { + if x.Device.Reference != nil { + if x.Device.Reference.Reference != nil { + refVal := *x.Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "device_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Device != nil { + if x.Device.Reference != nil { + if x.Device.Reference.Reference != nil { + refVal := *x.Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "device_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Device != nil { + if x.Device.Reference != nil { + if x.Device.Reference.Reference != nil { + refVal := *x.Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "device_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Device != nil { + if x.Device.Reference != nil { + if x.Device.Reference.Reference != nil { + refVal := *x.Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "device_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Device != nil { + if x.Device.Reference != nil { + if x.Device.Reference.Reference != nil { + refVal := *x.Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "device_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Device != nil { + if x.Device.Reference != nil { + if x.Device.Reference.Reference != nil { + refVal := *x.Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "device_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Device != nil { + if x.Device.Reference != nil { + if x.Device.Reference.Reference != nil { + refVal := *x.Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "device_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Device != nil { + if x.Device.Reference != nil { + if x.Device.Reference.Reference != nil { + refVal := *x.Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "device_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Device != nil { + if x.Device.Reference != nil { + if x.Device.Reference.Reference != nil { + refVal := *x.Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "device_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Device != nil { + if x.Device.Reference != nil { + if x.Device.Reference.Reference != nil { + refVal := *x.Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "device_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Device != nil { + if x.Device.Reference != nil { + if x.Device.Reference.Reference != nil { + refVal := *x.Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "device_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Device != nil { + if x.Device.Reference != nil { + if x.Device.Reference.Reference != nil { + refVal := *x.Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "device_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Device != nil { + if x.Device.Reference != nil { + if x.Device.Reference.Reference != nil { + refVal := *x.Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "device_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Device != nil { + if x.Device.Reference != nil { + if x.Device.Reference.Reference != nil { + refVal := *x.Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "device_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Device != nil { + if x.Device.Reference != nil { + if x.Device.Reference.Reference != nil { + refVal := *x.Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "device_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Device != nil { + if x.Device.Reference != nil { + if x.Device.Reference.Reference != nil { + refVal := *x.Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "device_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Device != nil { + if x.Device.Reference != nil { + if x.Device.Reference.Reference != nil { + refVal := *x.Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "device_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Device != nil { + if x.Device.Reference != nil { + if x.Device.Reference.Reference != nil { + refVal := *x.Device.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "device_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "device_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from SpecimenContainer. +func (x *SpecimenContainer) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "SpecimenContainer" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from SpecimenFeature. +func (x *SpecimenFeature) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "SpecimenFeature" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from SpecimenProcessing. +func (x *SpecimenProcessing) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "SpecimenProcessing" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Additive != nil { + for _, item_2_x_Additive := range x.Additive { + if item_2_x_Additive != nil { + if item_2_x_Additive.Reference != nil { + refVal := *item_2_x_Additive.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "additive") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("additive", targetID), + "additive", + projectJSON, + sourceType, + "additive", + )) + } + backrefKey := getEdgeUUID(id, targetID, "additive_specimen_processing") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("processing", id), + "additive_specimen_processing", + projectJSON, + sourceType, + "processing", + )) + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from Substance. +func (x *Substance) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Substance" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Code != nil { + if x.Code.Reference != nil { + if x.Code.Reference.Reference != nil { + refVal := *x.Code.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "code_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "code_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Code != nil { + if x.Code.Reference != nil { + if x.Code.Reference.Reference != nil { + refVal := *x.Code.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "code_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "code_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Code != nil { + if x.Code.Reference != nil { + if x.Code.Reference.Reference != nil { + refVal := *x.Code.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "code_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "code_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Code != nil { + if x.Code.Reference != nil { + if x.Code.Reference.Reference != nil { + refVal := *x.Code.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "code_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "code_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Code != nil { + if x.Code.Reference != nil { + if x.Code.Reference.Reference != nil { + refVal := *x.Code.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "code_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "code_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Code != nil { + if x.Code.Reference != nil { + if x.Code.Reference.Reference != nil { + refVal := *x.Code.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "code_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "code_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Code != nil { + if x.Code.Reference != nil { + if x.Code.Reference.Reference != nil { + refVal := *x.Code.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "code_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "code_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Code != nil { + if x.Code.Reference != nil { + if x.Code.Reference.Reference != nil { + refVal := *x.Code.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "code_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "code_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Code != nil { + if x.Code.Reference != nil { + if x.Code.Reference.Reference != nil { + refVal := *x.Code.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "code_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "code_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Code != nil { + if x.Code.Reference != nil { + if x.Code.Reference.Reference != nil { + refVal := *x.Code.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "code_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "code_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Code != nil { + if x.Code.Reference != nil { + if x.Code.Reference.Reference != nil { + refVal := *x.Code.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "code_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "code_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Code != nil { + if x.Code.Reference != nil { + if x.Code.Reference.Reference != nil { + refVal := *x.Code.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "code_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "code_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Code != nil { + if x.Code.Reference != nil { + if x.Code.Reference.Reference != nil { + refVal := *x.Code.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "code_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "code_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Code != nil { + if x.Code.Reference != nil { + if x.Code.Reference.Reference != nil { + refVal := *x.Code.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "code_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "code_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Code != nil { + if x.Code.Reference != nil { + if x.Code.Reference.Reference != nil { + refVal := *x.Code.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "code_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "code_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Code != nil { + if x.Code.Reference != nil { + if x.Code.Reference.Reference != nil { + refVal := *x.Code.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "code_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "code_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Code != nil { + if x.Code.Reference != nil { + if x.Code.Reference.Reference != nil { + refVal := *x.Code.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "code_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "code_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Code != nil { + if x.Code.Reference != nil { + if x.Code.Reference.Reference != nil { + refVal := *x.Code.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "code_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "code_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Code != nil { + if x.Code.Reference != nil { + if x.Code.Reference.Reference != nil { + refVal := *x.Code.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "code_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "code_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Code != nil { + if x.Code.Reference != nil { + if x.Code.Reference.Reference != nil { + refVal := *x.Code.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "code_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "code_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Code != nil { + if x.Code.Reference != nil { + if x.Code.Reference.Reference != nil { + refVal := *x.Code.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "code_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "code_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Code != nil { + if x.Code.Reference != nil { + if x.Code.Reference.Reference != nil { + refVal := *x.Code.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "code_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "code_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Code != nil { + if x.Code.Reference != nil { + if x.Code.Reference.Reference != nil { + refVal := *x.Code.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "code_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "code_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.Ingredient != nil { + for _, item_3_x_Ingredient := range x.Ingredient { + if item_3_x_Ingredient != nil { + if item_3_x_Ingredient.SubstanceReference != nil { + if item_3_x_Ingredient.SubstanceReference.Reference != nil { + refVal := *item_3_x_Ingredient.SubstanceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "ingredient_substanceReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("substanceReference", targetID), + "ingredient_substanceReference", + projectJSON, + sourceType, + "substanceReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "substance_ingredient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("ingredient", id), + "substance_ingredient", + projectJSON, + sourceType, + "ingredient", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from SubstanceDefinition. +func (x *SubstanceDefinition) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "SubstanceDefinition" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Manufacturer != nil { + for _, item_2_x_Manufacturer := range x.Manufacturer { + if item_2_x_Manufacturer != nil { + if item_2_x_Manufacturer.Reference != nil { + refVal := *item_2_x_Manufacturer.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "manufacturer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("manufacturer", targetID), + "manufacturer", + projectJSON, + sourceType, + "manufacturer", + )) + } + backrefKey := getEdgeUUID(id, targetID, "manufacturer_substance_definition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("definition", id), + "manufacturer_substance_definition", + projectJSON, + sourceType, + "definition", + )) + } + } + } + } + } + } + } + if x.Supplier != nil { + for _, item_2_x_Supplier := range x.Supplier { + if item_2_x_Supplier != nil { + if item_2_x_Supplier.Reference != nil { + refVal := *item_2_x_Supplier.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "supplier") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("supplier", targetID), + "supplier", + projectJSON, + sourceType, + "supplier", + )) + } + backrefKey := getEdgeUUID(id, targetID, "supplier_substance_definition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("definition", id), + "supplier_substance_definition", + projectJSON, + sourceType, + "definition", + )) + } + } + } + } + } + } + } + if x.Code != nil { + for _, item_4_x_Code := range x.Code { + if item_4_x_Code != nil { + if item_4_x_Code.Source != nil { + for _, item_2_item_4_x_Code_Source := range item_4_x_Code.Source { + if item_2_item_4_x_Code_Source != nil { + if item_2_item_4_x_Code_Source.Reference != nil { + refVal := *item_2_item_4_x_Code_Source.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "code_source") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("source", targetID), + "code_source", + projectJSON, + sourceType, + "source", + )) + } + backrefKey := getEdgeUUID(id, targetID, "source_substance_definition_code") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("code", id), + "source_substance_definition_code", + projectJSON, + sourceType, + "code", + )) + } + } + } + } + } + } + } + } + } + } + if x.Name != nil { + for _, item_4_x_Name := range x.Name { + if item_4_x_Name != nil { + if item_4_x_Name.Source != nil { + for _, item_2_item_4_x_Name_Source := range item_4_x_Name.Source { + if item_2_item_4_x_Name_Source != nil { + if item_2_item_4_x_Name_Source.Reference != nil { + refVal := *item_2_item_4_x_Name_Source.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "name_source") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("source", targetID), + "name_source", + projectJSON, + sourceType, + "source", + )) + } + backrefKey := getEdgeUUID(id, targetID, "source_substance_definition_name") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("name", id), + "source_substance_definition_name", + projectJSON, + sourceType, + "name", + )) + } + } + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "note_authorReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "note_authorReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "note_authorReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "note_authorReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Relationship != nil { + for _, item_4_x_Relationship := range x.Relationship { + if item_4_x_Relationship != nil { + if item_4_x_Relationship.Source != nil { + for _, item_2_item_4_x_Relationship_Source := range item_4_x_Relationship.Source { + if item_2_item_4_x_Relationship_Source != nil { + if item_2_item_4_x_Relationship_Source.Reference != nil { + refVal := *item_2_item_4_x_Relationship_Source.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "relationship_source") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("source", targetID), + "relationship_source", + projectJSON, + sourceType, + "source", + )) + } + backrefKey := getEdgeUUID(id, targetID, "source_substance_definition_relationship") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("relationship", id), + "source_substance_definition_relationship", + projectJSON, + sourceType, + "relationship", + )) + } + } + } + } + } + } + } + } + } + } + if x.Relationship != nil { + for _, item_3_x_Relationship := range x.Relationship { + if item_3_x_Relationship != nil { + if item_3_x_Relationship.SubstanceDefinitionReference != nil { + if item_3_x_Relationship.SubstanceDefinitionReference.Reference != nil { + refVal := *item_3_x_Relationship.SubstanceDefinitionReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "relationship_substanceDefinitionReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("substanceDefinitionReference", targetID), + "relationship_substanceDefinitionReference", + projectJSON, + sourceType, + "substanceDefinitionReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "substance_definition_relationship") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("relationship", id), + "substance_definition_relationship", + projectJSON, + sourceType, + "relationship", + )) + } + } + } + } + } + } + } + } + if x.Structure != nil { + if x.Structure.SourceDocument != nil { + for _, item_2_x_Structure_SourceDocument := range x.Structure.SourceDocument { + if item_2_x_Structure_SourceDocument != nil { + if item_2_x_Structure_SourceDocument.Reference != nil { + refVal := *item_2_x_Structure_SourceDocument.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "structure_sourceDocument") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("sourceDocument", targetID), + "structure_sourceDocument", + projectJSON, + sourceType, + "sourceDocument", + )) + } + backrefKey := getEdgeUUID(id, targetID, "sourceDocument_substance_definition_structure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("structure", id), + "sourceDocument_substance_definition_structure", + projectJSON, + sourceType, + "structure", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from SubstanceDefinitionCharacterization. +func (x *SubstanceDefinitionCharacterization) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "SubstanceDefinitionCharacterization" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from SubstanceDefinitionCode. +func (x *SubstanceDefinitionCode) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "SubstanceDefinitionCode" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Source != nil { + for _, item_2_x_Source := range x.Source { + if item_2_x_Source != nil { + if item_2_x_Source.Reference != nil { + refVal := *item_2_x_Source.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "source") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("source", targetID), + "source", + projectJSON, + sourceType, + "source", + )) + } + backrefKey := getEdgeUUID(id, targetID, "source_substance_definition_code") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("code", id), + "source_substance_definition_code", + projectJSON, + sourceType, + "code", + )) + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "note_authorReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "note_authorReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "note_authorReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "note_authorReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from SubstanceDefinitionMoiety. +func (x *SubstanceDefinitionMoiety) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "SubstanceDefinitionMoiety" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from SubstanceDefinitionMolecularWeight. +func (x *SubstanceDefinitionMolecularWeight) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "SubstanceDefinitionMolecularWeight" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from SubstanceDefinitionName. +func (x *SubstanceDefinitionName) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "SubstanceDefinitionName" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Source != nil { + for _, item_2_x_Source := range x.Source { + if item_2_x_Source != nil { + if item_2_x_Source.Reference != nil { + refVal := *item_2_x_Source.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "source") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("source", targetID), + "source", + projectJSON, + sourceType, + "source", + )) + } + backrefKey := getEdgeUUID(id, targetID, "source_substance_definition_name") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("name", id), + "source_substance_definition_name", + projectJSON, + sourceType, + "name", + )) + } + } + } + } + } + } + } + if x.Synonym != nil { + for _, item_4_x_Synonym := range x.Synonym { + if item_4_x_Synonym != nil { + if item_4_x_Synonym.Source != nil { + for _, item_2_item_4_x_Synonym_Source := range item_4_x_Synonym.Source { + if item_2_item_4_x_Synonym_Source != nil { + if item_2_item_4_x_Synonym_Source.Reference != nil { + refVal := *item_2_item_4_x_Synonym_Source.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "synonym_source") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("source", targetID), + "synonym_source", + projectJSON, + sourceType, + "source", + )) + } + backrefKey := getEdgeUUID(id, targetID, "source_substance_definition_name") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("name", id), + "source_substance_definition_name", + projectJSON, + sourceType, + "name", + )) + } + } + } + } + } + } + } + } + } + } + if x.Translation != nil { + for _, item_4_x_Translation := range x.Translation { + if item_4_x_Translation != nil { + if item_4_x_Translation.Source != nil { + for _, item_2_item_4_x_Translation_Source := range item_4_x_Translation.Source { + if item_2_item_4_x_Translation_Source != nil { + if item_2_item_4_x_Translation_Source.Reference != nil { + refVal := *item_2_item_4_x_Translation_Source.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "translation_source") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("source", targetID), + "translation_source", + projectJSON, + sourceType, + "source", + )) + } + backrefKey := getEdgeUUID(id, targetID, "source_substance_definition_name") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("name", id), + "source_substance_definition_name", + projectJSON, + sourceType, + "name", + )) + } + } + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from SubstanceDefinitionNameOfficial. +func (x *SubstanceDefinitionNameOfficial) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "SubstanceDefinitionNameOfficial" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from SubstanceDefinitionProperty. +func (x *SubstanceDefinitionProperty) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "SubstanceDefinitionProperty" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from SubstanceDefinitionRelationship. +func (x *SubstanceDefinitionRelationship) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "SubstanceDefinitionRelationship" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Source != nil { + for _, item_2_x_Source := range x.Source { + if item_2_x_Source != nil { + if item_2_x_Source.Reference != nil { + refVal := *item_2_x_Source.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "source") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("source", targetID), + "source", + projectJSON, + sourceType, + "source", + )) + } + backrefKey := getEdgeUUID(id, targetID, "source_substance_definition_relationship") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("relationship", id), + "source_substance_definition_relationship", + projectJSON, + sourceType, + "relationship", + )) + } + } + } + } + } + } + } + if x.SubstanceDefinitionReference != nil { + if x.SubstanceDefinitionReference.Reference != nil { + refVal := *x.SubstanceDefinitionReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "substanceDefinitionReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("substanceDefinitionReference", targetID), + "substanceDefinitionReference", + projectJSON, + sourceType, + "substanceDefinitionReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "substance_definition_relationship") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("relationship", id), + "substance_definition_relationship", + projectJSON, + sourceType, + "relationship", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from SubstanceDefinitionSourceMaterial. +func (x *SubstanceDefinitionSourceMaterial) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "SubstanceDefinitionSourceMaterial" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from SubstanceDefinitionStructure. +func (x *SubstanceDefinitionStructure) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "SubstanceDefinitionStructure" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.SourceDocument != nil { + for _, item_2_x_SourceDocument := range x.SourceDocument { + if item_2_x_SourceDocument != nil { + if item_2_x_SourceDocument.Reference != nil { + refVal := *item_2_x_SourceDocument.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "sourceDocument") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("sourceDocument", targetID), + "sourceDocument", + projectJSON, + sourceType, + "sourceDocument", + )) + } + backrefKey := getEdgeUUID(id, targetID, "sourceDocument_substance_definition_structure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("structure", id), + "sourceDocument_substance_definition_structure", + projectJSON, + sourceType, + "structure", + )) + } + } + } + } + } + } + } + if x.Representation != nil { + for _, item_3_x_Representation := range x.Representation { + if item_3_x_Representation != nil { + if item_3_x_Representation.Document != nil { + if item_3_x_Representation.Document.Reference != nil { + refVal := *item_3_x_Representation.Document.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "representation_document") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("document", targetID), + "representation_document", + projectJSON, + sourceType, + "document", + )) + } + backrefKey := getEdgeUUID(id, targetID, "substance_definition_structure_representation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("representation", id), + "substance_definition_structure_representation", + projectJSON, + sourceType, + "representation", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from SubstanceDefinitionStructureRepresentation. +func (x *SubstanceDefinitionStructureRepresentation) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "SubstanceDefinitionStructureRepresentation" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Document != nil { + if x.Document.Reference != nil { + refVal := *x.Document.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "document") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("document", targetID), + "document", + projectJSON, + sourceType, + "document", + )) + } + backrefKey := getEdgeUUID(id, targetID, "substance_definition_structure_representation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("representation", id), + "substance_definition_structure_representation", + projectJSON, + sourceType, + "representation", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from SubstanceIngredient. +func (x *SubstanceIngredient) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "SubstanceIngredient" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.SubstanceReference != nil { + if x.SubstanceReference.Reference != nil { + refVal := *x.SubstanceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "substanceReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("substanceReference", targetID), + "substanceReference", + projectJSON, + sourceType, + "substanceReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "substance_ingredient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("ingredient", id), + "substance_ingredient", + projectJSON, + sourceType, + "ingredient", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from Task. +func (x *Task) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Task" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "basedOn_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "basedOn_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "basedOn_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "basedOn_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "basedOn_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "basedOn_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "basedOn_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "basedOn_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "basedOn_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "basedOn_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "basedOn_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "basedOn_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "basedOn_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "basedOn_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "basedOn_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "basedOn_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "basedOn_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "basedOn_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "basedOn_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "basedOn_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "basedOn_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "basedOn_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "basedOn_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "basedOn_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "basedOn_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "basedOn_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "basedOn_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "basedOn_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "basedOn_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "basedOn_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "basedOn_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "basedOn_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "basedOn_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "basedOn_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "basedOn_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "basedOn_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "basedOn_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "basedOn_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "basedOn_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "basedOn_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "basedOn_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "basedOn_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "basedOn_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "basedOn_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.BasedOn != nil { + for _, item_2_x_BasedOn := range x.BasedOn { + if item_2_x_BasedOn != nil { + if item_2_x_BasedOn.Reference != nil { + refVal := *item_2_x_BasedOn.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "basedOn_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "basedOn_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "basedOn_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "basedOn_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "focus_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "focus_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "focus_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "focus_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "focus_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "focus_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "focus_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "focus_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "focus_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "focus_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "focus_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "focus_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "focus_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "focus_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "focus_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "focus_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "focus_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "focus_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "focus_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "focus_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "focus_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "focus_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "focus_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "focus_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "focus_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "focus_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "focus_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "focus_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "focus_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "focus_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "focus_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "focus_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "focus_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "focus_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "focus_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "focus_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "focus_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "focus_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "focus_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "focus_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "focus_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "focus_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "focus_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "focus_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "focus_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "focus_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "focus_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "focus_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "focus_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "focus_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "focus_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "focus_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "focus_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "focus_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "focus_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "focus_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "focus_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "focus_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "focus_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "focus_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "focus_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "focus_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "focus_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "focus_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "focus_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "focus_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Focus != nil { + if x.Focus.Reference != nil { + refVal := *x.Focus.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "focus_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "focus_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "focus_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "focus_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.ForFhir != nil { + if x.ForFhir.Reference != nil { + refVal := *x.ForFhir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "for_fhir_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "for_fhir_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "for_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "for_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.ForFhir != nil { + if x.ForFhir.Reference != nil { + refVal := *x.ForFhir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "for_fhir_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "for_fhir_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "for_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "for_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.ForFhir != nil { + if x.ForFhir.Reference != nil { + refVal := *x.ForFhir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "for_fhir_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "for_fhir_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "for_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "for_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.ForFhir != nil { + if x.ForFhir.Reference != nil { + refVal := *x.ForFhir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "for_fhir_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "for_fhir_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "for_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "for_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.ForFhir != nil { + if x.ForFhir.Reference != nil { + refVal := *x.ForFhir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "for_fhir_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "for_fhir_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "for_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "for_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.ForFhir != nil { + if x.ForFhir.Reference != nil { + refVal := *x.ForFhir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "for_fhir_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "for_fhir_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "for_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "for_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.ForFhir != nil { + if x.ForFhir.Reference != nil { + refVal := *x.ForFhir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "for_fhir_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "for_fhir_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "for_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "for_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.ForFhir != nil { + if x.ForFhir.Reference != nil { + refVal := *x.ForFhir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "for_fhir_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "for_fhir_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "for_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "for_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.ForFhir != nil { + if x.ForFhir.Reference != nil { + refVal := *x.ForFhir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "for_fhir_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "for_fhir_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "for_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "for_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.ForFhir != nil { + if x.ForFhir.Reference != nil { + refVal := *x.ForFhir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "for_fhir_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "for_fhir_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "for_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "for_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.ForFhir != nil { + if x.ForFhir.Reference != nil { + refVal := *x.ForFhir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "for_fhir_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "for_fhir_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "for_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "for_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.ForFhir != nil { + if x.ForFhir.Reference != nil { + refVal := *x.ForFhir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "for_fhir_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "for_fhir_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "for_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "for_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.ForFhir != nil { + if x.ForFhir.Reference != nil { + refVal := *x.ForFhir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "for_fhir_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "for_fhir_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "for_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "for_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.ForFhir != nil { + if x.ForFhir.Reference != nil { + refVal := *x.ForFhir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "for_fhir_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "for_fhir_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "for_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "for_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.ForFhir != nil { + if x.ForFhir.Reference != nil { + refVal := *x.ForFhir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "for_fhir_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "for_fhir_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "for_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "for_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.ForFhir != nil { + if x.ForFhir.Reference != nil { + refVal := *x.ForFhir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "for_fhir_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "for_fhir_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "for_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "for_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.ForFhir != nil { + if x.ForFhir.Reference != nil { + refVal := *x.ForFhir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "for_fhir_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "for_fhir_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "for_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "for_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.ForFhir != nil { + if x.ForFhir.Reference != nil { + refVal := *x.ForFhir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "for_fhir_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "for_fhir_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "for_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "for_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.ForFhir != nil { + if x.ForFhir.Reference != nil { + refVal := *x.ForFhir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "for_fhir_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "for_fhir_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "for_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "for_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.ForFhir != nil { + if x.ForFhir.Reference != nil { + refVal := *x.ForFhir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "for_fhir_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "for_fhir_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "for_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "for_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.ForFhir != nil { + if x.ForFhir.Reference != nil { + refVal := *x.ForFhir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "for_fhir_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "for_fhir_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "for_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "for_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.ForFhir != nil { + if x.ForFhir.Reference != nil { + refVal := *x.ForFhir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "for_fhir_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "for_fhir_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "for_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "for_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.ForFhir != nil { + if x.ForFhir.Reference != nil { + refVal := *x.ForFhir.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "for_fhir_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "for_fhir_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "for_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "for_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Owner != nil { + if x.Owner.Reference != nil { + refVal := *x.Owner.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "owner_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "owner_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "owner_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "owner_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Owner != nil { + if x.Owner.Reference != nil { + refVal := *x.Owner.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "owner_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "owner_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "owner_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "owner_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Owner != nil { + if x.Owner.Reference != nil { + refVal := *x.Owner.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "owner_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "owner_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "owner_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "owner_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Owner != nil { + if x.Owner.Reference != nil { + refVal := *x.Owner.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "owner_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "owner_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "owner_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "owner_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.PartOf != nil { + for _, item_2_x_PartOf := range x.PartOf { + if item_2_x_PartOf != nil { + if item_2_x_PartOf.Reference != nil { + refVal := *item_2_x_PartOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "partOf") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("partOf", targetID), + "partOf", + projectJSON, + sourceType, + "partOf", + )) + } + backrefKey := getEdgeUUID(id, targetID, "partOf_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "partOf_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + } + } + if x.Requester != nil { + if x.Requester.Reference != nil { + refVal := *x.Requester.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "requester_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "requester_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "requester_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "requester_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Requester != nil { + if x.Requester.Reference != nil { + refVal := *x.Requester.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "requester_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "requester_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "requester_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "requester_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Requester != nil { + if x.Requester.Reference != nil { + refVal := *x.Requester.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "requester_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "requester_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "requester_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "requester_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Requester != nil { + if x.Requester.Reference != nil { + refVal := *x.Requester.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "requester_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "requester_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "requester_task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("task", id), + "requester_task", + projectJSON, + sourceType, + "task", + )) + } + } + } + } + } + if x.Input != nil { + for _, item_3_x_Input := range x.Input { + if item_3_x_Input != nil { + if item_3_x_Input.ValueReference != nil { + if item_3_x_Input.ValueReference.Reference != nil { + refVal := *item_3_x_Input.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "input_valueReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "input_valueReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + } + } + } + if x.Input != nil { + for _, item_3_x_Input := range x.Input { + if item_3_x_Input != nil { + if item_3_x_Input.ValueReference != nil { + if item_3_x_Input.ValueReference.Reference != nil { + refVal := *item_3_x_Input.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "input_valueReference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "input_valueReference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + } + } + } + if x.Input != nil { + for _, item_3_x_Input := range x.Input { + if item_3_x_Input != nil { + if item_3_x_Input.ValueReference != nil { + if item_3_x_Input.ValueReference.Reference != nil { + refVal := *item_3_x_Input.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "input_valueReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "input_valueReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + } + } + } + if x.Input != nil { + for _, item_3_x_Input := range x.Input { + if item_3_x_Input != nil { + if item_3_x_Input.ValueReference != nil { + if item_3_x_Input.ValueReference.Reference != nil { + refVal := *item_3_x_Input.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "input_valueReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "input_valueReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + } + } + } + if x.Input != nil { + for _, item_3_x_Input := range x.Input { + if item_3_x_Input != nil { + if item_3_x_Input.ValueReference != nil { + if item_3_x_Input.ValueReference.Reference != nil { + refVal := *item_3_x_Input.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "input_valueReference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "input_valueReference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + } + } + } + if x.Input != nil { + for _, item_3_x_Input := range x.Input { + if item_3_x_Input != nil { + if item_3_x_Input.ValueReference != nil { + if item_3_x_Input.ValueReference.Reference != nil { + refVal := *item_3_x_Input.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "input_valueReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "input_valueReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + } + } + } + if x.Input != nil { + for _, item_3_x_Input := range x.Input { + if item_3_x_Input != nil { + if item_3_x_Input.ValueReference != nil { + if item_3_x_Input.ValueReference.Reference != nil { + refVal := *item_3_x_Input.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "input_valueReference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "input_valueReference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + } + } + } + if x.Input != nil { + for _, item_3_x_Input := range x.Input { + if item_3_x_Input != nil { + if item_3_x_Input.ValueReference != nil { + if item_3_x_Input.ValueReference.Reference != nil { + refVal := *item_3_x_Input.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "input_valueReference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "input_valueReference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + } + } + } + if x.Input != nil { + for _, item_3_x_Input := range x.Input { + if item_3_x_Input != nil { + if item_3_x_Input.ValueReference != nil { + if item_3_x_Input.ValueReference.Reference != nil { + refVal := *item_3_x_Input.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "input_valueReference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "input_valueReference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + } + } + } + if x.Input != nil { + for _, item_3_x_Input := range x.Input { + if item_3_x_Input != nil { + if item_3_x_Input.ValueReference != nil { + if item_3_x_Input.ValueReference.Reference != nil { + refVal := *item_3_x_Input.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "input_valueReference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "input_valueReference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + } + } + } + if x.Input != nil { + for _, item_3_x_Input := range x.Input { + if item_3_x_Input != nil { + if item_3_x_Input.ValueReference != nil { + if item_3_x_Input.ValueReference.Reference != nil { + refVal := *item_3_x_Input.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "input_valueReference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "input_valueReference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + } + } + } + if x.Input != nil { + for _, item_3_x_Input := range x.Input { + if item_3_x_Input != nil { + if item_3_x_Input.ValueReference != nil { + if item_3_x_Input.ValueReference.Reference != nil { + refVal := *item_3_x_Input.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "input_valueReference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "input_valueReference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + } + } + } + if x.Input != nil { + for _, item_3_x_Input := range x.Input { + if item_3_x_Input != nil { + if item_3_x_Input.ValueReference != nil { + if item_3_x_Input.ValueReference.Reference != nil { + refVal := *item_3_x_Input.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "input_valueReference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "input_valueReference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + } + } + } + if x.Input != nil { + for _, item_3_x_Input := range x.Input { + if item_3_x_Input != nil { + if item_3_x_Input.ValueReference != nil { + if item_3_x_Input.ValueReference.Reference != nil { + refVal := *item_3_x_Input.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "input_valueReference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "input_valueReference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + } + } + } + if x.Input != nil { + for _, item_3_x_Input := range x.Input { + if item_3_x_Input != nil { + if item_3_x_Input.ValueReference != nil { + if item_3_x_Input.ValueReference.Reference != nil { + refVal := *item_3_x_Input.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "input_valueReference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "input_valueReference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + } + } + } + if x.Input != nil { + for _, item_3_x_Input := range x.Input { + if item_3_x_Input != nil { + if item_3_x_Input.ValueReference != nil { + if item_3_x_Input.ValueReference.Reference != nil { + refVal := *item_3_x_Input.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "input_valueReference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "input_valueReference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + } + } + } + if x.Input != nil { + for _, item_3_x_Input := range x.Input { + if item_3_x_Input != nil { + if item_3_x_Input.ValueReference != nil { + if item_3_x_Input.ValueReference.Reference != nil { + refVal := *item_3_x_Input.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "input_valueReference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "input_valueReference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + } + } + } + if x.Input != nil { + for _, item_3_x_Input := range x.Input { + if item_3_x_Input != nil { + if item_3_x_Input.ValueReference != nil { + if item_3_x_Input.ValueReference.Reference != nil { + refVal := *item_3_x_Input.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "input_valueReference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "input_valueReference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + } + } + } + if x.Input != nil { + for _, item_3_x_Input := range x.Input { + if item_3_x_Input != nil { + if item_3_x_Input.ValueReference != nil { + if item_3_x_Input.ValueReference.Reference != nil { + refVal := *item_3_x_Input.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "input_valueReference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "input_valueReference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + } + } + } + if x.Input != nil { + for _, item_3_x_Input := range x.Input { + if item_3_x_Input != nil { + if item_3_x_Input.ValueReference != nil { + if item_3_x_Input.ValueReference.Reference != nil { + refVal := *item_3_x_Input.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "input_valueReference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "input_valueReference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + } + } + } + if x.Input != nil { + for _, item_3_x_Input := range x.Input { + if item_3_x_Input != nil { + if item_3_x_Input.ValueReference != nil { + if item_3_x_Input.ValueReference.Reference != nil { + refVal := *item_3_x_Input.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "input_valueReference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "input_valueReference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + } + } + } + if x.Input != nil { + for _, item_3_x_Input := range x.Input { + if item_3_x_Input != nil { + if item_3_x_Input.ValueReference != nil { + if item_3_x_Input.ValueReference.Reference != nil { + refVal := *item_3_x_Input.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "input_valueReference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "input_valueReference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + } + } + } + if x.Input != nil { + for _, item_3_x_Input := range x.Input { + if item_3_x_Input != nil { + if item_3_x_Input.ValueReference != nil { + if item_3_x_Input.ValueReference.Reference != nil { + refVal := *item_3_x_Input.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "input_valueReference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "input_valueReference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "note_authorReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "note_authorReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "note_authorReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Note != nil { + for _, item_3_x_Note := range x.Note { + if item_3_x_Note != nil { + if item_3_x_Note.AuthorReference != nil { + if item_3_x_Note.AuthorReference.Reference != nil { + refVal := *item_3_x_Note.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "note_authorReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "note_authorReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + } + } + if x.Output != nil { + for _, item_3_x_Output := range x.Output { + if item_3_x_Output != nil { + if item_3_x_Output.ValueReference != nil { + if item_3_x_Output.ValueReference.Reference != nil { + refVal := *item_3_x_Output.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "output_valueReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "output_valueReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + } + } + } + if x.Output != nil { + for _, item_3_x_Output := range x.Output { + if item_3_x_Output != nil { + if item_3_x_Output.ValueReference != nil { + if item_3_x_Output.ValueReference.Reference != nil { + refVal := *item_3_x_Output.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "output_valueReference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "output_valueReference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + } + } + } + if x.Output != nil { + for _, item_3_x_Output := range x.Output { + if item_3_x_Output != nil { + if item_3_x_Output.ValueReference != nil { + if item_3_x_Output.ValueReference.Reference != nil { + refVal := *item_3_x_Output.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "output_valueReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "output_valueReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + } + } + } + if x.Output != nil { + for _, item_3_x_Output := range x.Output { + if item_3_x_Output != nil { + if item_3_x_Output.ValueReference != nil { + if item_3_x_Output.ValueReference.Reference != nil { + refVal := *item_3_x_Output.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "output_valueReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "output_valueReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + } + } + } + if x.Output != nil { + for _, item_3_x_Output := range x.Output { + if item_3_x_Output != nil { + if item_3_x_Output.ValueReference != nil { + if item_3_x_Output.ValueReference.Reference != nil { + refVal := *item_3_x_Output.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "output_valueReference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "output_valueReference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + } + } + } + if x.Output != nil { + for _, item_3_x_Output := range x.Output { + if item_3_x_Output != nil { + if item_3_x_Output.ValueReference != nil { + if item_3_x_Output.ValueReference.Reference != nil { + refVal := *item_3_x_Output.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "output_valueReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "output_valueReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + } + } + } + if x.Output != nil { + for _, item_3_x_Output := range x.Output { + if item_3_x_Output != nil { + if item_3_x_Output.ValueReference != nil { + if item_3_x_Output.ValueReference.Reference != nil { + refVal := *item_3_x_Output.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "output_valueReference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "output_valueReference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + } + } + } + if x.Output != nil { + for _, item_3_x_Output := range x.Output { + if item_3_x_Output != nil { + if item_3_x_Output.ValueReference != nil { + if item_3_x_Output.ValueReference.Reference != nil { + refVal := *item_3_x_Output.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "output_valueReference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "output_valueReference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + } + } + } + if x.Output != nil { + for _, item_3_x_Output := range x.Output { + if item_3_x_Output != nil { + if item_3_x_Output.ValueReference != nil { + if item_3_x_Output.ValueReference.Reference != nil { + refVal := *item_3_x_Output.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "output_valueReference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "output_valueReference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + } + } + } + if x.Output != nil { + for _, item_3_x_Output := range x.Output { + if item_3_x_Output != nil { + if item_3_x_Output.ValueReference != nil { + if item_3_x_Output.ValueReference.Reference != nil { + refVal := *item_3_x_Output.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "output_valueReference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "output_valueReference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + } + } + } + if x.Output != nil { + for _, item_3_x_Output := range x.Output { + if item_3_x_Output != nil { + if item_3_x_Output.ValueReference != nil { + if item_3_x_Output.ValueReference.Reference != nil { + refVal := *item_3_x_Output.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "output_valueReference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "output_valueReference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + } + } + } + if x.Output != nil { + for _, item_3_x_Output := range x.Output { + if item_3_x_Output != nil { + if item_3_x_Output.ValueReference != nil { + if item_3_x_Output.ValueReference.Reference != nil { + refVal := *item_3_x_Output.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "output_valueReference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "output_valueReference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + } + } + } + if x.Output != nil { + for _, item_3_x_Output := range x.Output { + if item_3_x_Output != nil { + if item_3_x_Output.ValueReference != nil { + if item_3_x_Output.ValueReference.Reference != nil { + refVal := *item_3_x_Output.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "output_valueReference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "output_valueReference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + } + } + } + if x.Output != nil { + for _, item_3_x_Output := range x.Output { + if item_3_x_Output != nil { + if item_3_x_Output.ValueReference != nil { + if item_3_x_Output.ValueReference.Reference != nil { + refVal := *item_3_x_Output.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "output_valueReference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "output_valueReference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + } + } + } + if x.Output != nil { + for _, item_3_x_Output := range x.Output { + if item_3_x_Output != nil { + if item_3_x_Output.ValueReference != nil { + if item_3_x_Output.ValueReference.Reference != nil { + refVal := *item_3_x_Output.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "output_valueReference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "output_valueReference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + } + } + } + if x.Output != nil { + for _, item_3_x_Output := range x.Output { + if item_3_x_Output != nil { + if item_3_x_Output.ValueReference != nil { + if item_3_x_Output.ValueReference.Reference != nil { + refVal := *item_3_x_Output.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "output_valueReference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "output_valueReference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + } + } + } + if x.Output != nil { + for _, item_3_x_Output := range x.Output { + if item_3_x_Output != nil { + if item_3_x_Output.ValueReference != nil { + if item_3_x_Output.ValueReference.Reference != nil { + refVal := *item_3_x_Output.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "output_valueReference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "output_valueReference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + } + } + } + if x.Output != nil { + for _, item_3_x_Output := range x.Output { + if item_3_x_Output != nil { + if item_3_x_Output.ValueReference != nil { + if item_3_x_Output.ValueReference.Reference != nil { + refVal := *item_3_x_Output.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "output_valueReference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "output_valueReference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + } + } + } + if x.Output != nil { + for _, item_3_x_Output := range x.Output { + if item_3_x_Output != nil { + if item_3_x_Output.ValueReference != nil { + if item_3_x_Output.ValueReference.Reference != nil { + refVal := *item_3_x_Output.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "output_valueReference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "output_valueReference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + } + } + } + if x.Output != nil { + for _, item_3_x_Output := range x.Output { + if item_3_x_Output != nil { + if item_3_x_Output.ValueReference != nil { + if item_3_x_Output.ValueReference.Reference != nil { + refVal := *item_3_x_Output.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "output_valueReference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "output_valueReference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + } + } + } + if x.Output != nil { + for _, item_3_x_Output := range x.Output { + if item_3_x_Output != nil { + if item_3_x_Output.ValueReference != nil { + if item_3_x_Output.ValueReference.Reference != nil { + refVal := *item_3_x_Output.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "output_valueReference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "output_valueReference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + } + } + } + if x.Output != nil { + for _, item_3_x_Output := range x.Output { + if item_3_x_Output != nil { + if item_3_x_Output.ValueReference != nil { + if item_3_x_Output.ValueReference.Reference != nil { + refVal := *item_3_x_Output.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "output_valueReference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "output_valueReference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + } + } + } + if x.Output != nil { + for _, item_3_x_Output := range x.Output { + if item_3_x_Output != nil { + if item_3_x_Output.ValueReference != nil { + if item_3_x_Output.ValueReference.Reference != nil { + refVal := *item_3_x_Output.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "output_valueReference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "output_valueReference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + } + } + } + if x.Performer != nil { + for _, item_3_x_Performer := range x.Performer { + if item_3_x_Performer != nil { + if item_3_x_Performer.Actor != nil { + if item_3_x_Performer.Actor.Reference != nil { + refVal := *item_3_x_Performer.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "performer_actor_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "performer_actor_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "task_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + } + } + } + if x.Performer != nil { + for _, item_3_x_Performer := range x.Performer { + if item_3_x_Performer != nil { + if item_3_x_Performer.Actor != nil { + if item_3_x_Performer.Actor.Reference != nil { + refVal := *item_3_x_Performer.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "performer_actor_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "performer_actor_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "task_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + } + } + } + if x.Performer != nil { + for _, item_3_x_Performer := range x.Performer { + if item_3_x_Performer != nil { + if item_3_x_Performer.Actor != nil { + if item_3_x_Performer.Actor.Reference != nil { + refVal := *item_3_x_Performer.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "performer_actor_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "performer_actor_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "task_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + } + } + } + if x.Performer != nil { + for _, item_3_x_Performer := range x.Performer { + if item_3_x_Performer != nil { + if item_3_x_Performer.Actor != nil { + if item_3_x_Performer.Actor.Reference != nil { + refVal := *item_3_x_Performer.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "performer_actor_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "performer_actor_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "task_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "reason_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "reason_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "reason_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "reason_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "reason_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "reason_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "reason_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "reason_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "reason_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "reason_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "reason_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "reason_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "reason_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "reason_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "reason_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "reason_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "reason_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "reason_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "reason_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "reason_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "reason_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "reason_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Reason != nil { + for _, item_3_x_Reason := range x.Reason { + if item_3_x_Reason != nil { + if item_3_x_Reason.Reference != nil { + if item_3_x_Reason.Reference.Reference != nil { + refVal := *item_3_x_Reason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "reason_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "reason_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RequestedPerformer != nil { + for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { + if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer.Reference != nil { + if item_3_x_RequestedPerformer.Reference.Reference != nil { + refVal := *item_3_x_RequestedPerformer.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "requestedPerformer_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RequestedPerformer != nil { + for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { + if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer.Reference != nil { + if item_3_x_RequestedPerformer.Reference.Reference != nil { + refVal := *item_3_x_RequestedPerformer.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "requestedPerformer_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RequestedPerformer != nil { + for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { + if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer.Reference != nil { + if item_3_x_RequestedPerformer.Reference.Reference != nil { + refVal := *item_3_x_RequestedPerformer.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "requestedPerformer_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RequestedPerformer != nil { + for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { + if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer.Reference != nil { + if item_3_x_RequestedPerformer.Reference.Reference != nil { + refVal := *item_3_x_RequestedPerformer.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "requestedPerformer_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RequestedPerformer != nil { + for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { + if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer.Reference != nil { + if item_3_x_RequestedPerformer.Reference.Reference != nil { + refVal := *item_3_x_RequestedPerformer.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "requestedPerformer_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RequestedPerformer != nil { + for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { + if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer.Reference != nil { + if item_3_x_RequestedPerformer.Reference.Reference != nil { + refVal := *item_3_x_RequestedPerformer.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "requestedPerformer_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RequestedPerformer != nil { + for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { + if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer.Reference != nil { + if item_3_x_RequestedPerformer.Reference.Reference != nil { + refVal := *item_3_x_RequestedPerformer.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "requestedPerformer_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RequestedPerformer != nil { + for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { + if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer.Reference != nil { + if item_3_x_RequestedPerformer.Reference.Reference != nil { + refVal := *item_3_x_RequestedPerformer.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "requestedPerformer_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RequestedPerformer != nil { + for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { + if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer.Reference != nil { + if item_3_x_RequestedPerformer.Reference.Reference != nil { + refVal := *item_3_x_RequestedPerformer.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "requestedPerformer_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RequestedPerformer != nil { + for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { + if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer.Reference != nil { + if item_3_x_RequestedPerformer.Reference.Reference != nil { + refVal := *item_3_x_RequestedPerformer.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "requestedPerformer_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RequestedPerformer != nil { + for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { + if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer.Reference != nil { + if item_3_x_RequestedPerformer.Reference.Reference != nil { + refVal := *item_3_x_RequestedPerformer.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "requestedPerformer_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RequestedPerformer != nil { + for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { + if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer.Reference != nil { + if item_3_x_RequestedPerformer.Reference.Reference != nil { + refVal := *item_3_x_RequestedPerformer.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "requestedPerformer_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RequestedPerformer != nil { + for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { + if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer.Reference != nil { + if item_3_x_RequestedPerformer.Reference.Reference != nil { + refVal := *item_3_x_RequestedPerformer.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "requestedPerformer_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RequestedPerformer != nil { + for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { + if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer.Reference != nil { + if item_3_x_RequestedPerformer.Reference.Reference != nil { + refVal := *item_3_x_RequestedPerformer.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "requestedPerformer_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RequestedPerformer != nil { + for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { + if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer.Reference != nil { + if item_3_x_RequestedPerformer.Reference.Reference != nil { + refVal := *item_3_x_RequestedPerformer.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "requestedPerformer_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RequestedPerformer != nil { + for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { + if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer.Reference != nil { + if item_3_x_RequestedPerformer.Reference.Reference != nil { + refVal := *item_3_x_RequestedPerformer.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "requestedPerformer_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RequestedPerformer != nil { + for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { + if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer.Reference != nil { + if item_3_x_RequestedPerformer.Reference.Reference != nil { + refVal := *item_3_x_RequestedPerformer.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "requestedPerformer_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RequestedPerformer != nil { + for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { + if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer.Reference != nil { + if item_3_x_RequestedPerformer.Reference.Reference != nil { + refVal := *item_3_x_RequestedPerformer.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "requestedPerformer_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RequestedPerformer != nil { + for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { + if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer.Reference != nil { + if item_3_x_RequestedPerformer.Reference.Reference != nil { + refVal := *item_3_x_RequestedPerformer.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "requestedPerformer_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RequestedPerformer != nil { + for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { + if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer.Reference != nil { + if item_3_x_RequestedPerformer.Reference.Reference != nil { + refVal := *item_3_x_RequestedPerformer.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "requestedPerformer_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RequestedPerformer != nil { + for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { + if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer.Reference != nil { + if item_3_x_RequestedPerformer.Reference.Reference != nil { + refVal := *item_3_x_RequestedPerformer.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "requestedPerformer_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RequestedPerformer != nil { + for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { + if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer.Reference != nil { + if item_3_x_RequestedPerformer.Reference.Reference != nil { + refVal := *item_3_x_RequestedPerformer.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "requestedPerformer_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.RequestedPerformer != nil { + for _, item_3_x_RequestedPerformer := range x.RequestedPerformer { + if item_3_x_RequestedPerformer != nil { + if item_3_x_RequestedPerformer.Reference != nil { + if item_3_x_RequestedPerformer.Reference.Reference != nil { + refVal := *item_3_x_RequestedPerformer.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "requestedPerformer_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "requestedPerformer_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + } + } + if x.Restriction != nil { + if x.Restriction.Recipient != nil { + for _, item_2_x_Restriction_Recipient := range x.Restriction.Recipient { + if item_2_x_Restriction_Recipient != nil { + if item_2_x_Restriction_Recipient.Reference != nil { + refVal := *item_2_x_Restriction_Recipient.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "restriction_recipient_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "restriction_recipient_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "recipient_task_restriction") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("restriction", id), + "recipient_task_restriction", + projectJSON, + sourceType, + "restriction", + )) + } + } + } + } + } + } + } + } + if x.Restriction != nil { + if x.Restriction.Recipient != nil { + for _, item_2_x_Restriction_Recipient := range x.Restriction.Recipient { + if item_2_x_Restriction_Recipient != nil { + if item_2_x_Restriction_Recipient.Reference != nil { + refVal := *item_2_x_Restriction_Recipient.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "restriction_recipient_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "restriction_recipient_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "recipient_task_restriction") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("restriction", id), + "recipient_task_restriction", + projectJSON, + sourceType, + "restriction", + )) + } + } + } + } + } + } + } + } + if x.Restriction != nil { + if x.Restriction.Recipient != nil { + for _, item_2_x_Restriction_Recipient := range x.Restriction.Recipient { + if item_2_x_Restriction_Recipient != nil { + if item_2_x_Restriction_Recipient.Reference != nil { + refVal := *item_2_x_Restriction_Recipient.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "restriction_recipient_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "restriction_recipient_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "recipient_task_restriction") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("restriction", id), + "recipient_task_restriction", + projectJSON, + sourceType, + "restriction", + )) + } + } + } + } + } + } + } + } + if x.Restriction != nil { + if x.Restriction.Recipient != nil { + for _, item_2_x_Restriction_Recipient := range x.Restriction.Recipient { + if item_2_x_Restriction_Recipient != nil { + if item_2_x_Restriction_Recipient.Reference != nil { + refVal := *item_2_x_Restriction_Recipient.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "restriction_recipient_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "restriction_recipient_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "recipient_task_restriction") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("restriction", id), + "recipient_task_restriction", + projectJSON, + sourceType, + "restriction", + )) + } + } + } + } + } + } + } + } + if x.Restriction != nil { + if x.Restriction.Recipient != nil { + for _, item_2_x_Restriction_Recipient := range x.Restriction.Recipient { + if item_2_x_Restriction_Recipient != nil { + if item_2_x_Restriction_Recipient.Reference != nil { + refVal := *item_2_x_Restriction_Recipient.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "restriction_recipient_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "restriction_recipient_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "recipient_task_restriction") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("restriction", id), + "recipient_task_restriction", + projectJSON, + sourceType, + "restriction", + )) + } + } + } + } + } + } + } + } + if x.StatusReason != nil { + if x.StatusReason.Reference != nil { + if x.StatusReason.Reference.Reference != nil { + refVal := *x.StatusReason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "statusReason_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.StatusReason != nil { + if x.StatusReason.Reference != nil { + if x.StatusReason.Reference.Reference != nil { + refVal := *x.StatusReason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "statusReason_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.StatusReason != nil { + if x.StatusReason.Reference != nil { + if x.StatusReason.Reference.Reference != nil { + refVal := *x.StatusReason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "statusReason_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.StatusReason != nil { + if x.StatusReason.Reference != nil { + if x.StatusReason.Reference.Reference != nil { + refVal := *x.StatusReason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "statusReason_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.StatusReason != nil { + if x.StatusReason.Reference != nil { + if x.StatusReason.Reference.Reference != nil { + refVal := *x.StatusReason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "statusReason_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.StatusReason != nil { + if x.StatusReason.Reference != nil { + if x.StatusReason.Reference.Reference != nil { + refVal := *x.StatusReason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "statusReason_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.StatusReason != nil { + if x.StatusReason.Reference != nil { + if x.StatusReason.Reference.Reference != nil { + refVal := *x.StatusReason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "statusReason_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.StatusReason != nil { + if x.StatusReason.Reference != nil { + if x.StatusReason.Reference.Reference != nil { + refVal := *x.StatusReason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "statusReason_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.StatusReason != nil { + if x.StatusReason.Reference != nil { + if x.StatusReason.Reference.Reference != nil { + refVal := *x.StatusReason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "statusReason_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.StatusReason != nil { + if x.StatusReason.Reference != nil { + if x.StatusReason.Reference.Reference != nil { + refVal := *x.StatusReason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "statusReason_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.StatusReason != nil { + if x.StatusReason.Reference != nil { + if x.StatusReason.Reference.Reference != nil { + refVal := *x.StatusReason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "statusReason_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.StatusReason != nil { + if x.StatusReason.Reference != nil { + if x.StatusReason.Reference.Reference != nil { + refVal := *x.StatusReason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "statusReason_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.StatusReason != nil { + if x.StatusReason.Reference != nil { + if x.StatusReason.Reference.Reference != nil { + refVal := *x.StatusReason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "statusReason_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.StatusReason != nil { + if x.StatusReason.Reference != nil { + if x.StatusReason.Reference.Reference != nil { + refVal := *x.StatusReason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "statusReason_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.StatusReason != nil { + if x.StatusReason.Reference != nil { + if x.StatusReason.Reference.Reference != nil { + refVal := *x.StatusReason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "statusReason_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.StatusReason != nil { + if x.StatusReason.Reference != nil { + if x.StatusReason.Reference.Reference != nil { + refVal := *x.StatusReason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "statusReason_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.StatusReason != nil { + if x.StatusReason.Reference != nil { + if x.StatusReason.Reference.Reference != nil { + refVal := *x.StatusReason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "statusReason_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.StatusReason != nil { + if x.StatusReason.Reference != nil { + if x.StatusReason.Reference.Reference != nil { + refVal := *x.StatusReason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "statusReason_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.StatusReason != nil { + if x.StatusReason.Reference != nil { + if x.StatusReason.Reference.Reference != nil { + refVal := *x.StatusReason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "statusReason_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.StatusReason != nil { + if x.StatusReason.Reference != nil { + if x.StatusReason.Reference.Reference != nil { + refVal := *x.StatusReason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "statusReason_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.StatusReason != nil { + if x.StatusReason.Reference != nil { + if x.StatusReason.Reference.Reference != nil { + refVal := *x.StatusReason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "statusReason_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.StatusReason != nil { + if x.StatusReason.Reference != nil { + if x.StatusReason.Reference.Reference != nil { + refVal := *x.StatusReason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "statusReason_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.StatusReason != nil { + if x.StatusReason.Reference != nil { + if x.StatusReason.Reference.Reference != nil { + refVal := *x.StatusReason.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "statusReason_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "statusReason_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from TaskInput. +func (x *TaskInput) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "TaskInput" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "valueReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "valueReference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "valueReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "valueReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "valueReference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "valueReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "valueReference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "valueReference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "valueReference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "valueReference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "valueReference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "valueReference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "valueReference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "valueReference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "valueReference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "valueReference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "valueReference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "valueReference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "valueReference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "valueReference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "valueReference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "valueReference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "valueReference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_input") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("input", id), + "task_input", + projectJSON, + sourceType, + "input", + )) + } + } + } + } + } + if x.ValueAnnotation != nil { + if x.ValueAnnotation.AuthorReference != nil { + if x.ValueAnnotation.AuthorReference.Reference != nil { + refVal := *x.ValueAnnotation.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "valueAnnotation_authorReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + if x.ValueAnnotation != nil { + if x.ValueAnnotation.AuthorReference != nil { + if x.ValueAnnotation.AuthorReference.Reference != nil { + refVal := *x.ValueAnnotation.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "valueAnnotation_authorReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + if x.ValueAnnotation != nil { + if x.ValueAnnotation.AuthorReference != nil { + if x.ValueAnnotation.AuthorReference.Reference != nil { + refVal := *x.ValueAnnotation.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "valueAnnotation_authorReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + if x.ValueAnnotation != nil { + if x.ValueAnnotation.AuthorReference != nil { + if x.ValueAnnotation.AuthorReference.Reference != nil { + refVal := *x.ValueAnnotation.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "valueAnnotation_authorReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "valueCodeableReference_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "valueCodeableReference_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "valueCodeableReference_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "valueCodeableReference_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "valueCodeableReference_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "valueCodeableReference_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "valueCodeableReference_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "valueCodeableReference_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "valueCodeableReference_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "valueCodeableReference_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "valueCodeableReference_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "valueCodeableReference_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "valueCodeableReference_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "valueCodeableReference_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "valueCodeableReference_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "valueCodeableReference_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "valueCodeableReference_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "valueCodeableReference_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "valueCodeableReference_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "valueCodeableReference_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "valueCodeableReference_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "valueCodeableReference_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "valueCodeableReference_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueDataRequirement != nil { + if x.ValueDataRequirement.SubjectReference != nil { + if x.ValueDataRequirement.SubjectReference.Reference != nil { + refVal := *x.ValueDataRequirement.SubjectReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "valueDataRequirement_subjectReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("subjectReference", targetID), + "valueDataRequirement_subjectReference", + projectJSON, + sourceType, + "subjectReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "data_requirement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("requirement", id), + "data_requirement", + projectJSON, + sourceType, + "requirement", + )) + } + } + } + } + } + } + if x.ValueExtendedContactDetail != nil { + if x.ValueExtendedContactDetail.Organization != nil { + if x.ValueExtendedContactDetail.Organization.Reference != nil { + refVal := *x.ValueExtendedContactDetail.Organization.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueExtendedContactDetail_organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("organization", targetID), + "valueExtendedContactDetail_organization", + projectJSON, + sourceType, + "organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extended_contact_detail") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("detail", id), + "extended_contact_detail", + projectJSON, + sourceType, + "detail", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "valueRelatedArtifact_resourceReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "valueRelatedArtifact_resourceReference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "valueRelatedArtifact_resourceReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "valueRelatedArtifact_resourceReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "valueRelatedArtifact_resourceReference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "valueRelatedArtifact_resourceReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "valueRelatedArtifact_resourceReference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "valueRelatedArtifact_resourceReference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "valueRelatedArtifact_resourceReference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "valueRelatedArtifact_resourceReference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "valueRelatedArtifact_resourceReference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "valueRelatedArtifact_resourceReference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "valueRelatedArtifact_resourceReference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "valueRelatedArtifact_resourceReference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "valueRelatedArtifact_resourceReference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "valueRelatedArtifact_resourceReference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "valueRelatedArtifact_resourceReference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "valueRelatedArtifact_resourceReference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "valueRelatedArtifact_resourceReference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "valueRelatedArtifact_resourceReference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "valueRelatedArtifact_resourceReference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "valueRelatedArtifact_resourceReference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "valueRelatedArtifact_resourceReference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.OnBehalfOf != nil { + if x.ValueSignature.OnBehalfOf.Reference != nil { + refVal := *x.ValueSignature.OnBehalfOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "valueSignature_onBehalfOf_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "onBehalfOf_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.OnBehalfOf != nil { + if x.ValueSignature.OnBehalfOf.Reference != nil { + refVal := *x.ValueSignature.OnBehalfOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "valueSignature_onBehalfOf_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "onBehalfOf_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.OnBehalfOf != nil { + if x.ValueSignature.OnBehalfOf.Reference != nil { + refVal := *x.ValueSignature.OnBehalfOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "valueSignature_onBehalfOf_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "onBehalfOf_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.OnBehalfOf != nil { + if x.ValueSignature.OnBehalfOf.Reference != nil { + refVal := *x.ValueSignature.OnBehalfOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "valueSignature_onBehalfOf_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "onBehalfOf_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.Who != nil { + if x.ValueSignature.Who.Reference != nil { + refVal := *x.ValueSignature.Who.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "valueSignature_who_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "who_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "who_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.Who != nil { + if x.ValueSignature.Who.Reference != nil { + refVal := *x.ValueSignature.Who.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "valueSignature_who_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "who_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "who_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.Who != nil { + if x.ValueSignature.Who.Reference != nil { + refVal := *x.ValueSignature.Who.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "valueSignature_who_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "who_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "who_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.Who != nil { + if x.ValueSignature.Who.Reference != nil { + refVal := *x.ValueSignature.Who.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "valueSignature_who_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "who_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "who_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueUsageContext != nil { + if x.ValueUsageContext.ValueReference != nil { + if x.ValueUsageContext.ValueReference.Reference != nil { + refVal := *x.ValueUsageContext.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueUsageContext_valueReference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "valueUsageContext_valueReference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "usage_context") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("context", id), + "usage_context", + projectJSON, + sourceType, + "context", + )) + } + } + } + } + } + } + if x.ValueUsageContext != nil { + if x.ValueUsageContext.ValueReference != nil { + if x.ValueUsageContext.ValueReference.Reference != nil { + refVal := *x.ValueUsageContext.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "valueUsageContext_valueReference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "valueUsageContext_valueReference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "usage_context") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("context", id), + "usage_context", + projectJSON, + sourceType, + "context", + )) + } + } + } + } + } + } + if x.ValueUsageContext != nil { + if x.ValueUsageContext.ValueReference != nil { + if x.ValueUsageContext.ValueReference.Reference != nil { + refVal := *x.ValueUsageContext.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueUsageContext_valueReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "valueUsageContext_valueReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "usage_context") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("context", id), + "usage_context", + projectJSON, + sourceType, + "context", + )) + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from TaskOutput. +func (x *TaskOutput) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "TaskOutput" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "valueReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "valueReference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "valueReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "valueReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "valueReference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "valueReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "valueReference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "valueReference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "valueReference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "valueReference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "valueReference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "valueReference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "valueReference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "valueReference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "valueReference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "valueReference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "valueReference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "valueReference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "valueReference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "valueReference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "valueReference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "valueReference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "valueReference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_output") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("output", id), + "task_output", + projectJSON, + sourceType, + "output", + )) + } + } + } + } + } + if x.ValueAnnotation != nil { + if x.ValueAnnotation.AuthorReference != nil { + if x.ValueAnnotation.AuthorReference.Reference != nil { + refVal := *x.ValueAnnotation.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "valueAnnotation_authorReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + if x.ValueAnnotation != nil { + if x.ValueAnnotation.AuthorReference != nil { + if x.ValueAnnotation.AuthorReference.Reference != nil { + refVal := *x.ValueAnnotation.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "valueAnnotation_authorReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + if x.ValueAnnotation != nil { + if x.ValueAnnotation.AuthorReference != nil { + if x.ValueAnnotation.AuthorReference.Reference != nil { + refVal := *x.ValueAnnotation.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "valueAnnotation_authorReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + if x.ValueAnnotation != nil { + if x.ValueAnnotation.AuthorReference != nil { + if x.ValueAnnotation.AuthorReference.Reference != nil { + refVal := *x.ValueAnnotation.AuthorReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueAnnotation_authorReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "valueAnnotation_authorReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "annotation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("annotation", id), + "annotation", + projectJSON, + sourceType, + "annotation", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "valueCodeableReference_reference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "valueCodeableReference_reference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "valueCodeableReference_reference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "valueCodeableReference_reference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "valueCodeableReference_reference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "valueCodeableReference_reference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "valueCodeableReference_reference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "valueCodeableReference_reference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "valueCodeableReference_reference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "valueCodeableReference_reference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "valueCodeableReference_reference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "valueCodeableReference_reference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "valueCodeableReference_reference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "valueCodeableReference_reference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "valueCodeableReference_reference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "valueCodeableReference_reference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "valueCodeableReference_reference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "valueCodeableReference_reference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "valueCodeableReference_reference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "valueCodeableReference_reference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "valueCodeableReference_reference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "valueCodeableReference_reference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueCodeableReference != nil { + if x.ValueCodeableReference.Reference != nil { + if x.ValueCodeableReference.Reference.Reference != nil { + refVal := *x.ValueCodeableReference.Reference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "valueCodeableReference_reference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "valueCodeableReference_reference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "codeable_reference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("reference", id), + "codeable_reference", + projectJSON, + sourceType, + "reference", + )) + } + } + } + } + } + } + if x.ValueDataRequirement != nil { + if x.ValueDataRequirement.SubjectReference != nil { + if x.ValueDataRequirement.SubjectReference.Reference != nil { + refVal := *x.ValueDataRequirement.SubjectReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "valueDataRequirement_subjectReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("subjectReference", targetID), + "valueDataRequirement_subjectReference", + projectJSON, + sourceType, + "subjectReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "data_requirement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("requirement", id), + "data_requirement", + projectJSON, + sourceType, + "requirement", + )) + } + } + } + } + } + } + if x.ValueExtendedContactDetail != nil { + if x.ValueExtendedContactDetail.Organization != nil { + if x.ValueExtendedContactDetail.Organization.Reference != nil { + refVal := *x.ValueExtendedContactDetail.Organization.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueExtendedContactDetail_organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("organization", targetID), + "valueExtendedContactDetail_organization", + projectJSON, + sourceType, + "organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "extended_contact_detail") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("detail", id), + "extended_contact_detail", + projectJSON, + sourceType, + "detail", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "valueRelatedArtifact_resourceReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "valueRelatedArtifact_resourceReference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "valueRelatedArtifact_resourceReference_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "valueRelatedArtifact_resourceReference_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "valueRelatedArtifact_resourceReference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "valueRelatedArtifact_resourceReference_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchSubject" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_ResearchSubject") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchSubject", targetID), + "valueRelatedArtifact_resourceReference_ResearchSubject", + projectJSON, + sourceType, + "ResearchSubject", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Substance" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Substance") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Substance", targetID), + "valueRelatedArtifact_resourceReference_Substance", + projectJSON, + sourceType, + "Substance", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "SubstanceDefinition" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_SubstanceDefinition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("SubstanceDefinition", targetID), + "valueRelatedArtifact_resourceReference_SubstanceDefinition", + projectJSON, + sourceType, + "SubstanceDefinition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Specimen" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Specimen") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Specimen", targetID), + "valueRelatedArtifact_resourceReference_Specimen", + projectJSON, + sourceType, + "Specimen", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Observation" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Observation") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Observation", targetID), + "valueRelatedArtifact_resourceReference_Observation", + projectJSON, + sourceType, + "Observation", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DiagnosticReport" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_DiagnosticReport") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DiagnosticReport", targetID), + "valueRelatedArtifact_resourceReference_DiagnosticReport", + projectJSON, + sourceType, + "DiagnosticReport", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Condition" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Condition") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Condition", targetID), + "valueRelatedArtifact_resourceReference_Condition", + projectJSON, + sourceType, + "Condition", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Medication" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Medication") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Medication", targetID), + "valueRelatedArtifact_resourceReference_Medication", + projectJSON, + sourceType, + "Medication", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationAdministration" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_MedicationAdministration") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationAdministration", targetID), + "valueRelatedArtifact_resourceReference_MedicationAdministration", + projectJSON, + sourceType, + "MedicationAdministration", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationStatement" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_MedicationStatement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationStatement", targetID), + "valueRelatedArtifact_resourceReference_MedicationStatement", + projectJSON, + sourceType, + "MedicationStatement", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "MedicationRequest" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_MedicationRequest") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("MedicationRequest", targetID), + "valueRelatedArtifact_resourceReference_MedicationRequest", + projectJSON, + sourceType, + "MedicationRequest", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Procedure" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Procedure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Procedure", targetID), + "valueRelatedArtifact_resourceReference_Procedure", + projectJSON, + sourceType, + "Procedure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "DocumentReference" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_DocumentReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("DocumentReference", targetID), + "valueRelatedArtifact_resourceReference_DocumentReference", + projectJSON, + sourceType, + "DocumentReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Task" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_Task") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Task", targetID), + "valueRelatedArtifact_resourceReference_Task", + projectJSON, + sourceType, + "Task", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ImagingStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_ImagingStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ImagingStudy", targetID), + "valueRelatedArtifact_resourceReference_ImagingStudy", + projectJSON, + sourceType, + "ImagingStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "FamilyMemberHistory" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_FamilyMemberHistory") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("FamilyMemberHistory", targetID), + "valueRelatedArtifact_resourceReference_FamilyMemberHistory", + projectJSON, + sourceType, + "FamilyMemberHistory", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueRelatedArtifact != nil { + if x.ValueRelatedArtifact.ResourceReference != nil { + if x.ValueRelatedArtifact.ResourceReference.Reference != nil { + refVal := *x.ValueRelatedArtifact.ResourceReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "BodyStructure" { + forwardKey := getEdgeUUID(targetID, id, "valueRelatedArtifact_resourceReference_BodyStructure") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("BodyStructure", targetID), + "valueRelatedArtifact_resourceReference_BodyStructure", + projectJSON, + sourceType, + "BodyStructure", + )) + } + backrefKey := getEdgeUUID(id, targetID, "related_artifact") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("artifact", id), + "related_artifact", + projectJSON, + sourceType, + "artifact", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.OnBehalfOf != nil { + if x.ValueSignature.OnBehalfOf.Reference != nil { + refVal := *x.ValueSignature.OnBehalfOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "valueSignature_onBehalfOf_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "onBehalfOf_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.OnBehalfOf != nil { + if x.ValueSignature.OnBehalfOf.Reference != nil { + refVal := *x.ValueSignature.OnBehalfOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "valueSignature_onBehalfOf_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "onBehalfOf_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.OnBehalfOf != nil { + if x.ValueSignature.OnBehalfOf.Reference != nil { + refVal := *x.ValueSignature.OnBehalfOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "valueSignature_onBehalfOf_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "onBehalfOf_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.OnBehalfOf != nil { + if x.ValueSignature.OnBehalfOf.Reference != nil { + refVal := *x.ValueSignature.OnBehalfOf.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_onBehalfOf_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "valueSignature_onBehalfOf_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "onBehalfOf_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "onBehalfOf_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.Who != nil { + if x.ValueSignature.Who.Reference != nil { + refVal := *x.ValueSignature.Who.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "valueSignature_who_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "who_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "who_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.Who != nil { + if x.ValueSignature.Who.Reference != nil { + refVal := *x.ValueSignature.Who.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "valueSignature_who_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "who_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "who_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.Who != nil { + if x.ValueSignature.Who.Reference != nil { + refVal := *x.ValueSignature.Who.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "valueSignature_who_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "who_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "who_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueSignature != nil { + if x.ValueSignature.Who != nil { + if x.ValueSignature.Who.Reference != nil { + refVal := *x.ValueSignature.Who.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueSignature_who_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "valueSignature_who_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "who_signature") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("signature", id), + "who_signature", + projectJSON, + sourceType, + "signature", + )) + } + } + } + } + } + } + if x.ValueUsageContext != nil { + if x.ValueUsageContext.ValueReference != nil { + if x.ValueUsageContext.ValueReference.Reference != nil { + refVal := *x.ValueUsageContext.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueUsageContext_valueReference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "valueUsageContext_valueReference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "usage_context") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("context", id), + "usage_context", + projectJSON, + sourceType, + "context", + )) + } + } + } + } + } + } + if x.ValueUsageContext != nil { + if x.ValueUsageContext.ValueReference != nil { + if x.ValueUsageContext.ValueReference.Reference != nil { + refVal := *x.ValueUsageContext.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "valueUsageContext_valueReference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "valueUsageContext_valueReference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "usage_context") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("context", id), + "usage_context", + projectJSON, + sourceType, + "context", + )) + } + } + } + } + } + } + if x.ValueUsageContext != nil { + if x.ValueUsageContext.ValueReference != nil { + if x.ValueUsageContext.ValueReference.Reference != nil { + refVal := *x.ValueUsageContext.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueUsageContext_valueReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "valueUsageContext_valueReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "usage_context") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("context", id), + "usage_context", + projectJSON, + sourceType, + "context", + )) + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from TaskPerformer. +func (x *TaskPerformer) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "TaskPerformer" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Actor != nil { + if x.Actor.Reference != nil { + refVal := *x.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "actor_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "actor_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "task_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + refVal := *x.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "actor_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "actor_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "task_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + refVal := *x.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "actor_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "actor_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "task_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + if x.Actor != nil { + if x.Actor.Reference != nil { + refVal := *x.Actor.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "actor_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "actor_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "task_performer") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("performer", id), + "task_performer", + projectJSON, + sourceType, + "performer", + )) + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from TaskRestriction. +func (x *TaskRestriction) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "TaskRestriction" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Recipient != nil { + for _, item_2_x_Recipient := range x.Recipient { + if item_2_x_Recipient != nil { + if item_2_x_Recipient.Reference != nil { + refVal := *item_2_x_Recipient.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Patient" { + forwardKey := getEdgeUUID(targetID, id, "recipient_Patient") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Patient", targetID), + "recipient_Patient", + projectJSON, + sourceType, + "Patient", + )) + } + backrefKey := getEdgeUUID(id, targetID, "recipient_task_restriction") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("restriction", id), + "recipient_task_restriction", + projectJSON, + sourceType, + "restriction", + )) + } + } + } + } + } + } + } + if x.Recipient != nil { + for _, item_2_x_Recipient := range x.Recipient { + if item_2_x_Recipient != nil { + if item_2_x_Recipient.Reference != nil { + refVal := *item_2_x_Recipient.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Practitioner" { + forwardKey := getEdgeUUID(targetID, id, "recipient_Practitioner") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Practitioner", targetID), + "recipient_Practitioner", + projectJSON, + sourceType, + "Practitioner", + )) + } + backrefKey := getEdgeUUID(id, targetID, "recipient_task_restriction") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("restriction", id), + "recipient_task_restriction", + projectJSON, + sourceType, + "restriction", + )) + } + } + } + } + } + } + } + if x.Recipient != nil { + for _, item_2_x_Recipient := range x.Recipient { + if item_2_x_Recipient != nil { + if item_2_x_Recipient.Reference != nil { + refVal := *item_2_x_Recipient.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "PractitionerRole" { + forwardKey := getEdgeUUID(targetID, id, "recipient_PractitionerRole") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("PractitionerRole", targetID), + "recipient_PractitionerRole", + projectJSON, + sourceType, + "PractitionerRole", + )) + } + backrefKey := getEdgeUUID(id, targetID, "recipient_task_restriction") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("restriction", id), + "recipient_task_restriction", + projectJSON, + sourceType, + "restriction", + )) + } + } + } + } + } + } + } + if x.Recipient != nil { + for _, item_2_x_Recipient := range x.Recipient { + if item_2_x_Recipient != nil { + if item_2_x_Recipient.Reference != nil { + refVal := *item_2_x_Recipient.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "recipient_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "recipient_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "recipient_task_restriction") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("restriction", id), + "recipient_task_restriction", + projectJSON, + sourceType, + "restriction", + )) + } + } + } + } + } + } + } + if x.Recipient != nil { + for _, item_2_x_Recipient := range x.Recipient { + if item_2_x_Recipient != nil { + if item_2_x_Recipient.Reference != nil { + refVal := *item_2_x_Recipient.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "recipient_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "recipient_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "recipient_task_restriction") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("restriction", id), + "recipient_task_restriction", + projectJSON, + sourceType, + "restriction", + )) + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from Timing. +func (x *Timing) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "Timing" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from TimingRepeat. +func (x *TimingRepeat) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "TimingRepeat" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + return edges, nil +} + +// ExtractEdges extracts graph links from TriggerDefinition. +func (x *TriggerDefinition) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "TriggerDefinition" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.Data != nil { + for _, item_3_x_Data := range x.Data { + if item_3_x_Data != nil { + if item_3_x_Data.SubjectReference != nil { + if item_3_x_Data.SubjectReference.Reference != nil { + refVal := *item_3_x_Data.SubjectReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "data_subjectReference") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("subjectReference", targetID), + "data_subjectReference", + projectJSON, + sourceType, + "subjectReference", + )) + } + backrefKey := getEdgeUUID(id, targetID, "data_requirement") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("requirement", id), + "data_requirement", + projectJSON, + sourceType, + "requirement", + )) + } + } + } + } + } + } + } + } + return edges, nil +} + +// ExtractEdges extracts graph links from UsageContext. +func (x *UsageContext) ExtractEdges(project string) ([]json.RawMessage, error) { + var edges []json.RawMessage + if x == nil || x.ID == nil { + return edges, nil + } + id := *x.ID + sourceType := "UsageContext" + projectJSON := strconv.Quote(project) + _ = id + _ = sourceType + _ = projectJSON + var seen map[string]struct{} + _ = seen + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "ResearchStudy" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_ResearchStudy") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("ResearchStudy", targetID), + "valueReference_ResearchStudy", + projectJSON, + sourceType, + "ResearchStudy", + )) + } + backrefKey := getEdgeUUID(id, targetID, "usage_context") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("context", id), + "usage_context", + projectJSON, + sourceType, + "context", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Group" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Group") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Group", targetID), + "valueReference_Group", + projectJSON, + sourceType, + "Group", + )) + } + backrefKey := getEdgeUUID(id, targetID, "usage_context") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("context", id), + "usage_context", + projectJSON, + sourceType, + "context", + )) + } + } + } + } + } + if x.ValueReference != nil { + if x.ValueReference.Reference != nil { + refVal := *x.ValueReference.Reference + refType, targetID, ok := splitFHIRReference(refVal) + if ok { + if refType == "Organization" { + forwardKey := getEdgeUUID(targetID, id, "valueReference_Organization") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[forwardKey]; !exists { + seen[forwardKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + forwardKey, + collectionID(sourceType, id), + collectionID("Organization", targetID), + "valueReference_Organization", + projectJSON, + sourceType, + "Organization", + )) + } + backrefKey := getEdgeUUID(id, targetID, "usage_context") + if seen == nil { + seen = make(map[string]struct{}, 4) + } + if _, exists := seen[backrefKey]; !exists { + seen[backrefKey] = struct{}{} + edges = append(edges, buildEdgeRawJSON( + backrefKey, + collectionID(sourceType, targetID), + collectionID("context", id), + "usage_context", + projectJSON, + sourceType, + "context", + )) + } + } + } + } + } + return edges, nil +} + +// ValidateAndExtract parses, validates, and extracts edges for a FHIR resource. +func ValidateAndExtract(raw []byte, resourceType string, project string) (Result, error) { + switch resourceType { + case "Address": + var val Address + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Age": + var val Age + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Annotation": + var val Annotation + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Attachment": + var val Attachment + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Availability": + var val Availability + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "AvailabilityAvailableTime": + var val AvailabilityAvailableTime + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "AvailabilityNotAvailableTime": + var val AvailabilityNotAvailableTime + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "BodyStructure": + var val BodyStructure + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "BodyStructureIncludedStructure": + var val BodyStructureIncludedStructure + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "BodyStructureIncludedStructureBodyLandmarkOrientation": + var val BodyStructureIncludedStructureBodyLandmarkOrientation + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": + var val BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "CodeableConcept": + var val CodeableConcept + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "CodeableReference": + var val CodeableReference + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Coding": + var val Coding + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Condition": + var val Condition + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ConditionParticipant": + var val ConditionParticipant + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ConditionStage": + var val ConditionStage + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ContactDetail": + var val ContactDetail + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ContactPoint": + var val ContactPoint + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Count": + var val Count + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "DataRequirement": + var val DataRequirement + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "DataRequirementCodeFilter": + var val DataRequirementCodeFilter + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "DataRequirementDateFilter": + var val DataRequirementDateFilter + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "DataRequirementSort": + var val DataRequirementSort + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "DataRequirementValueFilter": + var val DataRequirementValueFilter + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "DiagnosticReport": + var val DiagnosticReport + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "DiagnosticReportMedia": + var val DiagnosticReportMedia + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "DiagnosticReportSupportingInfo": + var val DiagnosticReportSupportingInfo + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Directory": + var val Directory + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Distance": + var val Distance + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "DocumentReference": + var val DocumentReference + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "DocumentReferenceAttester": + var val DocumentReferenceAttester + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "DocumentReferenceContent": + var val DocumentReferenceContent + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "DocumentReferenceContentProfile": + var val DocumentReferenceContentProfile + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "DocumentReferenceRelatesTo": + var val DocumentReferenceRelatesTo + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Dosage": + var val Dosage + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "DosageDoseAndRate": + var val DosageDoseAndRate + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Duration": + var val Duration + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Expression": + var val Expression + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ExtendedContactDetail": + var val ExtendedContactDetail + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Extension": + var val Extension + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "FHIRPrimitiveExtension": + var val FHIRPrimitiveExtension + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "FamilyMemberHistory": + var val FamilyMemberHistory + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "FamilyMemberHistoryCondition": + var val FamilyMemberHistoryCondition + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "FamilyMemberHistoryParticipant": + var val FamilyMemberHistoryParticipant + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "FamilyMemberHistoryProcedure": + var val FamilyMemberHistoryProcedure + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Group": + var val Group + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "GroupCharacteristic": + var val GroupCharacteristic + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "GroupMember": + var val GroupMember + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "HumanName": + var val HumanName + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Identifier": + var val Identifier + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ImagingStudy": + var val ImagingStudy + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ImagingStudySeries": + var val ImagingStudySeries + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ImagingStudySeriesInstance": + var val ImagingStudySeriesInstance + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ImagingStudySeriesPerformer": + var val ImagingStudySeriesPerformer + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Medication": + var val Medication + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "MedicationAdministration": + var val MedicationAdministration + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "MedicationAdministrationDosage": + var val MedicationAdministrationDosage + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "MedicationAdministrationPerformer": + var val MedicationAdministrationPerformer + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "MedicationBatch": + var val MedicationBatch + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "MedicationIngredient": + var val MedicationIngredient + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "MedicationRequest": + var val MedicationRequest + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "MedicationRequestDispenseRequest": + var val MedicationRequestDispenseRequest + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "MedicationRequestDispenseRequestInitialFill": + var val MedicationRequestDispenseRequestInitialFill + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "MedicationRequestSubstitution": + var val MedicationRequestSubstitution + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "MedicationStatement": + var val MedicationStatement + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "MedicationStatementAdherence": + var val MedicationStatementAdherence + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Meta": + var val Meta + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Money": + var val Money + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Narrative": + var val Narrative + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Observation": + var val Observation + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ObservationComponent": + var val ObservationComponent + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ObservationReferenceRange": + var val ObservationReferenceRange + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ObservationTriggeredBy": + var val ObservationTriggeredBy + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Organization": + var val Organization + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "OrganizationQualification": + var val OrganizationQualification + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ParameterDefinition": + var val ParameterDefinition + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Patient": + var val Patient + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "PatientCommunication": + var val PatientCommunication + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "PatientContact": + var val PatientContact + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "PatientLink": + var val PatientLink + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Period": + var val Period + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Practitioner": + var val Practitioner + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "PractitionerCommunication": + var val PractitionerCommunication + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "PractitionerQualification": + var val PractitionerQualification + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "PractitionerRole": + var val PractitionerRole + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Procedure": + var val Procedure + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ProcedureFocalDevice": + var val ProcedureFocalDevice + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ProcedurePerformer": + var val ProcedurePerformer + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Quantity": + var val Quantity + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Range": + var val Range + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Ratio": + var val Ratio + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "RatioRange": + var val RatioRange + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Reference": + var val Reference + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "RelatedArtifact": + var val RelatedArtifact + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ResearchStudy": + var val ResearchStudy + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ResearchStudyAssociatedParty": + var val ResearchStudyAssociatedParty + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ResearchStudyComparisonGroup": + var val ResearchStudyComparisonGroup + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ResearchStudyLabel": + var val ResearchStudyLabel + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ResearchStudyObjective": + var val ResearchStudyObjective + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ResearchStudyOutcomeMeasure": + var val ResearchStudyOutcomeMeasure + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ResearchStudyProgressStatus": + var val ResearchStudyProgressStatus + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ResearchStudyRecruitment": + var val ResearchStudyRecruitment + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ResearchSubject": + var val ResearchSubject + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "ResearchSubjectProgress": + var val ResearchSubjectProgress + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Resource": + var val Resource + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "SampledData": + var val SampledData + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Signature": + var val Signature + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Specimen": + var val Specimen + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "SpecimenCollection": + var val SpecimenCollection + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "SpecimenContainer": + var val SpecimenContainer + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "SpecimenFeature": + var val SpecimenFeature + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "SpecimenProcessing": + var val SpecimenProcessing + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Substance": + var val Substance + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "SubstanceDefinition": + var val SubstanceDefinition + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "SubstanceDefinitionCharacterization": + var val SubstanceDefinitionCharacterization + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "SubstanceDefinitionCode": + var val SubstanceDefinitionCode + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "SubstanceDefinitionMoiety": + var val SubstanceDefinitionMoiety + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "SubstanceDefinitionMolecularWeight": + var val SubstanceDefinitionMolecularWeight + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "SubstanceDefinitionName": + var val SubstanceDefinitionName + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "SubstanceDefinitionNameOfficial": + var val SubstanceDefinitionNameOfficial + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "SubstanceDefinitionProperty": + var val SubstanceDefinitionProperty + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "SubstanceDefinitionRelationship": + var val SubstanceDefinitionRelationship + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "SubstanceDefinitionSourceMaterial": + var val SubstanceDefinitionSourceMaterial + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "SubstanceDefinitionStructure": + var val SubstanceDefinitionStructure + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "SubstanceDefinitionStructureRepresentation": + var val SubstanceDefinitionStructureRepresentation + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "SubstanceIngredient": + var val SubstanceIngredient + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Task": + var val Task + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "TaskInput": + var val TaskInput + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "TaskOutput": + var val TaskOutput + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "TaskPerformer": + var val TaskPerformer + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "TaskRestriction": + var val TaskRestriction + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "Timing": + var val Timing + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "TimingRepeat": + var val TimingRepeat + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "TriggerDefinition": + var val TriggerDefinition + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + case "UsageContext": + var val UsageContext + if err := sonic.Unmarshal(raw, &val); err != nil { + return Result{}, fmt.Errorf("decode error: %w", err) + } + if err := val.Validate(); err != nil { + return Result{}, fmt.Errorf("validation error: %w", err) + } + edges, err := val.ExtractEdges(project) + if err != nil { + return Result{}, fmt.Errorf("extraction error: %w", err) + } + var objectID string + if val.ID != nil { + objectID = *val.ID + } + return Result{ + ObjectID: objectID, + ResourceType: resourceType, + Vertex: json.RawMessage(raw), + Edges: edges, + }, nil + default: + return Result{}, fmt.Errorf("unsupported resource type %s", resourceType) + } +} diff --git a/fhirstructs/helpers.go b/fhirstructs/helpers.go new file mode 100644 index 0000000..a603a38 --- /dev/null +++ b/fhirstructs/helpers.go @@ -0,0 +1,143 @@ +// Package fhirstructs contains generated FHIR structs, validation, and graph +// edge extraction. It is generated from schemas/graph-fhir.json; do not +// hand-edit generated files in this package. +package fhirstructs + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "net/url" + "strings" + "time" + + "github.com/google/uuid" +) + +// FHIRComments handles comments that can be a single JSON string or a JSON array of strings. +type FHIRComments []string + +// UnmarshalJSON unmarshals FHIR comments from a string or array of strings. +func (c *FHIRComments) UnmarshalJSON(data []byte) error { + if len(data) == 0 { + return nil + } + if data[0] == '"' { + var s string + if err := json.Unmarshal(data, &s); err != nil { + return err + } + *c = []string{s} + return nil + } + var arr []string + if err := json.Unmarshal(data, &arr); err != nil { + return err + } + *c = arr + return nil +} + +// MarshalJSON marshals FHIR comments to a single string (if length is 1) or an array of strings. +func (c FHIRComments) MarshalJSON() ([]byte, error) { + if len(c) == 1 { + return json.Marshal(c[0]) + } + return json.Marshal([]string(c)) +} + +// ValidateFhirDateTime checks a string against FHIR date-time rules (YYYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm] or partial date). +func ValidateFhirDateTime(s string) error { + if !strings.Contains(s, "T") { + return validatePartialFhirDate(s, "FHIR date-time") + } + if _, err := time.Parse(time.RFC3339Nano, s); err != nil { + return fmt.Errorf("value '%s' is not a valid FHIR date-time: %w", s, err) + } + return nil +} + +func validatePartialFhirDate(s, typeName string) error { + switch len(s) { + case 4: // YYYY + if _, err := time.Parse("2006", s); err != nil { + return fmt.Errorf("value '%s' is not a valid partial %s (YYYY): %w", s, typeName, err) + } + case 7: // YYYY-MM + if _, err := time.Parse("2006-01", s); err != nil { + return fmt.Errorf("value '%s' is not a valid partial %s (YYYY-MM): %w", s, typeName, err) + } + case 10: // YYYY-MM-DD + if _, err := time.Parse("2006-01-02", s); err != nil { + return fmt.Errorf("value '%s' is not a valid partial %s (YYYY-MM-DD): %w", s, typeName, err) + } + default: + return fmt.Errorf("value '%s' has invalid length for a partial %s", s, typeName) + } + return nil +} + +// ValidateFhirDate checks a string against FHIR date rules (YYYY[-MM[-DD]]). +func ValidateFhirDate(s string) error { + return validatePartialFhirDate(s, "FHIR date") +} + +// ValidateFhirTime checks a string against FHIR time rules (HH:MM:SS[.SSSS]). +func ValidateFhirTime(s string) error { + if len(s) < 8 { + return fmt.Errorf("value '%s' is too short for a FHIR time (minimum 8 characters)", s) + } + + timePart := s + if s[8] == '.' { + timePart = s[:8] + if len(s) == 9 { + return fmt.Errorf("value '%s' is not a valid FHIR time: missing fractional second digits after '.'", s) + } + for i := 9; i < len(s); i++ { + if s[i] < '0' || s[i] > '9' { + return fmt.Errorf("value '%s' is not a valid FHIR time: non-digit characters in fractional seconds", s) + } + } + } else if len(s) != 8 { + return fmt.Errorf("value '%s' has invalid length for FHIR time (expected 8 or 9+ with fractional seconds)", s) + } + + if timePart[2] != ':' || timePart[5] != ':' { + return fmt.Errorf("value '%s' is not a valid FHIR time: missing or misplaced colons", s) + } + + if _, err := time.Parse("15:04:05", timePart); err != nil { + return fmt.Errorf("value '%s' is not a valid FHIR time: invalid time components (%w)", s, err) + } + + return nil +} + +// ValidateFhirURI checks a string against FHIR URI rules (must be an absolute URI). +func ValidateFhirURI(s string) error { + u, err := url.ParseRequestURI(s) + if err != nil { + return fmt.Errorf("value '%s' is not a valid URI: %w", s, err) + } + if !u.IsAbs() { + return fmt.Errorf("value '%s' is not an absolute URI (must include a scheme like 'http://' or 'urn:')", s) + } + return nil +} + +// ValidateFhirUUID checks a string against FHIR UUID rules (RFC 4122). +func ValidateFhirUUID(s string) error { + if _, err := uuid.Parse(s); err != nil { + return fmt.Errorf("value '%s' is not a valid UUID (RFC 4122): %w", s, err) + } + return nil +} + +// ValidateFhirBinary checks that a string is a valid base64-encoded value. +func ValidateFhirBinary(s string) error { + if _, err := base64.StdEncoding.DecodeString(s); err != nil { + return fmt.Errorf("value is not a valid Base64 encoded string: %w", err) + } + return nil +} diff --git a/fhirstructs/model.go b/fhirstructs/model.go new file mode 100644 index 0000000..51d25ad --- /dev/null +++ b/fhirstructs/model.go @@ -0,0 +1,3044 @@ +// Code generated by cmd/generate/main.go. DO NOT EDIT. +package fhirstructs + +// Address +type Address struct { + XCity *FHIRPrimitiveExtension `json:"_city,omitempty"` + XCountry *FHIRPrimitiveExtension `json:"_country,omitempty"` + XDistrict *FHIRPrimitiveExtension `json:"_district,omitempty"` + XLine []*FHIRPrimitiveExtension `json:"_line,omitempty"` + XPostalCode *FHIRPrimitiveExtension `json:"_postalCode,omitempty"` + XState *FHIRPrimitiveExtension `json:"_state,omitempty"` + XText *FHIRPrimitiveExtension `json:"_text,omitempty"` + XType *FHIRPrimitiveExtension `json:"_type,omitempty"` + XUse *FHIRPrimitiveExtension `json:"_use,omitempty"` + City *string `json:"city,omitempty"` + Country *string `json:"country,omitempty"` + District *string `json:"district,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Line []string `json:"line,omitempty"` + Links [][]any `json:"links,omitempty"` + Period *Period `json:"period,omitempty"` + PostalCode *string `json:"postalCode,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + State *string `json:"state,omitempty"` + Text *string `json:"text,omitempty"` + Type *string `json:"type,omitempty"` + Use *string `json:"use,omitempty"` +} + +// Age +type Age struct { + XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` + XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` + XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` + XUnit *FHIRPrimitiveExtension `json:"_unit,omitempty"` + XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` + Code *string `json:"code,omitempty"` + Comparator *string `json:"comparator,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + System *string `json:"system,omitempty"` + Unit *string `json:"unit,omitempty"` + Value *float64 `json:"value,omitempty"` +} + +// Annotation +type Annotation struct { + XAuthorString *FHIRPrimitiveExtension `json:"_authorString,omitempty"` + XText *FHIRPrimitiveExtension `json:"_text,omitempty"` + XTime *FHIRPrimitiveExtension `json:"_time,omitempty"` + AuthorReference *Reference `json:"authorReference,omitempty"` + AuthorString *string `json:"authorString,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Text *string `json:"text,omitempty"` + Time *string `json:"time,omitempty"` +} + +// Attachment +type Attachment struct { + XContentType *FHIRPrimitiveExtension `json:"_contentType,omitempty"` + XCreation *FHIRPrimitiveExtension `json:"_creation,omitempty"` + XData *FHIRPrimitiveExtension `json:"_data,omitempty"` + XDuration *FHIRPrimitiveExtension `json:"_duration,omitempty"` + XFrames *FHIRPrimitiveExtension `json:"_frames,omitempty"` + XHash *FHIRPrimitiveExtension `json:"_hash,omitempty"` + XHeight *FHIRPrimitiveExtension `json:"_height,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XPages *FHIRPrimitiveExtension `json:"_pages,omitempty"` + XSize *FHIRPrimitiveExtension `json:"_size,omitempty"` + XTitle *FHIRPrimitiveExtension `json:"_title,omitempty"` + XURL *FHIRPrimitiveExtension `json:"_url,omitempty"` + XWidth *FHIRPrimitiveExtension `json:"_width,omitempty"` + ContentType *string `json:"contentType,omitempty"` + Creation *string `json:"creation,omitempty"` + Data *string `json:"data,omitempty"` + Duration *float64 `json:"duration,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Frames *int64 `json:"frames,omitempty"` + Hash *string `json:"hash,omitempty"` + Height *int64 `json:"height,omitempty"` + ID *string `json:"id,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Pages *int64 `json:"pages,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Size *int64 `json:"size,omitempty"` + Title *string `json:"title,omitempty"` + URL *string `json:"url,omitempty"` + Width *int64 `json:"width,omitempty"` +} + +// Availability +type Availability struct { + AvailableTime []*AvailabilityAvailableTime `json:"availableTime,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + NotAvailableTime []*AvailabilityNotAvailableTime `json:"notAvailableTime,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// AvailabilityAvailableTime +type AvailabilityAvailableTime struct { + XAllDay *FHIRPrimitiveExtension `json:"_allDay,omitempty"` + XAvailableEndTime *FHIRPrimitiveExtension `json:"_availableEndTime,omitempty"` + XAvailableStartTime *FHIRPrimitiveExtension `json:"_availableStartTime,omitempty"` + XDaysOfWeek []*FHIRPrimitiveExtension `json:"_daysOfWeek,omitempty"` + AllDay *bool `json:"allDay,omitempty"` + AvailableEndTime *string `json:"availableEndTime,omitempty"` + AvailableStartTime *string `json:"availableStartTime,omitempty"` + DaysOfWeek []string `json:"daysOfWeek,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// AvailabilityNotAvailableTime +type AvailabilityNotAvailableTime struct { + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + Description *string `json:"description,omitempty"` + During *Period `json:"during,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// BodyStructure +type BodyStructure struct { + XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + Active *bool `json:"active,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Description *string `json:"description,omitempty"` + ExcludedStructure []*BodyStructureIncludedStructure `json:"excludedStructure,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + Image []*Attachment `json:"image,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + IncludedStructure []*BodyStructureIncludedStructure `json:"includedStructure"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Morphology *CodeableConcept `json:"morphology,omitempty"` + Patient *Reference `json:"patient"` + ResourceType *string `json:"resourceType,omitempty"` + Text *Narrative `json:"text,omitempty"` +} + +// BodyStructureIncludedStructure +type BodyStructureIncludedStructure struct { + BodyLandmarkOrientation []*BodyStructureIncludedStructureBodyLandmarkOrientation `json:"bodyLandmarkOrientation,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Laterality *CodeableConcept `json:"laterality,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Qualifier []*CodeableConcept `json:"qualifier,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SpatialReference []*Reference `json:"spatialReference,omitempty"` + Structure *CodeableConcept `json:"structure"` +} + +// BodyStructureIncludedStructureBodyLandmarkOrientation +type BodyStructureIncludedStructureBodyLandmarkOrientation struct { + ClockFacePosition []*CodeableConcept `json:"clockFacePosition,omitempty"` + DistanceFromLandmark []*BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark `json:"distanceFromLandmark,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + LandmarkDescription []*CodeableConcept `json:"landmarkDescription,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SurfaceOrientation []*CodeableConcept `json:"surfaceOrientation,omitempty"` +} + +// BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark +type BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark struct { + Device []*CodeableReference `json:"device,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Value []*Quantity `json:"value,omitempty"` +} + +// CodeableConcept +type CodeableConcept struct { + XText *FHIRPrimitiveExtension `json:"_text,omitempty"` + Coding []*Coding `json:"coding,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Text *string `json:"text,omitempty"` +} + +// CodeableReference +type CodeableReference struct { + Concept *CodeableConcept `json:"concept,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Reference *Reference `json:"reference,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// Coding +type Coding struct { + XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` + XDisplay *FHIRPrimitiveExtension `json:"_display,omitempty"` + XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` + XUserSelected *FHIRPrimitiveExtension `json:"_userSelected,omitempty"` + XVersion *FHIRPrimitiveExtension `json:"_version,omitempty"` + Code *string `json:"code,omitempty"` + Display *string `json:"display,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + System *string `json:"system,omitempty"` + UserSelected *bool `json:"userSelected,omitempty"` + Version *string `json:"version,omitempty"` +} + +// Condition +type Condition struct { + XAbatementDateTime *FHIRPrimitiveExtension `json:"_abatementDateTime,omitempty"` + XAbatementString *FHIRPrimitiveExtension `json:"_abatementString,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XOnsetDateTime *FHIRPrimitiveExtension `json:"_onsetDateTime,omitempty"` + XOnsetString *FHIRPrimitiveExtension `json:"_onsetString,omitempty"` + XRecordedDate *FHIRPrimitiveExtension `json:"_recordedDate,omitempty"` + AbatementAge *Age `json:"abatementAge,omitempty"` + AbatementDateTime *string `json:"abatementDateTime,omitempty"` + AbatementPeriod *Period `json:"abatementPeriod,omitempty"` + AbatementRange *Range `json:"abatementRange,omitempty"` + AbatementString *string `json:"abatementString,omitempty"` + BodySite []*CodeableConcept `json:"bodySite,omitempty"` + Category []*CodeableConcept `json:"category,omitempty"` + ClinicalStatus *CodeableConcept `json:"clinicalStatus"` + Code *CodeableConcept `json:"code,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Encounter *Reference `json:"encounter,omitempty"` + Evidence []*CodeableReference `json:"evidence,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + OnsetAge *Age `json:"onsetAge,omitempty"` + OnsetDateTime *string `json:"onsetDateTime,omitempty"` + OnsetPeriod *Period `json:"onsetPeriod,omitempty"` + OnsetRange *Range `json:"onsetRange,omitempty"` + OnsetString *string `json:"onsetString,omitempty"` + Participant []*ConditionParticipant `json:"participant,omitempty"` + RecordedDate *string `json:"recordedDate,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Severity *CodeableConcept `json:"severity,omitempty"` + Stage []*ConditionStage `json:"stage,omitempty"` + Subject *Reference `json:"subject"` + Text *Narrative `json:"text,omitempty"` + VerificationStatus *CodeableConcept `json:"verificationStatus,omitempty"` +} + +// ConditionParticipant +type ConditionParticipant struct { + Actor *Reference `json:"actor"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Function *CodeableConcept `json:"function,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// ConditionStage +type ConditionStage struct { + Assessment []*Reference `json:"assessment,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Summary *CodeableConcept `json:"summary,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` +} + +// ContactDetail +type ContactDetail struct { + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Name *string `json:"name,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Telecom []*ContactPoint `json:"telecom,omitempty"` +} + +// ContactPoint +type ContactPoint struct { + XRank *FHIRPrimitiveExtension `json:"_rank,omitempty"` + XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` + XUse *FHIRPrimitiveExtension `json:"_use,omitempty"` + XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Period *Period `json:"period,omitempty"` + Rank *int64 `json:"rank,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + System *string `json:"system,omitempty"` + Use *string `json:"use,omitempty"` + Value *string `json:"value,omitempty"` +} + +// Count +type Count struct { + XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` + XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` + XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` + XUnit *FHIRPrimitiveExtension `json:"_unit,omitempty"` + XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` + Code *string `json:"code,omitempty"` + Comparator *string `json:"comparator,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + System *string `json:"system,omitempty"` + Unit *string `json:"unit,omitempty"` + Value *float64 `json:"value,omitempty"` +} + +// DataRequirement +type DataRequirement struct { + XLimit *FHIRPrimitiveExtension `json:"_limit,omitempty"` + XMustSupport []*FHIRPrimitiveExtension `json:"_mustSupport,omitempty"` + XProfile []*FHIRPrimitiveExtension `json:"_profile,omitempty"` + XType *FHIRPrimitiveExtension `json:"_type,omitempty"` + CodeFilter []*DataRequirementCodeFilter `json:"codeFilter,omitempty"` + DateFilter []*DataRequirementDateFilter `json:"dateFilter,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Limit *int64 `json:"limit,omitempty"` + Links [][]any `json:"links,omitempty"` + MustSupport []string `json:"mustSupport,omitempty"` + Profile []string `json:"profile,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Sort []*DataRequirementSort `json:"sort,omitempty"` + SubjectCodeableConcept *CodeableConcept `json:"subjectCodeableConcept,omitempty"` + SubjectReference *Reference `json:"subjectReference,omitempty"` + Type *string `json:"type,omitempty"` + ValueFilter []*DataRequirementValueFilter `json:"valueFilter,omitempty"` +} + +// DataRequirementCodeFilter +type DataRequirementCodeFilter struct { + XPath *FHIRPrimitiveExtension `json:"_path,omitempty"` + XSearchParam *FHIRPrimitiveExtension `json:"_searchParam,omitempty"` + XValueSet *FHIRPrimitiveExtension `json:"_valueSet,omitempty"` + Code []*Coding `json:"code,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Path *string `json:"path,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SearchParam *string `json:"searchParam,omitempty"` + ValueSet *string `json:"valueSet,omitempty"` +} + +// DataRequirementDateFilter +type DataRequirementDateFilter struct { + XPath *FHIRPrimitiveExtension `json:"_path,omitempty"` + XSearchParam *FHIRPrimitiveExtension `json:"_searchParam,omitempty"` + XValueDateTime *FHIRPrimitiveExtension `json:"_valueDateTime,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Path *string `json:"path,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SearchParam *string `json:"searchParam,omitempty"` + ValueDateTime *string `json:"valueDateTime,omitempty"` + ValueDuration *Duration `json:"valueDuration,omitempty"` + ValuePeriod *Period `json:"valuePeriod,omitempty"` +} + +// DataRequirementSort +type DataRequirementSort struct { + XDirection *FHIRPrimitiveExtension `json:"_direction,omitempty"` + XPath *FHIRPrimitiveExtension `json:"_path,omitempty"` + Direction *string `json:"direction,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Path *string `json:"path,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// DataRequirementValueFilter +type DataRequirementValueFilter struct { + XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` + XPath *FHIRPrimitiveExtension `json:"_path,omitempty"` + XSearchParam *FHIRPrimitiveExtension `json:"_searchParam,omitempty"` + XValueDateTime *FHIRPrimitiveExtension `json:"_valueDateTime,omitempty"` + Comparator *string `json:"comparator,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Path *string `json:"path,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SearchParam *string `json:"searchParam,omitempty"` + ValueDateTime *string `json:"valueDateTime,omitempty"` + ValueDuration *Duration `json:"valueDuration,omitempty"` + ValuePeriod *Period `json:"valuePeriod,omitempty"` +} + +// DiagnosticReport +type DiagnosticReport struct { + XConclusion *FHIRPrimitiveExtension `json:"_conclusion,omitempty"` + XEffectiveDateTime *FHIRPrimitiveExtension `json:"_effectiveDateTime,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XIssued *FHIRPrimitiveExtension `json:"_issued,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + BasedOn []*Reference `json:"basedOn,omitempty"` + Category []*CodeableConcept `json:"category,omitempty"` + Code *CodeableConcept `json:"code"` + Composition *Reference `json:"composition,omitempty"` + Conclusion *string `json:"conclusion,omitempty"` + ConclusionCode []*CodeableConcept `json:"conclusionCode,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + EffectiveDateTime *string `json:"effectiveDateTime,omitempty"` + EffectivePeriod *Period `json:"effectivePeriod,omitempty"` + Encounter *Reference `json:"encounter,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Issued *string `json:"issued,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Media []*DiagnosticReportMedia `json:"media,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + Performer []*Reference `json:"performer,omitempty"` + PresentedForm []*Attachment `json:"presentedForm,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Result []*Reference `json:"result,omitempty"` + ResultsInterpreter []*Reference `json:"resultsInterpreter,omitempty"` + Specimen []*Reference `json:"specimen,omitempty"` + Status *string `json:"status,omitempty"` + Study []*Reference `json:"study,omitempty"` + Subject *Reference `json:"subject,omitempty"` + SupportingInfo []*DiagnosticReportSupportingInfo `json:"supportingInfo,omitempty"` + Text *Narrative `json:"text,omitempty"` +} + +// DiagnosticReportMedia +type DiagnosticReportMedia struct { + XComment *FHIRPrimitiveExtension `json:"_comment,omitempty"` + Comment *string `json:"comment,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Link *Reference `json:"link"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// DiagnosticReportSupportingInfo +type DiagnosticReportSupportingInfo struct { + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Reference *Reference `json:"reference"` + ResourceType *string `json:"resourceType,omitempty"` + Type *CodeableConcept `json:"type"` +} + +// Directory +type Directory struct { + Child []*Reference `json:"child"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Name *string `json:"name"` + Path *string `json:"path,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// Distance +type Distance struct { + XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` + XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` + XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` + XUnit *FHIRPrimitiveExtension `json:"_unit,omitempty"` + XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` + Code *string `json:"code,omitempty"` + Comparator *string `json:"comparator,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + System *string `json:"system,omitempty"` + Unit *string `json:"unit,omitempty"` + Value *float64 `json:"value,omitempty"` +} + +// DocumentReference +type DocumentReference struct { + XDate *FHIRPrimitiveExtension `json:"_date,omitempty"` + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XDocStatus *FHIRPrimitiveExtension `json:"_docStatus,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + XVersion *FHIRPrimitiveExtension `json:"_version,omitempty"` + Attester []*DocumentReferenceAttester `json:"attester,omitempty"` + Author []*Reference `json:"author,omitempty"` + BasedOn []*Reference `json:"basedOn,omitempty"` + BodySite []*CodeableReference `json:"bodySite,omitempty"` + Category []*CodeableConcept `json:"category,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Content []*DocumentReferenceContent `json:"content"` + Context []*Reference `json:"context,omitempty"` + Custodian *Reference `json:"custodian,omitempty"` + Date *string `json:"date,omitempty"` + Description *string `json:"description,omitempty"` + DocStatus *string `json:"docStatus,omitempty"` + Event []*CodeableReference `json:"event,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FacilityType *CodeableConcept `json:"facilityType,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + Modality []*CodeableConcept `json:"modality,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Period *Period `json:"period,omitempty"` + PracticeSetting *CodeableConcept `json:"practiceSetting,omitempty"` + RelatesTo []*DocumentReferenceRelatesTo `json:"relatesTo,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SecurityLabel []*CodeableConcept `json:"securityLabel,omitempty"` + Status *string `json:"status,omitempty"` + Subject *Reference `json:"subject,omitempty"` + Text *Narrative `json:"text,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` + Version *string `json:"version,omitempty"` +} + +// DocumentReferenceAttester +type DocumentReferenceAttester struct { + XTime *FHIRPrimitiveExtension `json:"_time,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Mode *CodeableConcept `json:"mode"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Party *Reference `json:"party,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Time *string `json:"time,omitempty"` +} + +// DocumentReferenceContent +type DocumentReferenceContent struct { + Attachment *Attachment `json:"attachment"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Profile []*DocumentReferenceContentProfile `json:"profile,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// DocumentReferenceContentProfile +type DocumentReferenceContentProfile struct { + XValueCanonical *FHIRPrimitiveExtension `json:"_valueCanonical,omitempty"` + XValueURI *FHIRPrimitiveExtension `json:"_valueUri,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + ValueCanonical *string `json:"valueCanonical,omitempty"` + ValueCoding *Coding `json:"valueCoding,omitempty"` + ValueURI *string `json:"valueUri,omitempty"` +} + +// DocumentReferenceRelatesTo +type DocumentReferenceRelatesTo struct { + Code *CodeableConcept `json:"code"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Target *Reference `json:"target"` +} + +// Dosage +type Dosage struct { + XAsNeeded *FHIRPrimitiveExtension `json:"_asNeeded,omitempty"` + XPatientInstruction *FHIRPrimitiveExtension `json:"_patientInstruction,omitempty"` + XSequence *FHIRPrimitiveExtension `json:"_sequence,omitempty"` + XText *FHIRPrimitiveExtension `json:"_text,omitempty"` + AdditionalInstruction []*CodeableConcept `json:"additionalInstruction,omitempty"` + AsNeeded *bool `json:"asNeeded,omitempty"` + AsNeededFor []*CodeableConcept `json:"asNeededFor,omitempty"` + DoseAndRate []*DosageDoseAndRate `json:"doseAndRate,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + MaxDosePerAdministration *Quantity `json:"maxDosePerAdministration,omitempty"` + MaxDosePerLifetime *Quantity `json:"maxDosePerLifetime,omitempty"` + MaxDosePerPeriod []*Ratio `json:"maxDosePerPeriod,omitempty"` + Method *CodeableConcept `json:"method,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + PatientInstruction *string `json:"patientInstruction,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Route *CodeableConcept `json:"route,omitempty"` + Sequence *int64 `json:"sequence,omitempty"` + Site *CodeableConcept `json:"site,omitempty"` + Text *string `json:"text,omitempty"` + Timing *Timing `json:"timing,omitempty"` +} + +// DosageDoseAndRate +type DosageDoseAndRate struct { + DoseQuantity *Quantity `json:"doseQuantity,omitempty"` + DoseRange *Range `json:"doseRange,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + RateQuantity *Quantity `json:"rateQuantity,omitempty"` + RateRange *Range `json:"rateRange,omitempty"` + RateRatio *Ratio `json:"rateRatio,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` +} + +// Duration +type Duration struct { + XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` + XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` + XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` + XUnit *FHIRPrimitiveExtension `json:"_unit,omitempty"` + XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` + Code *string `json:"code,omitempty"` + Comparator *string `json:"comparator,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + System *string `json:"system,omitempty"` + Unit *string `json:"unit,omitempty"` + Value *float64 `json:"value,omitempty"` +} + +// Expression +type Expression struct { + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XExpression *FHIRPrimitiveExtension `json:"_expression,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + XReference *FHIRPrimitiveExtension `json:"_reference,omitempty"` + Description *string `json:"description,omitempty"` + Expression *string `json:"expression,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Name *string `json:"name,omitempty"` + Reference *string `json:"reference,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// ExtendedContactDetail +type ExtendedContactDetail struct { + Address *Address `json:"address,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Name []*HumanName `json:"name,omitempty"` + Organization *Reference `json:"organization,omitempty"` + Period *Period `json:"period,omitempty"` + Purpose *CodeableConcept `json:"purpose,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Telecom []*ContactPoint `json:"telecom,omitempty"` +} + +// Extension +type Extension struct { + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + URL *string `json:"url,omitempty"` + ValueAddress *Address `json:"valueAddress,omitempty"` + ValueAge *Age `json:"valueAge,omitempty"` + ValueAnnotation *Annotation `json:"valueAnnotation,omitempty"` + ValueAttachment *Attachment `json:"valueAttachment,omitempty"` + ValueAvailability *Availability `json:"valueAvailability,omitempty"` + ValueBase64Binary *string `json:"valueBase64Binary,omitempty"` + ValueBoolean *bool `json:"valueBoolean,omitempty"` + ValueCanonical *string `json:"valueCanonical,omitempty"` + ValueCode *string `json:"valueCode,omitempty"` + ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` + ValueCodeableReference *CodeableReference `json:"valueCodeableReference,omitempty"` + ValueCoding *Coding `json:"valueCoding,omitempty"` + ValueContactDetail *ContactDetail `json:"valueContactDetail,omitempty"` + ValueContactPoint *ContactPoint `json:"valueContactPoint,omitempty"` + ValueCount *Count `json:"valueCount,omitempty"` + ValueDataRequirement *DataRequirement `json:"valueDataRequirement,omitempty"` + ValueDate *string `json:"valueDate,omitempty"` + ValueDateTime *string `json:"valueDateTime,omitempty"` + ValueDecimal *float64 `json:"valueDecimal,omitempty"` + ValueDistance *Distance `json:"valueDistance,omitempty"` + ValueDosage *Dosage `json:"valueDosage,omitempty"` + ValueDuration *Duration `json:"valueDuration,omitempty"` + ValueExpression *Expression `json:"valueExpression,omitempty"` + ValueExtendedContactDetail *ExtendedContactDetail `json:"valueExtendedContactDetail,omitempty"` + ValueHumanName *HumanName `json:"valueHumanName,omitempty"` + ValueID *string `json:"valueId,omitempty"` + ValueIDentifier *Identifier `json:"valueIdentifier,omitempty"` + ValueInstant *string `json:"valueInstant,omitempty"` + ValueInteger *int64 `json:"valueInteger,omitempty"` + ValueInteger64 *int64 `json:"valueInteger64,omitempty"` + ValueMarkdown *string `json:"valueMarkdown,omitempty"` + ValueMeta *Meta `json:"valueMeta,omitempty"` + ValueMoney *Money `json:"valueMoney,omitempty"` + ValueOid *string `json:"valueOid,omitempty"` + ValueParameterDefinition *ParameterDefinition `json:"valueParameterDefinition,omitempty"` + ValuePeriod *Period `json:"valuePeriod,omitempty"` + ValuePositiveInt *int64 `json:"valuePositiveInt,omitempty"` + ValueQuantity *Quantity `json:"valueQuantity,omitempty"` + ValueRange *Range `json:"valueRange,omitempty"` + ValueRatio *Ratio `json:"valueRatio,omitempty"` + ValueRatioRange *RatioRange `json:"valueRatioRange,omitempty"` + ValueReference *Reference `json:"valueReference,omitempty"` + ValueRelatedArtifact *RelatedArtifact `json:"valueRelatedArtifact,omitempty"` + ValueSampledData *SampledData `json:"valueSampledData,omitempty"` + ValueSignature *Signature `json:"valueSignature,omitempty"` + ValueString *string `json:"valueString,omitempty"` + ValueTime *string `json:"valueTime,omitempty"` + ValueTiming *Timing `json:"valueTiming,omitempty"` + ValueTriggerDefinition *TriggerDefinition `json:"valueTriggerDefinition,omitempty"` + ValueUnsignedInt *int64 `json:"valueUnsignedInt,omitempty"` + ValueURI *string `json:"valueUri,omitempty"` + ValueURL *string `json:"valueUrl,omitempty"` + ValueUsageContext *UsageContext `json:"valueUsageContext,omitempty"` + ValueUUID *string `json:"valueUuid,omitempty"` +} + +// FHIRPrimitiveExtension +type FHIRPrimitiveExtension struct { + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// FamilyMemberHistory +type FamilyMemberHistory struct { + XAgeString *FHIRPrimitiveExtension `json:"_ageString,omitempty"` + XBornDate *FHIRPrimitiveExtension `json:"_bornDate,omitempty"` + XBornString *FHIRPrimitiveExtension `json:"_bornString,omitempty"` + XDate *FHIRPrimitiveExtension `json:"_date,omitempty"` + XDeceasedBoolean *FHIRPrimitiveExtension `json:"_deceasedBoolean,omitempty"` + XDeceasedDate *FHIRPrimitiveExtension `json:"_deceasedDate,omitempty"` + XDeceasedString *FHIRPrimitiveExtension `json:"_deceasedString,omitempty"` + XEstimatedAge *FHIRPrimitiveExtension `json:"_estimatedAge,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XInstantiatesCanonical []*FHIRPrimitiveExtension `json:"_instantiatesCanonical,omitempty"` + XInstantiatesURI []*FHIRPrimitiveExtension `json:"_instantiatesUri,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + AgeAge *Age `json:"ageAge,omitempty"` + AgeRange *Range `json:"ageRange,omitempty"` + AgeString *string `json:"ageString,omitempty"` + BornDate *string `json:"bornDate,omitempty"` + BornPeriod *Period `json:"bornPeriod,omitempty"` + BornString *string `json:"bornString,omitempty"` + Condition []*FamilyMemberHistoryCondition `json:"condition,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + DataAbsentReason *CodeableConcept `json:"dataAbsentReason,omitempty"` + Date *string `json:"date,omitempty"` + DeceasedAge *Age `json:"deceasedAge,omitempty"` + DeceasedBoolean *bool `json:"deceasedBoolean,omitempty"` + DeceasedDate *string `json:"deceasedDate,omitempty"` + DeceasedRange *Range `json:"deceasedRange,omitempty"` + DeceasedString *string `json:"deceasedString,omitempty"` + EstimatedAge *bool `json:"estimatedAge,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + InstantiatesCanonical []string `json:"instantiatesCanonical,omitempty"` + InstantiatesURI []string `json:"instantiatesUri,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Name *string `json:"name,omitempty"` + Note []*Annotation `json:"note,omitempty"` + Participant []*FamilyMemberHistoryParticipant `json:"participant,omitempty"` + Patient *Reference `json:"patient"` + Procedure []*FamilyMemberHistoryProcedure `json:"procedure,omitempty"` + Reason []*CodeableReference `json:"reason,omitempty"` + Relationship *CodeableConcept `json:"relationship"` + ResourceType *string `json:"resourceType,omitempty"` + Sex *CodeableConcept `json:"sex,omitempty"` + Status *string `json:"status,omitempty"` + Text *Narrative `json:"text,omitempty"` +} + +// FamilyMemberHistoryCondition +type FamilyMemberHistoryCondition struct { + XContributedToDeath *FHIRPrimitiveExtension `json:"_contributedToDeath,omitempty"` + XOnsetString *FHIRPrimitiveExtension `json:"_onsetString,omitempty"` + Code *CodeableConcept `json:"code"` + ContributedToDeath *bool `json:"contributedToDeath,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + OnsetAge *Age `json:"onsetAge,omitempty"` + OnsetPeriod *Period `json:"onsetPeriod,omitempty"` + OnsetRange *Range `json:"onsetRange,omitempty"` + OnsetString *string `json:"onsetString,omitempty"` + Outcome *CodeableConcept `json:"outcome,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// FamilyMemberHistoryParticipant +type FamilyMemberHistoryParticipant struct { + Actor *Reference `json:"actor"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Function *CodeableConcept `json:"function,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// FamilyMemberHistoryProcedure +type FamilyMemberHistoryProcedure struct { + XContributedToDeath *FHIRPrimitiveExtension `json:"_contributedToDeath,omitempty"` + XPerformedDateTime *FHIRPrimitiveExtension `json:"_performedDateTime,omitempty"` + XPerformedString *FHIRPrimitiveExtension `json:"_performedString,omitempty"` + Code *CodeableConcept `json:"code"` + ContributedToDeath *bool `json:"contributedToDeath,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + Outcome *CodeableConcept `json:"outcome,omitempty"` + PerformedAge *Age `json:"performedAge,omitempty"` + PerformedDateTime *string `json:"performedDateTime,omitempty"` + PerformedPeriod *Period `json:"performedPeriod,omitempty"` + PerformedRange *Range `json:"performedRange,omitempty"` + PerformedString *string `json:"performedString,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// Group +type Group struct { + XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XMembership *FHIRPrimitiveExtension `json:"_membership,omitempty"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + XQuantity *FHIRPrimitiveExtension `json:"_quantity,omitempty"` + XType *FHIRPrimitiveExtension `json:"_type,omitempty"` + Active *bool `json:"active,omitempty"` + Characteristic []*GroupCharacteristic `json:"characteristic,omitempty"` + Code *CodeableConcept `json:"code,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Description *string `json:"description,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + ManagingEntity *Reference `json:"managingEntity,omitempty"` + Member []*GroupMember `json:"member,omitempty"` + Membership *string `json:"membership,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Name *string `json:"name,omitempty"` + Quantity *int64 `json:"quantity,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Text *Narrative `json:"text,omitempty"` + Type *string `json:"type,omitempty"` +} + +// GroupCharacteristic +type GroupCharacteristic struct { + XExclude *FHIRPrimitiveExtension `json:"_exclude,omitempty"` + XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` + Code *CodeableConcept `json:"code"` + Exclude *bool `json:"exclude,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Period *Period `json:"period,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + ValueBoolean *bool `json:"valueBoolean,omitempty"` + ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` + ValueQuantity *Quantity `json:"valueQuantity,omitempty"` + ValueRange *Range `json:"valueRange,omitempty"` + ValueReference *Reference `json:"valueReference,omitempty"` +} + +// GroupMember +type GroupMember struct { + XInactive *FHIRPrimitiveExtension `json:"_inactive,omitempty"` + Entity *Reference `json:"entity"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Inactive *bool `json:"inactive,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Period *Period `json:"period,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// HumanName +type HumanName struct { + XFamily *FHIRPrimitiveExtension `json:"_family,omitempty"` + XGiven []*FHIRPrimitiveExtension `json:"_given,omitempty"` + XPrefix []*FHIRPrimitiveExtension `json:"_prefix,omitempty"` + XSuffix []*FHIRPrimitiveExtension `json:"_suffix,omitempty"` + XText *FHIRPrimitiveExtension `json:"_text,omitempty"` + XUse *FHIRPrimitiveExtension `json:"_use,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + Family *string `json:"family,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Given []string `json:"given,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Period *Period `json:"period,omitempty"` + Prefix []string `json:"prefix,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Suffix []string `json:"suffix,omitempty"` + Text *string `json:"text,omitempty"` + Use *string `json:"use,omitempty"` +} + +// Identifier +type Identifier struct { + XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` + XUse *FHIRPrimitiveExtension `json:"_use,omitempty"` + XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` + Assigner *Reference `json:"assigner,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Period *Period `json:"period,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + System *string `json:"system,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` + Use *string `json:"use,omitempty"` + Value *string `json:"value,omitempty"` +} + +// ImagingStudy +type ImagingStudy struct { + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XNumberOfInstances *FHIRPrimitiveExtension `json:"_numberOfInstances,omitempty"` + XNumberOfSeries *FHIRPrimitiveExtension `json:"_numberOfSeries,omitempty"` + XStarted *FHIRPrimitiveExtension `json:"_started,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + BasedOn []*Reference `json:"basedOn,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Description *string `json:"description,omitempty"` + Encounter *Reference `json:"encounter,omitempty"` + Endpoint []*Reference `json:"endpoint,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Location *Reference `json:"location,omitempty"` + Meta *Meta `json:"meta,omitempty"` + Modality []*CodeableConcept `json:"modality,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + NumberOfInstances *int64 `json:"numberOfInstances,omitempty"` + NumberOfSeries *int64 `json:"numberOfSeries,omitempty"` + PartOf []*Reference `json:"partOf,omitempty"` + Procedure []*CodeableReference `json:"procedure,omitempty"` + Reason []*CodeableReference `json:"reason,omitempty"` + Referrer *Reference `json:"referrer,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Series []*ImagingStudySeries `json:"series,omitempty"` + Started *string `json:"started,omitempty"` + Status *string `json:"status,omitempty"` + Subject *Reference `json:"subject"` + Text *Narrative `json:"text,omitempty"` +} + +// ImagingStudySeries +type ImagingStudySeries struct { + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XNumber *FHIRPrimitiveExtension `json:"_number,omitempty"` + XNumberOfInstances *FHIRPrimitiveExtension `json:"_numberOfInstances,omitempty"` + XStarted *FHIRPrimitiveExtension `json:"_started,omitempty"` + XUid *FHIRPrimitiveExtension `json:"_uid,omitempty"` + BodySite *CodeableReference `json:"bodySite,omitempty"` + Description *string `json:"description,omitempty"` + Endpoint []*Reference `json:"endpoint,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Instance []*ImagingStudySeriesInstance `json:"instance,omitempty"` + Laterality *CodeableConcept `json:"laterality,omitempty"` + Links [][]any `json:"links,omitempty"` + Modality *CodeableConcept `json:"modality"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Number *int64 `json:"number,omitempty"` + NumberOfInstances *int64 `json:"numberOfInstances,omitempty"` + Performer []*ImagingStudySeriesPerformer `json:"performer,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Specimen []*Reference `json:"specimen,omitempty"` + Started *string `json:"started,omitempty"` + Uid *string `json:"uid,omitempty"` +} + +// ImagingStudySeriesInstance +type ImagingStudySeriesInstance struct { + XNumber *FHIRPrimitiveExtension `json:"_number,omitempty"` + XTitle *FHIRPrimitiveExtension `json:"_title,omitempty"` + XUid *FHIRPrimitiveExtension `json:"_uid,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Number *int64 `json:"number,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SopClass *Coding `json:"sopClass"` + Title *string `json:"title,omitempty"` + Uid *string `json:"uid,omitempty"` +} + +// ImagingStudySeriesPerformer +type ImagingStudySeriesPerformer struct { + Actor *Reference `json:"actor"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Function *CodeableConcept `json:"function,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// Medication +type Medication struct { + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + Batch *MedicationBatch `json:"batch,omitempty"` + Code *CodeableConcept `json:"code,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Definition *Reference `json:"definition,omitempty"` + DoseForm *CodeableConcept `json:"doseForm,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Ingredient []*MedicationIngredient `json:"ingredient,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + MarketingAuthorizationHolder *Reference `json:"marketingAuthorizationHolder,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Status *string `json:"status,omitempty"` + Text *Narrative `json:"text,omitempty"` + TotalVolume *Quantity `json:"totalVolume,omitempty"` +} + +// MedicationAdministration +type MedicationAdministration struct { + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XIsSubPotent *FHIRPrimitiveExtension `json:"_isSubPotent,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XOccurenceDateTime *FHIRPrimitiveExtension `json:"_occurenceDateTime,omitempty"` + XRecorded *FHIRPrimitiveExtension `json:"_recorded,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + BasedOn []*Reference `json:"basedOn,omitempty"` + Category []*CodeableConcept `json:"category,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Device []*CodeableReference `json:"device,omitempty"` + Dosage *MedicationAdministrationDosage `json:"dosage,omitempty"` + Encounter *Reference `json:"encounter,omitempty"` + EventHistory []*Reference `json:"eventHistory,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + IsSubPotent *bool `json:"isSubPotent,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Medication *CodeableReference `json:"medication"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + OccurenceDateTime *string `json:"occurenceDateTime,omitempty"` + OccurencePeriod *Period `json:"occurencePeriod,omitempty"` + OccurenceTiming *Timing `json:"occurenceTiming,omitempty"` + PartOf []*Reference `json:"partOf,omitempty"` + Performer []*MedicationAdministrationPerformer `json:"performer,omitempty"` + Reason []*CodeableReference `json:"reason,omitempty"` + Recorded *string `json:"recorded,omitempty"` + Request *Reference `json:"request,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Status *string `json:"status,omitempty"` + StatusReason []*CodeableConcept `json:"statusReason,omitempty"` + SubPotentReason []*CodeableConcept `json:"subPotentReason,omitempty"` + Subject *Reference `json:"subject"` + SupportingInformation []*Reference `json:"supportingInformation,omitempty"` + Text *Narrative `json:"text,omitempty"` +} + +// MedicationAdministrationDosage +type MedicationAdministrationDosage struct { + XText *FHIRPrimitiveExtension `json:"_text,omitempty"` + Dose *Quantity `json:"dose,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Method *CodeableConcept `json:"method,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + RateQuantity *Quantity `json:"rateQuantity,omitempty"` + RateRatio *Ratio `json:"rateRatio,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Route *CodeableConcept `json:"route,omitempty"` + Site *CodeableConcept `json:"site,omitempty"` + Text *string `json:"text,omitempty"` +} + +// MedicationAdministrationPerformer +type MedicationAdministrationPerformer struct { + Actor *CodeableReference `json:"actor"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Function *CodeableConcept `json:"function,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// MedicationBatch +type MedicationBatch struct { + XExpirationDate *FHIRPrimitiveExtension `json:"_expirationDate,omitempty"` + XLotNumber *FHIRPrimitiveExtension `json:"_lotNumber,omitempty"` + ExpirationDate *string `json:"expirationDate,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + LotNumber *string `json:"lotNumber,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// MedicationIngredient +type MedicationIngredient struct { + XIsActive *FHIRPrimitiveExtension `json:"_isActive,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IsActive *bool `json:"isActive,omitempty"` + Item *CodeableReference `json:"item"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + StrengthCodeableConcept *CodeableConcept `json:"strengthCodeableConcept,omitempty"` + StrengthQuantity *Quantity `json:"strengthQuantity,omitempty"` + StrengthRatio *Ratio `json:"strengthRatio,omitempty"` +} + +// MedicationRequest +type MedicationRequest struct { + XAuthoredOn *FHIRPrimitiveExtension `json:"_authoredOn,omitempty"` + XDoNotPerform *FHIRPrimitiveExtension `json:"_doNotPerform,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XIntent *FHIRPrimitiveExtension `json:"_intent,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XPriority *FHIRPrimitiveExtension `json:"_priority,omitempty"` + XRenderedDosageInstruction *FHIRPrimitiveExtension `json:"_renderedDosageInstruction,omitempty"` + XReported *FHIRPrimitiveExtension `json:"_reported,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + XStatusChanged *FHIRPrimitiveExtension `json:"_statusChanged,omitempty"` + AuthoredOn *string `json:"authoredOn,omitempty"` + BasedOn []*Reference `json:"basedOn,omitempty"` + Category []*CodeableConcept `json:"category,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + CourseOfTherapyType *CodeableConcept `json:"courseOfTherapyType,omitempty"` + Device []*CodeableReference `json:"device,omitempty"` + DispenseRequest *MedicationRequestDispenseRequest `json:"dispenseRequest,omitempty"` + DoNotPerform *bool `json:"doNotPerform,omitempty"` + DosageInstruction []*Dosage `json:"dosageInstruction,omitempty"` + EffectiveDosePeriod *Period `json:"effectiveDosePeriod,omitempty"` + Encounter *Reference `json:"encounter,omitempty"` + EventHistory []*Reference `json:"eventHistory,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + GroupIDentifier *Identifier `json:"groupIdentifier,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + InformationSource []*Reference `json:"informationSource,omitempty"` + Insurance []*Reference `json:"insurance,omitempty"` + Intent *string `json:"intent,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Medication *CodeableReference `json:"medication"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + Performer []*Reference `json:"performer,omitempty"` + PerformerType *CodeableConcept `json:"performerType,omitempty"` + PriorPrescription *Reference `json:"priorPrescription,omitempty"` + Priority *string `json:"priority,omitempty"` + Reason []*CodeableReference `json:"reason,omitempty"` + Recorder *Reference `json:"recorder,omitempty"` + RenderedDosageInstruction *string `json:"renderedDosageInstruction,omitempty"` + Reported *bool `json:"reported,omitempty"` + Requester *Reference `json:"requester,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Status *string `json:"status,omitempty"` + StatusChanged *string `json:"statusChanged,omitempty"` + StatusReason *CodeableConcept `json:"statusReason,omitempty"` + Subject *Reference `json:"subject"` + Substitution *MedicationRequestSubstitution `json:"substitution,omitempty"` + SupportingInformation []*Reference `json:"supportingInformation,omitempty"` + Text *Narrative `json:"text,omitempty"` +} + +// MedicationRequestDispenseRequest +type MedicationRequestDispenseRequest struct { + XNumberOfRepeatsAllowed *FHIRPrimitiveExtension `json:"_numberOfRepeatsAllowed,omitempty"` + DispenseInterval *Duration `json:"dispenseInterval,omitempty"` + Dispenser *Reference `json:"dispenser,omitempty"` + DispenserInstruction []*Annotation `json:"dispenserInstruction,omitempty"` + DoseAdministrationAid *CodeableConcept `json:"doseAdministrationAid,omitempty"` + ExpectedSupplyDuration *Duration `json:"expectedSupplyDuration,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + InitialFill *MedicationRequestDispenseRequestInitialFill `json:"initialFill,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + NumberOfRepeatsAllowed *int64 `json:"numberOfRepeatsAllowed,omitempty"` + Quantity *Quantity `json:"quantity,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + ValidityPeriod *Period `json:"validityPeriod,omitempty"` +} + +// MedicationRequestDispenseRequestInitialFill +type MedicationRequestDispenseRequestInitialFill struct { + Duration *Duration `json:"duration,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Quantity *Quantity `json:"quantity,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// MedicationRequestSubstitution +type MedicationRequestSubstitution struct { + XAllowedBoolean *FHIRPrimitiveExtension `json:"_allowedBoolean,omitempty"` + AllowedBoolean *bool `json:"allowedBoolean,omitempty"` + AllowedCodeableConcept *CodeableConcept `json:"allowedCodeableConcept,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Reason *CodeableConcept `json:"reason,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// MedicationStatement +type MedicationStatement struct { + XDateAsserted *FHIRPrimitiveExtension `json:"_dateAsserted,omitempty"` + XEffectiveDateTime *FHIRPrimitiveExtension `json:"_effectiveDateTime,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XRenderedDosageInstruction *FHIRPrimitiveExtension `json:"_renderedDosageInstruction,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + Adherence *MedicationStatementAdherence `json:"adherence,omitempty"` + Category []*CodeableConcept `json:"category,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + DateAsserted *string `json:"dateAsserted,omitempty"` + DerivedFrom []*Reference `json:"derivedFrom,omitempty"` + Dosage []*Dosage `json:"dosage,omitempty"` + EffectiveDateTime *string `json:"effectiveDateTime,omitempty"` + EffectivePeriod *Period `json:"effectivePeriod,omitempty"` + EffectiveTiming *Timing `json:"effectiveTiming,omitempty"` + Encounter *Reference `json:"encounter,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + InformationSource []*Reference `json:"informationSource,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Medication *CodeableReference `json:"medication"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + PartOf []*Reference `json:"partOf,omitempty"` + Reason []*CodeableReference `json:"reason,omitempty"` + RelatedClinicalInformation []*Reference `json:"relatedClinicalInformation,omitempty"` + RenderedDosageInstruction *string `json:"renderedDosageInstruction,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Status *string `json:"status,omitempty"` + Subject *Reference `json:"subject"` + Text *Narrative `json:"text,omitempty"` +} + +// MedicationStatementAdherence +type MedicationStatementAdherence struct { + Code *CodeableConcept `json:"code"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Reason *CodeableConcept `json:"reason,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// Meta +type Meta struct { + XLastUpdated *FHIRPrimitiveExtension `json:"_lastUpdated,omitempty"` + XProfile []*FHIRPrimitiveExtension `json:"_profile,omitempty"` + XSource *FHIRPrimitiveExtension `json:"_source,omitempty"` + XVersionID *FHIRPrimitiveExtension `json:"_versionId,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + LastUpdated *string `json:"lastUpdated,omitempty"` + Links [][]any `json:"links,omitempty"` + Profile []string `json:"profile,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Security []*Coding `json:"security,omitempty"` + Source *string `json:"source,omitempty"` + Tag []*Coding `json:"tag,omitempty"` + VersionID *string `json:"versionId,omitempty"` +} + +// Money +type Money struct { + XCurrency *FHIRPrimitiveExtension `json:"_currency,omitempty"` + XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` + Currency *string `json:"currency,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Value *float64 `json:"value,omitempty"` +} + +// Narrative +type Narrative struct { + XDiv *FHIRPrimitiveExtension `json:"_div,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + Div *string `json:"div,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Status *string `json:"status,omitempty"` +} + +// Observation +type Observation struct { + XEffectiveDateTime *FHIRPrimitiveExtension `json:"_effectiveDateTime,omitempty"` + XEffectiveInstant *FHIRPrimitiveExtension `json:"_effectiveInstant,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XInstantiatesCanonical *FHIRPrimitiveExtension `json:"_instantiatesCanonical,omitempty"` + XIssued *FHIRPrimitiveExtension `json:"_issued,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` + XValueDateTime *FHIRPrimitiveExtension `json:"_valueDateTime,omitempty"` + XValueInteger *FHIRPrimitiveExtension `json:"_valueInteger,omitempty"` + XValueString *FHIRPrimitiveExtension `json:"_valueString,omitempty"` + XValueTime *FHIRPrimitiveExtension `json:"_valueTime,omitempty"` + BasedOn []*Reference `json:"basedOn,omitempty"` + BodySite *CodeableConcept `json:"bodySite,omitempty"` + BodyStructure *Reference `json:"bodyStructure,omitempty"` + Category []*CodeableConcept `json:"category,omitempty"` + Code *CodeableConcept `json:"code"` + Component []*ObservationComponent `json:"component,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + DataAbsentReason *CodeableConcept `json:"dataAbsentReason,omitempty"` + DerivedFrom []*Reference `json:"derivedFrom,omitempty"` + Device *Reference `json:"device,omitempty"` + EffectiveDateTime *string `json:"effectiveDateTime,omitempty"` + EffectiveInstant *string `json:"effectiveInstant,omitempty"` + EffectivePeriod *Period `json:"effectivePeriod,omitempty"` + EffectiveTiming *Timing `json:"effectiveTiming,omitempty"` + Encounter *Reference `json:"encounter,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Focus []*Reference `json:"focus,omitempty"` + HasMember []*Reference `json:"hasMember,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + InstantiatesCanonical *string `json:"instantiatesCanonical,omitempty"` + InstantiatesReference *Reference `json:"instantiatesReference,omitempty"` + Interpretation []*CodeableConcept `json:"interpretation,omitempty"` + Issued *string `json:"issued,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + Method *CodeableConcept `json:"method,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + PartOf []*Reference `json:"partOf,omitempty"` + Performer []*Reference `json:"performer,omitempty"` + ReferenceRange []*ObservationReferenceRange `json:"referenceRange,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Specimen *Reference `json:"specimen,omitempty"` + Status *string `json:"status,omitempty"` + Subject *Reference `json:"subject,omitempty"` + Text *Narrative `json:"text,omitempty"` + TriggeredBy []*ObservationTriggeredBy `json:"triggeredBy,omitempty"` + ValueAttachment *Attachment `json:"valueAttachment,omitempty"` + ValueBoolean *bool `json:"valueBoolean,omitempty"` + ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` + ValueDateTime *string `json:"valueDateTime,omitempty"` + ValueInteger *int64 `json:"valueInteger,omitempty"` + ValuePeriod *Period `json:"valuePeriod,omitempty"` + ValueQuantity *Quantity `json:"valueQuantity,omitempty"` + ValueRange *Range `json:"valueRange,omitempty"` + ValueRatio *Ratio `json:"valueRatio,omitempty"` + ValueReference *Reference `json:"valueReference,omitempty"` + ValueSampledData *SampledData `json:"valueSampledData,omitempty"` + ValueString *string `json:"valueString,omitempty"` + ValueTime *string `json:"valueTime,omitempty"` +} + +// ObservationComponent +type ObservationComponent struct { + XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` + XValueDateTime *FHIRPrimitiveExtension `json:"_valueDateTime,omitempty"` + XValueInteger *FHIRPrimitiveExtension `json:"_valueInteger,omitempty"` + XValueString *FHIRPrimitiveExtension `json:"_valueString,omitempty"` + XValueTime *FHIRPrimitiveExtension `json:"_valueTime,omitempty"` + Code *CodeableConcept `json:"code"` + DataAbsentReason *CodeableConcept `json:"dataAbsentReason,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Interpretation []*CodeableConcept `json:"interpretation,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ReferenceRange []*ObservationReferenceRange `json:"referenceRange,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + ValueAttachment *Attachment `json:"valueAttachment,omitempty"` + ValueBoolean *bool `json:"valueBoolean,omitempty"` + ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` + ValueDateTime *string `json:"valueDateTime,omitempty"` + ValueInteger *int64 `json:"valueInteger,omitempty"` + ValuePeriod *Period `json:"valuePeriod,omitempty"` + ValueQuantity *Quantity `json:"valueQuantity,omitempty"` + ValueRange *Range `json:"valueRange,omitempty"` + ValueRatio *Ratio `json:"valueRatio,omitempty"` + ValueReference *Reference `json:"valueReference,omitempty"` + ValueSampledData *SampledData `json:"valueSampledData,omitempty"` + ValueString *string `json:"valueString,omitempty"` + ValueTime *string `json:"valueTime,omitempty"` +} + +// ObservationReferenceRange +type ObservationReferenceRange struct { + XText *FHIRPrimitiveExtension `json:"_text,omitempty"` + Age *Range `json:"age,omitempty"` + AppliesTo []*CodeableConcept `json:"appliesTo,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + High *Quantity `json:"high,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Low *Quantity `json:"low,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + NormalValue *CodeableConcept `json:"normalValue,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Text *string `json:"text,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` +} + +// ObservationTriggeredBy +type ObservationTriggeredBy struct { + XReason *FHIRPrimitiveExtension `json:"_reason,omitempty"` + XType *FHIRPrimitiveExtension `json:"_type,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Observation *Reference `json:"observation"` + Reason *string `json:"reason,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *string `json:"type,omitempty"` +} + +// Organization +type Organization struct { + XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` + XAlias []*FHIRPrimitiveExtension `json:"_alias,omitempty"` + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + Active *bool `json:"active,omitempty"` + Alias []string `json:"alias,omitempty"` + Contact []*ExtendedContactDetail `json:"contact,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Description *string `json:"description,omitempty"` + Endpoint []*Reference `json:"endpoint,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Name *string `json:"name,omitempty"` + PartOf *Reference `json:"partOf,omitempty"` + Qualification []*OrganizationQualification `json:"qualification,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Text *Narrative `json:"text,omitempty"` + Type []*CodeableConcept `json:"type,omitempty"` +} + +// OrganizationQualification +type OrganizationQualification struct { + Code *CodeableConcept `json:"code"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + Issuer *Reference `json:"issuer,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Period *Period `json:"period,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// ParameterDefinition +type ParameterDefinition struct { + XDocumentation *FHIRPrimitiveExtension `json:"_documentation,omitempty"` + XMax *FHIRPrimitiveExtension `json:"_max,omitempty"` + XMin *FHIRPrimitiveExtension `json:"_min,omitempty"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + XProfile *FHIRPrimitiveExtension `json:"_profile,omitempty"` + XType *FHIRPrimitiveExtension `json:"_type,omitempty"` + XUse *FHIRPrimitiveExtension `json:"_use,omitempty"` + Documentation *string `json:"documentation,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Max *string `json:"max,omitempty"` + Min *int64 `json:"min,omitempty"` + Name *string `json:"name,omitempty"` + Profile *string `json:"profile,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *string `json:"type,omitempty"` + Use *string `json:"use,omitempty"` +} + +// Patient +type Patient struct { + XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` + XBirthDate *FHIRPrimitiveExtension `json:"_birthDate,omitempty"` + XDeceasedBoolean *FHIRPrimitiveExtension `json:"_deceasedBoolean,omitempty"` + XDeceasedDateTime *FHIRPrimitiveExtension `json:"_deceasedDateTime,omitempty"` + XGender *FHIRPrimitiveExtension `json:"_gender,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XMultipleBirthBoolean *FHIRPrimitiveExtension `json:"_multipleBirthBoolean,omitempty"` + XMultipleBirthInteger *FHIRPrimitiveExtension `json:"_multipleBirthInteger,omitempty"` + Active *bool `json:"active,omitempty"` + Address []*Address `json:"address,omitempty"` + BirthDate *string `json:"birthDate,omitempty"` + Communication []*PatientCommunication `json:"communication,omitempty"` + Contact []*PatientContact `json:"contact,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + DeceasedBoolean *bool `json:"deceasedBoolean,omitempty"` + DeceasedDateTime *string `json:"deceasedDateTime,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Gender *string `json:"gender,omitempty"` + GeneralPractitioner []*Reference `json:"generalPractitioner,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Language *string `json:"language,omitempty"` + Link []*PatientLink `json:"link,omitempty"` + Links [][]any `json:"links,omitempty"` + ManagingOrganization *Reference `json:"managingOrganization,omitempty"` + MaritalStatus *CodeableConcept `json:"maritalStatus,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + MultipleBirthBoolean *bool `json:"multipleBirthBoolean,omitempty"` + MultipleBirthInteger *int64 `json:"multipleBirthInteger,omitempty"` + Name []*HumanName `json:"name,omitempty"` + Photo []*Attachment `json:"photo,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Telecom []*ContactPoint `json:"telecom,omitempty"` + Text *Narrative `json:"text,omitempty"` +} + +// PatientCommunication +type PatientCommunication struct { + XPreferred *FHIRPrimitiveExtension `json:"_preferred,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Language *CodeableConcept `json:"language"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Preferred *bool `json:"preferred,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// PatientContact +type PatientContact struct { + XGender *FHIRPrimitiveExtension `json:"_gender,omitempty"` + Address *Address `json:"address,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Gender *string `json:"gender,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Name *HumanName `json:"name,omitempty"` + Organization *Reference `json:"organization,omitempty"` + Period *Period `json:"period,omitempty"` + Relationship []*CodeableConcept `json:"relationship,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Telecom []*ContactPoint `json:"telecom,omitempty"` +} + +// PatientLink +type PatientLink struct { + XType *FHIRPrimitiveExtension `json:"_type,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Other *Reference `json:"other"` + ResourceType *string `json:"resourceType,omitempty"` + Type *string `json:"type,omitempty"` +} + +// Period +type Period struct { + XEnd *FHIRPrimitiveExtension `json:"_end,omitempty"` + XStart *FHIRPrimitiveExtension `json:"_start,omitempty"` + End *string `json:"end,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Start *string `json:"start,omitempty"` +} + +// Practitioner +type Practitioner struct { + XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` + XBirthDate *FHIRPrimitiveExtension `json:"_birthDate,omitempty"` + XDeceasedBoolean *FHIRPrimitiveExtension `json:"_deceasedBoolean,omitempty"` + XDeceasedDateTime *FHIRPrimitiveExtension `json:"_deceasedDateTime,omitempty"` + XGender *FHIRPrimitiveExtension `json:"_gender,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + Active *bool `json:"active,omitempty"` + Address []*Address `json:"address,omitempty"` + BirthDate *string `json:"birthDate,omitempty"` + Communication []*PractitionerCommunication `json:"communication,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + DeceasedBoolean *bool `json:"deceasedBoolean,omitempty"` + DeceasedDateTime *string `json:"deceasedDateTime,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Gender *string `json:"gender,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Name []*HumanName `json:"name,omitempty"` + Photo []*Attachment `json:"photo,omitempty"` + Qualification []*PractitionerQualification `json:"qualification,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Telecom []*ContactPoint `json:"telecom,omitempty"` + Text *Narrative `json:"text,omitempty"` +} + +// PractitionerCommunication +type PractitionerCommunication struct { + XPreferred *FHIRPrimitiveExtension `json:"_preferred,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Language *CodeableConcept `json:"language"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Preferred *bool `json:"preferred,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// PractitionerQualification +type PractitionerQualification struct { + Code *CodeableConcept `json:"code"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + Issuer *Reference `json:"issuer,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Period *Period `json:"period,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// PractitionerRole +type PractitionerRole struct { + XActive *FHIRPrimitiveExtension `json:"_active,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + Active *bool `json:"active,omitempty"` + Availability []*Availability `json:"availability,omitempty"` + Characteristic []*CodeableConcept `json:"characteristic,omitempty"` + Code []*CodeableConcept `json:"code,omitempty"` + Communication []*CodeableConcept `json:"communication,omitempty"` + Contact []*ExtendedContactDetail `json:"contact,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Endpoint []*Reference `json:"endpoint,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + HealthcareService []*Reference `json:"healthcareService,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Location []*Reference `json:"location,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Organization *Reference `json:"organization,omitempty"` + Period *Period `json:"period,omitempty"` + Practitioner *Reference `json:"practitioner,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Specialty []*CodeableConcept `json:"specialty,omitempty"` + Text *Narrative `json:"text,omitempty"` +} + +// Procedure +type Procedure struct { + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XInstantiatesCanonical []*FHIRPrimitiveExtension `json:"_instantiatesCanonical,omitempty"` + XInstantiatesURI []*FHIRPrimitiveExtension `json:"_instantiatesUri,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XOccurrenceDateTime *FHIRPrimitiveExtension `json:"_occurrenceDateTime,omitempty"` + XOccurrenceString *FHIRPrimitiveExtension `json:"_occurrenceString,omitempty"` + XRecorded *FHIRPrimitiveExtension `json:"_recorded,omitempty"` + XReportedBoolean *FHIRPrimitiveExtension `json:"_reportedBoolean,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + BasedOn []*Reference `json:"basedOn,omitempty"` + BodySite []*CodeableConcept `json:"bodySite,omitempty"` + Category []*CodeableConcept `json:"category,omitempty"` + Code *CodeableConcept `json:"code,omitempty"` + Complication []*CodeableReference `json:"complication,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Encounter *Reference `json:"encounter,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + FocalDevice []*ProcedureFocalDevice `json:"focalDevice,omitempty"` + Focus *Reference `json:"focus,omitempty"` + FollowUp []*CodeableConcept `json:"followUp,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + InstantiatesCanonical []string `json:"instantiatesCanonical,omitempty"` + InstantiatesURI []string `json:"instantiatesUri,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Location *Reference `json:"location,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + OccurrenceAge *Age `json:"occurrenceAge,omitempty"` + OccurrenceDateTime *string `json:"occurrenceDateTime,omitempty"` + OccurrencePeriod *Period `json:"occurrencePeriod,omitempty"` + OccurrenceRange *Range `json:"occurrenceRange,omitempty"` + OccurrenceString *string `json:"occurrenceString,omitempty"` + OccurrenceTiming *Timing `json:"occurrenceTiming,omitempty"` + Outcome *CodeableConcept `json:"outcome,omitempty"` + PartOf []*Reference `json:"partOf,omitempty"` + Performer []*ProcedurePerformer `json:"performer,omitempty"` + Reason []*CodeableReference `json:"reason,omitempty"` + Recorded *string `json:"recorded,omitempty"` + Recorder *Reference `json:"recorder,omitempty"` + Report []*Reference `json:"report,omitempty"` + ReportedBoolean *bool `json:"reportedBoolean,omitempty"` + ReportedReference *Reference `json:"reportedReference,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Status *string `json:"status,omitempty"` + StatusReason *CodeableConcept `json:"statusReason,omitempty"` + Subject *Reference `json:"subject"` + SupportingInfo []*Reference `json:"supportingInfo,omitempty"` + Text *Narrative `json:"text,omitempty"` + Used []*CodeableReference `json:"used,omitempty"` +} + +// ProcedureFocalDevice +type ProcedureFocalDevice struct { + Action *CodeableConcept `json:"action,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Manipulated *Reference `json:"manipulated"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// ProcedurePerformer +type ProcedurePerformer struct { + Actor *Reference `json:"actor"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Function *CodeableConcept `json:"function,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + OnBehalfOf *Reference `json:"onBehalfOf,omitempty"` + Period *Period `json:"period,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// Quantity +type Quantity struct { + XCode *FHIRPrimitiveExtension `json:"_code,omitempty"` + XComparator *FHIRPrimitiveExtension `json:"_comparator,omitempty"` + XSystem *FHIRPrimitiveExtension `json:"_system,omitempty"` + XUnit *FHIRPrimitiveExtension `json:"_unit,omitempty"` + XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` + Code *string `json:"code,omitempty"` + Comparator *string `json:"comparator,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + System *string `json:"system,omitempty"` + Unit *string `json:"unit,omitempty"` + Value *float64 `json:"value,omitempty"` +} + +// Range +type Range struct { + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + High *Quantity `json:"high,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Low *Quantity `json:"low,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// Ratio +type Ratio struct { + Denominator *Quantity `json:"denominator,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Numerator *Quantity `json:"numerator,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// RatioRange +type RatioRange struct { + Denominator *Quantity `json:"denominator,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + HighNumerator *Quantity `json:"highNumerator,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + LowNumerator *Quantity `json:"lowNumerator,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// Reference +type Reference struct { + XDisplay *FHIRPrimitiveExtension `json:"_display,omitempty"` + XReference *FHIRPrimitiveExtension `json:"_reference,omitempty"` + XType *FHIRPrimitiveExtension `json:"_type,omitempty"` + Display *string `json:"display,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier *Identifier `json:"identifier,omitempty"` + Links [][]any `json:"links,omitempty"` + Reference *string `json:"reference,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *string `json:"type,omitempty"` +} + +// RelatedArtifact +type RelatedArtifact struct { + XCitation *FHIRPrimitiveExtension `json:"_citation,omitempty"` + XDisplay *FHIRPrimitiveExtension `json:"_display,omitempty"` + XLabel *FHIRPrimitiveExtension `json:"_label,omitempty"` + XPublicationDate *FHIRPrimitiveExtension `json:"_publicationDate,omitempty"` + XPublicationStatus *FHIRPrimitiveExtension `json:"_publicationStatus,omitempty"` + XResource *FHIRPrimitiveExtension `json:"_resource,omitempty"` + XType *FHIRPrimitiveExtension `json:"_type,omitempty"` + Citation *string `json:"citation,omitempty"` + Classifier []*CodeableConcept `json:"classifier,omitempty"` + Display *string `json:"display,omitempty"` + Document *Attachment `json:"document,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Label *string `json:"label,omitempty"` + Links [][]any `json:"links,omitempty"` + PublicationDate *string `json:"publicationDate,omitempty"` + PublicationStatus *string `json:"publicationStatus,omitempty"` + Resource *string `json:"resource,omitempty"` + ResourceReference *Reference `json:"resourceReference,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *string `json:"type,omitempty"` +} + +// ResearchStudy +type ResearchStudy struct { + XDate *FHIRPrimitiveExtension `json:"_date,omitempty"` + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XDescriptionSummary *FHIRPrimitiveExtension `json:"_descriptionSummary,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + XTitle *FHIRPrimitiveExtension `json:"_title,omitempty"` + XURL *FHIRPrimitiveExtension `json:"_url,omitempty"` + XVersion *FHIRPrimitiveExtension `json:"_version,omitempty"` + AssociatedParty []*ResearchStudyAssociatedParty `json:"associatedParty,omitempty"` + Classifier []*CodeableConcept `json:"classifier,omitempty"` + ComparisonGroup []*ResearchStudyComparisonGroup `json:"comparisonGroup,omitempty"` + Condition []*CodeableConcept `json:"condition,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Date *string `json:"date,omitempty"` + Description *string `json:"description,omitempty"` + DescriptionSummary *string `json:"descriptionSummary,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Focus []*CodeableReference `json:"focus,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Keyword []*CodeableConcept `json:"keyword,omitempty"` + Label []*ResearchStudyLabel `json:"label,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Name *string `json:"name,omitempty"` + Note []*Annotation `json:"note,omitempty"` + Objective []*ResearchStudyObjective `json:"objective,omitempty"` + OutcomeMeasure []*ResearchStudyOutcomeMeasure `json:"outcomeMeasure,omitempty"` + PartOf []*Reference `json:"partOf,omitempty"` + Period *Period `json:"period,omitempty"` + Phase *CodeableConcept `json:"phase,omitempty"` + PrimaryPurposeType *CodeableConcept `json:"primaryPurposeType,omitempty"` + ProgressStatus []*ResearchStudyProgressStatus `json:"progressStatus,omitempty"` + Protocol []*Reference `json:"protocol,omitempty"` + Recruitment *ResearchStudyRecruitment `json:"recruitment,omitempty"` + Region []*CodeableConcept `json:"region,omitempty"` + RelatedArtifact []*RelatedArtifact `json:"relatedArtifact,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Result []*Reference `json:"result,omitempty"` + RootDir *Reference `json:"rootDir,omitempty"` + Site []*Reference `json:"site,omitempty"` + Status *string `json:"status,omitempty"` + StudyDesign []*CodeableConcept `json:"studyDesign,omitempty"` + Text *Narrative `json:"text,omitempty"` + Title *string `json:"title,omitempty"` + URL *string `json:"url,omitempty"` + Version *string `json:"version,omitempty"` + WhyStopped *CodeableConcept `json:"whyStopped,omitempty"` +} + +// ResearchStudyAssociatedParty +type ResearchStudyAssociatedParty struct { + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + Classifier []*CodeableConcept `json:"classifier,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Name *string `json:"name,omitempty"` + Party *Reference `json:"party,omitempty"` + Period []*Period `json:"period,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Role *CodeableConcept `json:"role"` +} + +// ResearchStudyComparisonGroup +type ResearchStudyComparisonGroup struct { + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XLinkID *FHIRPrimitiveExtension `json:"_linkId,omitempty"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + Description *string `json:"description,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IntendedExposure []*Reference `json:"intendedExposure,omitempty"` + LinkID *string `json:"linkId,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Name *string `json:"name,omitempty"` + ObservedGroup *Reference `json:"observedGroup,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` +} + +// ResearchStudyLabel +type ResearchStudyLabel struct { + XValue *FHIRPrimitiveExtension `json:"_value,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` + Value *string `json:"value,omitempty"` +} + +// ResearchStudyObjective +type ResearchStudyObjective struct { + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + Description *string `json:"description,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Name *string `json:"name,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` +} + +// ResearchStudyOutcomeMeasure +type ResearchStudyOutcomeMeasure struct { + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + Description *string `json:"description,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Name *string `json:"name,omitempty"` + Reference *Reference `json:"reference,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type []*CodeableConcept `json:"type,omitempty"` +} + +// ResearchStudyProgressStatus +type ResearchStudyProgressStatus struct { + XActual *FHIRPrimitiveExtension `json:"_actual,omitempty"` + Actual *bool `json:"actual,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Period *Period `json:"period,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + State *CodeableConcept `json:"state"` +} + +// ResearchStudyRecruitment +type ResearchStudyRecruitment struct { + XActualNumber *FHIRPrimitiveExtension `json:"_actualNumber,omitempty"` + XTargetNumber *FHIRPrimitiveExtension `json:"_targetNumber,omitempty"` + ActualGroup *Reference `json:"actualGroup,omitempty"` + ActualNumber *int64 `json:"actualNumber,omitempty"` + Eligibility *Reference `json:"eligibility,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + TargetNumber *int64 `json:"targetNumber,omitempty"` +} + +// ResearchSubject +type ResearchSubject struct { + XActualComparisonGroup *FHIRPrimitiveExtension `json:"_actualComparisonGroup,omitempty"` + XAssignedComparisonGroup *FHIRPrimitiveExtension `json:"_assignedComparisonGroup,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + ActualComparisonGroup *string `json:"actualComparisonGroup,omitempty"` + AssignedComparisonGroup *string `json:"assignedComparisonGroup,omitempty"` + Consent []*Reference `json:"consent,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Period *Period `json:"period,omitempty"` + Progress []*ResearchSubjectProgress `json:"progress,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Status *string `json:"status,omitempty"` + Study *Reference `json:"study"` + Subject *Reference `json:"subject"` + Text *Narrative `json:"text,omitempty"` +} + +// ResearchSubjectProgress +type ResearchSubjectProgress struct { + XEndDate *FHIRPrimitiveExtension `json:"_endDate,omitempty"` + XStartDate *FHIRPrimitiveExtension `json:"_startDate,omitempty"` + EndDate *string `json:"endDate,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Milestone *CodeableConcept `json:"milestone,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Reason *CodeableConcept `json:"reason,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + StartDate *string `json:"startDate,omitempty"` + SubjectState *CodeableConcept `json:"subjectState,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` +} + +// Resource +type Resource struct { + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// SampledData +type SampledData struct { + XCodeMap *FHIRPrimitiveExtension `json:"_codeMap,omitempty"` + XData *FHIRPrimitiveExtension `json:"_data,omitempty"` + XDimensions *FHIRPrimitiveExtension `json:"_dimensions,omitempty"` + XFactor *FHIRPrimitiveExtension `json:"_factor,omitempty"` + XInterval *FHIRPrimitiveExtension `json:"_interval,omitempty"` + XIntervalUnit *FHIRPrimitiveExtension `json:"_intervalUnit,omitempty"` + XLowerLimit *FHIRPrimitiveExtension `json:"_lowerLimit,omitempty"` + XOffsets *FHIRPrimitiveExtension `json:"_offsets,omitempty"` + XUpperLimit *FHIRPrimitiveExtension `json:"_upperLimit,omitempty"` + CodeMap *string `json:"codeMap,omitempty"` + Data *string `json:"data,omitempty"` + Dimensions *int64 `json:"dimensions,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + Factor *float64 `json:"factor,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Interval *float64 `json:"interval,omitempty"` + IntervalUnit *string `json:"intervalUnit,omitempty"` + Links [][]any `json:"links,omitempty"` + LowerLimit *float64 `json:"lowerLimit,omitempty"` + Offsets *string `json:"offsets,omitempty"` + Origin *Quantity `json:"origin"` + ResourceType *string `json:"resourceType,omitempty"` + UpperLimit *float64 `json:"upperLimit,omitempty"` +} + +// Signature +type Signature struct { + XData *FHIRPrimitiveExtension `json:"_data,omitempty"` + XSigFormat *FHIRPrimitiveExtension `json:"_sigFormat,omitempty"` + XTargetFormat *FHIRPrimitiveExtension `json:"_targetFormat,omitempty"` + XWhen *FHIRPrimitiveExtension `json:"_when,omitempty"` + Data *string `json:"data,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + OnBehalfOf *Reference `json:"onBehalfOf,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SigFormat *string `json:"sigFormat,omitempty"` + TargetFormat *string `json:"targetFormat,omitempty"` + Type []*Coding `json:"type,omitempty"` + When *string `json:"when,omitempty"` + Who *Reference `json:"who,omitempty"` +} + +// Specimen +type Specimen struct { + XCombined *FHIRPrimitiveExtension `json:"_combined,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XReceivedTime *FHIRPrimitiveExtension `json:"_receivedTime,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + AccessionIDentifier *Identifier `json:"accessionIdentifier,omitempty"` + Collection *SpecimenCollection `json:"collection,omitempty"` + Combined *string `json:"combined,omitempty"` + Condition []*CodeableConcept `json:"condition,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Container []*SpecimenContainer `json:"container,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + Feature []*SpecimenFeature `json:"feature,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + Parent []*Reference `json:"parent,omitempty"` + Processing []*SpecimenProcessing `json:"processing,omitempty"` + ReceivedTime *string `json:"receivedTime,omitempty"` + Request []*Reference `json:"request,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Role []*CodeableConcept `json:"role,omitempty"` + Status *string `json:"status,omitempty"` + Subject *Reference `json:"subject,omitempty"` + Text *Narrative `json:"text,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` +} + +// SpecimenCollection +type SpecimenCollection struct { + XCollectedDateTime *FHIRPrimitiveExtension `json:"_collectedDateTime,omitempty"` + BodySite *CodeableReference `json:"bodySite,omitempty"` + CollectedDateTime *string `json:"collectedDateTime,omitempty"` + CollectedPeriod *Period `json:"collectedPeriod,omitempty"` + Collector *Reference `json:"collector,omitempty"` + Device *CodeableReference `json:"device,omitempty"` + Duration *Duration `json:"duration,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FastingStatusCodeableConcept *CodeableConcept `json:"fastingStatusCodeableConcept,omitempty"` + FastingStatusDuration *Duration `json:"fastingStatusDuration,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Method *CodeableConcept `json:"method,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Procedure *Reference `json:"procedure,omitempty"` + Quantity *Quantity `json:"quantity,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// SpecimenContainer +type SpecimenContainer struct { + Device *Reference `json:"device"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Location *Reference `json:"location,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SpecimenQuantity *Quantity `json:"specimenQuantity,omitempty"` +} + +// SpecimenFeature +type SpecimenFeature struct { + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + Description *string `json:"description,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *CodeableConcept `json:"type"` +} + +// SpecimenProcessing +type SpecimenProcessing struct { + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XTimeDateTime *FHIRPrimitiveExtension `json:"_timeDateTime,omitempty"` + Additive []*Reference `json:"additive,omitempty"` + Description *string `json:"description,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Method *CodeableConcept `json:"method,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + TimeDateTime *string `json:"timeDateTime,omitempty"` + TimePeriod *Period `json:"timePeriod,omitempty"` +} + +// Substance +type Substance struct { + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XExpiry *FHIRPrimitiveExtension `json:"_expiry,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XInstance *FHIRPrimitiveExtension `json:"_instance,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + Category []*CodeableConcept `json:"category,omitempty"` + Code *CodeableReference `json:"code"` + Contained []*Resource `json:"contained,omitempty"` + Description *string `json:"description,omitempty"` + Expiry *string `json:"expiry,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Ingredient []*SubstanceIngredient `json:"ingredient,omitempty"` + Instance *bool `json:"instance,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Quantity *Quantity `json:"quantity,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Status *string `json:"status,omitempty"` + Text *Narrative `json:"text,omitempty"` +} + +// SubstanceDefinition +type SubstanceDefinition struct { + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XVersion *FHIRPrimitiveExtension `json:"_version,omitempty"` + Characterization []*SubstanceDefinitionCharacterization `json:"characterization,omitempty"` + Classification []*CodeableConcept `json:"classification,omitempty"` + Code []*SubstanceDefinitionCode `json:"code,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Description *string `json:"description,omitempty"` + Domain *CodeableConcept `json:"domain,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Grade []*CodeableConcept `json:"grade,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + InformationSource []*Reference `json:"informationSource,omitempty"` + Language *string `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + Manufacturer []*Reference `json:"manufacturer,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Moiety []*SubstanceDefinitionMoiety `json:"moiety,omitempty"` + MolecularWeight []*SubstanceDefinitionMolecularWeight `json:"molecularWeight,omitempty"` + Name []*SubstanceDefinitionName `json:"name,omitempty"` + Note []*Annotation `json:"note,omitempty"` + NucleicAcid *Reference `json:"nucleicAcid,omitempty"` + Polymer *Reference `json:"polymer,omitempty"` + Property []*SubstanceDefinitionProperty `json:"property,omitempty"` + Protein *Reference `json:"protein,omitempty"` + ReferenceInformation *Reference `json:"referenceInformation,omitempty"` + Relationship []*SubstanceDefinitionRelationship `json:"relationship,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SourceMaterial *SubstanceDefinitionSourceMaterial `json:"sourceMaterial,omitempty"` + Status *CodeableConcept `json:"status,omitempty"` + Structure *SubstanceDefinitionStructure `json:"structure,omitempty"` + Supplier []*Reference `json:"supplier,omitempty"` + Text *Narrative `json:"text,omitempty"` + Version *string `json:"version,omitempty"` +} + +// SubstanceDefinitionCharacterization +type SubstanceDefinitionCharacterization struct { + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + Description *string `json:"description,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + File []*Attachment `json:"file,omitempty"` + Form *CodeableConcept `json:"form,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Technique *CodeableConcept `json:"technique,omitempty"` +} + +// SubstanceDefinitionCode +type SubstanceDefinitionCode struct { + XStatusDate *FHIRPrimitiveExtension `json:"_statusDate,omitempty"` + Code *CodeableConcept `json:"code,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Source []*Reference `json:"source,omitempty"` + Status *CodeableConcept `json:"status,omitempty"` + StatusDate *string `json:"statusDate,omitempty"` +} + +// SubstanceDefinitionMoiety +type SubstanceDefinitionMoiety struct { + XAmountString *FHIRPrimitiveExtension `json:"_amountString,omitempty"` + XMolecularFormula *FHIRPrimitiveExtension `json:"_molecularFormula,omitempty"` + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + AmountQuantity *Quantity `json:"amountQuantity,omitempty"` + AmountString *string `json:"amountString,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier *Identifier `json:"identifier,omitempty"` + Links [][]any `json:"links,omitempty"` + MeasurementType *CodeableConcept `json:"measurementType,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + MolecularFormula *string `json:"molecularFormula,omitempty"` + Name *string `json:"name,omitempty"` + OpticalActivity *CodeableConcept `json:"opticalActivity,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Role *CodeableConcept `json:"role,omitempty"` + Stereochemistry *CodeableConcept `json:"stereochemistry,omitempty"` +} + +// SubstanceDefinitionMolecularWeight +type SubstanceDefinitionMolecularWeight struct { + Amount *Quantity `json:"amount"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Method *CodeableConcept `json:"method,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` +} + +// SubstanceDefinitionName +type SubstanceDefinitionName struct { + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + XPreferred *FHIRPrimitiveExtension `json:"_preferred,omitempty"` + Domain []*CodeableConcept `json:"domain,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Jurisdiction []*CodeableConcept `json:"jurisdiction,omitempty"` + Language []*CodeableConcept `json:"language,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Name *string `json:"name,omitempty"` + Official []*SubstanceDefinitionNameOfficial `json:"official,omitempty"` + Preferred *bool `json:"preferred,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Source []*Reference `json:"source,omitempty"` + Status *CodeableConcept `json:"status,omitempty"` + Synonym []*SubstanceDefinitionName `json:"synonym,omitempty"` + Translation []*SubstanceDefinitionName `json:"translation,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` +} + +// SubstanceDefinitionNameOfficial +type SubstanceDefinitionNameOfficial struct { + XDate *FHIRPrimitiveExtension `json:"_date,omitempty"` + Authority *CodeableConcept `json:"authority,omitempty"` + Date *string `json:"date,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Status *CodeableConcept `json:"status,omitempty"` +} + +// SubstanceDefinitionProperty +type SubstanceDefinitionProperty struct { + XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` + XValueDate *FHIRPrimitiveExtension `json:"_valueDate,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *CodeableConcept `json:"type"` + ValueAttachment *Attachment `json:"valueAttachment,omitempty"` + ValueBoolean *bool `json:"valueBoolean,omitempty"` + ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` + ValueDate *string `json:"valueDate,omitempty"` + ValueQuantity *Quantity `json:"valueQuantity,omitempty"` +} + +// SubstanceDefinitionRelationship +type SubstanceDefinitionRelationship struct { + XAmountString *FHIRPrimitiveExtension `json:"_amountString,omitempty"` + XIsDefining *FHIRPrimitiveExtension `json:"_isDefining,omitempty"` + AmountQuantity *Quantity `json:"amountQuantity,omitempty"` + AmountRatio *Ratio `json:"amountRatio,omitempty"` + AmountString *string `json:"amountString,omitempty"` + Comparator *CodeableConcept `json:"comparator,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + IsDefining *bool `json:"isDefining,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + RatioHighLimitAmount *Ratio `json:"ratioHighLimitAmount,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Source []*Reference `json:"source,omitempty"` + SubstanceDefinitionCodeableConcept *CodeableConcept `json:"substanceDefinitionCodeableConcept,omitempty"` + SubstanceDefinitionReference *Reference `json:"substanceDefinitionReference,omitempty"` + Type *CodeableConcept `json:"type"` +} + +// SubstanceDefinitionSourceMaterial +type SubstanceDefinitionSourceMaterial struct { + CountryOfOrigin []*CodeableConcept `json:"countryOfOrigin,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Genus *CodeableConcept `json:"genus,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Part *CodeableConcept `json:"part,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Species *CodeableConcept `json:"species,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` +} + +// SubstanceDefinitionStructure +type SubstanceDefinitionStructure struct { + XMolecularFormula *FHIRPrimitiveExtension `json:"_molecularFormula,omitempty"` + XMolecularFormulaByMoiety *FHIRPrimitiveExtension `json:"_molecularFormulaByMoiety,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + MolecularFormula *string `json:"molecularFormula,omitempty"` + MolecularFormulaByMoiety *string `json:"molecularFormulaByMoiety,omitempty"` + MolecularWeight *SubstanceDefinitionMolecularWeight `json:"molecularWeight,omitempty"` + OpticalActivity *CodeableConcept `json:"opticalActivity,omitempty"` + Representation []*SubstanceDefinitionStructureRepresentation `json:"representation,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SourceDocument []*Reference `json:"sourceDocument,omitempty"` + Stereochemistry *CodeableConcept `json:"stereochemistry,omitempty"` + Technique []*CodeableConcept `json:"technique,omitempty"` +} + +// SubstanceDefinitionStructureRepresentation +type SubstanceDefinitionStructureRepresentation struct { + XRepresentation *FHIRPrimitiveExtension `json:"_representation,omitempty"` + Document *Reference `json:"document,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Format *CodeableConcept `json:"format,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Representation *string `json:"representation,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *CodeableConcept `json:"type,omitempty"` +} + +// SubstanceIngredient +type SubstanceIngredient struct { + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Quantity *Ratio `json:"quantity,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SubstanceCodeableConcept *CodeableConcept `json:"substanceCodeableConcept,omitempty"` + SubstanceReference *Reference `json:"substanceReference,omitempty"` +} + +// Task +type Task struct { + XAuthoredOn *FHIRPrimitiveExtension `json:"_authoredOn,omitempty"` + XDescription *FHIRPrimitiveExtension `json:"_description,omitempty"` + XDoNotPerform *FHIRPrimitiveExtension `json:"_doNotPerform,omitempty"` + XImplicitRules *FHIRPrimitiveExtension `json:"_implicitRules,omitempty"` + XInstantiatesCanonical *FHIRPrimitiveExtension `json:"_instantiatesCanonical,omitempty"` + XInstantiatesURI *FHIRPrimitiveExtension `json:"_instantiatesUri,omitempty"` + XIntent *FHIRPrimitiveExtension `json:"_intent,omitempty"` + XLanguage *FHIRPrimitiveExtension `json:"_language,omitempty"` + XLastModified *FHIRPrimitiveExtension `json:"_lastModified,omitempty"` + XPriority *FHIRPrimitiveExtension `json:"_priority,omitempty"` + XStatus *FHIRPrimitiveExtension `json:"_status,omitempty"` + AuthoredOn *string `json:"authoredOn,omitempty"` + BasedOn []*Reference `json:"basedOn,omitempty"` + BusinessStatus *CodeableConcept `json:"businessStatus,omitempty"` + Code *CodeableConcept `json:"code,omitempty"` + Contained []*Resource `json:"contained,omitempty"` + Description *string `json:"description,omitempty"` + DoNotPerform *bool `json:"doNotPerform,omitempty"` + Encounter *Reference `json:"encounter,omitempty"` + ExecutionPeriod *Period `json:"executionPeriod,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Focus *Reference `json:"focus,omitempty"` + ForFhir *Reference `json:"for_fhir,omitempty"` + GroupIDentifier *Identifier `json:"groupIdentifier,omitempty"` + ID *string `json:"id,omitempty"` + IDentifier []*Identifier `json:"identifier,omitempty"` + ImplicitRules *string `json:"implicitRules,omitempty"` + Input []*TaskInput `json:"input,omitempty"` + InstantiatesCanonical *string `json:"instantiatesCanonical,omitempty"` + InstantiatesURI *string `json:"instantiatesUri,omitempty"` + Insurance []*Reference `json:"insurance,omitempty"` + Intent *string `json:"intent,omitempty"` + Language *string `json:"language,omitempty"` + LastModified *string `json:"lastModified,omitempty"` + Links [][]any `json:"links,omitempty"` + Location *Reference `json:"location,omitempty"` + Meta *Meta `json:"meta,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Note []*Annotation `json:"note,omitempty"` + Output []*TaskOutput `json:"output,omitempty"` + Owner *Reference `json:"owner,omitempty"` + PartOf []*Reference `json:"partOf,omitempty"` + Performer []*TaskPerformer `json:"performer,omitempty"` + Priority *string `json:"priority,omitempty"` + Reason []*CodeableReference `json:"reason,omitempty"` + RelevantHistory []*Reference `json:"relevantHistory,omitempty"` + RequestedPerformer []*CodeableReference `json:"requestedPerformer,omitempty"` + RequestedPeriod *Period `json:"requestedPeriod,omitempty"` + Requester *Reference `json:"requester,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Restriction *TaskRestriction `json:"restriction,omitempty"` + Status *string `json:"status,omitempty"` + StatusReason *CodeableReference `json:"statusReason,omitempty"` + Text *Narrative `json:"text,omitempty"` +} + +// TaskInput +type TaskInput struct { + XValueBase64Binary *FHIRPrimitiveExtension `json:"_valueBase64Binary,omitempty"` + XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` + XValueCanonical *FHIRPrimitiveExtension `json:"_valueCanonical,omitempty"` + XValueCode *FHIRPrimitiveExtension `json:"_valueCode,omitempty"` + XValueDate *FHIRPrimitiveExtension `json:"_valueDate,omitempty"` + XValueDateTime *FHIRPrimitiveExtension `json:"_valueDateTime,omitempty"` + XValueDecimal *FHIRPrimitiveExtension `json:"_valueDecimal,omitempty"` + XValueID *FHIRPrimitiveExtension `json:"_valueId,omitempty"` + XValueInstant *FHIRPrimitiveExtension `json:"_valueInstant,omitempty"` + XValueInteger *FHIRPrimitiveExtension `json:"_valueInteger,omitempty"` + XValueInteger64 *FHIRPrimitiveExtension `json:"_valueInteger64,omitempty"` + XValueMarkdown *FHIRPrimitiveExtension `json:"_valueMarkdown,omitempty"` + XValueOid *FHIRPrimitiveExtension `json:"_valueOid,omitempty"` + XValuePositiveInt *FHIRPrimitiveExtension `json:"_valuePositiveInt,omitempty"` + XValueString *FHIRPrimitiveExtension `json:"_valueString,omitempty"` + XValueTime *FHIRPrimitiveExtension `json:"_valueTime,omitempty"` + XValueUnsignedInt *FHIRPrimitiveExtension `json:"_valueUnsignedInt,omitempty"` + XValueURI *FHIRPrimitiveExtension `json:"_valueUri,omitempty"` + XValueURL *FHIRPrimitiveExtension `json:"_valueUrl,omitempty"` + XValueUUID *FHIRPrimitiveExtension `json:"_valueUuid,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *CodeableConcept `json:"type"` + ValueAddress *Address `json:"valueAddress,omitempty"` + ValueAge *Age `json:"valueAge,omitempty"` + ValueAnnotation *Annotation `json:"valueAnnotation,omitempty"` + ValueAttachment *Attachment `json:"valueAttachment,omitempty"` + ValueAvailability *Availability `json:"valueAvailability,omitempty"` + ValueBase64Binary *string `json:"valueBase64Binary,omitempty"` + ValueBoolean *bool `json:"valueBoolean,omitempty"` + ValueCanonical *string `json:"valueCanonical,omitempty"` + ValueCode *string `json:"valueCode,omitempty"` + ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` + ValueCodeableReference *CodeableReference `json:"valueCodeableReference,omitempty"` + ValueCoding *Coding `json:"valueCoding,omitempty"` + ValueContactDetail *ContactDetail `json:"valueContactDetail,omitempty"` + ValueContactPoint *ContactPoint `json:"valueContactPoint,omitempty"` + ValueCount *Count `json:"valueCount,omitempty"` + ValueDataRequirement *DataRequirement `json:"valueDataRequirement,omitempty"` + ValueDate *string `json:"valueDate,omitempty"` + ValueDateTime *string `json:"valueDateTime,omitempty"` + ValueDecimal *float64 `json:"valueDecimal,omitempty"` + ValueDistance *Distance `json:"valueDistance,omitempty"` + ValueDosage *Dosage `json:"valueDosage,omitempty"` + ValueDuration *Duration `json:"valueDuration,omitempty"` + ValueExpression *Expression `json:"valueExpression,omitempty"` + ValueExtendedContactDetail *ExtendedContactDetail `json:"valueExtendedContactDetail,omitempty"` + ValueHumanName *HumanName `json:"valueHumanName,omitempty"` + ValueID *string `json:"valueId,omitempty"` + ValueIDentifier *Identifier `json:"valueIdentifier,omitempty"` + ValueInstant *string `json:"valueInstant,omitempty"` + ValueInteger *int64 `json:"valueInteger,omitempty"` + ValueInteger64 *int64 `json:"valueInteger64,omitempty"` + ValueMarkdown *string `json:"valueMarkdown,omitempty"` + ValueMeta *Meta `json:"valueMeta,omitempty"` + ValueMoney *Money `json:"valueMoney,omitempty"` + ValueOid *string `json:"valueOid,omitempty"` + ValueParameterDefinition *ParameterDefinition `json:"valueParameterDefinition,omitempty"` + ValuePeriod *Period `json:"valuePeriod,omitempty"` + ValuePositiveInt *int64 `json:"valuePositiveInt,omitempty"` + ValueQuantity *Quantity `json:"valueQuantity,omitempty"` + ValueRange *Range `json:"valueRange,omitempty"` + ValueRatio *Ratio `json:"valueRatio,omitempty"` + ValueRatioRange *RatioRange `json:"valueRatioRange,omitempty"` + ValueReference *Reference `json:"valueReference,omitempty"` + ValueRelatedArtifact *RelatedArtifact `json:"valueRelatedArtifact,omitempty"` + ValueSampledData *SampledData `json:"valueSampledData,omitempty"` + ValueSignature *Signature `json:"valueSignature,omitempty"` + ValueString *string `json:"valueString,omitempty"` + ValueTime *string `json:"valueTime,omitempty"` + ValueTiming *Timing `json:"valueTiming,omitempty"` + ValueTriggerDefinition *TriggerDefinition `json:"valueTriggerDefinition,omitempty"` + ValueUnsignedInt *int64 `json:"valueUnsignedInt,omitempty"` + ValueURI *string `json:"valueUri,omitempty"` + ValueURL *string `json:"valueUrl,omitempty"` + ValueUsageContext *UsageContext `json:"valueUsageContext,omitempty"` + ValueUUID *string `json:"valueUuid,omitempty"` +} + +// TaskOutput +type TaskOutput struct { + XValueBase64Binary *FHIRPrimitiveExtension `json:"_valueBase64Binary,omitempty"` + XValueBoolean *FHIRPrimitiveExtension `json:"_valueBoolean,omitempty"` + XValueCanonical *FHIRPrimitiveExtension `json:"_valueCanonical,omitempty"` + XValueCode *FHIRPrimitiveExtension `json:"_valueCode,omitempty"` + XValueDate *FHIRPrimitiveExtension `json:"_valueDate,omitempty"` + XValueDateTime *FHIRPrimitiveExtension `json:"_valueDateTime,omitempty"` + XValueDecimal *FHIRPrimitiveExtension `json:"_valueDecimal,omitempty"` + XValueID *FHIRPrimitiveExtension `json:"_valueId,omitempty"` + XValueInstant *FHIRPrimitiveExtension `json:"_valueInstant,omitempty"` + XValueInteger *FHIRPrimitiveExtension `json:"_valueInteger,omitempty"` + XValueInteger64 *FHIRPrimitiveExtension `json:"_valueInteger64,omitempty"` + XValueMarkdown *FHIRPrimitiveExtension `json:"_valueMarkdown,omitempty"` + XValueOid *FHIRPrimitiveExtension `json:"_valueOid,omitempty"` + XValuePositiveInt *FHIRPrimitiveExtension `json:"_valuePositiveInt,omitempty"` + XValueString *FHIRPrimitiveExtension `json:"_valueString,omitempty"` + XValueTime *FHIRPrimitiveExtension `json:"_valueTime,omitempty"` + XValueUnsignedInt *FHIRPrimitiveExtension `json:"_valueUnsignedInt,omitempty"` + XValueURI *FHIRPrimitiveExtension `json:"_valueUri,omitempty"` + XValueURL *FHIRPrimitiveExtension `json:"_valueUrl,omitempty"` + XValueUUID *FHIRPrimitiveExtension `json:"_valueUuid,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + Type *CodeableConcept `json:"type"` + ValueAddress *Address `json:"valueAddress,omitempty"` + ValueAge *Age `json:"valueAge,omitempty"` + ValueAnnotation *Annotation `json:"valueAnnotation,omitempty"` + ValueAttachment *Attachment `json:"valueAttachment,omitempty"` + ValueAvailability *Availability `json:"valueAvailability,omitempty"` + ValueBase64Binary *string `json:"valueBase64Binary,omitempty"` + ValueBoolean *bool `json:"valueBoolean,omitempty"` + ValueCanonical *string `json:"valueCanonical,omitempty"` + ValueCode *string `json:"valueCode,omitempty"` + ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` + ValueCodeableReference *CodeableReference `json:"valueCodeableReference,omitempty"` + ValueCoding *Coding `json:"valueCoding,omitempty"` + ValueContactDetail *ContactDetail `json:"valueContactDetail,omitempty"` + ValueContactPoint *ContactPoint `json:"valueContactPoint,omitempty"` + ValueCount *Count `json:"valueCount,omitempty"` + ValueDataRequirement *DataRequirement `json:"valueDataRequirement,omitempty"` + ValueDate *string `json:"valueDate,omitempty"` + ValueDateTime *string `json:"valueDateTime,omitempty"` + ValueDecimal *float64 `json:"valueDecimal,omitempty"` + ValueDistance *Distance `json:"valueDistance,omitempty"` + ValueDosage *Dosage `json:"valueDosage,omitempty"` + ValueDuration *Duration `json:"valueDuration,omitempty"` + ValueExpression *Expression `json:"valueExpression,omitempty"` + ValueExtendedContactDetail *ExtendedContactDetail `json:"valueExtendedContactDetail,omitempty"` + ValueHumanName *HumanName `json:"valueHumanName,omitempty"` + ValueID *string `json:"valueId,omitempty"` + ValueIDentifier *Identifier `json:"valueIdentifier,omitempty"` + ValueInstant *string `json:"valueInstant,omitempty"` + ValueInteger *int64 `json:"valueInteger,omitempty"` + ValueInteger64 *int64 `json:"valueInteger64,omitempty"` + ValueMarkdown *string `json:"valueMarkdown,omitempty"` + ValueMeta *Meta `json:"valueMeta,omitempty"` + ValueMoney *Money `json:"valueMoney,omitempty"` + ValueOid *string `json:"valueOid,omitempty"` + ValueParameterDefinition *ParameterDefinition `json:"valueParameterDefinition,omitempty"` + ValuePeriod *Period `json:"valuePeriod,omitempty"` + ValuePositiveInt *int64 `json:"valuePositiveInt,omitempty"` + ValueQuantity *Quantity `json:"valueQuantity,omitempty"` + ValueRange *Range `json:"valueRange,omitempty"` + ValueRatio *Ratio `json:"valueRatio,omitempty"` + ValueRatioRange *RatioRange `json:"valueRatioRange,omitempty"` + ValueReference *Reference `json:"valueReference,omitempty"` + ValueRelatedArtifact *RelatedArtifact `json:"valueRelatedArtifact,omitempty"` + ValueSampledData *SampledData `json:"valueSampledData,omitempty"` + ValueSignature *Signature `json:"valueSignature,omitempty"` + ValueString *string `json:"valueString,omitempty"` + ValueTime *string `json:"valueTime,omitempty"` + ValueTiming *Timing `json:"valueTiming,omitempty"` + ValueTriggerDefinition *TriggerDefinition `json:"valueTriggerDefinition,omitempty"` + ValueUnsignedInt *int64 `json:"valueUnsignedInt,omitempty"` + ValueURI *string `json:"valueUri,omitempty"` + ValueURL *string `json:"valueUrl,omitempty"` + ValueUsageContext *UsageContext `json:"valueUsageContext,omitempty"` + ValueUUID *string `json:"valueUuid,omitempty"` +} + +// TaskPerformer +type TaskPerformer struct { + Actor *Reference `json:"actor"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Function *CodeableConcept `json:"function,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// TaskRestriction +type TaskRestriction struct { + XRepetitions *FHIRPrimitiveExtension `json:"_repetitions,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Period *Period `json:"period,omitempty"` + Recipient []*Reference `json:"recipient,omitempty"` + Repetitions *int64 `json:"repetitions,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// Timing +type Timing struct { + XEvent []*FHIRPrimitiveExtension `json:"_event,omitempty"` + Code *CodeableConcept `json:"code,omitempty"` + Event []string `json:"event,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ModifierExtension []*Extension `json:"modifierExtension,omitempty"` + Repeat *TimingRepeat `json:"repeat,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` +} + +// TimingRepeat +type TimingRepeat struct { + XCount *FHIRPrimitiveExtension `json:"_count,omitempty"` + XCountMax *FHIRPrimitiveExtension `json:"_countMax,omitempty"` + XDayOfWeek []*FHIRPrimitiveExtension `json:"_dayOfWeek,omitempty"` + XDuration *FHIRPrimitiveExtension `json:"_duration,omitempty"` + XDurationMax *FHIRPrimitiveExtension `json:"_durationMax,omitempty"` + XDurationUnit *FHIRPrimitiveExtension `json:"_durationUnit,omitempty"` + XFrequency *FHIRPrimitiveExtension `json:"_frequency,omitempty"` + XFrequencyMax *FHIRPrimitiveExtension `json:"_frequencyMax,omitempty"` + XOffset *FHIRPrimitiveExtension `json:"_offset,omitempty"` + XPeriod *FHIRPrimitiveExtension `json:"_period,omitempty"` + XPeriodMax *FHIRPrimitiveExtension `json:"_periodMax,omitempty"` + XPeriodUnit *FHIRPrimitiveExtension `json:"_periodUnit,omitempty"` + XTimeOfDay []*FHIRPrimitiveExtension `json:"_timeOfDay,omitempty"` + XWhen []*FHIRPrimitiveExtension `json:"_when,omitempty"` + BoundsDuration *Duration `json:"boundsDuration,omitempty"` + BoundsPeriod *Period `json:"boundsPeriod,omitempty"` + BoundsRange *Range `json:"boundsRange,omitempty"` + Count *int64 `json:"count,omitempty"` + CountMax *int64 `json:"countMax,omitempty"` + DayOfWeek []string `json:"dayOfWeek,omitempty"` + Duration *float64 `json:"duration,omitempty"` + DurationMax *float64 `json:"durationMax,omitempty"` + DurationUnit *string `json:"durationUnit,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + Frequency *int64 `json:"frequency,omitempty"` + FrequencyMax *int64 `json:"frequencyMax,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Offset *int64 `json:"offset,omitempty"` + Period *float64 `json:"period,omitempty"` + PeriodMax *float64 `json:"periodMax,omitempty"` + PeriodUnit *string `json:"periodUnit,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + TimeOfDay []string `json:"timeOfDay,omitempty"` + When []string `json:"when,omitempty"` +} + +// TriggerDefinition +type TriggerDefinition struct { + XName *FHIRPrimitiveExtension `json:"_name,omitempty"` + XSubscriptionTopic *FHIRPrimitiveExtension `json:"_subscriptionTopic,omitempty"` + XTimingDate *FHIRPrimitiveExtension `json:"_timingDate,omitempty"` + XTimingDateTime *FHIRPrimitiveExtension `json:"_timingDateTime,omitempty"` + XType *FHIRPrimitiveExtension `json:"_type,omitempty"` + Code *CodeableConcept `json:"code,omitempty"` + Condition *Expression `json:"condition,omitempty"` + Data []*DataRequirement `json:"data,omitempty"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + Name *string `json:"name,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + SubscriptionTopic *string `json:"subscriptionTopic,omitempty"` + TimingDate *string `json:"timingDate,omitempty"` + TimingDateTime *string `json:"timingDateTime,omitempty"` + TimingReference *Reference `json:"timingReference,omitempty"` + TimingTiming *Timing `json:"timingTiming,omitempty"` + Type *string `json:"type,omitempty"` +} + +// UsageContext +type UsageContext struct { + Code *Coding `json:"code"` + Extension []*Extension `json:"extension,omitempty"` + FhirComments FHIRComments `json:"fhir_comments,omitempty"` + ID *string `json:"id,omitempty"` + Links [][]any `json:"links,omitempty"` + ResourceType *string `json:"resourceType,omitempty"` + ValueCodeableConcept *CodeableConcept `json:"valueCodeableConcept,omitempty"` + ValueQuantity *Quantity `json:"valueQuantity,omitempty"` + ValueRange *Range `json:"valueRange,omitempty"` + ValueReference *Reference `json:"valueReference,omitempty"` +} diff --git a/fhirstructs/validate.go b/fhirstructs/validate.go new file mode 100644 index 0000000..d29c6bc --- /dev/null +++ b/fhirstructs/validate.go @@ -0,0 +1,14864 @@ +// Code generated by cmd/generate/main.go. DO NOT EDIT. +package fhirstructs + +import ( + "fmt" + "regexp" + "unicode/utf8" +) + +// Pre-compiled regular expressions for pattern validation +var ( + rx_Address_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Address_Use = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Age_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Age_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Annotation_Text = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_Attachment_ContentType = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Attachment_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_AvailabilityAvailableTime_DaysOfWeek_items = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_BodyStructure_Description = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_BodyStructure_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_BodyStructure_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Coding_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Condition_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Condition_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ContactPoint_System = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ContactPoint_Use = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Count_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Count_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_DataRequirement_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_DataRequirementSort_Direction = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_DataRequirementValueFilter_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_DiagnosticReport_Conclusion = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_DiagnosticReport_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_DiagnosticReport_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_DiagnosticReport_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Directory_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Distance_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Distance_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_DocumentReference_Description = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_DocumentReference_DocStatus = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_DocumentReference_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_DocumentReference_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_DocumentReference_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Duration_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Duration_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Expression_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Expression_Name = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Extension_ValueCode = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Extension_ValueID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Extension_ValueMarkdown = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_Extension_ValueOid = regexp.MustCompile("^urn:oid:[0-2](\\.(0|[1-9][0-9]*))+$") + rx_FamilyMemberHistory_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_FamilyMemberHistory_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_FamilyMemberHistory_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Group_Description = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_Group_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Group_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Group_Membership = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Group_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_HumanName_Use = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Identifier_Use = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ImagingStudy_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_ImagingStudy_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ImagingStudy_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ImagingStudySeries_Uid = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_ImagingStudySeriesInstance_Uid = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Medication_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Medication_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Medication_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_MedicationAdministration_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_MedicationAdministration_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_MedicationAdministration_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_MedicationRequest_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_MedicationRequest_Intent = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_MedicationRequest_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_MedicationRequest_Priority = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_MedicationRequest_RenderedDosageInstruction = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_MedicationRequest_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_MedicationStatement_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_MedicationStatement_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_MedicationStatement_RenderedDosageInstruction = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_MedicationStatement_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Meta_VersionID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Money_Currency = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Narrative_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Observation_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Observation_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Observation_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ObservationReferenceRange_Text = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_ObservationTriggeredBy_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Organization_Description = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_Organization_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Organization_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ParameterDefinition_Name = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ParameterDefinition_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ParameterDefinition_Use = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Patient_Gender = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Patient_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Patient_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_PatientContact_Gender = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_PatientLink_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Practitioner_Gender = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Practitioner_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Practitioner_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_PractitionerRole_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_PractitionerRole_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Procedure_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Procedure_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Procedure_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Quantity_Code = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Quantity_Comparator = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_RelatedArtifact_Citation = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_RelatedArtifact_PublicationStatus = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_RelatedArtifact_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ResearchStudy_Description = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_ResearchStudy_DescriptionSummary = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_ResearchStudy_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_ResearchStudy_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ResearchStudy_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ResearchStudyComparisonGroup_Description = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_ResearchStudyComparisonGroup_LinkID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_ResearchStudyObjective_Description = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_ResearchStudyOutcomeMeasure_Description = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_ResearchSubject_ActualComparisonGroup = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_ResearchSubject_AssignedComparisonGroup = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_ResearchSubject_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_ResearchSubject_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_ResearchSubject_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Resource_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Resource_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_SampledData_IntervalUnit = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Signature_SigFormat = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Signature_TargetFormat = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Specimen_Combined = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Specimen_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Specimen_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Specimen_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Substance_Description = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_Substance_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Substance_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Substance_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_SubstanceDefinition_Description = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_SubstanceDefinition_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_SubstanceDefinition_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_SubstanceDefinitionCharacterization_Description = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_Task_ID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_Task_Intent = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Task_Language = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Task_Priority = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_Task_Status = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_TaskInput_ValueCode = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_TaskInput_ValueID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_TaskInput_ValueMarkdown = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_TaskInput_ValueOid = regexp.MustCompile("^urn:oid:[0-2](\\.(0|[1-9][0-9]*))+$") + rx_TaskOutput_ValueCode = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_TaskOutput_ValueID = regexp.MustCompile("^[A-Za-z0-9\\-.]+$") + rx_TaskOutput_ValueMarkdown = regexp.MustCompile("\\s*(\\S|\\s)*") + rx_TaskOutput_ValueOid = regexp.MustCompile("^urn:oid:[0-2](\\.(0|[1-9][0-9]*))+$") + rx_TimingRepeat_DayOfWeek_items = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_TimingRepeat_DurationUnit = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_TimingRepeat_PeriodUnit = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_TimingRepeat_When_items = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") + rx_TriggerDefinition_Type = regexp.MustCompile("^[^\\s]+(\\s[^\\s]+)*$") +) + +// Validate validates a Address struct against its schema constraints. +func (x *Address) Validate() error { + if x == nil { + return nil + } + if x.XCity != nil { + if err := x.XCity.Validate(); err != nil { + return fmt.Errorf("field '_city' is invalid: %w", err) + } + } + if x.XCountry != nil { + if err := x.XCountry.Validate(); err != nil { + return fmt.Errorf("field '_country' is invalid: %w", err) + } + } + if x.XDistrict != nil { + if err := x.XDistrict.Validate(); err != nil { + return fmt.Errorf("field '_district' is invalid: %w", err) + } + } + if x.XLine != nil { + for i, item := range x.XLine { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field '_line[%d]' is invalid: %w", i, err) + } + } + } + } + if x.XPostalCode != nil { + if err := x.XPostalCode.Validate(); err != nil { + return fmt.Errorf("field '_postalCode' is invalid: %w", err) + } + } + if x.XState != nil { + if err := x.XState.Validate(); err != nil { + return fmt.Errorf("field '_state' is invalid: %w", err) + } + } + if x.XText != nil { + if err := x.XText.Validate(); err != nil { + return fmt.Errorf("field '_text' is invalid: %w", err) + } + } + if x.XType != nil { + if err := x.XType.Validate(); err != nil { + return fmt.Errorf("field '_type' is invalid: %w", err) + } + } + if x.XUse != nil { + if err := x.XUse.Validate(); err != nil { + return fmt.Errorf("field '_use' is invalid: %w", err) + } + } + if x.City != nil { + if *x.City == "" { + return fmt.Errorf("field 'city' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Country != nil { + if *x.Country == "" { + return fmt.Errorf("field 'country' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.District != nil { + if *x.District == "" { + return fmt.Errorf("field 'district' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Line != nil { + for i, item := range x.Line { + if item == "" { + return fmt.Errorf("field 'line[%d]' does not match pattern '[ \\r\\n\\t\\S]+'", i) + } + } + } + if x.Links != nil { + } + if x.Period != nil { + if err := x.Period.Validate(); err != nil { + return fmt.Errorf("field 'period' is invalid: %w", err) + } + } + if x.PostalCode != nil { + if *x.PostalCode == "" { + return fmt.Errorf("field 'postalCode' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.ResourceType != nil { + if *x.ResourceType != "Address" { + return fmt.Errorf("field 'resourceType' must be exactly 'Address'") + } + } + if x.State != nil { + if *x.State == "" { + return fmt.Errorf("field 'state' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Text != nil { + if *x.Text == "" { + return fmt.Errorf("field 'text' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Type != nil { + if !rx_Address_Type.MatchString(*x.Type) { + return fmt.Errorf("field 'type' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Use != nil { + if !rx_Address_Use.MatchString(*x.Use) { + return fmt.Errorf("field 'use' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + return nil +} + +// Validate validates a Age struct against its schema constraints. +func (x *Age) Validate() error { + if x == nil { + return nil + } + if x.XCode != nil { + if err := x.XCode.Validate(); err != nil { + return fmt.Errorf("field '_code' is invalid: %w", err) + } + } + if x.XComparator != nil { + if err := x.XComparator.Validate(); err != nil { + return fmt.Errorf("field '_comparator' is invalid: %w", err) + } + } + if x.XSystem != nil { + if err := x.XSystem.Validate(); err != nil { + return fmt.Errorf("field '_system' is invalid: %w", err) + } + } + if x.XUnit != nil { + if err := x.XUnit.Validate(); err != nil { + return fmt.Errorf("field '_unit' is invalid: %w", err) + } + } + if x.XValue != nil { + if err := x.XValue.Validate(); err != nil { + return fmt.Errorf("field '_value' is invalid: %w", err) + } + } + if x.Code != nil { + if !rx_Age_Code.MatchString(*x.Code) { + return fmt.Errorf("field 'code' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Comparator != nil { + if !rx_Age_Comparator.MatchString(*x.Comparator) { + return fmt.Errorf("field 'comparator' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "Age" { + return fmt.Errorf("field 'resourceType' must be exactly 'Age'") + } + } + if x.System != nil { + } + if x.Unit != nil { + if *x.Unit == "" { + return fmt.Errorf("field 'unit' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Value != nil { + } + return nil +} + +// Validate validates a Annotation struct against its schema constraints. +func (x *Annotation) Validate() error { + if x == nil { + return nil + } + if x.XAuthorString != nil { + if err := x.XAuthorString.Validate(); err != nil { + return fmt.Errorf("field '_authorString' is invalid: %w", err) + } + } + if x.XText != nil { + if err := x.XText.Validate(); err != nil { + return fmt.Errorf("field '_text' is invalid: %w", err) + } + } + if x.XTime != nil { + if err := x.XTime.Validate(); err != nil { + return fmt.Errorf("field '_time' is invalid: %w", err) + } + } + if x.AuthorReference != nil { + if err := x.AuthorReference.Validate(); err != nil { + return fmt.Errorf("field 'authorReference' is invalid: %w", err) + } + } + if x.AuthorString != nil { + if *x.AuthorString == "" { + return fmt.Errorf("field 'authorString' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "Annotation" { + return fmt.Errorf("field 'resourceType' must be exactly 'Annotation'") + } + } + if x.Text != nil { + if !rx_Annotation_Text.MatchString(*x.Text) { + return fmt.Errorf("field 'text' does not match pattern '\\s*(\\S|\\s)*'") + } + } + if x.Time != nil { + if err := ValidateFhirDateTime(*x.Time); err != nil { + return fmt.Errorf("field 'time' has invalid date-time format: %w", err) + } + } + return nil +} + +// Validate validates a Attachment struct against its schema constraints. +func (x *Attachment) Validate() error { + if x == nil { + return nil + } + if x.XContentType != nil { + if err := x.XContentType.Validate(); err != nil { + return fmt.Errorf("field '_contentType' is invalid: %w", err) + } + } + if x.XCreation != nil { + if err := x.XCreation.Validate(); err != nil { + return fmt.Errorf("field '_creation' is invalid: %w", err) + } + } + if x.XData != nil { + if err := x.XData.Validate(); err != nil { + return fmt.Errorf("field '_data' is invalid: %w", err) + } + } + if x.XDuration != nil { + if err := x.XDuration.Validate(); err != nil { + return fmt.Errorf("field '_duration' is invalid: %w", err) + } + } + if x.XFrames != nil { + if err := x.XFrames.Validate(); err != nil { + return fmt.Errorf("field '_frames' is invalid: %w", err) + } + } + if x.XHash != nil { + if err := x.XHash.Validate(); err != nil { + return fmt.Errorf("field '_hash' is invalid: %w", err) + } + } + if x.XHeight != nil { + if err := x.XHeight.Validate(); err != nil { + return fmt.Errorf("field '_height' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.XPages != nil { + if err := x.XPages.Validate(); err != nil { + return fmt.Errorf("field '_pages' is invalid: %w", err) + } + } + if x.XSize != nil { + if err := x.XSize.Validate(); err != nil { + return fmt.Errorf("field '_size' is invalid: %w", err) + } + } + if x.XTitle != nil { + if err := x.XTitle.Validate(); err != nil { + return fmt.Errorf("field '_title' is invalid: %w", err) + } + } + if x.XURL != nil { + if err := x.XURL.Validate(); err != nil { + return fmt.Errorf("field '_url' is invalid: %w", err) + } + } + if x.XWidth != nil { + if err := x.XWidth.Validate(); err != nil { + return fmt.Errorf("field '_width' is invalid: %w", err) + } + } + if x.ContentType != nil { + if !rx_Attachment_ContentType.MatchString(*x.ContentType) { + return fmt.Errorf("field 'contentType' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Creation != nil { + if err := ValidateFhirDateTime(*x.Creation); err != nil { + return fmt.Errorf("field 'creation' has invalid date-time format: %w", err) + } + } + if x.Data != nil { + if err := ValidateFhirBinary(*x.Data); err != nil { + return fmt.Errorf("field 'data' has invalid binary format: %w", err) + } + } + if x.Duration != nil { + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Frames != nil { + if *x.Frames <= 0.000000 { + return fmt.Errorf("field 'frames' is below exclusive minimum 0.000000") + } + } + if x.Hash != nil { + if err := ValidateFhirBinary(*x.Hash); err != nil { + return fmt.Errorf("field 'hash' has invalid binary format: %w", err) + } + } + if x.Height != nil { + if *x.Height <= 0.000000 { + return fmt.Errorf("field 'height' is below exclusive minimum 0.000000") + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Language != nil { + if !rx_Attachment_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.Pages != nil { + if *x.Pages <= 0.000000 { + return fmt.Errorf("field 'pages' is below exclusive minimum 0.000000") + } + } + if x.ResourceType != nil { + if *x.ResourceType != "Attachment" { + return fmt.Errorf("field 'resourceType' must be exactly 'Attachment'") + } + } + if x.Size != nil { + } + if x.Title != nil { + if *x.Title == "" { + return fmt.Errorf("field 'title' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.URL != nil { + if utf8.RuneCountInString(*x.URL) < 1 { + return fmt.Errorf("field 'url' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.URL) > 65536 { + return fmt.Errorf("field 'url' is too long (max 65536 characters)") + } + if err := ValidateFhirURI(*x.URL); err != nil { + return fmt.Errorf("field 'url' has invalid URI format: %w", err) + } + } + if x.Width != nil { + if *x.Width <= 0.000000 { + return fmt.Errorf("field 'width' is below exclusive minimum 0.000000") + } + } + return nil +} + +// Validate validates a Availability struct against its schema constraints. +func (x *Availability) Validate() error { + if x == nil { + return nil + } + if x.AvailableTime != nil { + for i, item := range x.AvailableTime { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'availableTime[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.NotAvailableTime != nil { + for i, item := range x.NotAvailableTime { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'notAvailableTime[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "Availability" { + return fmt.Errorf("field 'resourceType' must be exactly 'Availability'") + } + } + return nil +} + +// Validate validates a AvailabilityAvailableTime struct against its schema constraints. +func (x *AvailabilityAvailableTime) Validate() error { + if x == nil { + return nil + } + if x.XAllDay != nil { + if err := x.XAllDay.Validate(); err != nil { + return fmt.Errorf("field '_allDay' is invalid: %w", err) + } + } + if x.XAvailableEndTime != nil { + if err := x.XAvailableEndTime.Validate(); err != nil { + return fmt.Errorf("field '_availableEndTime' is invalid: %w", err) + } + } + if x.XAvailableStartTime != nil { + if err := x.XAvailableStartTime.Validate(); err != nil { + return fmt.Errorf("field '_availableStartTime' is invalid: %w", err) + } + } + if x.XDaysOfWeek != nil { + for i, item := range x.XDaysOfWeek { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field '_daysOfWeek[%d]' is invalid: %w", i, err) + } + } + } + } + if x.AllDay != nil { + } + if x.AvailableEndTime != nil { + if err := ValidateFhirTime(*x.AvailableEndTime); err != nil { + return fmt.Errorf("field 'availableEndTime' has invalid time format: %w", err) + } + } + if x.AvailableStartTime != nil { + if err := ValidateFhirTime(*x.AvailableStartTime); err != nil { + return fmt.Errorf("field 'availableStartTime' has invalid time format: %w", err) + } + } + if x.DaysOfWeek != nil { + for i, item := range x.DaysOfWeek { + if !rx_AvailabilityAvailableTime_DaysOfWeek_items.MatchString(item) { + return fmt.Errorf("field 'daysOfWeek[%d]' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'", i) + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "AvailabilityAvailableTime" { + return fmt.Errorf("field 'resourceType' must be exactly 'AvailabilityAvailableTime'") + } + } + return nil +} + +// Validate validates a AvailabilityNotAvailableTime struct against its schema constraints. +func (x *AvailabilityNotAvailableTime) Validate() error { + if x == nil { + return nil + } + if x.XDescription != nil { + if err := x.XDescription.Validate(); err != nil { + return fmt.Errorf("field '_description' is invalid: %w", err) + } + } + if x.Description != nil { + if *x.Description == "" { + return fmt.Errorf("field 'description' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.During != nil { + if err := x.During.Validate(); err != nil { + return fmt.Errorf("field 'during' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "AvailabilityNotAvailableTime" { + return fmt.Errorf("field 'resourceType' must be exactly 'AvailabilityNotAvailableTime'") + } + } + return nil +} + +// Validate validates a BodyStructure struct against its schema constraints. +func (x *BodyStructure) Validate() error { + if x == nil { + return nil + } + if x.XActive != nil { + if err := x.XActive.Validate(); err != nil { + return fmt.Errorf("field '_active' is invalid: %w", err) + } + } + if x.XDescription != nil { + if err := x.XDescription.Validate(); err != nil { + return fmt.Errorf("field '_description' is invalid: %w", err) + } + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.Active != nil { + } + if x.Contained != nil { + for i, item := range x.Contained { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Description != nil { + if !rx_BodyStructure_Description.MatchString(*x.Description) { + return fmt.Errorf("field 'description' does not match pattern '\\s*(\\S|\\s)*'") + } + } + if x.ExcludedStructure != nil { + for i, item := range x.ExcludedStructure { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'excludedStructure[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if !rx_BodyStructure_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Image != nil { + for i, item := range x.Image { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'image[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ImplicitRules != nil { + } + if x.IncludedStructure == nil { + return fmt.Errorf("required field 'includedStructure' is missing") + } + if x.IncludedStructure != nil { + for i, item := range x.IncludedStructure { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'includedStructure[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Language != nil { + if !rx_BodyStructure_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Morphology != nil { + if err := x.Morphology.Validate(); err != nil { + return fmt.Errorf("field 'morphology' is invalid: %w", err) + } + } + if x.Patient == nil { + return fmt.Errorf("required field 'patient' is missing") + } + if x.Patient != nil { + if err := x.Patient.Validate(); err != nil { + return fmt.Errorf("field 'patient' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "BodyStructure" { + return fmt.Errorf("field 'resourceType' must be exactly 'BodyStructure'") + } + } + if x.Text != nil { + if err := x.Text.Validate(); err != nil { + return fmt.Errorf("field 'text' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a BodyStructureIncludedStructure struct against its schema constraints. +func (x *BodyStructureIncludedStructure) Validate() error { + if x == nil { + return nil + } + if x.BodyLandmarkOrientation != nil { + for i, item := range x.BodyLandmarkOrientation { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'bodyLandmarkOrientation[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Laterality != nil { + if err := x.Laterality.Validate(); err != nil { + return fmt.Errorf("field 'laterality' is invalid: %w", err) + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Qualifier != nil { + for i, item := range x.Qualifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'qualifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "BodyStructureIncludedStructure" { + return fmt.Errorf("field 'resourceType' must be exactly 'BodyStructureIncludedStructure'") + } + } + if x.SpatialReference != nil { + for i, item := range x.SpatialReference { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'spatialReference[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Structure == nil { + return fmt.Errorf("required field 'structure' is missing") + } + if x.Structure != nil { + if err := x.Structure.Validate(); err != nil { + return fmt.Errorf("field 'structure' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a BodyStructureIncludedStructureBodyLandmarkOrientation struct against its schema constraints. +func (x *BodyStructureIncludedStructureBodyLandmarkOrientation) Validate() error { + if x == nil { + return nil + } + if x.ClockFacePosition != nil { + for i, item := range x.ClockFacePosition { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'clockFacePosition[%d]' is invalid: %w", i, err) + } + } + } + } + if x.DistanceFromLandmark != nil { + for i, item := range x.DistanceFromLandmark { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'distanceFromLandmark[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.LandmarkDescription != nil { + for i, item := range x.LandmarkDescription { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'landmarkDescription[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "BodyStructureIncludedStructureBodyLandmarkOrientation" { + return fmt.Errorf("field 'resourceType' must be exactly 'BodyStructureIncludedStructureBodyLandmarkOrientation'") + } + } + if x.SurfaceOrientation != nil { + for i, item := range x.SurfaceOrientation { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'surfaceOrientation[%d]' is invalid: %w", i, err) + } + } + } + } + return nil +} + +// Validate validates a BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark struct against its schema constraints. +func (x *BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark) Validate() error { + if x == nil { + return nil + } + if x.Device != nil { + for i, item := range x.Device { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'device[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark" { + return fmt.Errorf("field 'resourceType' must be exactly 'BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark'") + } + } + if x.Value != nil { + for i, item := range x.Value { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'value[%d]' is invalid: %w", i, err) + } + } + } + } + return nil +} + +// Validate validates a CodeableConcept struct against its schema constraints. +func (x *CodeableConcept) Validate() error { + if x == nil { + return nil + } + if x.XText != nil { + if err := x.XText.Validate(); err != nil { + return fmt.Errorf("field '_text' is invalid: %w", err) + } + } + if x.Coding != nil { + for i, item := range x.Coding { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'coding[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "CodeableConcept" { + return fmt.Errorf("field 'resourceType' must be exactly 'CodeableConcept'") + } + } + if x.Text != nil { + if *x.Text == "" { + return fmt.Errorf("field 'text' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + return nil +} + +// Validate validates a CodeableReference struct against its schema constraints. +func (x *CodeableReference) Validate() error { + if x == nil { + return nil + } + if x.Concept != nil { + if err := x.Concept.Validate(); err != nil { + return fmt.Errorf("field 'concept' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Reference != nil { + if err := x.Reference.Validate(); err != nil { + return fmt.Errorf("field 'reference' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "CodeableReference" { + return fmt.Errorf("field 'resourceType' must be exactly 'CodeableReference'") + } + } + return nil +} + +// Validate validates a Coding struct against its schema constraints. +func (x *Coding) Validate() error { + if x == nil { + return nil + } + if x.XCode != nil { + if err := x.XCode.Validate(); err != nil { + return fmt.Errorf("field '_code' is invalid: %w", err) + } + } + if x.XDisplay != nil { + if err := x.XDisplay.Validate(); err != nil { + return fmt.Errorf("field '_display' is invalid: %w", err) + } + } + if x.XSystem != nil { + if err := x.XSystem.Validate(); err != nil { + return fmt.Errorf("field '_system' is invalid: %w", err) + } + } + if x.XUserSelected != nil { + if err := x.XUserSelected.Validate(); err != nil { + return fmt.Errorf("field '_userSelected' is invalid: %w", err) + } + } + if x.XVersion != nil { + if err := x.XVersion.Validate(); err != nil { + return fmt.Errorf("field '_version' is invalid: %w", err) + } + } + if x.Code != nil { + if !rx_Coding_Code.MatchString(*x.Code) { + return fmt.Errorf("field 'code' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Display != nil { + if *x.Display == "" { + return fmt.Errorf("field 'display' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "Coding" { + return fmt.Errorf("field 'resourceType' must be exactly 'Coding'") + } + } + if x.System != nil { + } + if x.UserSelected != nil { + } + if x.Version != nil { + if *x.Version == "" { + return fmt.Errorf("field 'version' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + return nil +} + +// Validate validates a Condition struct against its schema constraints. +func (x *Condition) Validate() error { + if x == nil { + return nil + } + if x.XAbatementDateTime != nil { + if err := x.XAbatementDateTime.Validate(); err != nil { + return fmt.Errorf("field '_abatementDateTime' is invalid: %w", err) + } + } + if x.XAbatementString != nil { + if err := x.XAbatementString.Validate(); err != nil { + return fmt.Errorf("field '_abatementString' is invalid: %w", err) + } + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.XOnsetDateTime != nil { + if err := x.XOnsetDateTime.Validate(); err != nil { + return fmt.Errorf("field '_onsetDateTime' is invalid: %w", err) + } + } + if x.XOnsetString != nil { + if err := x.XOnsetString.Validate(); err != nil { + return fmt.Errorf("field '_onsetString' is invalid: %w", err) + } + } + if x.XRecordedDate != nil { + if err := x.XRecordedDate.Validate(); err != nil { + return fmt.Errorf("field '_recordedDate' is invalid: %w", err) + } + } + if x.AbatementAge != nil { + if err := x.AbatementAge.Validate(); err != nil { + return fmt.Errorf("field 'abatementAge' is invalid: %w", err) + } + } + if x.AbatementDateTime != nil { + if err := ValidateFhirDateTime(*x.AbatementDateTime); err != nil { + return fmt.Errorf("field 'abatementDateTime' has invalid date-time format: %w", err) + } + } + if x.AbatementPeriod != nil { + if err := x.AbatementPeriod.Validate(); err != nil { + return fmt.Errorf("field 'abatementPeriod' is invalid: %w", err) + } + } + if x.AbatementRange != nil { + if err := x.AbatementRange.Validate(); err != nil { + return fmt.Errorf("field 'abatementRange' is invalid: %w", err) + } + } + if x.AbatementString != nil { + if *x.AbatementString == "" { + return fmt.Errorf("field 'abatementString' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.BodySite != nil { + for i, item := range x.BodySite { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'bodySite[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Category != nil { + for i, item := range x.Category { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'category[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ClinicalStatus == nil { + return fmt.Errorf("required field 'clinicalStatus' is missing") + } + if x.ClinicalStatus != nil { + if err := x.ClinicalStatus.Validate(); err != nil { + return fmt.Errorf("field 'clinicalStatus' is invalid: %w", err) + } + } + if x.Code != nil { + if err := x.Code.Validate(); err != nil { + return fmt.Errorf("field 'code' is invalid: %w", err) + } + } + if x.Contained != nil { + for i, item := range x.Contained { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Encounter != nil { + if err := x.Encounter.Validate(); err != nil { + return fmt.Errorf("field 'encounter' is invalid: %w", err) + } + } + if x.Evidence != nil { + for i, item := range x.Evidence { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'evidence[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if !rx_Condition_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ImplicitRules != nil { + } + if x.Language != nil { + if !rx_Condition_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Note != nil { + for i, item := range x.Note { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) + } + } + } + } + if x.OnsetAge != nil { + if err := x.OnsetAge.Validate(); err != nil { + return fmt.Errorf("field 'onsetAge' is invalid: %w", err) + } + } + if x.OnsetDateTime != nil { + if err := ValidateFhirDateTime(*x.OnsetDateTime); err != nil { + return fmt.Errorf("field 'onsetDateTime' has invalid date-time format: %w", err) + } + } + if x.OnsetPeriod != nil { + if err := x.OnsetPeriod.Validate(); err != nil { + return fmt.Errorf("field 'onsetPeriod' is invalid: %w", err) + } + } + if x.OnsetRange != nil { + if err := x.OnsetRange.Validate(); err != nil { + return fmt.Errorf("field 'onsetRange' is invalid: %w", err) + } + } + if x.OnsetString != nil { + if *x.OnsetString == "" { + return fmt.Errorf("field 'onsetString' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Participant != nil { + for i, item := range x.Participant { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'participant[%d]' is invalid: %w", i, err) + } + } + } + } + if x.RecordedDate != nil { + if err := ValidateFhirDateTime(*x.RecordedDate); err != nil { + return fmt.Errorf("field 'recordedDate' has invalid date-time format: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "Condition" { + return fmt.Errorf("field 'resourceType' must be exactly 'Condition'") + } + } + if x.Severity != nil { + if err := x.Severity.Validate(); err != nil { + return fmt.Errorf("field 'severity' is invalid: %w", err) + } + } + if x.Stage != nil { + for i, item := range x.Stage { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'stage[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Subject == nil { + return fmt.Errorf("required field 'subject' is missing") + } + if x.Subject != nil { + if err := x.Subject.Validate(); err != nil { + return fmt.Errorf("field 'subject' is invalid: %w", err) + } + } + if x.Text != nil { + if err := x.Text.Validate(); err != nil { + return fmt.Errorf("field 'text' is invalid: %w", err) + } + } + if x.VerificationStatus != nil { + if err := x.VerificationStatus.Validate(); err != nil { + return fmt.Errorf("field 'verificationStatus' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a ConditionParticipant struct against its schema constraints. +func (x *ConditionParticipant) Validate() error { + if x == nil { + return nil + } + if x.Actor == nil { + return fmt.Errorf("required field 'actor' is missing") + } + if x.Actor != nil { + if err := x.Actor.Validate(); err != nil { + return fmt.Errorf("field 'actor' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Function != nil { + if err := x.Function.Validate(); err != nil { + return fmt.Errorf("field 'function' is invalid: %w", err) + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ConditionParticipant" { + return fmt.Errorf("field 'resourceType' must be exactly 'ConditionParticipant'") + } + } + return nil +} + +// Validate validates a ConditionStage struct against its schema constraints. +func (x *ConditionStage) Validate() error { + if x == nil { + return nil + } + if x.Assessment != nil { + for i, item := range x.Assessment { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'assessment[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ConditionStage" { + return fmt.Errorf("field 'resourceType' must be exactly 'ConditionStage'") + } + } + if x.Summary != nil { + if err := x.Summary.Validate(); err != nil { + return fmt.Errorf("field 'summary' is invalid: %w", err) + } + } + if x.Type != nil { + if err := x.Type.Validate(); err != nil { + return fmt.Errorf("field 'type' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a ContactDetail struct against its schema constraints. +func (x *ContactDetail) Validate() error { + if x == nil { + return nil + } + if x.XName != nil { + if err := x.XName.Validate(); err != nil { + return fmt.Errorf("field '_name' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Name != nil { + if *x.Name == "" { + return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ContactDetail" { + return fmt.Errorf("field 'resourceType' must be exactly 'ContactDetail'") + } + } + if x.Telecom != nil { + for i, item := range x.Telecom { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'telecom[%d]' is invalid: %w", i, err) + } + } + } + } + return nil +} + +// Validate validates a ContactPoint struct against its schema constraints. +func (x *ContactPoint) Validate() error { + if x == nil { + return nil + } + if x.XRank != nil { + if err := x.XRank.Validate(); err != nil { + return fmt.Errorf("field '_rank' is invalid: %w", err) + } + } + if x.XSystem != nil { + if err := x.XSystem.Validate(); err != nil { + return fmt.Errorf("field '_system' is invalid: %w", err) + } + } + if x.XUse != nil { + if err := x.XUse.Validate(); err != nil { + return fmt.Errorf("field '_use' is invalid: %w", err) + } + } + if x.XValue != nil { + if err := x.XValue.Validate(); err != nil { + return fmt.Errorf("field '_value' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Period != nil { + if err := x.Period.Validate(); err != nil { + return fmt.Errorf("field 'period' is invalid: %w", err) + } + } + if x.Rank != nil { + if *x.Rank <= 0.000000 { + return fmt.Errorf("field 'rank' is below exclusive minimum 0.000000") + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ContactPoint" { + return fmt.Errorf("field 'resourceType' must be exactly 'ContactPoint'") + } + } + if x.System != nil { + if !rx_ContactPoint_System.MatchString(*x.System) { + return fmt.Errorf("field 'system' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Use != nil { + if !rx_ContactPoint_Use.MatchString(*x.Use) { + return fmt.Errorf("field 'use' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Value != nil { + if *x.Value == "" { + return fmt.Errorf("field 'value' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + return nil +} + +// Validate validates a Count struct against its schema constraints. +func (x *Count) Validate() error { + if x == nil { + return nil + } + if x.XCode != nil { + if err := x.XCode.Validate(); err != nil { + return fmt.Errorf("field '_code' is invalid: %w", err) + } + } + if x.XComparator != nil { + if err := x.XComparator.Validate(); err != nil { + return fmt.Errorf("field '_comparator' is invalid: %w", err) + } + } + if x.XSystem != nil { + if err := x.XSystem.Validate(); err != nil { + return fmt.Errorf("field '_system' is invalid: %w", err) + } + } + if x.XUnit != nil { + if err := x.XUnit.Validate(); err != nil { + return fmt.Errorf("field '_unit' is invalid: %w", err) + } + } + if x.XValue != nil { + if err := x.XValue.Validate(); err != nil { + return fmt.Errorf("field '_value' is invalid: %w", err) + } + } + if x.Code != nil { + if !rx_Count_Code.MatchString(*x.Code) { + return fmt.Errorf("field 'code' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Comparator != nil { + if !rx_Count_Comparator.MatchString(*x.Comparator) { + return fmt.Errorf("field 'comparator' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "Count" { + return fmt.Errorf("field 'resourceType' must be exactly 'Count'") + } + } + if x.System != nil { + } + if x.Unit != nil { + if *x.Unit == "" { + return fmt.Errorf("field 'unit' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Value != nil { + } + return nil +} + +// Validate validates a DataRequirement struct against its schema constraints. +func (x *DataRequirement) Validate() error { + if x == nil { + return nil + } + if x.XLimit != nil { + if err := x.XLimit.Validate(); err != nil { + return fmt.Errorf("field '_limit' is invalid: %w", err) + } + } + if x.XMustSupport != nil { + for i, item := range x.XMustSupport { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field '_mustSupport[%d]' is invalid: %w", i, err) + } + } + } + } + if x.XProfile != nil { + for i, item := range x.XProfile { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field '_profile[%d]' is invalid: %w", i, err) + } + } + } + } + if x.XType != nil { + if err := x.XType.Validate(); err != nil { + return fmt.Errorf("field '_type' is invalid: %w", err) + } + } + if x.CodeFilter != nil { + for i, item := range x.CodeFilter { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'codeFilter[%d]' is invalid: %w", i, err) + } + } + } + } + if x.DateFilter != nil { + for i, item := range x.DateFilter { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'dateFilter[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Limit != nil { + if *x.Limit <= 0.000000 { + return fmt.Errorf("field 'limit' is below exclusive minimum 0.000000") + } + } + if x.Links != nil { + } + if x.MustSupport != nil { + for i, item := range x.MustSupport { + if item == "" { + return fmt.Errorf("field 'mustSupport[%d]' does not match pattern '[ \\r\\n\\t\\S]+'", i) + } + } + } + if x.Profile != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "DataRequirement" { + return fmt.Errorf("field 'resourceType' must be exactly 'DataRequirement'") + } + } + if x.Sort != nil { + for i, item := range x.Sort { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'sort[%d]' is invalid: %w", i, err) + } + } + } + } + if x.SubjectCodeableConcept != nil { + if err := x.SubjectCodeableConcept.Validate(); err != nil { + return fmt.Errorf("field 'subjectCodeableConcept' is invalid: %w", err) + } + } + if x.SubjectReference != nil { + if err := x.SubjectReference.Validate(); err != nil { + return fmt.Errorf("field 'subjectReference' is invalid: %w", err) + } + } + if x.Type != nil { + if !rx_DataRequirement_Type.MatchString(*x.Type) { + return fmt.Errorf("field 'type' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.ValueFilter != nil { + for i, item := range x.ValueFilter { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'valueFilter[%d]' is invalid: %w", i, err) + } + } + } + } + return nil +} + +// Validate validates a DataRequirementCodeFilter struct against its schema constraints. +func (x *DataRequirementCodeFilter) Validate() error { + if x == nil { + return nil + } + if x.XPath != nil { + if err := x.XPath.Validate(); err != nil { + return fmt.Errorf("field '_path' is invalid: %w", err) + } + } + if x.XSearchParam != nil { + if err := x.XSearchParam.Validate(); err != nil { + return fmt.Errorf("field '_searchParam' is invalid: %w", err) + } + } + if x.XValueSet != nil { + if err := x.XValueSet.Validate(); err != nil { + return fmt.Errorf("field '_valueSet' is invalid: %w", err) + } + } + if x.Code != nil { + for i, item := range x.Code { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'code[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Path != nil { + if *x.Path == "" { + return fmt.Errorf("field 'path' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.ResourceType != nil { + if *x.ResourceType != "DataRequirementCodeFilter" { + return fmt.Errorf("field 'resourceType' must be exactly 'DataRequirementCodeFilter'") + } + } + if x.SearchParam != nil { + if *x.SearchParam == "" { + return fmt.Errorf("field 'searchParam' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.ValueSet != nil { + } + return nil +} + +// Validate validates a DataRequirementDateFilter struct against its schema constraints. +func (x *DataRequirementDateFilter) Validate() error { + if x == nil { + return nil + } + if x.XPath != nil { + if err := x.XPath.Validate(); err != nil { + return fmt.Errorf("field '_path' is invalid: %w", err) + } + } + if x.XSearchParam != nil { + if err := x.XSearchParam.Validate(); err != nil { + return fmt.Errorf("field '_searchParam' is invalid: %w", err) + } + } + if x.XValueDateTime != nil { + if err := x.XValueDateTime.Validate(); err != nil { + return fmt.Errorf("field '_valueDateTime' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Path != nil { + if *x.Path == "" { + return fmt.Errorf("field 'path' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.ResourceType != nil { + if *x.ResourceType != "DataRequirementDateFilter" { + return fmt.Errorf("field 'resourceType' must be exactly 'DataRequirementDateFilter'") + } + } + if x.SearchParam != nil { + if *x.SearchParam == "" { + return fmt.Errorf("field 'searchParam' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.ValueDateTime != nil { + if err := ValidateFhirDateTime(*x.ValueDateTime); err != nil { + return fmt.Errorf("field 'valueDateTime' has invalid date-time format: %w", err) + } + } + if x.ValueDuration != nil { + if err := x.ValueDuration.Validate(); err != nil { + return fmt.Errorf("field 'valueDuration' is invalid: %w", err) + } + } + if x.ValuePeriod != nil { + if err := x.ValuePeriod.Validate(); err != nil { + return fmt.Errorf("field 'valuePeriod' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a DataRequirementSort struct against its schema constraints. +func (x *DataRequirementSort) Validate() error { + if x == nil { + return nil + } + if x.XDirection != nil { + if err := x.XDirection.Validate(); err != nil { + return fmt.Errorf("field '_direction' is invalid: %w", err) + } + } + if x.XPath != nil { + if err := x.XPath.Validate(); err != nil { + return fmt.Errorf("field '_path' is invalid: %w", err) + } + } + if x.Direction != nil { + if !rx_DataRequirementSort_Direction.MatchString(*x.Direction) { + return fmt.Errorf("field 'direction' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Path != nil { + if *x.Path == "" { + return fmt.Errorf("field 'path' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.ResourceType != nil { + if *x.ResourceType != "DataRequirementSort" { + return fmt.Errorf("field 'resourceType' must be exactly 'DataRequirementSort'") + } + } + return nil +} + +// Validate validates a DataRequirementValueFilter struct against its schema constraints. +func (x *DataRequirementValueFilter) Validate() error { + if x == nil { + return nil + } + if x.XComparator != nil { + if err := x.XComparator.Validate(); err != nil { + return fmt.Errorf("field '_comparator' is invalid: %w", err) + } + } + if x.XPath != nil { + if err := x.XPath.Validate(); err != nil { + return fmt.Errorf("field '_path' is invalid: %w", err) + } + } + if x.XSearchParam != nil { + if err := x.XSearchParam.Validate(); err != nil { + return fmt.Errorf("field '_searchParam' is invalid: %w", err) + } + } + if x.XValueDateTime != nil { + if err := x.XValueDateTime.Validate(); err != nil { + return fmt.Errorf("field '_valueDateTime' is invalid: %w", err) + } + } + if x.Comparator != nil { + if !rx_DataRequirementValueFilter_Comparator.MatchString(*x.Comparator) { + return fmt.Errorf("field 'comparator' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Path != nil { + if *x.Path == "" { + return fmt.Errorf("field 'path' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.ResourceType != nil { + if *x.ResourceType != "DataRequirementValueFilter" { + return fmt.Errorf("field 'resourceType' must be exactly 'DataRequirementValueFilter'") + } + } + if x.SearchParam != nil { + if *x.SearchParam == "" { + return fmt.Errorf("field 'searchParam' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.ValueDateTime != nil { + if err := ValidateFhirDateTime(*x.ValueDateTime); err != nil { + return fmt.Errorf("field 'valueDateTime' has invalid date-time format: %w", err) + } + } + if x.ValueDuration != nil { + if err := x.ValueDuration.Validate(); err != nil { + return fmt.Errorf("field 'valueDuration' is invalid: %w", err) + } + } + if x.ValuePeriod != nil { + if err := x.ValuePeriod.Validate(); err != nil { + return fmt.Errorf("field 'valuePeriod' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a DiagnosticReport struct against its schema constraints. +func (x *DiagnosticReport) Validate() error { + if x == nil { + return nil + } + if x.XConclusion != nil { + if err := x.XConclusion.Validate(); err != nil { + return fmt.Errorf("field '_conclusion' is invalid: %w", err) + } + } + if x.XEffectiveDateTime != nil { + if err := x.XEffectiveDateTime.Validate(); err != nil { + return fmt.Errorf("field '_effectiveDateTime' is invalid: %w", err) + } + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XIssued != nil { + if err := x.XIssued.Validate(); err != nil { + return fmt.Errorf("field '_issued' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.XStatus != nil { + if err := x.XStatus.Validate(); err != nil { + return fmt.Errorf("field '_status' is invalid: %w", err) + } + } + if x.BasedOn != nil { + for i, item := range x.BasedOn { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'basedOn[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Category != nil { + for i, item := range x.Category { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'category[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Code == nil { + return fmt.Errorf("required field 'code' is missing") + } + if x.Code != nil { + if err := x.Code.Validate(); err != nil { + return fmt.Errorf("field 'code' is invalid: %w", err) + } + } + if x.Composition != nil { + if err := x.Composition.Validate(); err != nil { + return fmt.Errorf("field 'composition' is invalid: %w", err) + } + } + if x.Conclusion != nil { + if !rx_DiagnosticReport_Conclusion.MatchString(*x.Conclusion) { + return fmt.Errorf("field 'conclusion' does not match pattern '\\s*(\\S|\\s)*'") + } + } + if x.ConclusionCode != nil { + for i, item := range x.ConclusionCode { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'conclusionCode[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Contained != nil { + for i, item := range x.Contained { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) + } + } + } + } + if x.EffectiveDateTime != nil { + if err := ValidateFhirDateTime(*x.EffectiveDateTime); err != nil { + return fmt.Errorf("field 'effectiveDateTime' has invalid date-time format: %w", err) + } + } + if x.EffectivePeriod != nil { + if err := x.EffectivePeriod.Validate(); err != nil { + return fmt.Errorf("field 'effectivePeriod' is invalid: %w", err) + } + } + if x.Encounter != nil { + if err := x.Encounter.Validate(); err != nil { + return fmt.Errorf("field 'encounter' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if !rx_DiagnosticReport_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ImplicitRules != nil { + } + if x.Issued != nil { + if err := ValidateFhirDateTime(*x.Issued); err != nil { + return fmt.Errorf("field 'issued' has invalid date-time format: %w", err) + } + } + if x.Language != nil { + if !rx_DiagnosticReport_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.Media != nil { + for i, item := range x.Media { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'media[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Note != nil { + for i, item := range x.Note { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Performer != nil { + for i, item := range x.Performer { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'performer[%d]' is invalid: %w", i, err) + } + } + } + } + if x.PresentedForm != nil { + for i, item := range x.PresentedForm { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'presentedForm[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "DiagnosticReport" { + return fmt.Errorf("field 'resourceType' must be exactly 'DiagnosticReport'") + } + } + if x.Result != nil { + for i, item := range x.Result { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'result[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResultsInterpreter != nil { + for i, item := range x.ResultsInterpreter { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'resultsInterpreter[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Specimen != nil { + for i, item := range x.Specimen { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'specimen[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Status != nil { + if !rx_DiagnosticReport_Status.MatchString(*x.Status) { + return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Study != nil { + for i, item := range x.Study { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'study[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Subject != nil { + if err := x.Subject.Validate(); err != nil { + return fmt.Errorf("field 'subject' is invalid: %w", err) + } + } + if x.SupportingInfo != nil { + for i, item := range x.SupportingInfo { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'supportingInfo[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Text != nil { + if err := x.Text.Validate(); err != nil { + return fmt.Errorf("field 'text' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a DiagnosticReportMedia struct against its schema constraints. +func (x *DiagnosticReportMedia) Validate() error { + if x == nil { + return nil + } + if x.XComment != nil { + if err := x.XComment.Validate(); err != nil { + return fmt.Errorf("field '_comment' is invalid: %w", err) + } + } + if x.Comment != nil { + if *x.Comment == "" { + return fmt.Errorf("field 'comment' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Link == nil { + return fmt.Errorf("required field 'link' is missing") + } + if x.Link != nil { + if err := x.Link.Validate(); err != nil { + return fmt.Errorf("field 'link' is invalid: %w", err) + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "DiagnosticReportMedia" { + return fmt.Errorf("field 'resourceType' must be exactly 'DiagnosticReportMedia'") + } + } + return nil +} + +// Validate validates a DiagnosticReportSupportingInfo struct against its schema constraints. +func (x *DiagnosticReportSupportingInfo) Validate() error { + if x == nil { + return nil + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Reference == nil { + return fmt.Errorf("required field 'reference' is missing") + } + if x.Reference != nil { + if err := x.Reference.Validate(); err != nil { + return fmt.Errorf("field 'reference' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "DiagnosticReportSupportingInfo" { + return fmt.Errorf("field 'resourceType' must be exactly 'DiagnosticReportSupportingInfo'") + } + } + if x.Type == nil { + return fmt.Errorf("required field 'type' is missing") + } + if x.Type != nil { + if err := x.Type.Validate(); err != nil { + return fmt.Errorf("field 'type' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a Directory struct against its schema constraints. +func (x *Directory) Validate() error { + if x == nil { + return nil + } + if x.Child == nil { + return fmt.Errorf("required field 'child' is missing") + } + if x.Child != nil { + for i, item := range x.Child { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'child[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if !rx_Directory_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.Links != nil { + } + if x.Name == nil { + return fmt.Errorf("required field 'name' is missing") + } + if x.Name != nil { + } + if x.Path != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "Directory" { + return fmt.Errorf("field 'resourceType' must be exactly 'Directory'") + } + } + return nil +} + +// Validate validates a Distance struct against its schema constraints. +func (x *Distance) Validate() error { + if x == nil { + return nil + } + if x.XCode != nil { + if err := x.XCode.Validate(); err != nil { + return fmt.Errorf("field '_code' is invalid: %w", err) + } + } + if x.XComparator != nil { + if err := x.XComparator.Validate(); err != nil { + return fmt.Errorf("field '_comparator' is invalid: %w", err) + } + } + if x.XSystem != nil { + if err := x.XSystem.Validate(); err != nil { + return fmt.Errorf("field '_system' is invalid: %w", err) + } + } + if x.XUnit != nil { + if err := x.XUnit.Validate(); err != nil { + return fmt.Errorf("field '_unit' is invalid: %w", err) + } + } + if x.XValue != nil { + if err := x.XValue.Validate(); err != nil { + return fmt.Errorf("field '_value' is invalid: %w", err) + } + } + if x.Code != nil { + if !rx_Distance_Code.MatchString(*x.Code) { + return fmt.Errorf("field 'code' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Comparator != nil { + if !rx_Distance_Comparator.MatchString(*x.Comparator) { + return fmt.Errorf("field 'comparator' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "Distance" { + return fmt.Errorf("field 'resourceType' must be exactly 'Distance'") + } + } + if x.System != nil { + } + if x.Unit != nil { + if *x.Unit == "" { + return fmt.Errorf("field 'unit' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Value != nil { + } + return nil +} + +// Validate validates a DocumentReference struct against its schema constraints. +func (x *DocumentReference) Validate() error { + if x == nil { + return nil + } + if x.XDate != nil { + if err := x.XDate.Validate(); err != nil { + return fmt.Errorf("field '_date' is invalid: %w", err) + } + } + if x.XDescription != nil { + if err := x.XDescription.Validate(); err != nil { + return fmt.Errorf("field '_description' is invalid: %w", err) + } + } + if x.XDocStatus != nil { + if err := x.XDocStatus.Validate(); err != nil { + return fmt.Errorf("field '_docStatus' is invalid: %w", err) + } + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.XStatus != nil { + if err := x.XStatus.Validate(); err != nil { + return fmt.Errorf("field '_status' is invalid: %w", err) + } + } + if x.XVersion != nil { + if err := x.XVersion.Validate(); err != nil { + return fmt.Errorf("field '_version' is invalid: %w", err) + } + } + if x.Attester != nil { + for i, item := range x.Attester { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'attester[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Author != nil { + for i, item := range x.Author { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'author[%d]' is invalid: %w", i, err) + } + } + } + } + if x.BasedOn != nil { + for i, item := range x.BasedOn { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'basedOn[%d]' is invalid: %w", i, err) + } + } + } + } + if x.BodySite != nil { + for i, item := range x.BodySite { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'bodySite[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Category != nil { + for i, item := range x.Category { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'category[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Contained != nil { + for i, item := range x.Contained { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Content == nil { + return fmt.Errorf("required field 'content' is missing") + } + if x.Content != nil { + for i, item := range x.Content { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'content[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Context != nil { + for i, item := range x.Context { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'context[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Custodian != nil { + if err := x.Custodian.Validate(); err != nil { + return fmt.Errorf("field 'custodian' is invalid: %w", err) + } + } + if x.Date != nil { + if err := ValidateFhirDateTime(*x.Date); err != nil { + return fmt.Errorf("field 'date' has invalid date-time format: %w", err) + } + } + if x.Description != nil { + if !rx_DocumentReference_Description.MatchString(*x.Description) { + return fmt.Errorf("field 'description' does not match pattern '\\s*(\\S|\\s)*'") + } + } + if x.DocStatus != nil { + if !rx_DocumentReference_DocStatus.MatchString(*x.DocStatus) { + return fmt.Errorf("field 'docStatus' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Event != nil { + for i, item := range x.Event { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'event[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.FacilityType != nil { + if err := x.FacilityType.Validate(); err != nil { + return fmt.Errorf("field 'facilityType' is invalid: %w", err) + } + } + if x.ID != nil { + if !rx_DocumentReference_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ImplicitRules != nil { + } + if x.Language != nil { + if !rx_DocumentReference_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.Modality != nil { + for i, item := range x.Modality { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modality[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Period != nil { + if err := x.Period.Validate(); err != nil { + return fmt.Errorf("field 'period' is invalid: %w", err) + } + } + if x.PracticeSetting != nil { + if err := x.PracticeSetting.Validate(); err != nil { + return fmt.Errorf("field 'practiceSetting' is invalid: %w", err) + } + } + if x.RelatesTo != nil { + for i, item := range x.RelatesTo { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'relatesTo[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "DocumentReference" { + return fmt.Errorf("field 'resourceType' must be exactly 'DocumentReference'") + } + } + if x.SecurityLabel != nil { + for i, item := range x.SecurityLabel { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'securityLabel[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Status != nil { + if !rx_DocumentReference_Status.MatchString(*x.Status) { + return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Subject != nil { + if err := x.Subject.Validate(); err != nil { + return fmt.Errorf("field 'subject' is invalid: %w", err) + } + } + if x.Text != nil { + if err := x.Text.Validate(); err != nil { + return fmt.Errorf("field 'text' is invalid: %w", err) + } + } + if x.Type != nil { + if err := x.Type.Validate(); err != nil { + return fmt.Errorf("field 'type' is invalid: %w", err) + } + } + if x.Version != nil { + if *x.Version == "" { + return fmt.Errorf("field 'version' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + return nil +} + +// Validate validates a DocumentReferenceAttester struct against its schema constraints. +func (x *DocumentReferenceAttester) Validate() error { + if x == nil { + return nil + } + if x.XTime != nil { + if err := x.XTime.Validate(); err != nil { + return fmt.Errorf("field '_time' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Mode == nil { + return fmt.Errorf("required field 'mode' is missing") + } + if x.Mode != nil { + if err := x.Mode.Validate(); err != nil { + return fmt.Errorf("field 'mode' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Party != nil { + if err := x.Party.Validate(); err != nil { + return fmt.Errorf("field 'party' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "DocumentReferenceAttester" { + return fmt.Errorf("field 'resourceType' must be exactly 'DocumentReferenceAttester'") + } + } + if x.Time != nil { + if err := ValidateFhirDateTime(*x.Time); err != nil { + return fmt.Errorf("field 'time' has invalid date-time format: %w", err) + } + } + return nil +} + +// Validate validates a DocumentReferenceContent struct against its schema constraints. +func (x *DocumentReferenceContent) Validate() error { + if x == nil { + return nil + } + if x.Attachment == nil { + return fmt.Errorf("required field 'attachment' is missing") + } + if x.Attachment != nil { + if err := x.Attachment.Validate(); err != nil { + return fmt.Errorf("field 'attachment' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Profile != nil { + for i, item := range x.Profile { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'profile[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "DocumentReferenceContent" { + return fmt.Errorf("field 'resourceType' must be exactly 'DocumentReferenceContent'") + } + } + return nil +} + +// Validate validates a DocumentReferenceContentProfile struct against its schema constraints. +func (x *DocumentReferenceContentProfile) Validate() error { + if x == nil { + return nil + } + if x.XValueCanonical != nil { + if err := x.XValueCanonical.Validate(); err != nil { + return fmt.Errorf("field '_valueCanonical' is invalid: %w", err) + } + } + if x.XValueURI != nil { + if err := x.XValueURI.Validate(); err != nil { + return fmt.Errorf("field '_valueUri' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "DocumentReferenceContentProfile" { + return fmt.Errorf("field 'resourceType' must be exactly 'DocumentReferenceContentProfile'") + } + } + if x.ValueCanonical != nil { + } + if x.ValueCoding != nil { + if err := x.ValueCoding.Validate(); err != nil { + return fmt.Errorf("field 'valueCoding' is invalid: %w", err) + } + } + if x.ValueURI != nil { + } + return nil +} + +// Validate validates a DocumentReferenceRelatesTo struct against its schema constraints. +func (x *DocumentReferenceRelatesTo) Validate() error { + if x == nil { + return nil + } + if x.Code == nil { + return fmt.Errorf("required field 'code' is missing") + } + if x.Code != nil { + if err := x.Code.Validate(); err != nil { + return fmt.Errorf("field 'code' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "DocumentReferenceRelatesTo" { + return fmt.Errorf("field 'resourceType' must be exactly 'DocumentReferenceRelatesTo'") + } + } + if x.Target == nil { + return fmt.Errorf("required field 'target' is missing") + } + if x.Target != nil { + if err := x.Target.Validate(); err != nil { + return fmt.Errorf("field 'target' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a Dosage struct against its schema constraints. +func (x *Dosage) Validate() error { + if x == nil { + return nil + } + if x.XAsNeeded != nil { + if err := x.XAsNeeded.Validate(); err != nil { + return fmt.Errorf("field '_asNeeded' is invalid: %w", err) + } + } + if x.XPatientInstruction != nil { + if err := x.XPatientInstruction.Validate(); err != nil { + return fmt.Errorf("field '_patientInstruction' is invalid: %w", err) + } + } + if x.XSequence != nil { + if err := x.XSequence.Validate(); err != nil { + return fmt.Errorf("field '_sequence' is invalid: %w", err) + } + } + if x.XText != nil { + if err := x.XText.Validate(); err != nil { + return fmt.Errorf("field '_text' is invalid: %w", err) + } + } + if x.AdditionalInstruction != nil { + for i, item := range x.AdditionalInstruction { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'additionalInstruction[%d]' is invalid: %w", i, err) + } + } + } + } + if x.AsNeeded != nil { + } + if x.AsNeededFor != nil { + for i, item := range x.AsNeededFor { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'asNeededFor[%d]' is invalid: %w", i, err) + } + } + } + } + if x.DoseAndRate != nil { + for i, item := range x.DoseAndRate { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'doseAndRate[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.MaxDosePerAdministration != nil { + if err := x.MaxDosePerAdministration.Validate(); err != nil { + return fmt.Errorf("field 'maxDosePerAdministration' is invalid: %w", err) + } + } + if x.MaxDosePerLifetime != nil { + if err := x.MaxDosePerLifetime.Validate(); err != nil { + return fmt.Errorf("field 'maxDosePerLifetime' is invalid: %w", err) + } + } + if x.MaxDosePerPeriod != nil { + for i, item := range x.MaxDosePerPeriod { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'maxDosePerPeriod[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Method != nil { + if err := x.Method.Validate(); err != nil { + return fmt.Errorf("field 'method' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.PatientInstruction != nil { + if *x.PatientInstruction == "" { + return fmt.Errorf("field 'patientInstruction' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.ResourceType != nil { + if *x.ResourceType != "Dosage" { + return fmt.Errorf("field 'resourceType' must be exactly 'Dosage'") + } + } + if x.Route != nil { + if err := x.Route.Validate(); err != nil { + return fmt.Errorf("field 'route' is invalid: %w", err) + } + } + if x.Sequence != nil { + } + if x.Site != nil { + if err := x.Site.Validate(); err != nil { + return fmt.Errorf("field 'site' is invalid: %w", err) + } + } + if x.Text != nil { + if *x.Text == "" { + return fmt.Errorf("field 'text' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Timing != nil { + if err := x.Timing.Validate(); err != nil { + return fmt.Errorf("field 'timing' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a DosageDoseAndRate struct against its schema constraints. +func (x *DosageDoseAndRate) Validate() error { + if x == nil { + return nil + } + if x.DoseQuantity != nil { + if err := x.DoseQuantity.Validate(); err != nil { + return fmt.Errorf("field 'doseQuantity' is invalid: %w", err) + } + } + if x.DoseRange != nil { + if err := x.DoseRange.Validate(); err != nil { + return fmt.Errorf("field 'doseRange' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.RateQuantity != nil { + if err := x.RateQuantity.Validate(); err != nil { + return fmt.Errorf("field 'rateQuantity' is invalid: %w", err) + } + } + if x.RateRange != nil { + if err := x.RateRange.Validate(); err != nil { + return fmt.Errorf("field 'rateRange' is invalid: %w", err) + } + } + if x.RateRatio != nil { + if err := x.RateRatio.Validate(); err != nil { + return fmt.Errorf("field 'rateRatio' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "DosageDoseAndRate" { + return fmt.Errorf("field 'resourceType' must be exactly 'DosageDoseAndRate'") + } + } + if x.Type != nil { + if err := x.Type.Validate(); err != nil { + return fmt.Errorf("field 'type' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a Duration struct against its schema constraints. +func (x *Duration) Validate() error { + if x == nil { + return nil + } + if x.XCode != nil { + if err := x.XCode.Validate(); err != nil { + return fmt.Errorf("field '_code' is invalid: %w", err) + } + } + if x.XComparator != nil { + if err := x.XComparator.Validate(); err != nil { + return fmt.Errorf("field '_comparator' is invalid: %w", err) + } + } + if x.XSystem != nil { + if err := x.XSystem.Validate(); err != nil { + return fmt.Errorf("field '_system' is invalid: %w", err) + } + } + if x.XUnit != nil { + if err := x.XUnit.Validate(); err != nil { + return fmt.Errorf("field '_unit' is invalid: %w", err) + } + } + if x.XValue != nil { + if err := x.XValue.Validate(); err != nil { + return fmt.Errorf("field '_value' is invalid: %w", err) + } + } + if x.Code != nil { + if !rx_Duration_Code.MatchString(*x.Code) { + return fmt.Errorf("field 'code' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Comparator != nil { + if !rx_Duration_Comparator.MatchString(*x.Comparator) { + return fmt.Errorf("field 'comparator' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "Duration" { + return fmt.Errorf("field 'resourceType' must be exactly 'Duration'") + } + } + if x.System != nil { + } + if x.Unit != nil { + if *x.Unit == "" { + return fmt.Errorf("field 'unit' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Value != nil { + } + return nil +} + +// Validate validates a Expression struct against its schema constraints. +func (x *Expression) Validate() error { + if x == nil { + return nil + } + if x.XDescription != nil { + if err := x.XDescription.Validate(); err != nil { + return fmt.Errorf("field '_description' is invalid: %w", err) + } + } + if x.XExpression != nil { + if err := x.XExpression.Validate(); err != nil { + return fmt.Errorf("field '_expression' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.XName != nil { + if err := x.XName.Validate(); err != nil { + return fmt.Errorf("field '_name' is invalid: %w", err) + } + } + if x.XReference != nil { + if err := x.XReference.Validate(); err != nil { + return fmt.Errorf("field '_reference' is invalid: %w", err) + } + } + if x.Description != nil { + if *x.Description == "" { + return fmt.Errorf("field 'description' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Expression != nil { + if *x.Expression == "" { + return fmt.Errorf("field 'expression' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Language != nil { + if !rx_Expression_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.Name != nil { + if !rx_Expression_Name.MatchString(*x.Name) { + return fmt.Errorf("field 'name' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Reference != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "Expression" { + return fmt.Errorf("field 'resourceType' must be exactly 'Expression'") + } + } + return nil +} + +// Validate validates a ExtendedContactDetail struct against its schema constraints. +func (x *ExtendedContactDetail) Validate() error { + if x == nil { + return nil + } + if x.Address != nil { + if err := x.Address.Validate(); err != nil { + return fmt.Errorf("field 'address' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Name != nil { + for i, item := range x.Name { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'name[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Organization != nil { + if err := x.Organization.Validate(); err != nil { + return fmt.Errorf("field 'organization' is invalid: %w", err) + } + } + if x.Period != nil { + if err := x.Period.Validate(); err != nil { + return fmt.Errorf("field 'period' is invalid: %w", err) + } + } + if x.Purpose != nil { + if err := x.Purpose.Validate(); err != nil { + return fmt.Errorf("field 'purpose' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ExtendedContactDetail" { + return fmt.Errorf("field 'resourceType' must be exactly 'ExtendedContactDetail'") + } + } + if x.Telecom != nil { + for i, item := range x.Telecom { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'telecom[%d]' is invalid: %w", i, err) + } + } + } + } + return nil +} + +// Validate validates a Extension struct against its schema constraints. +func (x *Extension) Validate() error { + if x == nil { + return nil + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "Extension" { + return fmt.Errorf("field 'resourceType' must be exactly 'Extension'") + } + } + if x.URL != nil { + } + if x.ValueAddress != nil { + if err := x.ValueAddress.Validate(); err != nil { + return fmt.Errorf("field 'valueAddress' is invalid: %w", err) + } + } + if x.ValueAge != nil { + if err := x.ValueAge.Validate(); err != nil { + return fmt.Errorf("field 'valueAge' is invalid: %w", err) + } + } + if x.ValueAnnotation != nil { + if err := x.ValueAnnotation.Validate(); err != nil { + return fmt.Errorf("field 'valueAnnotation' is invalid: %w", err) + } + } + if x.ValueAttachment != nil { + if err := x.ValueAttachment.Validate(); err != nil { + return fmt.Errorf("field 'valueAttachment' is invalid: %w", err) + } + } + if x.ValueAvailability != nil { + if err := x.ValueAvailability.Validate(); err != nil { + return fmt.Errorf("field 'valueAvailability' is invalid: %w", err) + } + } + if x.ValueBase64Binary != nil { + if err := ValidateFhirBinary(*x.ValueBase64Binary); err != nil { + return fmt.Errorf("field 'valueBase64Binary' has invalid binary format: %w", err) + } + } + if x.ValueBoolean != nil { + } + if x.ValueCanonical != nil { + } + if x.ValueCode != nil { + if !rx_Extension_ValueCode.MatchString(*x.ValueCode) { + return fmt.Errorf("field 'valueCode' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.ValueCodeableConcept != nil { + if err := x.ValueCodeableConcept.Validate(); err != nil { + return fmt.Errorf("field 'valueCodeableConcept' is invalid: %w", err) + } + } + if x.ValueCodeableReference != nil { + if err := x.ValueCodeableReference.Validate(); err != nil { + return fmt.Errorf("field 'valueCodeableReference' is invalid: %w", err) + } + } + if x.ValueCoding != nil { + if err := x.ValueCoding.Validate(); err != nil { + return fmt.Errorf("field 'valueCoding' is invalid: %w", err) + } + } + if x.ValueContactDetail != nil { + if err := x.ValueContactDetail.Validate(); err != nil { + return fmt.Errorf("field 'valueContactDetail' is invalid: %w", err) + } + } + if x.ValueContactPoint != nil { + if err := x.ValueContactPoint.Validate(); err != nil { + return fmt.Errorf("field 'valueContactPoint' is invalid: %w", err) + } + } + if x.ValueCount != nil { + if err := x.ValueCount.Validate(); err != nil { + return fmt.Errorf("field 'valueCount' is invalid: %w", err) + } + } + if x.ValueDataRequirement != nil { + if err := x.ValueDataRequirement.Validate(); err != nil { + return fmt.Errorf("field 'valueDataRequirement' is invalid: %w", err) + } + } + if x.ValueDate != nil { + if err := ValidateFhirDate(*x.ValueDate); err != nil { + return fmt.Errorf("field 'valueDate' has invalid date format: %w", err) + } + } + if x.ValueDateTime != nil { + if err := ValidateFhirDateTime(*x.ValueDateTime); err != nil { + return fmt.Errorf("field 'valueDateTime' has invalid date-time format: %w", err) + } + } + if x.ValueDecimal != nil { + } + if x.ValueDistance != nil { + if err := x.ValueDistance.Validate(); err != nil { + return fmt.Errorf("field 'valueDistance' is invalid: %w", err) + } + } + if x.ValueDosage != nil { + if err := x.ValueDosage.Validate(); err != nil { + return fmt.Errorf("field 'valueDosage' is invalid: %w", err) + } + } + if x.ValueDuration != nil { + if err := x.ValueDuration.Validate(); err != nil { + return fmt.Errorf("field 'valueDuration' is invalid: %w", err) + } + } + if x.ValueExpression != nil { + if err := x.ValueExpression.Validate(); err != nil { + return fmt.Errorf("field 'valueExpression' is invalid: %w", err) + } + } + if x.ValueExtendedContactDetail != nil { + if err := x.ValueExtendedContactDetail.Validate(); err != nil { + return fmt.Errorf("field 'valueExtendedContactDetail' is invalid: %w", err) + } + } + if x.ValueHumanName != nil { + if err := x.ValueHumanName.Validate(); err != nil { + return fmt.Errorf("field 'valueHumanName' is invalid: %w", err) + } + } + if x.ValueID != nil { + if !rx_Extension_ValueID.MatchString(*x.ValueID) { + return fmt.Errorf("field 'valueId' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ValueID) < 1 { + return fmt.Errorf("field 'valueId' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ValueID) > 64 { + return fmt.Errorf("field 'valueId' is too long (max 64 characters)") + } + } + if x.ValueIDentifier != nil { + if err := x.ValueIDentifier.Validate(); err != nil { + return fmt.Errorf("field 'valueIdentifier' is invalid: %w", err) + } + } + if x.ValueInstant != nil { + if err := ValidateFhirDateTime(*x.ValueInstant); err != nil { + return fmt.Errorf("field 'valueInstant' has invalid date-time format: %w", err) + } + } + if x.ValueInteger != nil { + } + if x.ValueInteger64 != nil { + } + if x.ValueMarkdown != nil { + if !rx_Extension_ValueMarkdown.MatchString(*x.ValueMarkdown) { + return fmt.Errorf("field 'valueMarkdown' does not match pattern '\\s*(\\S|\\s)*'") + } + } + if x.ValueMeta != nil { + if err := x.ValueMeta.Validate(); err != nil { + return fmt.Errorf("field 'valueMeta' is invalid: %w", err) + } + } + if x.ValueMoney != nil { + if err := x.ValueMoney.Validate(); err != nil { + return fmt.Errorf("field 'valueMoney' is invalid: %w", err) + } + } + if x.ValueOid != nil { + if !rx_Extension_ValueOid.MatchString(*x.ValueOid) { + return fmt.Errorf("field 'valueOid' does not match pattern '^urn:oid:[0-2](\\.(0|[1-9][0-9]*))+$'") + } + } + if x.ValueParameterDefinition != nil { + if err := x.ValueParameterDefinition.Validate(); err != nil { + return fmt.Errorf("field 'valueParameterDefinition' is invalid: %w", err) + } + } + if x.ValuePeriod != nil { + if err := x.ValuePeriod.Validate(); err != nil { + return fmt.Errorf("field 'valuePeriod' is invalid: %w", err) + } + } + if x.ValuePositiveInt != nil { + if *x.ValuePositiveInt <= 0.000000 { + return fmt.Errorf("field 'valuePositiveInt' is below exclusive minimum 0.000000") + } + } + if x.ValueQuantity != nil { + if err := x.ValueQuantity.Validate(); err != nil { + return fmt.Errorf("field 'valueQuantity' is invalid: %w", err) + } + } + if x.ValueRange != nil { + if err := x.ValueRange.Validate(); err != nil { + return fmt.Errorf("field 'valueRange' is invalid: %w", err) + } + } + if x.ValueRatio != nil { + if err := x.ValueRatio.Validate(); err != nil { + return fmt.Errorf("field 'valueRatio' is invalid: %w", err) + } + } + if x.ValueRatioRange != nil { + if err := x.ValueRatioRange.Validate(); err != nil { + return fmt.Errorf("field 'valueRatioRange' is invalid: %w", err) + } + } + if x.ValueReference != nil { + if err := x.ValueReference.Validate(); err != nil { + return fmt.Errorf("field 'valueReference' is invalid: %w", err) + } + } + if x.ValueRelatedArtifact != nil { + if err := x.ValueRelatedArtifact.Validate(); err != nil { + return fmt.Errorf("field 'valueRelatedArtifact' is invalid: %w", err) + } + } + if x.ValueSampledData != nil { + if err := x.ValueSampledData.Validate(); err != nil { + return fmt.Errorf("field 'valueSampledData' is invalid: %w", err) + } + } + if x.ValueSignature != nil { + if err := x.ValueSignature.Validate(); err != nil { + return fmt.Errorf("field 'valueSignature' is invalid: %w", err) + } + } + if x.ValueString != nil { + if *x.ValueString == "" { + return fmt.Errorf("field 'valueString' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.ValueTime != nil { + if err := ValidateFhirTime(*x.ValueTime); err != nil { + return fmt.Errorf("field 'valueTime' has invalid time format: %w", err) + } + } + if x.ValueTiming != nil { + if err := x.ValueTiming.Validate(); err != nil { + return fmt.Errorf("field 'valueTiming' is invalid: %w", err) + } + } + if x.ValueTriggerDefinition != nil { + if err := x.ValueTriggerDefinition.Validate(); err != nil { + return fmt.Errorf("field 'valueTriggerDefinition' is invalid: %w", err) + } + } + if x.ValueUnsignedInt != nil { + if *x.ValueUnsignedInt < 0.000000 { + return fmt.Errorf("field 'valueUnsignedInt' is below minimum 0.000000") + } + } + if x.ValueURI != nil { + } + if x.ValueURL != nil { + if utf8.RuneCountInString(*x.ValueURL) < 1 { + return fmt.Errorf("field 'valueUrl' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ValueURL) > 65536 { + return fmt.Errorf("field 'valueUrl' is too long (max 65536 characters)") + } + if err := ValidateFhirURI(*x.ValueURL); err != nil { + return fmt.Errorf("field 'valueUrl' has invalid URI format: %w", err) + } + } + if x.ValueUsageContext != nil { + if err := x.ValueUsageContext.Validate(); err != nil { + return fmt.Errorf("field 'valueUsageContext' is invalid: %w", err) + } + } + if x.ValueUUID != nil { + if err := ValidateFhirUUID(*x.ValueUUID); err != nil { + return fmt.Errorf("field 'valueUuid' has invalid UUID format: %w", err) + } + } + return nil +} + +// Validate validates a FHIRPrimitiveExtension struct against its schema constraints. +func (x *FHIRPrimitiveExtension) Validate() error { + if x == nil { + return nil + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "FHIRPrimitiveExtension" { + return fmt.Errorf("field 'resourceType' must be exactly 'FHIRPrimitiveExtension'") + } + } + return nil +} + +// Validate validates a FamilyMemberHistory struct against its schema constraints. +func (x *FamilyMemberHistory) Validate() error { + if x == nil { + return nil + } + if x.XAgeString != nil { + if err := x.XAgeString.Validate(); err != nil { + return fmt.Errorf("field '_ageString' is invalid: %w", err) + } + } + if x.XBornDate != nil { + if err := x.XBornDate.Validate(); err != nil { + return fmt.Errorf("field '_bornDate' is invalid: %w", err) + } + } + if x.XBornString != nil { + if err := x.XBornString.Validate(); err != nil { + return fmt.Errorf("field '_bornString' is invalid: %w", err) + } + } + if x.XDate != nil { + if err := x.XDate.Validate(); err != nil { + return fmt.Errorf("field '_date' is invalid: %w", err) + } + } + if x.XDeceasedBoolean != nil { + if err := x.XDeceasedBoolean.Validate(); err != nil { + return fmt.Errorf("field '_deceasedBoolean' is invalid: %w", err) + } + } + if x.XDeceasedDate != nil { + if err := x.XDeceasedDate.Validate(); err != nil { + return fmt.Errorf("field '_deceasedDate' is invalid: %w", err) + } + } + if x.XDeceasedString != nil { + if err := x.XDeceasedString.Validate(); err != nil { + return fmt.Errorf("field '_deceasedString' is invalid: %w", err) + } + } + if x.XEstimatedAge != nil { + if err := x.XEstimatedAge.Validate(); err != nil { + return fmt.Errorf("field '_estimatedAge' is invalid: %w", err) + } + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XInstantiatesCanonical != nil { + for i, item := range x.XInstantiatesCanonical { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field '_instantiatesCanonical[%d]' is invalid: %w", i, err) + } + } + } + } + if x.XInstantiatesURI != nil { + for i, item := range x.XInstantiatesURI { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field '_instantiatesUri[%d]' is invalid: %w", i, err) + } + } + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.XName != nil { + if err := x.XName.Validate(); err != nil { + return fmt.Errorf("field '_name' is invalid: %w", err) + } + } + if x.XStatus != nil { + if err := x.XStatus.Validate(); err != nil { + return fmt.Errorf("field '_status' is invalid: %w", err) + } + } + if x.AgeAge != nil { + if err := x.AgeAge.Validate(); err != nil { + return fmt.Errorf("field 'ageAge' is invalid: %w", err) + } + } + if x.AgeRange != nil { + if err := x.AgeRange.Validate(); err != nil { + return fmt.Errorf("field 'ageRange' is invalid: %w", err) + } + } + if x.AgeString != nil { + if *x.AgeString == "" { + return fmt.Errorf("field 'ageString' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.BornDate != nil { + if err := ValidateFhirDate(*x.BornDate); err != nil { + return fmt.Errorf("field 'bornDate' has invalid date format: %w", err) + } + } + if x.BornPeriod != nil { + if err := x.BornPeriod.Validate(); err != nil { + return fmt.Errorf("field 'bornPeriod' is invalid: %w", err) + } + } + if x.BornString != nil { + if *x.BornString == "" { + return fmt.Errorf("field 'bornString' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Condition != nil { + for i, item := range x.Condition { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'condition[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Contained != nil { + for i, item := range x.Contained { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) + } + } + } + } + if x.DataAbsentReason != nil { + if err := x.DataAbsentReason.Validate(); err != nil { + return fmt.Errorf("field 'dataAbsentReason' is invalid: %w", err) + } + } + if x.Date != nil { + if err := ValidateFhirDateTime(*x.Date); err != nil { + return fmt.Errorf("field 'date' has invalid date-time format: %w", err) + } + } + if x.DeceasedAge != nil { + if err := x.DeceasedAge.Validate(); err != nil { + return fmt.Errorf("field 'deceasedAge' is invalid: %w", err) + } + } + if x.DeceasedBoolean != nil { + } + if x.DeceasedDate != nil { + if err := ValidateFhirDate(*x.DeceasedDate); err != nil { + return fmt.Errorf("field 'deceasedDate' has invalid date format: %w", err) + } + } + if x.DeceasedRange != nil { + if err := x.DeceasedRange.Validate(); err != nil { + return fmt.Errorf("field 'deceasedRange' is invalid: %w", err) + } + } + if x.DeceasedString != nil { + if *x.DeceasedString == "" { + return fmt.Errorf("field 'deceasedString' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.EstimatedAge != nil { + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if !rx_FamilyMemberHistory_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ImplicitRules != nil { + } + if x.InstantiatesCanonical != nil { + } + if x.InstantiatesURI != nil { + } + if x.Language != nil { + if !rx_FamilyMemberHistory_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Name != nil { + if *x.Name == "" { + return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Note != nil { + for i, item := range x.Note { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Participant != nil { + for i, item := range x.Participant { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'participant[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Patient == nil { + return fmt.Errorf("required field 'patient' is missing") + } + if x.Patient != nil { + if err := x.Patient.Validate(); err != nil { + return fmt.Errorf("field 'patient' is invalid: %w", err) + } + } + if x.Procedure != nil { + for i, item := range x.Procedure { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'procedure[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Reason != nil { + for i, item := range x.Reason { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'reason[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Relationship == nil { + return fmt.Errorf("required field 'relationship' is missing") + } + if x.Relationship != nil { + if err := x.Relationship.Validate(); err != nil { + return fmt.Errorf("field 'relationship' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "FamilyMemberHistory" { + return fmt.Errorf("field 'resourceType' must be exactly 'FamilyMemberHistory'") + } + } + if x.Sex != nil { + if err := x.Sex.Validate(); err != nil { + return fmt.Errorf("field 'sex' is invalid: %w", err) + } + } + if x.Status != nil { + if !rx_FamilyMemberHistory_Status.MatchString(*x.Status) { + return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Text != nil { + if err := x.Text.Validate(); err != nil { + return fmt.Errorf("field 'text' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a FamilyMemberHistoryCondition struct against its schema constraints. +func (x *FamilyMemberHistoryCondition) Validate() error { + if x == nil { + return nil + } + if x.XContributedToDeath != nil { + if err := x.XContributedToDeath.Validate(); err != nil { + return fmt.Errorf("field '_contributedToDeath' is invalid: %w", err) + } + } + if x.XOnsetString != nil { + if err := x.XOnsetString.Validate(); err != nil { + return fmt.Errorf("field '_onsetString' is invalid: %w", err) + } + } + if x.Code == nil { + return fmt.Errorf("required field 'code' is missing") + } + if x.Code != nil { + if err := x.Code.Validate(); err != nil { + return fmt.Errorf("field 'code' is invalid: %w", err) + } + } + if x.ContributedToDeath != nil { + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Note != nil { + for i, item := range x.Note { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) + } + } + } + } + if x.OnsetAge != nil { + if err := x.OnsetAge.Validate(); err != nil { + return fmt.Errorf("field 'onsetAge' is invalid: %w", err) + } + } + if x.OnsetPeriod != nil { + if err := x.OnsetPeriod.Validate(); err != nil { + return fmt.Errorf("field 'onsetPeriod' is invalid: %w", err) + } + } + if x.OnsetRange != nil { + if err := x.OnsetRange.Validate(); err != nil { + return fmt.Errorf("field 'onsetRange' is invalid: %w", err) + } + } + if x.OnsetString != nil { + if *x.OnsetString == "" { + return fmt.Errorf("field 'onsetString' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Outcome != nil { + if err := x.Outcome.Validate(); err != nil { + return fmt.Errorf("field 'outcome' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "FamilyMemberHistoryCondition" { + return fmt.Errorf("field 'resourceType' must be exactly 'FamilyMemberHistoryCondition'") + } + } + return nil +} + +// Validate validates a FamilyMemberHistoryParticipant struct against its schema constraints. +func (x *FamilyMemberHistoryParticipant) Validate() error { + if x == nil { + return nil + } + if x.Actor == nil { + return fmt.Errorf("required field 'actor' is missing") + } + if x.Actor != nil { + if err := x.Actor.Validate(); err != nil { + return fmt.Errorf("field 'actor' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Function != nil { + if err := x.Function.Validate(); err != nil { + return fmt.Errorf("field 'function' is invalid: %w", err) + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "FamilyMemberHistoryParticipant" { + return fmt.Errorf("field 'resourceType' must be exactly 'FamilyMemberHistoryParticipant'") + } + } + return nil +} + +// Validate validates a FamilyMemberHistoryProcedure struct against its schema constraints. +func (x *FamilyMemberHistoryProcedure) Validate() error { + if x == nil { + return nil + } + if x.XContributedToDeath != nil { + if err := x.XContributedToDeath.Validate(); err != nil { + return fmt.Errorf("field '_contributedToDeath' is invalid: %w", err) + } + } + if x.XPerformedDateTime != nil { + if err := x.XPerformedDateTime.Validate(); err != nil { + return fmt.Errorf("field '_performedDateTime' is invalid: %w", err) + } + } + if x.XPerformedString != nil { + if err := x.XPerformedString.Validate(); err != nil { + return fmt.Errorf("field '_performedString' is invalid: %w", err) + } + } + if x.Code == nil { + return fmt.Errorf("required field 'code' is missing") + } + if x.Code != nil { + if err := x.Code.Validate(); err != nil { + return fmt.Errorf("field 'code' is invalid: %w", err) + } + } + if x.ContributedToDeath != nil { + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Note != nil { + for i, item := range x.Note { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Outcome != nil { + if err := x.Outcome.Validate(); err != nil { + return fmt.Errorf("field 'outcome' is invalid: %w", err) + } + } + if x.PerformedAge != nil { + if err := x.PerformedAge.Validate(); err != nil { + return fmt.Errorf("field 'performedAge' is invalid: %w", err) + } + } + if x.PerformedDateTime != nil { + if err := ValidateFhirDateTime(*x.PerformedDateTime); err != nil { + return fmt.Errorf("field 'performedDateTime' has invalid date-time format: %w", err) + } + } + if x.PerformedPeriod != nil { + if err := x.PerformedPeriod.Validate(); err != nil { + return fmt.Errorf("field 'performedPeriod' is invalid: %w", err) + } + } + if x.PerformedRange != nil { + if err := x.PerformedRange.Validate(); err != nil { + return fmt.Errorf("field 'performedRange' is invalid: %w", err) + } + } + if x.PerformedString != nil { + if *x.PerformedString == "" { + return fmt.Errorf("field 'performedString' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.ResourceType != nil { + if *x.ResourceType != "FamilyMemberHistoryProcedure" { + return fmt.Errorf("field 'resourceType' must be exactly 'FamilyMemberHistoryProcedure'") + } + } + return nil +} + +// Validate validates a Group struct against its schema constraints. +func (x *Group) Validate() error { + if x == nil { + return nil + } + if x.XActive != nil { + if err := x.XActive.Validate(); err != nil { + return fmt.Errorf("field '_active' is invalid: %w", err) + } + } + if x.XDescription != nil { + if err := x.XDescription.Validate(); err != nil { + return fmt.Errorf("field '_description' is invalid: %w", err) + } + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.XMembership != nil { + if err := x.XMembership.Validate(); err != nil { + return fmt.Errorf("field '_membership' is invalid: %w", err) + } + } + if x.XName != nil { + if err := x.XName.Validate(); err != nil { + return fmt.Errorf("field '_name' is invalid: %w", err) + } + } + if x.XQuantity != nil { + if err := x.XQuantity.Validate(); err != nil { + return fmt.Errorf("field '_quantity' is invalid: %w", err) + } + } + if x.XType != nil { + if err := x.XType.Validate(); err != nil { + return fmt.Errorf("field '_type' is invalid: %w", err) + } + } + if x.Active != nil { + } + if x.Characteristic != nil { + for i, item := range x.Characteristic { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'characteristic[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Code != nil { + if err := x.Code.Validate(); err != nil { + return fmt.Errorf("field 'code' is invalid: %w", err) + } + } + if x.Contained != nil { + for i, item := range x.Contained { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Description != nil { + if !rx_Group_Description.MatchString(*x.Description) { + return fmt.Errorf("field 'description' does not match pattern '\\s*(\\S|\\s)*'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if !rx_Group_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ImplicitRules != nil { + } + if x.Language != nil { + if !rx_Group_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.ManagingEntity != nil { + if err := x.ManagingEntity.Validate(); err != nil { + return fmt.Errorf("field 'managingEntity' is invalid: %w", err) + } + } + if x.Member != nil { + for i, item := range x.Member { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'member[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Membership != nil { + if !rx_Group_Membership.MatchString(*x.Membership) { + return fmt.Errorf("field 'membership' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Name != nil { + if *x.Name == "" { + return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Quantity != nil { + if *x.Quantity < 0.000000 { + return fmt.Errorf("field 'quantity' is below minimum 0.000000") + } + } + if x.ResourceType != nil { + if *x.ResourceType != "Group" { + return fmt.Errorf("field 'resourceType' must be exactly 'Group'") + } + } + if x.Text != nil { + if err := x.Text.Validate(); err != nil { + return fmt.Errorf("field 'text' is invalid: %w", err) + } + } + if x.Type != nil { + if !rx_Group_Type.MatchString(*x.Type) { + return fmt.Errorf("field 'type' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + return nil +} + +// Validate validates a GroupCharacteristic struct against its schema constraints. +func (x *GroupCharacteristic) Validate() error { + if x == nil { + return nil + } + if x.XExclude != nil { + if err := x.XExclude.Validate(); err != nil { + return fmt.Errorf("field '_exclude' is invalid: %w", err) + } + } + if x.XValueBoolean != nil { + if err := x.XValueBoolean.Validate(); err != nil { + return fmt.Errorf("field '_valueBoolean' is invalid: %w", err) + } + } + if x.Code == nil { + return fmt.Errorf("required field 'code' is missing") + } + if x.Code != nil { + if err := x.Code.Validate(); err != nil { + return fmt.Errorf("field 'code' is invalid: %w", err) + } + } + if x.Exclude != nil { + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Period != nil { + if err := x.Period.Validate(); err != nil { + return fmt.Errorf("field 'period' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "GroupCharacteristic" { + return fmt.Errorf("field 'resourceType' must be exactly 'GroupCharacteristic'") + } + } + if x.ValueBoolean != nil { + } + if x.ValueCodeableConcept != nil { + if err := x.ValueCodeableConcept.Validate(); err != nil { + return fmt.Errorf("field 'valueCodeableConcept' is invalid: %w", err) + } + } + if x.ValueQuantity != nil { + if err := x.ValueQuantity.Validate(); err != nil { + return fmt.Errorf("field 'valueQuantity' is invalid: %w", err) + } + } + if x.ValueRange != nil { + if err := x.ValueRange.Validate(); err != nil { + return fmt.Errorf("field 'valueRange' is invalid: %w", err) + } + } + if x.ValueReference != nil { + if err := x.ValueReference.Validate(); err != nil { + return fmt.Errorf("field 'valueReference' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a GroupMember struct against its schema constraints. +func (x *GroupMember) Validate() error { + if x == nil { + return nil + } + if x.XInactive != nil { + if err := x.XInactive.Validate(); err != nil { + return fmt.Errorf("field '_inactive' is invalid: %w", err) + } + } + if x.Entity == nil { + return fmt.Errorf("required field 'entity' is missing") + } + if x.Entity != nil { + if err := x.Entity.Validate(); err != nil { + return fmt.Errorf("field 'entity' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Inactive != nil { + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Period != nil { + if err := x.Period.Validate(); err != nil { + return fmt.Errorf("field 'period' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "GroupMember" { + return fmt.Errorf("field 'resourceType' must be exactly 'GroupMember'") + } + } + return nil +} + +// Validate validates a HumanName struct against its schema constraints. +func (x *HumanName) Validate() error { + if x == nil { + return nil + } + if x.XFamily != nil { + if err := x.XFamily.Validate(); err != nil { + return fmt.Errorf("field '_family' is invalid: %w", err) + } + } + if x.XGiven != nil { + for i, item := range x.XGiven { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field '_given[%d]' is invalid: %w", i, err) + } + } + } + } + if x.XPrefix != nil { + for i, item := range x.XPrefix { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field '_prefix[%d]' is invalid: %w", i, err) + } + } + } + } + if x.XSuffix != nil { + for i, item := range x.XSuffix { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field '_suffix[%d]' is invalid: %w", i, err) + } + } + } + } + if x.XText != nil { + if err := x.XText.Validate(); err != nil { + return fmt.Errorf("field '_text' is invalid: %w", err) + } + } + if x.XUse != nil { + if err := x.XUse.Validate(); err != nil { + return fmt.Errorf("field '_use' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Family != nil { + if *x.Family == "" { + return fmt.Errorf("field 'family' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Given != nil { + for i, item := range x.Given { + if item == "" { + return fmt.Errorf("field 'given[%d]' does not match pattern '[ \\r\\n\\t\\S]+'", i) + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Period != nil { + if err := x.Period.Validate(); err != nil { + return fmt.Errorf("field 'period' is invalid: %w", err) + } + } + if x.Prefix != nil { + for i, item := range x.Prefix { + if item == "" { + return fmt.Errorf("field 'prefix[%d]' does not match pattern '[ \\r\\n\\t\\S]+'", i) + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "HumanName" { + return fmt.Errorf("field 'resourceType' must be exactly 'HumanName'") + } + } + if x.Suffix != nil { + for i, item := range x.Suffix { + if item == "" { + return fmt.Errorf("field 'suffix[%d]' does not match pattern '[ \\r\\n\\t\\S]+'", i) + } + } + } + if x.Text != nil { + if *x.Text == "" { + return fmt.Errorf("field 'text' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Use != nil { + if !rx_HumanName_Use.MatchString(*x.Use) { + return fmt.Errorf("field 'use' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + return nil +} + +// Validate validates a Identifier struct against its schema constraints. +func (x *Identifier) Validate() error { + if x == nil { + return nil + } + if x.XSystem != nil { + if err := x.XSystem.Validate(); err != nil { + return fmt.Errorf("field '_system' is invalid: %w", err) + } + } + if x.XUse != nil { + if err := x.XUse.Validate(); err != nil { + return fmt.Errorf("field '_use' is invalid: %w", err) + } + } + if x.XValue != nil { + if err := x.XValue.Validate(); err != nil { + return fmt.Errorf("field '_value' is invalid: %w", err) + } + } + if x.Assigner != nil { + if err := x.Assigner.Validate(); err != nil { + return fmt.Errorf("field 'assigner' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Period != nil { + if err := x.Period.Validate(); err != nil { + return fmt.Errorf("field 'period' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "Identifier" { + return fmt.Errorf("field 'resourceType' must be exactly 'Identifier'") + } + } + if x.System != nil { + } + if x.Type != nil { + if err := x.Type.Validate(); err != nil { + return fmt.Errorf("field 'type' is invalid: %w", err) + } + } + if x.Use != nil { + if !rx_Identifier_Use.MatchString(*x.Use) { + return fmt.Errorf("field 'use' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Value != nil { + if *x.Value == "" { + return fmt.Errorf("field 'value' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + return nil +} + +// Validate validates a ImagingStudy struct against its schema constraints. +func (x *ImagingStudy) Validate() error { + if x == nil { + return nil + } + if x.XDescription != nil { + if err := x.XDescription.Validate(); err != nil { + return fmt.Errorf("field '_description' is invalid: %w", err) + } + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.XNumberOfInstances != nil { + if err := x.XNumberOfInstances.Validate(); err != nil { + return fmt.Errorf("field '_numberOfInstances' is invalid: %w", err) + } + } + if x.XNumberOfSeries != nil { + if err := x.XNumberOfSeries.Validate(); err != nil { + return fmt.Errorf("field '_numberOfSeries' is invalid: %w", err) + } + } + if x.XStarted != nil { + if err := x.XStarted.Validate(); err != nil { + return fmt.Errorf("field '_started' is invalid: %w", err) + } + } + if x.XStatus != nil { + if err := x.XStatus.Validate(); err != nil { + return fmt.Errorf("field '_status' is invalid: %w", err) + } + } + if x.BasedOn != nil { + for i, item := range x.BasedOn { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'basedOn[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Contained != nil { + for i, item := range x.Contained { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Description != nil { + if *x.Description == "" { + return fmt.Errorf("field 'description' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Encounter != nil { + if err := x.Encounter.Validate(); err != nil { + return fmt.Errorf("field 'encounter' is invalid: %w", err) + } + } + if x.Endpoint != nil { + for i, item := range x.Endpoint { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'endpoint[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if !rx_ImagingStudy_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ImplicitRules != nil { + } + if x.Language != nil { + if !rx_ImagingStudy_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.Location != nil { + if err := x.Location.Validate(); err != nil { + return fmt.Errorf("field 'location' is invalid: %w", err) + } + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.Modality != nil { + for i, item := range x.Modality { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modality[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Note != nil { + for i, item := range x.Note { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) + } + } + } + } + if x.NumberOfInstances != nil { + if *x.NumberOfInstances < 0.000000 { + return fmt.Errorf("field 'numberOfInstances' is below minimum 0.000000") + } + } + if x.NumberOfSeries != nil { + if *x.NumberOfSeries < 0.000000 { + return fmt.Errorf("field 'numberOfSeries' is below minimum 0.000000") + } + } + if x.PartOf != nil { + for i, item := range x.PartOf { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'partOf[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Procedure != nil { + for i, item := range x.Procedure { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'procedure[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Reason != nil { + for i, item := range x.Reason { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'reason[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Referrer != nil { + if err := x.Referrer.Validate(); err != nil { + return fmt.Errorf("field 'referrer' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ImagingStudy" { + return fmt.Errorf("field 'resourceType' must be exactly 'ImagingStudy'") + } + } + if x.Series != nil { + for i, item := range x.Series { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'series[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Started != nil { + if err := ValidateFhirDateTime(*x.Started); err != nil { + return fmt.Errorf("field 'started' has invalid date-time format: %w", err) + } + } + if x.Status != nil { + if !rx_ImagingStudy_Status.MatchString(*x.Status) { + return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Subject == nil { + return fmt.Errorf("required field 'subject' is missing") + } + if x.Subject != nil { + if err := x.Subject.Validate(); err != nil { + return fmt.Errorf("field 'subject' is invalid: %w", err) + } + } + if x.Text != nil { + if err := x.Text.Validate(); err != nil { + return fmt.Errorf("field 'text' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a ImagingStudySeries struct against its schema constraints. +func (x *ImagingStudySeries) Validate() error { + if x == nil { + return nil + } + if x.XDescription != nil { + if err := x.XDescription.Validate(); err != nil { + return fmt.Errorf("field '_description' is invalid: %w", err) + } + } + if x.XNumber != nil { + if err := x.XNumber.Validate(); err != nil { + return fmt.Errorf("field '_number' is invalid: %w", err) + } + } + if x.XNumberOfInstances != nil { + if err := x.XNumberOfInstances.Validate(); err != nil { + return fmt.Errorf("field '_numberOfInstances' is invalid: %w", err) + } + } + if x.XStarted != nil { + if err := x.XStarted.Validate(); err != nil { + return fmt.Errorf("field '_started' is invalid: %w", err) + } + } + if x.XUid != nil { + if err := x.XUid.Validate(); err != nil { + return fmt.Errorf("field '_uid' is invalid: %w", err) + } + } + if x.BodySite != nil { + if err := x.BodySite.Validate(); err != nil { + return fmt.Errorf("field 'bodySite' is invalid: %w", err) + } + } + if x.Description != nil { + if *x.Description == "" { + return fmt.Errorf("field 'description' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Endpoint != nil { + for i, item := range x.Endpoint { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'endpoint[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Instance != nil { + for i, item := range x.Instance { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'instance[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Laterality != nil { + if err := x.Laterality.Validate(); err != nil { + return fmt.Errorf("field 'laterality' is invalid: %w", err) + } + } + if x.Links != nil { + } + if x.Modality == nil { + return fmt.Errorf("required field 'modality' is missing") + } + if x.Modality != nil { + if err := x.Modality.Validate(); err != nil { + return fmt.Errorf("field 'modality' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Number != nil { + if *x.Number < 0.000000 { + return fmt.Errorf("field 'number' is below minimum 0.000000") + } + } + if x.NumberOfInstances != nil { + if *x.NumberOfInstances < 0.000000 { + return fmt.Errorf("field 'numberOfInstances' is below minimum 0.000000") + } + } + if x.Performer != nil { + for i, item := range x.Performer { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'performer[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ImagingStudySeries" { + return fmt.Errorf("field 'resourceType' must be exactly 'ImagingStudySeries'") + } + } + if x.Specimen != nil { + for i, item := range x.Specimen { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'specimen[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Started != nil { + if err := ValidateFhirDateTime(*x.Started); err != nil { + return fmt.Errorf("field 'started' has invalid date-time format: %w", err) + } + } + if x.Uid != nil { + if !rx_ImagingStudySeries_Uid.MatchString(*x.Uid) { + return fmt.Errorf("field 'uid' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.Uid) < 1 { + return fmt.Errorf("field 'uid' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.Uid) > 64 { + return fmt.Errorf("field 'uid' is too long (max 64 characters)") + } + } + return nil +} + +// Validate validates a ImagingStudySeriesInstance struct against its schema constraints. +func (x *ImagingStudySeriesInstance) Validate() error { + if x == nil { + return nil + } + if x.XNumber != nil { + if err := x.XNumber.Validate(); err != nil { + return fmt.Errorf("field '_number' is invalid: %w", err) + } + } + if x.XTitle != nil { + if err := x.XTitle.Validate(); err != nil { + return fmt.Errorf("field '_title' is invalid: %w", err) + } + } + if x.XUid != nil { + if err := x.XUid.Validate(); err != nil { + return fmt.Errorf("field '_uid' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Number != nil { + if *x.Number < 0.000000 { + return fmt.Errorf("field 'number' is below minimum 0.000000") + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ImagingStudySeriesInstance" { + return fmt.Errorf("field 'resourceType' must be exactly 'ImagingStudySeriesInstance'") + } + } + if x.SopClass == nil { + return fmt.Errorf("required field 'sopClass' is missing") + } + if x.SopClass != nil { + if err := x.SopClass.Validate(); err != nil { + return fmt.Errorf("field 'sopClass' is invalid: %w", err) + } + } + if x.Title != nil { + if *x.Title == "" { + return fmt.Errorf("field 'title' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Uid != nil { + if !rx_ImagingStudySeriesInstance_Uid.MatchString(*x.Uid) { + return fmt.Errorf("field 'uid' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.Uid) < 1 { + return fmt.Errorf("field 'uid' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.Uid) > 64 { + return fmt.Errorf("field 'uid' is too long (max 64 characters)") + } + } + return nil +} + +// Validate validates a ImagingStudySeriesPerformer struct against its schema constraints. +func (x *ImagingStudySeriesPerformer) Validate() error { + if x == nil { + return nil + } + if x.Actor == nil { + return fmt.Errorf("required field 'actor' is missing") + } + if x.Actor != nil { + if err := x.Actor.Validate(); err != nil { + return fmt.Errorf("field 'actor' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Function != nil { + if err := x.Function.Validate(); err != nil { + return fmt.Errorf("field 'function' is invalid: %w", err) + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ImagingStudySeriesPerformer" { + return fmt.Errorf("field 'resourceType' must be exactly 'ImagingStudySeriesPerformer'") + } + } + return nil +} + +// Validate validates a Medication struct against its schema constraints. +func (x *Medication) Validate() error { + if x == nil { + return nil + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.XStatus != nil { + if err := x.XStatus.Validate(); err != nil { + return fmt.Errorf("field '_status' is invalid: %w", err) + } + } + if x.Batch != nil { + if err := x.Batch.Validate(); err != nil { + return fmt.Errorf("field 'batch' is invalid: %w", err) + } + } + if x.Code != nil { + if err := x.Code.Validate(); err != nil { + return fmt.Errorf("field 'code' is invalid: %w", err) + } + } + if x.Contained != nil { + for i, item := range x.Contained { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Definition != nil { + if err := x.Definition.Validate(); err != nil { + return fmt.Errorf("field 'definition' is invalid: %w", err) + } + } + if x.DoseForm != nil { + if err := x.DoseForm.Validate(); err != nil { + return fmt.Errorf("field 'doseForm' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if !rx_Medication_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ImplicitRules != nil { + } + if x.Ingredient != nil { + for i, item := range x.Ingredient { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'ingredient[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Language != nil { + if !rx_Medication_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.MarketingAuthorizationHolder != nil { + if err := x.MarketingAuthorizationHolder.Validate(); err != nil { + return fmt.Errorf("field 'marketingAuthorizationHolder' is invalid: %w", err) + } + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "Medication" { + return fmt.Errorf("field 'resourceType' must be exactly 'Medication'") + } + } + if x.Status != nil { + if !rx_Medication_Status.MatchString(*x.Status) { + return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Text != nil { + if err := x.Text.Validate(); err != nil { + return fmt.Errorf("field 'text' is invalid: %w", err) + } + } + if x.TotalVolume != nil { + if err := x.TotalVolume.Validate(); err != nil { + return fmt.Errorf("field 'totalVolume' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a MedicationAdministration struct against its schema constraints. +func (x *MedicationAdministration) Validate() error { + if x == nil { + return nil + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XIsSubPotent != nil { + if err := x.XIsSubPotent.Validate(); err != nil { + return fmt.Errorf("field '_isSubPotent' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.XOccurenceDateTime != nil { + if err := x.XOccurenceDateTime.Validate(); err != nil { + return fmt.Errorf("field '_occurenceDateTime' is invalid: %w", err) + } + } + if x.XRecorded != nil { + if err := x.XRecorded.Validate(); err != nil { + return fmt.Errorf("field '_recorded' is invalid: %w", err) + } + } + if x.XStatus != nil { + if err := x.XStatus.Validate(); err != nil { + return fmt.Errorf("field '_status' is invalid: %w", err) + } + } + if x.BasedOn != nil { + for i, item := range x.BasedOn { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'basedOn[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Category != nil { + for i, item := range x.Category { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'category[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Contained != nil { + for i, item := range x.Contained { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Device != nil { + for i, item := range x.Device { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'device[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Dosage != nil { + if err := x.Dosage.Validate(); err != nil { + return fmt.Errorf("field 'dosage' is invalid: %w", err) + } + } + if x.Encounter != nil { + if err := x.Encounter.Validate(); err != nil { + return fmt.Errorf("field 'encounter' is invalid: %w", err) + } + } + if x.EventHistory != nil { + for i, item := range x.EventHistory { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'eventHistory[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if !rx_MedicationAdministration_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ImplicitRules != nil { + } + if x.IsSubPotent != nil { + } + if x.Language != nil { + if !rx_MedicationAdministration_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.Medication == nil { + return fmt.Errorf("required field 'medication' is missing") + } + if x.Medication != nil { + if err := x.Medication.Validate(); err != nil { + return fmt.Errorf("field 'medication' is invalid: %w", err) + } + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Note != nil { + for i, item := range x.Note { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) + } + } + } + } + if x.OccurenceDateTime != nil { + if err := ValidateFhirDateTime(*x.OccurenceDateTime); err != nil { + return fmt.Errorf("field 'occurenceDateTime' has invalid date-time format: %w", err) + } + } + if x.OccurencePeriod != nil { + if err := x.OccurencePeriod.Validate(); err != nil { + return fmt.Errorf("field 'occurencePeriod' is invalid: %w", err) + } + } + if x.OccurenceTiming != nil { + if err := x.OccurenceTiming.Validate(); err != nil { + return fmt.Errorf("field 'occurenceTiming' is invalid: %w", err) + } + } + if x.PartOf != nil { + for i, item := range x.PartOf { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'partOf[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Performer != nil { + for i, item := range x.Performer { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'performer[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Reason != nil { + for i, item := range x.Reason { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'reason[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Recorded != nil { + if err := ValidateFhirDateTime(*x.Recorded); err != nil { + return fmt.Errorf("field 'recorded' has invalid date-time format: %w", err) + } + } + if x.Request != nil { + if err := x.Request.Validate(); err != nil { + return fmt.Errorf("field 'request' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "MedicationAdministration" { + return fmt.Errorf("field 'resourceType' must be exactly 'MedicationAdministration'") + } + } + if x.Status != nil { + if !rx_MedicationAdministration_Status.MatchString(*x.Status) { + return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.StatusReason != nil { + for i, item := range x.StatusReason { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'statusReason[%d]' is invalid: %w", i, err) + } + } + } + } + if x.SubPotentReason != nil { + for i, item := range x.SubPotentReason { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'subPotentReason[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Subject == nil { + return fmt.Errorf("required field 'subject' is missing") + } + if x.Subject != nil { + if err := x.Subject.Validate(); err != nil { + return fmt.Errorf("field 'subject' is invalid: %w", err) + } + } + if x.SupportingInformation != nil { + for i, item := range x.SupportingInformation { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'supportingInformation[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Text != nil { + if err := x.Text.Validate(); err != nil { + return fmt.Errorf("field 'text' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a MedicationAdministrationDosage struct against its schema constraints. +func (x *MedicationAdministrationDosage) Validate() error { + if x == nil { + return nil + } + if x.XText != nil { + if err := x.XText.Validate(); err != nil { + return fmt.Errorf("field '_text' is invalid: %w", err) + } + } + if x.Dose != nil { + if err := x.Dose.Validate(); err != nil { + return fmt.Errorf("field 'dose' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Method != nil { + if err := x.Method.Validate(); err != nil { + return fmt.Errorf("field 'method' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.RateQuantity != nil { + if err := x.RateQuantity.Validate(); err != nil { + return fmt.Errorf("field 'rateQuantity' is invalid: %w", err) + } + } + if x.RateRatio != nil { + if err := x.RateRatio.Validate(); err != nil { + return fmt.Errorf("field 'rateRatio' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "MedicationAdministrationDosage" { + return fmt.Errorf("field 'resourceType' must be exactly 'MedicationAdministrationDosage'") + } + } + if x.Route != nil { + if err := x.Route.Validate(); err != nil { + return fmt.Errorf("field 'route' is invalid: %w", err) + } + } + if x.Site != nil { + if err := x.Site.Validate(); err != nil { + return fmt.Errorf("field 'site' is invalid: %w", err) + } + } + if x.Text != nil { + if *x.Text == "" { + return fmt.Errorf("field 'text' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + return nil +} + +// Validate validates a MedicationAdministrationPerformer struct against its schema constraints. +func (x *MedicationAdministrationPerformer) Validate() error { + if x == nil { + return nil + } + if x.Actor == nil { + return fmt.Errorf("required field 'actor' is missing") + } + if x.Actor != nil { + if err := x.Actor.Validate(); err != nil { + return fmt.Errorf("field 'actor' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Function != nil { + if err := x.Function.Validate(); err != nil { + return fmt.Errorf("field 'function' is invalid: %w", err) + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "MedicationAdministrationPerformer" { + return fmt.Errorf("field 'resourceType' must be exactly 'MedicationAdministrationPerformer'") + } + } + return nil +} + +// Validate validates a MedicationBatch struct against its schema constraints. +func (x *MedicationBatch) Validate() error { + if x == nil { + return nil + } + if x.XExpirationDate != nil { + if err := x.XExpirationDate.Validate(); err != nil { + return fmt.Errorf("field '_expirationDate' is invalid: %w", err) + } + } + if x.XLotNumber != nil { + if err := x.XLotNumber.Validate(); err != nil { + return fmt.Errorf("field '_lotNumber' is invalid: %w", err) + } + } + if x.ExpirationDate != nil { + if err := ValidateFhirDateTime(*x.ExpirationDate); err != nil { + return fmt.Errorf("field 'expirationDate' has invalid date-time format: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.LotNumber != nil { + if *x.LotNumber == "" { + return fmt.Errorf("field 'lotNumber' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "MedicationBatch" { + return fmt.Errorf("field 'resourceType' must be exactly 'MedicationBatch'") + } + } + return nil +} + +// Validate validates a MedicationIngredient struct against its schema constraints. +func (x *MedicationIngredient) Validate() error { + if x == nil { + return nil + } + if x.XIsActive != nil { + if err := x.XIsActive.Validate(); err != nil { + return fmt.Errorf("field '_isActive' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.IsActive != nil { + } + if x.Item == nil { + return fmt.Errorf("required field 'item' is missing") + } + if x.Item != nil { + if err := x.Item.Validate(); err != nil { + return fmt.Errorf("field 'item' is invalid: %w", err) + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "MedicationIngredient" { + return fmt.Errorf("field 'resourceType' must be exactly 'MedicationIngredient'") + } + } + if x.StrengthCodeableConcept != nil { + if err := x.StrengthCodeableConcept.Validate(); err != nil { + return fmt.Errorf("field 'strengthCodeableConcept' is invalid: %w", err) + } + } + if x.StrengthQuantity != nil { + if err := x.StrengthQuantity.Validate(); err != nil { + return fmt.Errorf("field 'strengthQuantity' is invalid: %w", err) + } + } + if x.StrengthRatio != nil { + if err := x.StrengthRatio.Validate(); err != nil { + return fmt.Errorf("field 'strengthRatio' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a MedicationRequest struct against its schema constraints. +func (x *MedicationRequest) Validate() error { + if x == nil { + return nil + } + if x.XAuthoredOn != nil { + if err := x.XAuthoredOn.Validate(); err != nil { + return fmt.Errorf("field '_authoredOn' is invalid: %w", err) + } + } + if x.XDoNotPerform != nil { + if err := x.XDoNotPerform.Validate(); err != nil { + return fmt.Errorf("field '_doNotPerform' is invalid: %w", err) + } + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XIntent != nil { + if err := x.XIntent.Validate(); err != nil { + return fmt.Errorf("field '_intent' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.XPriority != nil { + if err := x.XPriority.Validate(); err != nil { + return fmt.Errorf("field '_priority' is invalid: %w", err) + } + } + if x.XRenderedDosageInstruction != nil { + if err := x.XRenderedDosageInstruction.Validate(); err != nil { + return fmt.Errorf("field '_renderedDosageInstruction' is invalid: %w", err) + } + } + if x.XReported != nil { + if err := x.XReported.Validate(); err != nil { + return fmt.Errorf("field '_reported' is invalid: %w", err) + } + } + if x.XStatus != nil { + if err := x.XStatus.Validate(); err != nil { + return fmt.Errorf("field '_status' is invalid: %w", err) + } + } + if x.XStatusChanged != nil { + if err := x.XStatusChanged.Validate(); err != nil { + return fmt.Errorf("field '_statusChanged' is invalid: %w", err) + } + } + if x.AuthoredOn != nil { + if err := ValidateFhirDateTime(*x.AuthoredOn); err != nil { + return fmt.Errorf("field 'authoredOn' has invalid date-time format: %w", err) + } + } + if x.BasedOn != nil { + for i, item := range x.BasedOn { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'basedOn[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Category != nil { + for i, item := range x.Category { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'category[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Contained != nil { + for i, item := range x.Contained { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) + } + } + } + } + if x.CourseOfTherapyType != nil { + if err := x.CourseOfTherapyType.Validate(); err != nil { + return fmt.Errorf("field 'courseOfTherapyType' is invalid: %w", err) + } + } + if x.Device != nil { + for i, item := range x.Device { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'device[%d]' is invalid: %w", i, err) + } + } + } + } + if x.DispenseRequest != nil { + if err := x.DispenseRequest.Validate(); err != nil { + return fmt.Errorf("field 'dispenseRequest' is invalid: %w", err) + } + } + if x.DoNotPerform != nil { + } + if x.DosageInstruction != nil { + for i, item := range x.DosageInstruction { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'dosageInstruction[%d]' is invalid: %w", i, err) + } + } + } + } + if x.EffectiveDosePeriod != nil { + if err := x.EffectiveDosePeriod.Validate(); err != nil { + return fmt.Errorf("field 'effectiveDosePeriod' is invalid: %w", err) + } + } + if x.Encounter != nil { + if err := x.Encounter.Validate(); err != nil { + return fmt.Errorf("field 'encounter' is invalid: %w", err) + } + } + if x.EventHistory != nil { + for i, item := range x.EventHistory { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'eventHistory[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.GroupIDentifier != nil { + if err := x.GroupIDentifier.Validate(); err != nil { + return fmt.Errorf("field 'groupIdentifier' is invalid: %w", err) + } + } + if x.ID != nil { + if !rx_MedicationRequest_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ImplicitRules != nil { + } + if x.InformationSource != nil { + for i, item := range x.InformationSource { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'informationSource[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Insurance != nil { + for i, item := range x.Insurance { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'insurance[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Intent != nil { + if !rx_MedicationRequest_Intent.MatchString(*x.Intent) { + return fmt.Errorf("field 'intent' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Language != nil { + if !rx_MedicationRequest_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.Medication == nil { + return fmt.Errorf("required field 'medication' is missing") + } + if x.Medication != nil { + if err := x.Medication.Validate(); err != nil { + return fmt.Errorf("field 'medication' is invalid: %w", err) + } + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Note != nil { + for i, item := range x.Note { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Performer != nil { + for i, item := range x.Performer { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'performer[%d]' is invalid: %w", i, err) + } + } + } + } + if x.PerformerType != nil { + if err := x.PerformerType.Validate(); err != nil { + return fmt.Errorf("field 'performerType' is invalid: %w", err) + } + } + if x.PriorPrescription != nil { + if err := x.PriorPrescription.Validate(); err != nil { + return fmt.Errorf("field 'priorPrescription' is invalid: %w", err) + } + } + if x.Priority != nil { + if !rx_MedicationRequest_Priority.MatchString(*x.Priority) { + return fmt.Errorf("field 'priority' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Reason != nil { + for i, item := range x.Reason { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'reason[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Recorder != nil { + if err := x.Recorder.Validate(); err != nil { + return fmt.Errorf("field 'recorder' is invalid: %w", err) + } + } + if x.RenderedDosageInstruction != nil { + if !rx_MedicationRequest_RenderedDosageInstruction.MatchString(*x.RenderedDosageInstruction) { + return fmt.Errorf("field 'renderedDosageInstruction' does not match pattern '\\s*(\\S|\\s)*'") + } + } + if x.Reported != nil { + } + if x.Requester != nil { + if err := x.Requester.Validate(); err != nil { + return fmt.Errorf("field 'requester' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "MedicationRequest" { + return fmt.Errorf("field 'resourceType' must be exactly 'MedicationRequest'") + } + } + if x.Status != nil { + if !rx_MedicationRequest_Status.MatchString(*x.Status) { + return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.StatusChanged != nil { + if err := ValidateFhirDateTime(*x.StatusChanged); err != nil { + return fmt.Errorf("field 'statusChanged' has invalid date-time format: %w", err) + } + } + if x.StatusReason != nil { + if err := x.StatusReason.Validate(); err != nil { + return fmt.Errorf("field 'statusReason' is invalid: %w", err) + } + } + if x.Subject == nil { + return fmt.Errorf("required field 'subject' is missing") + } + if x.Subject != nil { + if err := x.Subject.Validate(); err != nil { + return fmt.Errorf("field 'subject' is invalid: %w", err) + } + } + if x.Substitution != nil { + if err := x.Substitution.Validate(); err != nil { + return fmt.Errorf("field 'substitution' is invalid: %w", err) + } + } + if x.SupportingInformation != nil { + for i, item := range x.SupportingInformation { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'supportingInformation[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Text != nil { + if err := x.Text.Validate(); err != nil { + return fmt.Errorf("field 'text' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a MedicationRequestDispenseRequest struct against its schema constraints. +func (x *MedicationRequestDispenseRequest) Validate() error { + if x == nil { + return nil + } + if x.XNumberOfRepeatsAllowed != nil { + if err := x.XNumberOfRepeatsAllowed.Validate(); err != nil { + return fmt.Errorf("field '_numberOfRepeatsAllowed' is invalid: %w", err) + } + } + if x.DispenseInterval != nil { + if err := x.DispenseInterval.Validate(); err != nil { + return fmt.Errorf("field 'dispenseInterval' is invalid: %w", err) + } + } + if x.Dispenser != nil { + if err := x.Dispenser.Validate(); err != nil { + return fmt.Errorf("field 'dispenser' is invalid: %w", err) + } + } + if x.DispenserInstruction != nil { + for i, item := range x.DispenserInstruction { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'dispenserInstruction[%d]' is invalid: %w", i, err) + } + } + } + } + if x.DoseAdministrationAid != nil { + if err := x.DoseAdministrationAid.Validate(); err != nil { + return fmt.Errorf("field 'doseAdministrationAid' is invalid: %w", err) + } + } + if x.ExpectedSupplyDuration != nil { + if err := x.ExpectedSupplyDuration.Validate(); err != nil { + return fmt.Errorf("field 'expectedSupplyDuration' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.InitialFill != nil { + if err := x.InitialFill.Validate(); err != nil { + return fmt.Errorf("field 'initialFill' is invalid: %w", err) + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.NumberOfRepeatsAllowed != nil { + if *x.NumberOfRepeatsAllowed < 0.000000 { + return fmt.Errorf("field 'numberOfRepeatsAllowed' is below minimum 0.000000") + } + } + if x.Quantity != nil { + if err := x.Quantity.Validate(); err != nil { + return fmt.Errorf("field 'quantity' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "MedicationRequestDispenseRequest" { + return fmt.Errorf("field 'resourceType' must be exactly 'MedicationRequestDispenseRequest'") + } + } + if x.ValidityPeriod != nil { + if err := x.ValidityPeriod.Validate(); err != nil { + return fmt.Errorf("field 'validityPeriod' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a MedicationRequestDispenseRequestInitialFill struct against its schema constraints. +func (x *MedicationRequestDispenseRequestInitialFill) Validate() error { + if x == nil { + return nil + } + if x.Duration != nil { + if err := x.Duration.Validate(); err != nil { + return fmt.Errorf("field 'duration' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Quantity != nil { + if err := x.Quantity.Validate(); err != nil { + return fmt.Errorf("field 'quantity' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "MedicationRequestDispenseRequestInitialFill" { + return fmt.Errorf("field 'resourceType' must be exactly 'MedicationRequestDispenseRequestInitialFill'") + } + } + return nil +} + +// Validate validates a MedicationRequestSubstitution struct against its schema constraints. +func (x *MedicationRequestSubstitution) Validate() error { + if x == nil { + return nil + } + if x.XAllowedBoolean != nil { + if err := x.XAllowedBoolean.Validate(); err != nil { + return fmt.Errorf("field '_allowedBoolean' is invalid: %w", err) + } + } + if x.AllowedBoolean != nil { + } + if x.AllowedCodeableConcept != nil { + if err := x.AllowedCodeableConcept.Validate(); err != nil { + return fmt.Errorf("field 'allowedCodeableConcept' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Reason != nil { + if err := x.Reason.Validate(); err != nil { + return fmt.Errorf("field 'reason' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "MedicationRequestSubstitution" { + return fmt.Errorf("field 'resourceType' must be exactly 'MedicationRequestSubstitution'") + } + } + return nil +} + +// Validate validates a MedicationStatement struct against its schema constraints. +func (x *MedicationStatement) Validate() error { + if x == nil { + return nil + } + if x.XDateAsserted != nil { + if err := x.XDateAsserted.Validate(); err != nil { + return fmt.Errorf("field '_dateAsserted' is invalid: %w", err) + } + } + if x.XEffectiveDateTime != nil { + if err := x.XEffectiveDateTime.Validate(); err != nil { + return fmt.Errorf("field '_effectiveDateTime' is invalid: %w", err) + } + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.XRenderedDosageInstruction != nil { + if err := x.XRenderedDosageInstruction.Validate(); err != nil { + return fmt.Errorf("field '_renderedDosageInstruction' is invalid: %w", err) + } + } + if x.XStatus != nil { + if err := x.XStatus.Validate(); err != nil { + return fmt.Errorf("field '_status' is invalid: %w", err) + } + } + if x.Adherence != nil { + if err := x.Adherence.Validate(); err != nil { + return fmt.Errorf("field 'adherence' is invalid: %w", err) + } + } + if x.Category != nil { + for i, item := range x.Category { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'category[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Contained != nil { + for i, item := range x.Contained { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) + } + } + } + } + if x.DateAsserted != nil { + if err := ValidateFhirDateTime(*x.DateAsserted); err != nil { + return fmt.Errorf("field 'dateAsserted' has invalid date-time format: %w", err) + } + } + if x.DerivedFrom != nil { + for i, item := range x.DerivedFrom { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'derivedFrom[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Dosage != nil { + for i, item := range x.Dosage { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'dosage[%d]' is invalid: %w", i, err) + } + } + } + } + if x.EffectiveDateTime != nil { + if err := ValidateFhirDateTime(*x.EffectiveDateTime); err != nil { + return fmt.Errorf("field 'effectiveDateTime' has invalid date-time format: %w", err) + } + } + if x.EffectivePeriod != nil { + if err := x.EffectivePeriod.Validate(); err != nil { + return fmt.Errorf("field 'effectivePeriod' is invalid: %w", err) + } + } + if x.EffectiveTiming != nil { + if err := x.EffectiveTiming.Validate(); err != nil { + return fmt.Errorf("field 'effectiveTiming' is invalid: %w", err) + } + } + if x.Encounter != nil { + if err := x.Encounter.Validate(); err != nil { + return fmt.Errorf("field 'encounter' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if !rx_MedicationStatement_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ImplicitRules != nil { + } + if x.InformationSource != nil { + for i, item := range x.InformationSource { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'informationSource[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Language != nil { + if !rx_MedicationStatement_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.Medication == nil { + return fmt.Errorf("required field 'medication' is missing") + } + if x.Medication != nil { + if err := x.Medication.Validate(); err != nil { + return fmt.Errorf("field 'medication' is invalid: %w", err) + } + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Note != nil { + for i, item := range x.Note { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) + } + } + } + } + if x.PartOf != nil { + for i, item := range x.PartOf { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'partOf[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Reason != nil { + for i, item := range x.Reason { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'reason[%d]' is invalid: %w", i, err) + } + } + } + } + if x.RelatedClinicalInformation != nil { + for i, item := range x.RelatedClinicalInformation { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'relatedClinicalInformation[%d]' is invalid: %w", i, err) + } + } + } + } + if x.RenderedDosageInstruction != nil { + if !rx_MedicationStatement_RenderedDosageInstruction.MatchString(*x.RenderedDosageInstruction) { + return fmt.Errorf("field 'renderedDosageInstruction' does not match pattern '\\s*(\\S|\\s)*'") + } + } + if x.ResourceType != nil { + if *x.ResourceType != "MedicationStatement" { + return fmt.Errorf("field 'resourceType' must be exactly 'MedicationStatement'") + } + } + if x.Status != nil { + if !rx_MedicationStatement_Status.MatchString(*x.Status) { + return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Subject == nil { + return fmt.Errorf("required field 'subject' is missing") + } + if x.Subject != nil { + if err := x.Subject.Validate(); err != nil { + return fmt.Errorf("field 'subject' is invalid: %w", err) + } + } + if x.Text != nil { + if err := x.Text.Validate(); err != nil { + return fmt.Errorf("field 'text' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a MedicationStatementAdherence struct against its schema constraints. +func (x *MedicationStatementAdherence) Validate() error { + if x == nil { + return nil + } + if x.Code == nil { + return fmt.Errorf("required field 'code' is missing") + } + if x.Code != nil { + if err := x.Code.Validate(); err != nil { + return fmt.Errorf("field 'code' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Reason != nil { + if err := x.Reason.Validate(); err != nil { + return fmt.Errorf("field 'reason' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "MedicationStatementAdherence" { + return fmt.Errorf("field 'resourceType' must be exactly 'MedicationStatementAdherence'") + } + } + return nil +} + +// Validate validates a Meta struct against its schema constraints. +func (x *Meta) Validate() error { + if x == nil { + return nil + } + if x.XLastUpdated != nil { + if err := x.XLastUpdated.Validate(); err != nil { + return fmt.Errorf("field '_lastUpdated' is invalid: %w", err) + } + } + if x.XProfile != nil { + for i, item := range x.XProfile { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field '_profile[%d]' is invalid: %w", i, err) + } + } + } + } + if x.XSource != nil { + if err := x.XSource.Validate(); err != nil { + return fmt.Errorf("field '_source' is invalid: %w", err) + } + } + if x.XVersionID != nil { + if err := x.XVersionID.Validate(); err != nil { + return fmt.Errorf("field '_versionId' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.LastUpdated != nil { + if err := ValidateFhirDateTime(*x.LastUpdated); err != nil { + return fmt.Errorf("field 'lastUpdated' has invalid date-time format: %w", err) + } + } + if x.Links != nil { + } + if x.Profile != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "Meta" { + return fmt.Errorf("field 'resourceType' must be exactly 'Meta'") + } + } + if x.Security != nil { + for i, item := range x.Security { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'security[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Source != nil { + } + if x.Tag != nil { + for i, item := range x.Tag { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'tag[%d]' is invalid: %w", i, err) + } + } + } + } + if x.VersionID != nil { + if !rx_Meta_VersionID.MatchString(*x.VersionID) { + return fmt.Errorf("field 'versionId' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.VersionID) < 1 { + return fmt.Errorf("field 'versionId' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.VersionID) > 64 { + return fmt.Errorf("field 'versionId' is too long (max 64 characters)") + } + } + return nil +} + +// Validate validates a Money struct against its schema constraints. +func (x *Money) Validate() error { + if x == nil { + return nil + } + if x.XCurrency != nil { + if err := x.XCurrency.Validate(); err != nil { + return fmt.Errorf("field '_currency' is invalid: %w", err) + } + } + if x.XValue != nil { + if err := x.XValue.Validate(); err != nil { + return fmt.Errorf("field '_value' is invalid: %w", err) + } + } + if x.Currency != nil { + if !rx_Money_Currency.MatchString(*x.Currency) { + return fmt.Errorf("field 'currency' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "Money" { + return fmt.Errorf("field 'resourceType' must be exactly 'Money'") + } + } + if x.Value != nil { + } + return nil +} + +// Validate validates a Narrative struct against its schema constraints. +func (x *Narrative) Validate() error { + if x == nil { + return nil + } + if x.XDiv != nil { + if err := x.XDiv.Validate(); err != nil { + return fmt.Errorf("field '_div' is invalid: %w", err) + } + } + if x.XStatus != nil { + if err := x.XStatus.Validate(); err != nil { + return fmt.Errorf("field '_status' is invalid: %w", err) + } + } + if x.Div != nil { + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "Narrative" { + return fmt.Errorf("field 'resourceType' must be exactly 'Narrative'") + } + } + if x.Status != nil { + if !rx_Narrative_Status.MatchString(*x.Status) { + return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + return nil +} + +// Validate validates a Observation struct against its schema constraints. +func (x *Observation) Validate() error { + if x == nil { + return nil + } + if x.XEffectiveDateTime != nil { + if err := x.XEffectiveDateTime.Validate(); err != nil { + return fmt.Errorf("field '_effectiveDateTime' is invalid: %w", err) + } + } + if x.XEffectiveInstant != nil { + if err := x.XEffectiveInstant.Validate(); err != nil { + return fmt.Errorf("field '_effectiveInstant' is invalid: %w", err) + } + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XInstantiatesCanonical != nil { + if err := x.XInstantiatesCanonical.Validate(); err != nil { + return fmt.Errorf("field '_instantiatesCanonical' is invalid: %w", err) + } + } + if x.XIssued != nil { + if err := x.XIssued.Validate(); err != nil { + return fmt.Errorf("field '_issued' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.XStatus != nil { + if err := x.XStatus.Validate(); err != nil { + return fmt.Errorf("field '_status' is invalid: %w", err) + } + } + if x.XValueBoolean != nil { + if err := x.XValueBoolean.Validate(); err != nil { + return fmt.Errorf("field '_valueBoolean' is invalid: %w", err) + } + } + if x.XValueDateTime != nil { + if err := x.XValueDateTime.Validate(); err != nil { + return fmt.Errorf("field '_valueDateTime' is invalid: %w", err) + } + } + if x.XValueInteger != nil { + if err := x.XValueInteger.Validate(); err != nil { + return fmt.Errorf("field '_valueInteger' is invalid: %w", err) + } + } + if x.XValueString != nil { + if err := x.XValueString.Validate(); err != nil { + return fmt.Errorf("field '_valueString' is invalid: %w", err) + } + } + if x.XValueTime != nil { + if err := x.XValueTime.Validate(); err != nil { + return fmt.Errorf("field '_valueTime' is invalid: %w", err) + } + } + if x.BasedOn != nil { + for i, item := range x.BasedOn { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'basedOn[%d]' is invalid: %w", i, err) + } + } + } + } + if x.BodySite != nil { + if err := x.BodySite.Validate(); err != nil { + return fmt.Errorf("field 'bodySite' is invalid: %w", err) + } + } + if x.BodyStructure != nil { + if err := x.BodyStructure.Validate(); err != nil { + return fmt.Errorf("field 'bodyStructure' is invalid: %w", err) + } + } + if x.Category != nil { + for i, item := range x.Category { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'category[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Code == nil { + return fmt.Errorf("required field 'code' is missing") + } + if x.Code != nil { + if err := x.Code.Validate(); err != nil { + return fmt.Errorf("field 'code' is invalid: %w", err) + } + } + if x.Component != nil { + for i, item := range x.Component { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'component[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Contained != nil { + for i, item := range x.Contained { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) + } + } + } + } + if x.DataAbsentReason != nil { + if err := x.DataAbsentReason.Validate(); err != nil { + return fmt.Errorf("field 'dataAbsentReason' is invalid: %w", err) + } + } + if x.DerivedFrom != nil { + for i, item := range x.DerivedFrom { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'derivedFrom[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Device != nil { + if err := x.Device.Validate(); err != nil { + return fmt.Errorf("field 'device' is invalid: %w", err) + } + } + if x.EffectiveDateTime != nil { + if err := ValidateFhirDateTime(*x.EffectiveDateTime); err != nil { + return fmt.Errorf("field 'effectiveDateTime' has invalid date-time format: %w", err) + } + } + if x.EffectiveInstant != nil { + if err := ValidateFhirDateTime(*x.EffectiveInstant); err != nil { + return fmt.Errorf("field 'effectiveInstant' has invalid date-time format: %w", err) + } + } + if x.EffectivePeriod != nil { + if err := x.EffectivePeriod.Validate(); err != nil { + return fmt.Errorf("field 'effectivePeriod' is invalid: %w", err) + } + } + if x.EffectiveTiming != nil { + if err := x.EffectiveTiming.Validate(); err != nil { + return fmt.Errorf("field 'effectiveTiming' is invalid: %w", err) + } + } + if x.Encounter != nil { + if err := x.Encounter.Validate(); err != nil { + return fmt.Errorf("field 'encounter' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Focus != nil { + for i, item := range x.Focus { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'focus[%d]' is invalid: %w", i, err) + } + } + } + } + if x.HasMember != nil { + for i, item := range x.HasMember { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'hasMember[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if !rx_Observation_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ImplicitRules != nil { + } + if x.InstantiatesCanonical != nil { + } + if x.InstantiatesReference != nil { + if err := x.InstantiatesReference.Validate(); err != nil { + return fmt.Errorf("field 'instantiatesReference' is invalid: %w", err) + } + } + if x.Interpretation != nil { + for i, item := range x.Interpretation { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'interpretation[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Issued != nil { + if err := ValidateFhirDateTime(*x.Issued); err != nil { + return fmt.Errorf("field 'issued' has invalid date-time format: %w", err) + } + } + if x.Language != nil { + if !rx_Observation_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.Method != nil { + if err := x.Method.Validate(); err != nil { + return fmt.Errorf("field 'method' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Note != nil { + for i, item := range x.Note { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) + } + } + } + } + if x.PartOf != nil { + for i, item := range x.PartOf { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'partOf[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Performer != nil { + for i, item := range x.Performer { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'performer[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ReferenceRange != nil { + for i, item := range x.ReferenceRange { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'referenceRange[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "Observation" { + return fmt.Errorf("field 'resourceType' must be exactly 'Observation'") + } + } + if x.Specimen != nil { + if err := x.Specimen.Validate(); err != nil { + return fmt.Errorf("field 'specimen' is invalid: %w", err) + } + } + if x.Status != nil { + if !rx_Observation_Status.MatchString(*x.Status) { + return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Subject != nil { + if err := x.Subject.Validate(); err != nil { + return fmt.Errorf("field 'subject' is invalid: %w", err) + } + } + if x.Text != nil { + if err := x.Text.Validate(); err != nil { + return fmt.Errorf("field 'text' is invalid: %w", err) + } + } + if x.TriggeredBy != nil { + for i, item := range x.TriggeredBy { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'triggeredBy[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ValueAttachment != nil { + if err := x.ValueAttachment.Validate(); err != nil { + return fmt.Errorf("field 'valueAttachment' is invalid: %w", err) + } + } + if x.ValueBoolean != nil { + } + if x.ValueCodeableConcept != nil { + if err := x.ValueCodeableConcept.Validate(); err != nil { + return fmt.Errorf("field 'valueCodeableConcept' is invalid: %w", err) + } + } + if x.ValueDateTime != nil { + if err := ValidateFhirDateTime(*x.ValueDateTime); err != nil { + return fmt.Errorf("field 'valueDateTime' has invalid date-time format: %w", err) + } + } + if x.ValueInteger != nil { + } + if x.ValuePeriod != nil { + if err := x.ValuePeriod.Validate(); err != nil { + return fmt.Errorf("field 'valuePeriod' is invalid: %w", err) + } + } + if x.ValueQuantity != nil { + if err := x.ValueQuantity.Validate(); err != nil { + return fmt.Errorf("field 'valueQuantity' is invalid: %w", err) + } + } + if x.ValueRange != nil { + if err := x.ValueRange.Validate(); err != nil { + return fmt.Errorf("field 'valueRange' is invalid: %w", err) + } + } + if x.ValueRatio != nil { + if err := x.ValueRatio.Validate(); err != nil { + return fmt.Errorf("field 'valueRatio' is invalid: %w", err) + } + } + if x.ValueReference != nil { + if err := x.ValueReference.Validate(); err != nil { + return fmt.Errorf("field 'valueReference' is invalid: %w", err) + } + } + if x.ValueSampledData != nil { + if err := x.ValueSampledData.Validate(); err != nil { + return fmt.Errorf("field 'valueSampledData' is invalid: %w", err) + } + } + if x.ValueString != nil { + if *x.ValueString == "" { + return fmt.Errorf("field 'valueString' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.ValueTime != nil { + if err := ValidateFhirTime(*x.ValueTime); err != nil { + return fmt.Errorf("field 'valueTime' has invalid time format: %w", err) + } + } + return nil +} + +// Validate validates a ObservationComponent struct against its schema constraints. +func (x *ObservationComponent) Validate() error { + if x == nil { + return nil + } + if x.XValueBoolean != nil { + if err := x.XValueBoolean.Validate(); err != nil { + return fmt.Errorf("field '_valueBoolean' is invalid: %w", err) + } + } + if x.XValueDateTime != nil { + if err := x.XValueDateTime.Validate(); err != nil { + return fmt.Errorf("field '_valueDateTime' is invalid: %w", err) + } + } + if x.XValueInteger != nil { + if err := x.XValueInteger.Validate(); err != nil { + return fmt.Errorf("field '_valueInteger' is invalid: %w", err) + } + } + if x.XValueString != nil { + if err := x.XValueString.Validate(); err != nil { + return fmt.Errorf("field '_valueString' is invalid: %w", err) + } + } + if x.XValueTime != nil { + if err := x.XValueTime.Validate(); err != nil { + return fmt.Errorf("field '_valueTime' is invalid: %w", err) + } + } + if x.Code == nil { + return fmt.Errorf("required field 'code' is missing") + } + if x.Code != nil { + if err := x.Code.Validate(); err != nil { + return fmt.Errorf("field 'code' is invalid: %w", err) + } + } + if x.DataAbsentReason != nil { + if err := x.DataAbsentReason.Validate(); err != nil { + return fmt.Errorf("field 'dataAbsentReason' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Interpretation != nil { + for i, item := range x.Interpretation { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'interpretation[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ReferenceRange != nil { + for i, item := range x.ReferenceRange { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'referenceRange[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ObservationComponent" { + return fmt.Errorf("field 'resourceType' must be exactly 'ObservationComponent'") + } + } + if x.ValueAttachment != nil { + if err := x.ValueAttachment.Validate(); err != nil { + return fmt.Errorf("field 'valueAttachment' is invalid: %w", err) + } + } + if x.ValueBoolean != nil { + } + if x.ValueCodeableConcept != nil { + if err := x.ValueCodeableConcept.Validate(); err != nil { + return fmt.Errorf("field 'valueCodeableConcept' is invalid: %w", err) + } + } + if x.ValueDateTime != nil { + if err := ValidateFhirDateTime(*x.ValueDateTime); err != nil { + return fmt.Errorf("field 'valueDateTime' has invalid date-time format: %w", err) + } + } + if x.ValueInteger != nil { + } + if x.ValuePeriod != nil { + if err := x.ValuePeriod.Validate(); err != nil { + return fmt.Errorf("field 'valuePeriod' is invalid: %w", err) + } + } + if x.ValueQuantity != nil { + if err := x.ValueQuantity.Validate(); err != nil { + return fmt.Errorf("field 'valueQuantity' is invalid: %w", err) + } + } + if x.ValueRange != nil { + if err := x.ValueRange.Validate(); err != nil { + return fmt.Errorf("field 'valueRange' is invalid: %w", err) + } + } + if x.ValueRatio != nil { + if err := x.ValueRatio.Validate(); err != nil { + return fmt.Errorf("field 'valueRatio' is invalid: %w", err) + } + } + if x.ValueReference != nil { + if err := x.ValueReference.Validate(); err != nil { + return fmt.Errorf("field 'valueReference' is invalid: %w", err) + } + } + if x.ValueSampledData != nil { + if err := x.ValueSampledData.Validate(); err != nil { + return fmt.Errorf("field 'valueSampledData' is invalid: %w", err) + } + } + if x.ValueString != nil { + if *x.ValueString == "" { + return fmt.Errorf("field 'valueString' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.ValueTime != nil { + if err := ValidateFhirTime(*x.ValueTime); err != nil { + return fmt.Errorf("field 'valueTime' has invalid time format: %w", err) + } + } + return nil +} + +// Validate validates a ObservationReferenceRange struct against its schema constraints. +func (x *ObservationReferenceRange) Validate() error { + if x == nil { + return nil + } + if x.XText != nil { + if err := x.XText.Validate(); err != nil { + return fmt.Errorf("field '_text' is invalid: %w", err) + } + } + if x.Age != nil { + if err := x.Age.Validate(); err != nil { + return fmt.Errorf("field 'age' is invalid: %w", err) + } + } + if x.AppliesTo != nil { + for i, item := range x.AppliesTo { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'appliesTo[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.High != nil { + if err := x.High.Validate(); err != nil { + return fmt.Errorf("field 'high' is invalid: %w", err) + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Low != nil { + if err := x.Low.Validate(); err != nil { + return fmt.Errorf("field 'low' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.NormalValue != nil { + if err := x.NormalValue.Validate(); err != nil { + return fmt.Errorf("field 'normalValue' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ObservationReferenceRange" { + return fmt.Errorf("field 'resourceType' must be exactly 'ObservationReferenceRange'") + } + } + if x.Text != nil { + if !rx_ObservationReferenceRange_Text.MatchString(*x.Text) { + return fmt.Errorf("field 'text' does not match pattern '\\s*(\\S|\\s)*'") + } + } + if x.Type != nil { + if err := x.Type.Validate(); err != nil { + return fmt.Errorf("field 'type' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a ObservationTriggeredBy struct against its schema constraints. +func (x *ObservationTriggeredBy) Validate() error { + if x == nil { + return nil + } + if x.XReason != nil { + if err := x.XReason.Validate(); err != nil { + return fmt.Errorf("field '_reason' is invalid: %w", err) + } + } + if x.XType != nil { + if err := x.XType.Validate(); err != nil { + return fmt.Errorf("field '_type' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Observation == nil { + return fmt.Errorf("required field 'observation' is missing") + } + if x.Observation != nil { + if err := x.Observation.Validate(); err != nil { + return fmt.Errorf("field 'observation' is invalid: %w", err) + } + } + if x.Reason != nil { + if *x.Reason == "" { + return fmt.Errorf("field 'reason' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ObservationTriggeredBy" { + return fmt.Errorf("field 'resourceType' must be exactly 'ObservationTriggeredBy'") + } + } + if x.Type != nil { + if !rx_ObservationTriggeredBy_Type.MatchString(*x.Type) { + return fmt.Errorf("field 'type' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + return nil +} + +// Validate validates a Organization struct against its schema constraints. +func (x *Organization) Validate() error { + if x == nil { + return nil + } + if x.XActive != nil { + if err := x.XActive.Validate(); err != nil { + return fmt.Errorf("field '_active' is invalid: %w", err) + } + } + if x.XAlias != nil { + for i, item := range x.XAlias { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field '_alias[%d]' is invalid: %w", i, err) + } + } + } + } + if x.XDescription != nil { + if err := x.XDescription.Validate(); err != nil { + return fmt.Errorf("field '_description' is invalid: %w", err) + } + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.XName != nil { + if err := x.XName.Validate(); err != nil { + return fmt.Errorf("field '_name' is invalid: %w", err) + } + } + if x.Active != nil { + } + if x.Alias != nil { + for i, item := range x.Alias { + if item == "" { + return fmt.Errorf("field 'alias[%d]' does not match pattern '[ \\r\\n\\t\\S]+'", i) + } + } + } + if x.Contact != nil { + for i, item := range x.Contact { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contact[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Contained != nil { + for i, item := range x.Contained { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Description != nil { + if !rx_Organization_Description.MatchString(*x.Description) { + return fmt.Errorf("field 'description' does not match pattern '\\s*(\\S|\\s)*'") + } + } + if x.Endpoint != nil { + for i, item := range x.Endpoint { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'endpoint[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if !rx_Organization_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ImplicitRules != nil { + } + if x.Language != nil { + if !rx_Organization_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Name != nil { + if *x.Name == "" { + return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.PartOf != nil { + if err := x.PartOf.Validate(); err != nil { + return fmt.Errorf("field 'partOf' is invalid: %w", err) + } + } + if x.Qualification != nil { + for i, item := range x.Qualification { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'qualification[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "Organization" { + return fmt.Errorf("field 'resourceType' must be exactly 'Organization'") + } + } + if x.Text != nil { + if err := x.Text.Validate(); err != nil { + return fmt.Errorf("field 'text' is invalid: %w", err) + } + } + if x.Type != nil { + for i, item := range x.Type { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'type[%d]' is invalid: %w", i, err) + } + } + } + } + return nil +} + +// Validate validates a OrganizationQualification struct against its schema constraints. +func (x *OrganizationQualification) Validate() error { + if x == nil { + return nil + } + if x.Code == nil { + return fmt.Errorf("required field 'code' is missing") + } + if x.Code != nil { + if err := x.Code.Validate(); err != nil { + return fmt.Errorf("field 'code' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Issuer != nil { + if err := x.Issuer.Validate(); err != nil { + return fmt.Errorf("field 'issuer' is invalid: %w", err) + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Period != nil { + if err := x.Period.Validate(); err != nil { + return fmt.Errorf("field 'period' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "OrganizationQualification" { + return fmt.Errorf("field 'resourceType' must be exactly 'OrganizationQualification'") + } + } + return nil +} + +// Validate validates a ParameterDefinition struct against its schema constraints. +func (x *ParameterDefinition) Validate() error { + if x == nil { + return nil + } + if x.XDocumentation != nil { + if err := x.XDocumentation.Validate(); err != nil { + return fmt.Errorf("field '_documentation' is invalid: %w", err) + } + } + if x.XMax != nil { + if err := x.XMax.Validate(); err != nil { + return fmt.Errorf("field '_max' is invalid: %w", err) + } + } + if x.XMin != nil { + if err := x.XMin.Validate(); err != nil { + return fmt.Errorf("field '_min' is invalid: %w", err) + } + } + if x.XName != nil { + if err := x.XName.Validate(); err != nil { + return fmt.Errorf("field '_name' is invalid: %w", err) + } + } + if x.XProfile != nil { + if err := x.XProfile.Validate(); err != nil { + return fmt.Errorf("field '_profile' is invalid: %w", err) + } + } + if x.XType != nil { + if err := x.XType.Validate(); err != nil { + return fmt.Errorf("field '_type' is invalid: %w", err) + } + } + if x.XUse != nil { + if err := x.XUse.Validate(); err != nil { + return fmt.Errorf("field '_use' is invalid: %w", err) + } + } + if x.Documentation != nil { + if *x.Documentation == "" { + return fmt.Errorf("field 'documentation' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Max != nil { + if *x.Max == "" { + return fmt.Errorf("field 'max' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Min != nil { + } + if x.Name != nil { + if !rx_ParameterDefinition_Name.MatchString(*x.Name) { + return fmt.Errorf("field 'name' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Profile != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "ParameterDefinition" { + return fmt.Errorf("field 'resourceType' must be exactly 'ParameterDefinition'") + } + } + if x.Type != nil { + if !rx_ParameterDefinition_Type.MatchString(*x.Type) { + return fmt.Errorf("field 'type' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Use != nil { + if !rx_ParameterDefinition_Use.MatchString(*x.Use) { + return fmt.Errorf("field 'use' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + return nil +} + +// Validate validates a Patient struct against its schema constraints. +func (x *Patient) Validate() error { + if x == nil { + return nil + } + if x.XActive != nil { + if err := x.XActive.Validate(); err != nil { + return fmt.Errorf("field '_active' is invalid: %w", err) + } + } + if x.XBirthDate != nil { + if err := x.XBirthDate.Validate(); err != nil { + return fmt.Errorf("field '_birthDate' is invalid: %w", err) + } + } + if x.XDeceasedBoolean != nil { + if err := x.XDeceasedBoolean.Validate(); err != nil { + return fmt.Errorf("field '_deceasedBoolean' is invalid: %w", err) + } + } + if x.XDeceasedDateTime != nil { + if err := x.XDeceasedDateTime.Validate(); err != nil { + return fmt.Errorf("field '_deceasedDateTime' is invalid: %w", err) + } + } + if x.XGender != nil { + if err := x.XGender.Validate(); err != nil { + return fmt.Errorf("field '_gender' is invalid: %w", err) + } + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.XMultipleBirthBoolean != nil { + if err := x.XMultipleBirthBoolean.Validate(); err != nil { + return fmt.Errorf("field '_multipleBirthBoolean' is invalid: %w", err) + } + } + if x.XMultipleBirthInteger != nil { + if err := x.XMultipleBirthInteger.Validate(); err != nil { + return fmt.Errorf("field '_multipleBirthInteger' is invalid: %w", err) + } + } + if x.Active != nil { + } + if x.Address != nil { + for i, item := range x.Address { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'address[%d]' is invalid: %w", i, err) + } + } + } + } + if x.BirthDate != nil { + if err := ValidateFhirDate(*x.BirthDate); err != nil { + return fmt.Errorf("field 'birthDate' has invalid date format: %w", err) + } + } + if x.Communication != nil { + for i, item := range x.Communication { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'communication[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Contact != nil { + for i, item := range x.Contact { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contact[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Contained != nil { + for i, item := range x.Contained { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) + } + } + } + } + if x.DeceasedBoolean != nil { + } + if x.DeceasedDateTime != nil { + if err := ValidateFhirDateTime(*x.DeceasedDateTime); err != nil { + return fmt.Errorf("field 'deceasedDateTime' has invalid date-time format: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Gender != nil { + if !rx_Patient_Gender.MatchString(*x.Gender) { + return fmt.Errorf("field 'gender' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.GeneralPractitioner != nil { + for i, item := range x.GeneralPractitioner { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'generalPractitioner[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if !rx_Patient_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ImplicitRules != nil { + } + if x.Language != nil { + if !rx_Patient_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Link != nil { + for i, item := range x.Link { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'link[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Links != nil { + } + if x.ManagingOrganization != nil { + if err := x.ManagingOrganization.Validate(); err != nil { + return fmt.Errorf("field 'managingOrganization' is invalid: %w", err) + } + } + if x.MaritalStatus != nil { + if err := x.MaritalStatus.Validate(); err != nil { + return fmt.Errorf("field 'maritalStatus' is invalid: %w", err) + } + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.MultipleBirthBoolean != nil { + } + if x.MultipleBirthInteger != nil { + } + if x.Name != nil { + for i, item := range x.Name { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'name[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Photo != nil { + for i, item := range x.Photo { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'photo[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "Patient" { + return fmt.Errorf("field 'resourceType' must be exactly 'Patient'") + } + } + if x.Telecom != nil { + for i, item := range x.Telecom { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'telecom[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Text != nil { + if err := x.Text.Validate(); err != nil { + return fmt.Errorf("field 'text' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a PatientCommunication struct against its schema constraints. +func (x *PatientCommunication) Validate() error { + if x == nil { + return nil + } + if x.XPreferred != nil { + if err := x.XPreferred.Validate(); err != nil { + return fmt.Errorf("field '_preferred' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Language == nil { + return fmt.Errorf("required field 'language' is missing") + } + if x.Language != nil { + if err := x.Language.Validate(); err != nil { + return fmt.Errorf("field 'language' is invalid: %w", err) + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Preferred != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "PatientCommunication" { + return fmt.Errorf("field 'resourceType' must be exactly 'PatientCommunication'") + } + } + return nil +} + +// Validate validates a PatientContact struct against its schema constraints. +func (x *PatientContact) Validate() error { + if x == nil { + return nil + } + if x.XGender != nil { + if err := x.XGender.Validate(); err != nil { + return fmt.Errorf("field '_gender' is invalid: %w", err) + } + } + if x.Address != nil { + if err := x.Address.Validate(); err != nil { + return fmt.Errorf("field 'address' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Gender != nil { + if !rx_PatientContact_Gender.MatchString(*x.Gender) { + return fmt.Errorf("field 'gender' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Name != nil { + if err := x.Name.Validate(); err != nil { + return fmt.Errorf("field 'name' is invalid: %w", err) + } + } + if x.Organization != nil { + if err := x.Organization.Validate(); err != nil { + return fmt.Errorf("field 'organization' is invalid: %w", err) + } + } + if x.Period != nil { + if err := x.Period.Validate(); err != nil { + return fmt.Errorf("field 'period' is invalid: %w", err) + } + } + if x.Relationship != nil { + for i, item := range x.Relationship { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'relationship[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "PatientContact" { + return fmt.Errorf("field 'resourceType' must be exactly 'PatientContact'") + } + } + if x.Telecom != nil { + for i, item := range x.Telecom { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'telecom[%d]' is invalid: %w", i, err) + } + } + } + } + return nil +} + +// Validate validates a PatientLink struct against its schema constraints. +func (x *PatientLink) Validate() error { + if x == nil { + return nil + } + if x.XType != nil { + if err := x.XType.Validate(); err != nil { + return fmt.Errorf("field '_type' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Other == nil { + return fmt.Errorf("required field 'other' is missing") + } + if x.Other != nil { + if err := x.Other.Validate(); err != nil { + return fmt.Errorf("field 'other' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "PatientLink" { + return fmt.Errorf("field 'resourceType' must be exactly 'PatientLink'") + } + } + if x.Type != nil { + if !rx_PatientLink_Type.MatchString(*x.Type) { + return fmt.Errorf("field 'type' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + return nil +} + +// Validate validates a Period struct against its schema constraints. +func (x *Period) Validate() error { + if x == nil { + return nil + } + if x.XEnd != nil { + if err := x.XEnd.Validate(); err != nil { + return fmt.Errorf("field '_end' is invalid: %w", err) + } + } + if x.XStart != nil { + if err := x.XStart.Validate(); err != nil { + return fmt.Errorf("field '_start' is invalid: %w", err) + } + } + if x.End != nil { + if err := ValidateFhirDateTime(*x.End); err != nil { + return fmt.Errorf("field 'end' has invalid date-time format: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "Period" { + return fmt.Errorf("field 'resourceType' must be exactly 'Period'") + } + } + if x.Start != nil { + if err := ValidateFhirDateTime(*x.Start); err != nil { + return fmt.Errorf("field 'start' has invalid date-time format: %w", err) + } + } + return nil +} + +// Validate validates a Practitioner struct against its schema constraints. +func (x *Practitioner) Validate() error { + if x == nil { + return nil + } + if x.XActive != nil { + if err := x.XActive.Validate(); err != nil { + return fmt.Errorf("field '_active' is invalid: %w", err) + } + } + if x.XBirthDate != nil { + if err := x.XBirthDate.Validate(); err != nil { + return fmt.Errorf("field '_birthDate' is invalid: %w", err) + } + } + if x.XDeceasedBoolean != nil { + if err := x.XDeceasedBoolean.Validate(); err != nil { + return fmt.Errorf("field '_deceasedBoolean' is invalid: %w", err) + } + } + if x.XDeceasedDateTime != nil { + if err := x.XDeceasedDateTime.Validate(); err != nil { + return fmt.Errorf("field '_deceasedDateTime' is invalid: %w", err) + } + } + if x.XGender != nil { + if err := x.XGender.Validate(); err != nil { + return fmt.Errorf("field '_gender' is invalid: %w", err) + } + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.Active != nil { + } + if x.Address != nil { + for i, item := range x.Address { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'address[%d]' is invalid: %w", i, err) + } + } + } + } + if x.BirthDate != nil { + if err := ValidateFhirDate(*x.BirthDate); err != nil { + return fmt.Errorf("field 'birthDate' has invalid date format: %w", err) + } + } + if x.Communication != nil { + for i, item := range x.Communication { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'communication[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Contained != nil { + for i, item := range x.Contained { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) + } + } + } + } + if x.DeceasedBoolean != nil { + } + if x.DeceasedDateTime != nil { + if err := ValidateFhirDateTime(*x.DeceasedDateTime); err != nil { + return fmt.Errorf("field 'deceasedDateTime' has invalid date-time format: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Gender != nil { + if !rx_Practitioner_Gender.MatchString(*x.Gender) { + return fmt.Errorf("field 'gender' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.ID != nil { + if !rx_Practitioner_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ImplicitRules != nil { + } + if x.Language != nil { + if !rx_Practitioner_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Name != nil { + for i, item := range x.Name { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'name[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Photo != nil { + for i, item := range x.Photo { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'photo[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Qualification != nil { + for i, item := range x.Qualification { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'qualification[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "Practitioner" { + return fmt.Errorf("field 'resourceType' must be exactly 'Practitioner'") + } + } + if x.Telecom != nil { + for i, item := range x.Telecom { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'telecom[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Text != nil { + if err := x.Text.Validate(); err != nil { + return fmt.Errorf("field 'text' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a PractitionerCommunication struct against its schema constraints. +func (x *PractitionerCommunication) Validate() error { + if x == nil { + return nil + } + if x.XPreferred != nil { + if err := x.XPreferred.Validate(); err != nil { + return fmt.Errorf("field '_preferred' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Language == nil { + return fmt.Errorf("required field 'language' is missing") + } + if x.Language != nil { + if err := x.Language.Validate(); err != nil { + return fmt.Errorf("field 'language' is invalid: %w", err) + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Preferred != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "PractitionerCommunication" { + return fmt.Errorf("field 'resourceType' must be exactly 'PractitionerCommunication'") + } + } + return nil +} + +// Validate validates a PractitionerQualification struct against its schema constraints. +func (x *PractitionerQualification) Validate() error { + if x == nil { + return nil + } + if x.Code == nil { + return fmt.Errorf("required field 'code' is missing") + } + if x.Code != nil { + if err := x.Code.Validate(); err != nil { + return fmt.Errorf("field 'code' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Issuer != nil { + if err := x.Issuer.Validate(); err != nil { + return fmt.Errorf("field 'issuer' is invalid: %w", err) + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Period != nil { + if err := x.Period.Validate(); err != nil { + return fmt.Errorf("field 'period' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "PractitionerQualification" { + return fmt.Errorf("field 'resourceType' must be exactly 'PractitionerQualification'") + } + } + return nil +} + +// Validate validates a PractitionerRole struct against its schema constraints. +func (x *PractitionerRole) Validate() error { + if x == nil { + return nil + } + if x.XActive != nil { + if err := x.XActive.Validate(); err != nil { + return fmt.Errorf("field '_active' is invalid: %w", err) + } + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.Active != nil { + } + if x.Availability != nil { + for i, item := range x.Availability { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'availability[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Characteristic != nil { + for i, item := range x.Characteristic { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'characteristic[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Code != nil { + for i, item := range x.Code { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'code[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Communication != nil { + for i, item := range x.Communication { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'communication[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Contact != nil { + for i, item := range x.Contact { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contact[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Contained != nil { + for i, item := range x.Contained { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Endpoint != nil { + for i, item := range x.Endpoint { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'endpoint[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.HealthcareService != nil { + for i, item := range x.HealthcareService { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'healthcareService[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if !rx_PractitionerRole_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ImplicitRules != nil { + } + if x.Language != nil { + if !rx_PractitionerRole_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.Location != nil { + for i, item := range x.Location { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'location[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Organization != nil { + if err := x.Organization.Validate(); err != nil { + return fmt.Errorf("field 'organization' is invalid: %w", err) + } + } + if x.Period != nil { + if err := x.Period.Validate(); err != nil { + return fmt.Errorf("field 'period' is invalid: %w", err) + } + } + if x.Practitioner != nil { + if err := x.Practitioner.Validate(); err != nil { + return fmt.Errorf("field 'practitioner' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "PractitionerRole" { + return fmt.Errorf("field 'resourceType' must be exactly 'PractitionerRole'") + } + } + if x.Specialty != nil { + for i, item := range x.Specialty { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'specialty[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Text != nil { + if err := x.Text.Validate(); err != nil { + return fmt.Errorf("field 'text' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a Procedure struct against its schema constraints. +func (x *Procedure) Validate() error { + if x == nil { + return nil + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XInstantiatesCanonical != nil { + for i, item := range x.XInstantiatesCanonical { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field '_instantiatesCanonical[%d]' is invalid: %w", i, err) + } + } + } + } + if x.XInstantiatesURI != nil { + for i, item := range x.XInstantiatesURI { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field '_instantiatesUri[%d]' is invalid: %w", i, err) + } + } + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.XOccurrenceDateTime != nil { + if err := x.XOccurrenceDateTime.Validate(); err != nil { + return fmt.Errorf("field '_occurrenceDateTime' is invalid: %w", err) + } + } + if x.XOccurrenceString != nil { + if err := x.XOccurrenceString.Validate(); err != nil { + return fmt.Errorf("field '_occurrenceString' is invalid: %w", err) + } + } + if x.XRecorded != nil { + if err := x.XRecorded.Validate(); err != nil { + return fmt.Errorf("field '_recorded' is invalid: %w", err) + } + } + if x.XReportedBoolean != nil { + if err := x.XReportedBoolean.Validate(); err != nil { + return fmt.Errorf("field '_reportedBoolean' is invalid: %w", err) + } + } + if x.XStatus != nil { + if err := x.XStatus.Validate(); err != nil { + return fmt.Errorf("field '_status' is invalid: %w", err) + } + } + if x.BasedOn != nil { + for i, item := range x.BasedOn { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'basedOn[%d]' is invalid: %w", i, err) + } + } + } + } + if x.BodySite != nil { + for i, item := range x.BodySite { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'bodySite[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Category != nil { + for i, item := range x.Category { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'category[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Code != nil { + if err := x.Code.Validate(); err != nil { + return fmt.Errorf("field 'code' is invalid: %w", err) + } + } + if x.Complication != nil { + for i, item := range x.Complication { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'complication[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Contained != nil { + for i, item := range x.Contained { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Encounter != nil { + if err := x.Encounter.Validate(); err != nil { + return fmt.Errorf("field 'encounter' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.FocalDevice != nil { + for i, item := range x.FocalDevice { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'focalDevice[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Focus != nil { + if err := x.Focus.Validate(); err != nil { + return fmt.Errorf("field 'focus' is invalid: %w", err) + } + } + if x.FollowUp != nil { + for i, item := range x.FollowUp { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'followUp[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if !rx_Procedure_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ImplicitRules != nil { + } + if x.InstantiatesCanonical != nil { + } + if x.InstantiatesURI != nil { + } + if x.Language != nil { + if !rx_Procedure_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.Location != nil { + if err := x.Location.Validate(); err != nil { + return fmt.Errorf("field 'location' is invalid: %w", err) + } + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Note != nil { + for i, item := range x.Note { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) + } + } + } + } + if x.OccurrenceAge != nil { + if err := x.OccurrenceAge.Validate(); err != nil { + return fmt.Errorf("field 'occurrenceAge' is invalid: %w", err) + } + } + if x.OccurrenceDateTime != nil { + if err := ValidateFhirDateTime(*x.OccurrenceDateTime); err != nil { + return fmt.Errorf("field 'occurrenceDateTime' has invalid date-time format: %w", err) + } + } + if x.OccurrencePeriod != nil { + if err := x.OccurrencePeriod.Validate(); err != nil { + return fmt.Errorf("field 'occurrencePeriod' is invalid: %w", err) + } + } + if x.OccurrenceRange != nil { + if err := x.OccurrenceRange.Validate(); err != nil { + return fmt.Errorf("field 'occurrenceRange' is invalid: %w", err) + } + } + if x.OccurrenceString != nil { + if *x.OccurrenceString == "" { + return fmt.Errorf("field 'occurrenceString' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.OccurrenceTiming != nil { + if err := x.OccurrenceTiming.Validate(); err != nil { + return fmt.Errorf("field 'occurrenceTiming' is invalid: %w", err) + } + } + if x.Outcome != nil { + if err := x.Outcome.Validate(); err != nil { + return fmt.Errorf("field 'outcome' is invalid: %w", err) + } + } + if x.PartOf != nil { + for i, item := range x.PartOf { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'partOf[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Performer != nil { + for i, item := range x.Performer { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'performer[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Reason != nil { + for i, item := range x.Reason { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'reason[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Recorded != nil { + if err := ValidateFhirDateTime(*x.Recorded); err != nil { + return fmt.Errorf("field 'recorded' has invalid date-time format: %w", err) + } + } + if x.Recorder != nil { + if err := x.Recorder.Validate(); err != nil { + return fmt.Errorf("field 'recorder' is invalid: %w", err) + } + } + if x.Report != nil { + for i, item := range x.Report { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'report[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ReportedBoolean != nil { + } + if x.ReportedReference != nil { + if err := x.ReportedReference.Validate(); err != nil { + return fmt.Errorf("field 'reportedReference' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "Procedure" { + return fmt.Errorf("field 'resourceType' must be exactly 'Procedure'") + } + } + if x.Status != nil { + if !rx_Procedure_Status.MatchString(*x.Status) { + return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.StatusReason != nil { + if err := x.StatusReason.Validate(); err != nil { + return fmt.Errorf("field 'statusReason' is invalid: %w", err) + } + } + if x.Subject == nil { + return fmt.Errorf("required field 'subject' is missing") + } + if x.Subject != nil { + if err := x.Subject.Validate(); err != nil { + return fmt.Errorf("field 'subject' is invalid: %w", err) + } + } + if x.SupportingInfo != nil { + for i, item := range x.SupportingInfo { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'supportingInfo[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Text != nil { + if err := x.Text.Validate(); err != nil { + return fmt.Errorf("field 'text' is invalid: %w", err) + } + } + if x.Used != nil { + for i, item := range x.Used { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'used[%d]' is invalid: %w", i, err) + } + } + } + } + return nil +} + +// Validate validates a ProcedureFocalDevice struct against its schema constraints. +func (x *ProcedureFocalDevice) Validate() error { + if x == nil { + return nil + } + if x.Action != nil { + if err := x.Action.Validate(); err != nil { + return fmt.Errorf("field 'action' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Manipulated == nil { + return fmt.Errorf("required field 'manipulated' is missing") + } + if x.Manipulated != nil { + if err := x.Manipulated.Validate(); err != nil { + return fmt.Errorf("field 'manipulated' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ProcedureFocalDevice" { + return fmt.Errorf("field 'resourceType' must be exactly 'ProcedureFocalDevice'") + } + } + return nil +} + +// Validate validates a ProcedurePerformer struct against its schema constraints. +func (x *ProcedurePerformer) Validate() error { + if x == nil { + return nil + } + if x.Actor == nil { + return fmt.Errorf("required field 'actor' is missing") + } + if x.Actor != nil { + if err := x.Actor.Validate(); err != nil { + return fmt.Errorf("field 'actor' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Function != nil { + if err := x.Function.Validate(); err != nil { + return fmt.Errorf("field 'function' is invalid: %w", err) + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.OnBehalfOf != nil { + if err := x.OnBehalfOf.Validate(); err != nil { + return fmt.Errorf("field 'onBehalfOf' is invalid: %w", err) + } + } + if x.Period != nil { + if err := x.Period.Validate(); err != nil { + return fmt.Errorf("field 'period' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ProcedurePerformer" { + return fmt.Errorf("field 'resourceType' must be exactly 'ProcedurePerformer'") + } + } + return nil +} + +// Validate validates a Quantity struct against its schema constraints. +func (x *Quantity) Validate() error { + if x == nil { + return nil + } + if x.XCode != nil { + if err := x.XCode.Validate(); err != nil { + return fmt.Errorf("field '_code' is invalid: %w", err) + } + } + if x.XComparator != nil { + if err := x.XComparator.Validate(); err != nil { + return fmt.Errorf("field '_comparator' is invalid: %w", err) + } + } + if x.XSystem != nil { + if err := x.XSystem.Validate(); err != nil { + return fmt.Errorf("field '_system' is invalid: %w", err) + } + } + if x.XUnit != nil { + if err := x.XUnit.Validate(); err != nil { + return fmt.Errorf("field '_unit' is invalid: %w", err) + } + } + if x.XValue != nil { + if err := x.XValue.Validate(); err != nil { + return fmt.Errorf("field '_value' is invalid: %w", err) + } + } + if x.Code != nil { + if !rx_Quantity_Code.MatchString(*x.Code) { + return fmt.Errorf("field 'code' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Comparator != nil { + if !rx_Quantity_Comparator.MatchString(*x.Comparator) { + return fmt.Errorf("field 'comparator' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "Quantity" { + return fmt.Errorf("field 'resourceType' must be exactly 'Quantity'") + } + } + if x.System != nil { + } + if x.Unit != nil { + if *x.Unit == "" { + return fmt.Errorf("field 'unit' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Value != nil { + } + return nil +} + +// Validate validates a Range struct against its schema constraints. +func (x *Range) Validate() error { + if x == nil { + return nil + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.High != nil { + if err := x.High.Validate(); err != nil { + return fmt.Errorf("field 'high' is invalid: %w", err) + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Low != nil { + if err := x.Low.Validate(); err != nil { + return fmt.Errorf("field 'low' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "Range" { + return fmt.Errorf("field 'resourceType' must be exactly 'Range'") + } + } + return nil +} + +// Validate validates a Ratio struct against its schema constraints. +func (x *Ratio) Validate() error { + if x == nil { + return nil + } + if x.Denominator != nil { + if err := x.Denominator.Validate(); err != nil { + return fmt.Errorf("field 'denominator' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Numerator != nil { + if err := x.Numerator.Validate(); err != nil { + return fmt.Errorf("field 'numerator' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "Ratio" { + return fmt.Errorf("field 'resourceType' must be exactly 'Ratio'") + } + } + return nil +} + +// Validate validates a RatioRange struct against its schema constraints. +func (x *RatioRange) Validate() error { + if x == nil { + return nil + } + if x.Denominator != nil { + if err := x.Denominator.Validate(); err != nil { + return fmt.Errorf("field 'denominator' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.HighNumerator != nil { + if err := x.HighNumerator.Validate(); err != nil { + return fmt.Errorf("field 'highNumerator' is invalid: %w", err) + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.LowNumerator != nil { + if err := x.LowNumerator.Validate(); err != nil { + return fmt.Errorf("field 'lowNumerator' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "RatioRange" { + return fmt.Errorf("field 'resourceType' must be exactly 'RatioRange'") + } + } + return nil +} + +// Validate validates a Reference struct against its schema constraints. +func (x *Reference) Validate() error { + if x == nil { + return nil + } + if x.XDisplay != nil { + if err := x.XDisplay.Validate(); err != nil { + return fmt.Errorf("field '_display' is invalid: %w", err) + } + } + if x.XReference != nil { + if err := x.XReference.Validate(); err != nil { + return fmt.Errorf("field '_reference' is invalid: %w", err) + } + } + if x.XType != nil { + if err := x.XType.Validate(); err != nil { + return fmt.Errorf("field '_type' is invalid: %w", err) + } + } + if x.Display != nil { + if *x.Display == "" { + return fmt.Errorf("field 'display' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.IDentifier != nil { + if err := x.IDentifier.Validate(); err != nil { + return fmt.Errorf("field 'identifier' is invalid: %w", err) + } + } + if x.Links != nil { + } + if x.Reference != nil { + if *x.Reference == "" { + return fmt.Errorf("field 'reference' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.ResourceType != nil { + if *x.ResourceType != "Reference" { + return fmt.Errorf("field 'resourceType' must be exactly 'Reference'") + } + } + if x.Type != nil { + } + return nil +} + +// Validate validates a RelatedArtifact struct against its schema constraints. +func (x *RelatedArtifact) Validate() error { + if x == nil { + return nil + } + if x.XCitation != nil { + if err := x.XCitation.Validate(); err != nil { + return fmt.Errorf("field '_citation' is invalid: %w", err) + } + } + if x.XDisplay != nil { + if err := x.XDisplay.Validate(); err != nil { + return fmt.Errorf("field '_display' is invalid: %w", err) + } + } + if x.XLabel != nil { + if err := x.XLabel.Validate(); err != nil { + return fmt.Errorf("field '_label' is invalid: %w", err) + } + } + if x.XPublicationDate != nil { + if err := x.XPublicationDate.Validate(); err != nil { + return fmt.Errorf("field '_publicationDate' is invalid: %w", err) + } + } + if x.XPublicationStatus != nil { + if err := x.XPublicationStatus.Validate(); err != nil { + return fmt.Errorf("field '_publicationStatus' is invalid: %w", err) + } + } + if x.XResource != nil { + if err := x.XResource.Validate(); err != nil { + return fmt.Errorf("field '_resource' is invalid: %w", err) + } + } + if x.XType != nil { + if err := x.XType.Validate(); err != nil { + return fmt.Errorf("field '_type' is invalid: %w", err) + } + } + if x.Citation != nil { + if !rx_RelatedArtifact_Citation.MatchString(*x.Citation) { + return fmt.Errorf("field 'citation' does not match pattern '\\s*(\\S|\\s)*'") + } + } + if x.Classifier != nil { + for i, item := range x.Classifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'classifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Display != nil { + if *x.Display == "" { + return fmt.Errorf("field 'display' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Document != nil { + if err := x.Document.Validate(); err != nil { + return fmt.Errorf("field 'document' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Label != nil { + if *x.Label == "" { + return fmt.Errorf("field 'label' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.PublicationDate != nil { + if err := ValidateFhirDate(*x.PublicationDate); err != nil { + return fmt.Errorf("field 'publicationDate' has invalid date format: %w", err) + } + } + if x.PublicationStatus != nil { + if !rx_RelatedArtifact_PublicationStatus.MatchString(*x.PublicationStatus) { + return fmt.Errorf("field 'publicationStatus' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Resource != nil { + } + if x.ResourceReference != nil { + if err := x.ResourceReference.Validate(); err != nil { + return fmt.Errorf("field 'resourceReference' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "RelatedArtifact" { + return fmt.Errorf("field 'resourceType' must be exactly 'RelatedArtifact'") + } + } + if x.Type != nil { + if !rx_RelatedArtifact_Type.MatchString(*x.Type) { + return fmt.Errorf("field 'type' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + return nil +} + +// Validate validates a ResearchStudy struct against its schema constraints. +func (x *ResearchStudy) Validate() error { + if x == nil { + return nil + } + if x.XDate != nil { + if err := x.XDate.Validate(); err != nil { + return fmt.Errorf("field '_date' is invalid: %w", err) + } + } + if x.XDescription != nil { + if err := x.XDescription.Validate(); err != nil { + return fmt.Errorf("field '_description' is invalid: %w", err) + } + } + if x.XDescriptionSummary != nil { + if err := x.XDescriptionSummary.Validate(); err != nil { + return fmt.Errorf("field '_descriptionSummary' is invalid: %w", err) + } + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.XName != nil { + if err := x.XName.Validate(); err != nil { + return fmt.Errorf("field '_name' is invalid: %w", err) + } + } + if x.XStatus != nil { + if err := x.XStatus.Validate(); err != nil { + return fmt.Errorf("field '_status' is invalid: %w", err) + } + } + if x.XTitle != nil { + if err := x.XTitle.Validate(); err != nil { + return fmt.Errorf("field '_title' is invalid: %w", err) + } + } + if x.XURL != nil { + if err := x.XURL.Validate(); err != nil { + return fmt.Errorf("field '_url' is invalid: %w", err) + } + } + if x.XVersion != nil { + if err := x.XVersion.Validate(); err != nil { + return fmt.Errorf("field '_version' is invalid: %w", err) + } + } + if x.AssociatedParty != nil { + for i, item := range x.AssociatedParty { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'associatedParty[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Classifier != nil { + for i, item := range x.Classifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'classifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ComparisonGroup != nil { + for i, item := range x.ComparisonGroup { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'comparisonGroup[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Condition != nil { + for i, item := range x.Condition { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'condition[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Contained != nil { + for i, item := range x.Contained { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Date != nil { + if err := ValidateFhirDateTime(*x.Date); err != nil { + return fmt.Errorf("field 'date' has invalid date-time format: %w", err) + } + } + if x.Description != nil { + if !rx_ResearchStudy_Description.MatchString(*x.Description) { + return fmt.Errorf("field 'description' does not match pattern '\\s*(\\S|\\s)*'") + } + } + if x.DescriptionSummary != nil { + if !rx_ResearchStudy_DescriptionSummary.MatchString(*x.DescriptionSummary) { + return fmt.Errorf("field 'descriptionSummary' does not match pattern '\\s*(\\S|\\s)*'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Focus != nil { + for i, item := range x.Focus { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'focus[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if !rx_ResearchStudy_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ImplicitRules != nil { + } + if x.Keyword != nil { + for i, item := range x.Keyword { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'keyword[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Label != nil { + for i, item := range x.Label { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'label[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Language != nil { + if !rx_ResearchStudy_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Name != nil { + if *x.Name == "" { + return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Note != nil { + for i, item := range x.Note { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Objective != nil { + for i, item := range x.Objective { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'objective[%d]' is invalid: %w", i, err) + } + } + } + } + if x.OutcomeMeasure != nil { + for i, item := range x.OutcomeMeasure { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'outcomeMeasure[%d]' is invalid: %w", i, err) + } + } + } + } + if x.PartOf != nil { + for i, item := range x.PartOf { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'partOf[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Period != nil { + if err := x.Period.Validate(); err != nil { + return fmt.Errorf("field 'period' is invalid: %w", err) + } + } + if x.Phase != nil { + if err := x.Phase.Validate(); err != nil { + return fmt.Errorf("field 'phase' is invalid: %w", err) + } + } + if x.PrimaryPurposeType != nil { + if err := x.PrimaryPurposeType.Validate(); err != nil { + return fmt.Errorf("field 'primaryPurposeType' is invalid: %w", err) + } + } + if x.ProgressStatus != nil { + for i, item := range x.ProgressStatus { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'progressStatus[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Protocol != nil { + for i, item := range x.Protocol { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'protocol[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Recruitment != nil { + if err := x.Recruitment.Validate(); err != nil { + return fmt.Errorf("field 'recruitment' is invalid: %w", err) + } + } + if x.Region != nil { + for i, item := range x.Region { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'region[%d]' is invalid: %w", i, err) + } + } + } + } + if x.RelatedArtifact != nil { + for i, item := range x.RelatedArtifact { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'relatedArtifact[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ResearchStudy" { + return fmt.Errorf("field 'resourceType' must be exactly 'ResearchStudy'") + } + } + if x.Result != nil { + for i, item := range x.Result { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'result[%d]' is invalid: %w", i, err) + } + } + } + } + if x.RootDir != nil { + if err := x.RootDir.Validate(); err != nil { + return fmt.Errorf("field 'rootDir' is invalid: %w", err) + } + } + if x.Site != nil { + for i, item := range x.Site { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'site[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Status != nil { + if !rx_ResearchStudy_Status.MatchString(*x.Status) { + return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.StudyDesign != nil { + for i, item := range x.StudyDesign { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'studyDesign[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Text != nil { + if err := x.Text.Validate(); err != nil { + return fmt.Errorf("field 'text' is invalid: %w", err) + } + } + if x.Title != nil { + if *x.Title == "" { + return fmt.Errorf("field 'title' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.URL != nil { + } + if x.Version != nil { + if *x.Version == "" { + return fmt.Errorf("field 'version' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.WhyStopped != nil { + if err := x.WhyStopped.Validate(); err != nil { + return fmt.Errorf("field 'whyStopped' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a ResearchStudyAssociatedParty struct against its schema constraints. +func (x *ResearchStudyAssociatedParty) Validate() error { + if x == nil { + return nil + } + if x.XName != nil { + if err := x.XName.Validate(); err != nil { + return fmt.Errorf("field '_name' is invalid: %w", err) + } + } + if x.Classifier != nil { + for i, item := range x.Classifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'classifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Name != nil { + if *x.Name == "" { + return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Party != nil { + if err := x.Party.Validate(); err != nil { + return fmt.Errorf("field 'party' is invalid: %w", err) + } + } + if x.Period != nil { + for i, item := range x.Period { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'period[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ResearchStudyAssociatedParty" { + return fmt.Errorf("field 'resourceType' must be exactly 'ResearchStudyAssociatedParty'") + } + } + if x.Role == nil { + return fmt.Errorf("required field 'role' is missing") + } + if x.Role != nil { + if err := x.Role.Validate(); err != nil { + return fmt.Errorf("field 'role' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a ResearchStudyComparisonGroup struct against its schema constraints. +func (x *ResearchStudyComparisonGroup) Validate() error { + if x == nil { + return nil + } + if x.XDescription != nil { + if err := x.XDescription.Validate(); err != nil { + return fmt.Errorf("field '_description' is invalid: %w", err) + } + } + if x.XLinkID != nil { + if err := x.XLinkID.Validate(); err != nil { + return fmt.Errorf("field '_linkId' is invalid: %w", err) + } + } + if x.XName != nil { + if err := x.XName.Validate(); err != nil { + return fmt.Errorf("field '_name' is invalid: %w", err) + } + } + if x.Description != nil { + if !rx_ResearchStudyComparisonGroup_Description.MatchString(*x.Description) { + return fmt.Errorf("field 'description' does not match pattern '\\s*(\\S|\\s)*'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.IntendedExposure != nil { + for i, item := range x.IntendedExposure { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'intendedExposure[%d]' is invalid: %w", i, err) + } + } + } + } + if x.LinkID != nil { + if !rx_ResearchStudyComparisonGroup_LinkID.MatchString(*x.LinkID) { + return fmt.Errorf("field 'linkId' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.LinkID) < 1 { + return fmt.Errorf("field 'linkId' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.LinkID) > 64 { + return fmt.Errorf("field 'linkId' is too long (max 64 characters)") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Name != nil { + if *x.Name == "" { + return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.ObservedGroup != nil { + if err := x.ObservedGroup.Validate(); err != nil { + return fmt.Errorf("field 'observedGroup' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ResearchStudyComparisonGroup" { + return fmt.Errorf("field 'resourceType' must be exactly 'ResearchStudyComparisonGroup'") + } + } + if x.Type != nil { + if err := x.Type.Validate(); err != nil { + return fmt.Errorf("field 'type' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a ResearchStudyLabel struct against its schema constraints. +func (x *ResearchStudyLabel) Validate() error { + if x == nil { + return nil + } + if x.XValue != nil { + if err := x.XValue.Validate(); err != nil { + return fmt.Errorf("field '_value' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ResearchStudyLabel" { + return fmt.Errorf("field 'resourceType' must be exactly 'ResearchStudyLabel'") + } + } + if x.Type != nil { + if err := x.Type.Validate(); err != nil { + return fmt.Errorf("field 'type' is invalid: %w", err) + } + } + if x.Value != nil { + if *x.Value == "" { + return fmt.Errorf("field 'value' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + return nil +} + +// Validate validates a ResearchStudyObjective struct against its schema constraints. +func (x *ResearchStudyObjective) Validate() error { + if x == nil { + return nil + } + if x.XDescription != nil { + if err := x.XDescription.Validate(); err != nil { + return fmt.Errorf("field '_description' is invalid: %w", err) + } + } + if x.XName != nil { + if err := x.XName.Validate(); err != nil { + return fmt.Errorf("field '_name' is invalid: %w", err) + } + } + if x.Description != nil { + if !rx_ResearchStudyObjective_Description.MatchString(*x.Description) { + return fmt.Errorf("field 'description' does not match pattern '\\s*(\\S|\\s)*'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Name != nil { + if *x.Name == "" { + return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ResearchStudyObjective" { + return fmt.Errorf("field 'resourceType' must be exactly 'ResearchStudyObjective'") + } + } + if x.Type != nil { + if err := x.Type.Validate(); err != nil { + return fmt.Errorf("field 'type' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a ResearchStudyOutcomeMeasure struct against its schema constraints. +func (x *ResearchStudyOutcomeMeasure) Validate() error { + if x == nil { + return nil + } + if x.XDescription != nil { + if err := x.XDescription.Validate(); err != nil { + return fmt.Errorf("field '_description' is invalid: %w", err) + } + } + if x.XName != nil { + if err := x.XName.Validate(); err != nil { + return fmt.Errorf("field '_name' is invalid: %w", err) + } + } + if x.Description != nil { + if !rx_ResearchStudyOutcomeMeasure_Description.MatchString(*x.Description) { + return fmt.Errorf("field 'description' does not match pattern '\\s*(\\S|\\s)*'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Name != nil { + if *x.Name == "" { + return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Reference != nil { + if err := x.Reference.Validate(); err != nil { + return fmt.Errorf("field 'reference' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ResearchStudyOutcomeMeasure" { + return fmt.Errorf("field 'resourceType' must be exactly 'ResearchStudyOutcomeMeasure'") + } + } + if x.Type != nil { + for i, item := range x.Type { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'type[%d]' is invalid: %w", i, err) + } + } + } + } + return nil +} + +// Validate validates a ResearchStudyProgressStatus struct against its schema constraints. +func (x *ResearchStudyProgressStatus) Validate() error { + if x == nil { + return nil + } + if x.XActual != nil { + if err := x.XActual.Validate(); err != nil { + return fmt.Errorf("field '_actual' is invalid: %w", err) + } + } + if x.Actual != nil { + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Period != nil { + if err := x.Period.Validate(); err != nil { + return fmt.Errorf("field 'period' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ResearchStudyProgressStatus" { + return fmt.Errorf("field 'resourceType' must be exactly 'ResearchStudyProgressStatus'") + } + } + if x.State == nil { + return fmt.Errorf("required field 'state' is missing") + } + if x.State != nil { + if err := x.State.Validate(); err != nil { + return fmt.Errorf("field 'state' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a ResearchStudyRecruitment struct against its schema constraints. +func (x *ResearchStudyRecruitment) Validate() error { + if x == nil { + return nil + } + if x.XActualNumber != nil { + if err := x.XActualNumber.Validate(); err != nil { + return fmt.Errorf("field '_actualNumber' is invalid: %w", err) + } + } + if x.XTargetNumber != nil { + if err := x.XTargetNumber.Validate(); err != nil { + return fmt.Errorf("field '_targetNumber' is invalid: %w", err) + } + } + if x.ActualGroup != nil { + if err := x.ActualGroup.Validate(); err != nil { + return fmt.Errorf("field 'actualGroup' is invalid: %w", err) + } + } + if x.ActualNumber != nil { + if *x.ActualNumber < 0.000000 { + return fmt.Errorf("field 'actualNumber' is below minimum 0.000000") + } + } + if x.Eligibility != nil { + if err := x.Eligibility.Validate(); err != nil { + return fmt.Errorf("field 'eligibility' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ResearchStudyRecruitment" { + return fmt.Errorf("field 'resourceType' must be exactly 'ResearchStudyRecruitment'") + } + } + if x.TargetNumber != nil { + if *x.TargetNumber < 0.000000 { + return fmt.Errorf("field 'targetNumber' is below minimum 0.000000") + } + } + return nil +} + +// Validate validates a ResearchSubject struct against its schema constraints. +func (x *ResearchSubject) Validate() error { + if x == nil { + return nil + } + if x.XActualComparisonGroup != nil { + if err := x.XActualComparisonGroup.Validate(); err != nil { + return fmt.Errorf("field '_actualComparisonGroup' is invalid: %w", err) + } + } + if x.XAssignedComparisonGroup != nil { + if err := x.XAssignedComparisonGroup.Validate(); err != nil { + return fmt.Errorf("field '_assignedComparisonGroup' is invalid: %w", err) + } + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.XStatus != nil { + if err := x.XStatus.Validate(); err != nil { + return fmt.Errorf("field '_status' is invalid: %w", err) + } + } + if x.ActualComparisonGroup != nil { + if !rx_ResearchSubject_ActualComparisonGroup.MatchString(*x.ActualComparisonGroup) { + return fmt.Errorf("field 'actualComparisonGroup' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ActualComparisonGroup) < 1 { + return fmt.Errorf("field 'actualComparisonGroup' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ActualComparisonGroup) > 64 { + return fmt.Errorf("field 'actualComparisonGroup' is too long (max 64 characters)") + } + } + if x.AssignedComparisonGroup != nil { + if !rx_ResearchSubject_AssignedComparisonGroup.MatchString(*x.AssignedComparisonGroup) { + return fmt.Errorf("field 'assignedComparisonGroup' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.AssignedComparisonGroup) < 1 { + return fmt.Errorf("field 'assignedComparisonGroup' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.AssignedComparisonGroup) > 64 { + return fmt.Errorf("field 'assignedComparisonGroup' is too long (max 64 characters)") + } + } + if x.Consent != nil { + for i, item := range x.Consent { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'consent[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Contained != nil { + for i, item := range x.Contained { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if !rx_ResearchSubject_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ImplicitRules != nil { + } + if x.Language != nil { + if !rx_ResearchSubject_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Period != nil { + if err := x.Period.Validate(); err != nil { + return fmt.Errorf("field 'period' is invalid: %w", err) + } + } + if x.Progress != nil { + for i, item := range x.Progress { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'progress[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ResearchSubject" { + return fmt.Errorf("field 'resourceType' must be exactly 'ResearchSubject'") + } + } + if x.Status != nil { + if !rx_ResearchSubject_Status.MatchString(*x.Status) { + return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Study == nil { + return fmt.Errorf("required field 'study' is missing") + } + if x.Study != nil { + if err := x.Study.Validate(); err != nil { + return fmt.Errorf("field 'study' is invalid: %w", err) + } + } + if x.Subject == nil { + return fmt.Errorf("required field 'subject' is missing") + } + if x.Subject != nil { + if err := x.Subject.Validate(); err != nil { + return fmt.Errorf("field 'subject' is invalid: %w", err) + } + } + if x.Text != nil { + if err := x.Text.Validate(); err != nil { + return fmt.Errorf("field 'text' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a ResearchSubjectProgress struct against its schema constraints. +func (x *ResearchSubjectProgress) Validate() error { + if x == nil { + return nil + } + if x.XEndDate != nil { + if err := x.XEndDate.Validate(); err != nil { + return fmt.Errorf("field '_endDate' is invalid: %w", err) + } + } + if x.XStartDate != nil { + if err := x.XStartDate.Validate(); err != nil { + return fmt.Errorf("field '_startDate' is invalid: %w", err) + } + } + if x.EndDate != nil { + if err := ValidateFhirDateTime(*x.EndDate); err != nil { + return fmt.Errorf("field 'endDate' has invalid date-time format: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Milestone != nil { + if err := x.Milestone.Validate(); err != nil { + return fmt.Errorf("field 'milestone' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Reason != nil { + if err := x.Reason.Validate(); err != nil { + return fmt.Errorf("field 'reason' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "ResearchSubjectProgress" { + return fmt.Errorf("field 'resourceType' must be exactly 'ResearchSubjectProgress'") + } + } + if x.StartDate != nil { + if err := ValidateFhirDateTime(*x.StartDate); err != nil { + return fmt.Errorf("field 'startDate' has invalid date-time format: %w", err) + } + } + if x.SubjectState != nil { + if err := x.SubjectState.Validate(); err != nil { + return fmt.Errorf("field 'subjectState' is invalid: %w", err) + } + } + if x.Type != nil { + if err := x.Type.Validate(); err != nil { + return fmt.Errorf("field 'type' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a Resource struct against its schema constraints. +func (x *Resource) Validate() error { + if x == nil { + return nil + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.ID != nil { + if !rx_Resource_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.ImplicitRules != nil { + } + if x.Language != nil { + if !rx_Resource_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "Resource" { + return fmt.Errorf("field 'resourceType' must be exactly 'Resource'") + } + } + return nil +} + +// Validate validates a SampledData struct against its schema constraints. +func (x *SampledData) Validate() error { + if x == nil { + return nil + } + if x.XCodeMap != nil { + if err := x.XCodeMap.Validate(); err != nil { + return fmt.Errorf("field '_codeMap' is invalid: %w", err) + } + } + if x.XData != nil { + if err := x.XData.Validate(); err != nil { + return fmt.Errorf("field '_data' is invalid: %w", err) + } + } + if x.XDimensions != nil { + if err := x.XDimensions.Validate(); err != nil { + return fmt.Errorf("field '_dimensions' is invalid: %w", err) + } + } + if x.XFactor != nil { + if err := x.XFactor.Validate(); err != nil { + return fmt.Errorf("field '_factor' is invalid: %w", err) + } + } + if x.XInterval != nil { + if err := x.XInterval.Validate(); err != nil { + return fmt.Errorf("field '_interval' is invalid: %w", err) + } + } + if x.XIntervalUnit != nil { + if err := x.XIntervalUnit.Validate(); err != nil { + return fmt.Errorf("field '_intervalUnit' is invalid: %w", err) + } + } + if x.XLowerLimit != nil { + if err := x.XLowerLimit.Validate(); err != nil { + return fmt.Errorf("field '_lowerLimit' is invalid: %w", err) + } + } + if x.XOffsets != nil { + if err := x.XOffsets.Validate(); err != nil { + return fmt.Errorf("field '_offsets' is invalid: %w", err) + } + } + if x.XUpperLimit != nil { + if err := x.XUpperLimit.Validate(); err != nil { + return fmt.Errorf("field '_upperLimit' is invalid: %w", err) + } + } + if x.CodeMap != nil { + } + if x.Data != nil { + if *x.Data == "" { + return fmt.Errorf("field 'data' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Dimensions != nil { + if *x.Dimensions <= 0.000000 { + return fmt.Errorf("field 'dimensions' is below exclusive minimum 0.000000") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Factor != nil { + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Interval != nil { + } + if x.IntervalUnit != nil { + if !rx_SampledData_IntervalUnit.MatchString(*x.IntervalUnit) { + return fmt.Errorf("field 'intervalUnit' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.LowerLimit != nil { + } + if x.Offsets != nil { + if *x.Offsets == "" { + return fmt.Errorf("field 'offsets' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Origin == nil { + return fmt.Errorf("required field 'origin' is missing") + } + if x.Origin != nil { + if err := x.Origin.Validate(); err != nil { + return fmt.Errorf("field 'origin' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "SampledData" { + return fmt.Errorf("field 'resourceType' must be exactly 'SampledData'") + } + } + if x.UpperLimit != nil { + } + return nil +} + +// Validate validates a Signature struct against its schema constraints. +func (x *Signature) Validate() error { + if x == nil { + return nil + } + if x.XData != nil { + if err := x.XData.Validate(); err != nil { + return fmt.Errorf("field '_data' is invalid: %w", err) + } + } + if x.XSigFormat != nil { + if err := x.XSigFormat.Validate(); err != nil { + return fmt.Errorf("field '_sigFormat' is invalid: %w", err) + } + } + if x.XTargetFormat != nil { + if err := x.XTargetFormat.Validate(); err != nil { + return fmt.Errorf("field '_targetFormat' is invalid: %w", err) + } + } + if x.XWhen != nil { + if err := x.XWhen.Validate(); err != nil { + return fmt.Errorf("field '_when' is invalid: %w", err) + } + } + if x.Data != nil { + if err := ValidateFhirBinary(*x.Data); err != nil { + return fmt.Errorf("field 'data' has invalid binary format: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.OnBehalfOf != nil { + if err := x.OnBehalfOf.Validate(); err != nil { + return fmt.Errorf("field 'onBehalfOf' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "Signature" { + return fmt.Errorf("field 'resourceType' must be exactly 'Signature'") + } + } + if x.SigFormat != nil { + if !rx_Signature_SigFormat.MatchString(*x.SigFormat) { + return fmt.Errorf("field 'sigFormat' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.TargetFormat != nil { + if !rx_Signature_TargetFormat.MatchString(*x.TargetFormat) { + return fmt.Errorf("field 'targetFormat' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Type != nil { + for i, item := range x.Type { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'type[%d]' is invalid: %w", i, err) + } + } + } + } + if x.When != nil { + if err := ValidateFhirDateTime(*x.When); err != nil { + return fmt.Errorf("field 'when' has invalid date-time format: %w", err) + } + } + if x.Who != nil { + if err := x.Who.Validate(); err != nil { + return fmt.Errorf("field 'who' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a Specimen struct against its schema constraints. +func (x *Specimen) Validate() error { + if x == nil { + return nil + } + if x.XCombined != nil { + if err := x.XCombined.Validate(); err != nil { + return fmt.Errorf("field '_combined' is invalid: %w", err) + } + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.XReceivedTime != nil { + if err := x.XReceivedTime.Validate(); err != nil { + return fmt.Errorf("field '_receivedTime' is invalid: %w", err) + } + } + if x.XStatus != nil { + if err := x.XStatus.Validate(); err != nil { + return fmt.Errorf("field '_status' is invalid: %w", err) + } + } + if x.AccessionIDentifier != nil { + if err := x.AccessionIDentifier.Validate(); err != nil { + return fmt.Errorf("field 'accessionIdentifier' is invalid: %w", err) + } + } + if x.Collection != nil { + if err := x.Collection.Validate(); err != nil { + return fmt.Errorf("field 'collection' is invalid: %w", err) + } + } + if x.Combined != nil { + if !rx_Specimen_Combined.MatchString(*x.Combined) { + return fmt.Errorf("field 'combined' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Condition != nil { + for i, item := range x.Condition { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'condition[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Contained != nil { + for i, item := range x.Contained { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Container != nil { + for i, item := range x.Container { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'container[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Feature != nil { + for i, item := range x.Feature { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'feature[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if !rx_Specimen_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ImplicitRules != nil { + } + if x.Language != nil { + if !rx_Specimen_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Note != nil { + for i, item := range x.Note { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Parent != nil { + for i, item := range x.Parent { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'parent[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Processing != nil { + for i, item := range x.Processing { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'processing[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ReceivedTime != nil { + if err := ValidateFhirDateTime(*x.ReceivedTime); err != nil { + return fmt.Errorf("field 'receivedTime' has invalid date-time format: %w", err) + } + } + if x.Request != nil { + for i, item := range x.Request { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'request[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "Specimen" { + return fmt.Errorf("field 'resourceType' must be exactly 'Specimen'") + } + } + if x.Role != nil { + for i, item := range x.Role { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'role[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Status != nil { + if !rx_Specimen_Status.MatchString(*x.Status) { + return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Subject != nil { + if err := x.Subject.Validate(); err != nil { + return fmt.Errorf("field 'subject' is invalid: %w", err) + } + } + if x.Text != nil { + if err := x.Text.Validate(); err != nil { + return fmt.Errorf("field 'text' is invalid: %w", err) + } + } + if x.Type != nil { + if err := x.Type.Validate(); err != nil { + return fmt.Errorf("field 'type' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a SpecimenCollection struct against its schema constraints. +func (x *SpecimenCollection) Validate() error { + if x == nil { + return nil + } + if x.XCollectedDateTime != nil { + if err := x.XCollectedDateTime.Validate(); err != nil { + return fmt.Errorf("field '_collectedDateTime' is invalid: %w", err) + } + } + if x.BodySite != nil { + if err := x.BodySite.Validate(); err != nil { + return fmt.Errorf("field 'bodySite' is invalid: %w", err) + } + } + if x.CollectedDateTime != nil { + if err := ValidateFhirDateTime(*x.CollectedDateTime); err != nil { + return fmt.Errorf("field 'collectedDateTime' has invalid date-time format: %w", err) + } + } + if x.CollectedPeriod != nil { + if err := x.CollectedPeriod.Validate(); err != nil { + return fmt.Errorf("field 'collectedPeriod' is invalid: %w", err) + } + } + if x.Collector != nil { + if err := x.Collector.Validate(); err != nil { + return fmt.Errorf("field 'collector' is invalid: %w", err) + } + } + if x.Device != nil { + if err := x.Device.Validate(); err != nil { + return fmt.Errorf("field 'device' is invalid: %w", err) + } + } + if x.Duration != nil { + if err := x.Duration.Validate(); err != nil { + return fmt.Errorf("field 'duration' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.FastingStatusCodeableConcept != nil { + if err := x.FastingStatusCodeableConcept.Validate(); err != nil { + return fmt.Errorf("field 'fastingStatusCodeableConcept' is invalid: %w", err) + } + } + if x.FastingStatusDuration != nil { + if err := x.FastingStatusDuration.Validate(); err != nil { + return fmt.Errorf("field 'fastingStatusDuration' is invalid: %w", err) + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Method != nil { + if err := x.Method.Validate(); err != nil { + return fmt.Errorf("field 'method' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Procedure != nil { + if err := x.Procedure.Validate(); err != nil { + return fmt.Errorf("field 'procedure' is invalid: %w", err) + } + } + if x.Quantity != nil { + if err := x.Quantity.Validate(); err != nil { + return fmt.Errorf("field 'quantity' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "SpecimenCollection" { + return fmt.Errorf("field 'resourceType' must be exactly 'SpecimenCollection'") + } + } + return nil +} + +// Validate validates a SpecimenContainer struct against its schema constraints. +func (x *SpecimenContainer) Validate() error { + if x == nil { + return nil + } + if x.Device == nil { + return fmt.Errorf("required field 'device' is missing") + } + if x.Device != nil { + if err := x.Device.Validate(); err != nil { + return fmt.Errorf("field 'device' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Location != nil { + if err := x.Location.Validate(); err != nil { + return fmt.Errorf("field 'location' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "SpecimenContainer" { + return fmt.Errorf("field 'resourceType' must be exactly 'SpecimenContainer'") + } + } + if x.SpecimenQuantity != nil { + if err := x.SpecimenQuantity.Validate(); err != nil { + return fmt.Errorf("field 'specimenQuantity' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a SpecimenFeature struct against its schema constraints. +func (x *SpecimenFeature) Validate() error { + if x == nil { + return nil + } + if x.XDescription != nil { + if err := x.XDescription.Validate(); err != nil { + return fmt.Errorf("field '_description' is invalid: %w", err) + } + } + if x.Description != nil { + if *x.Description == "" { + return fmt.Errorf("field 'description' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "SpecimenFeature" { + return fmt.Errorf("field 'resourceType' must be exactly 'SpecimenFeature'") + } + } + if x.Type == nil { + return fmt.Errorf("required field 'type' is missing") + } + if x.Type != nil { + if err := x.Type.Validate(); err != nil { + return fmt.Errorf("field 'type' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a SpecimenProcessing struct against its schema constraints. +func (x *SpecimenProcessing) Validate() error { + if x == nil { + return nil + } + if x.XDescription != nil { + if err := x.XDescription.Validate(); err != nil { + return fmt.Errorf("field '_description' is invalid: %w", err) + } + } + if x.XTimeDateTime != nil { + if err := x.XTimeDateTime.Validate(); err != nil { + return fmt.Errorf("field '_timeDateTime' is invalid: %w", err) + } + } + if x.Additive != nil { + for i, item := range x.Additive { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'additive[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Description != nil { + if *x.Description == "" { + return fmt.Errorf("field 'description' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Method != nil { + if err := x.Method.Validate(); err != nil { + return fmt.Errorf("field 'method' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "SpecimenProcessing" { + return fmt.Errorf("field 'resourceType' must be exactly 'SpecimenProcessing'") + } + } + if x.TimeDateTime != nil { + if err := ValidateFhirDateTime(*x.TimeDateTime); err != nil { + return fmt.Errorf("field 'timeDateTime' has invalid date-time format: %w", err) + } + } + if x.TimePeriod != nil { + if err := x.TimePeriod.Validate(); err != nil { + return fmt.Errorf("field 'timePeriod' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a Substance struct against its schema constraints. +func (x *Substance) Validate() error { + if x == nil { + return nil + } + if x.XDescription != nil { + if err := x.XDescription.Validate(); err != nil { + return fmt.Errorf("field '_description' is invalid: %w", err) + } + } + if x.XExpiry != nil { + if err := x.XExpiry.Validate(); err != nil { + return fmt.Errorf("field '_expiry' is invalid: %w", err) + } + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XInstance != nil { + if err := x.XInstance.Validate(); err != nil { + return fmt.Errorf("field '_instance' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.XStatus != nil { + if err := x.XStatus.Validate(); err != nil { + return fmt.Errorf("field '_status' is invalid: %w", err) + } + } + if x.Category != nil { + for i, item := range x.Category { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'category[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Code == nil { + return fmt.Errorf("required field 'code' is missing") + } + if x.Code != nil { + if err := x.Code.Validate(); err != nil { + return fmt.Errorf("field 'code' is invalid: %w", err) + } + } + if x.Contained != nil { + for i, item := range x.Contained { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Description != nil { + if !rx_Substance_Description.MatchString(*x.Description) { + return fmt.Errorf("field 'description' does not match pattern '\\s*(\\S|\\s)*'") + } + } + if x.Expiry != nil { + if err := ValidateFhirDateTime(*x.Expiry); err != nil { + return fmt.Errorf("field 'expiry' has invalid date-time format: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if !rx_Substance_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ImplicitRules != nil { + } + if x.Ingredient != nil { + for i, item := range x.Ingredient { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'ingredient[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Instance != nil { + } + if x.Language != nil { + if !rx_Substance_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Quantity != nil { + if err := x.Quantity.Validate(); err != nil { + return fmt.Errorf("field 'quantity' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "Substance" { + return fmt.Errorf("field 'resourceType' must be exactly 'Substance'") + } + } + if x.Status != nil { + if !rx_Substance_Status.MatchString(*x.Status) { + return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Text != nil { + if err := x.Text.Validate(); err != nil { + return fmt.Errorf("field 'text' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a SubstanceDefinition struct against its schema constraints. +func (x *SubstanceDefinition) Validate() error { + if x == nil { + return nil + } + if x.XDescription != nil { + if err := x.XDescription.Validate(); err != nil { + return fmt.Errorf("field '_description' is invalid: %w", err) + } + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.XVersion != nil { + if err := x.XVersion.Validate(); err != nil { + return fmt.Errorf("field '_version' is invalid: %w", err) + } + } + if x.Characterization != nil { + for i, item := range x.Characterization { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'characterization[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Classification != nil { + for i, item := range x.Classification { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'classification[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Code != nil { + for i, item := range x.Code { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'code[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Contained != nil { + for i, item := range x.Contained { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Description != nil { + if !rx_SubstanceDefinition_Description.MatchString(*x.Description) { + return fmt.Errorf("field 'description' does not match pattern '\\s*(\\S|\\s)*'") + } + } + if x.Domain != nil { + if err := x.Domain.Validate(); err != nil { + return fmt.Errorf("field 'domain' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Grade != nil { + for i, item := range x.Grade { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'grade[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if !rx_SubstanceDefinition_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ImplicitRules != nil { + } + if x.InformationSource != nil { + for i, item := range x.InformationSource { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'informationSource[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Language != nil { + if !rx_SubstanceDefinition_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Links != nil { + } + if x.Manufacturer != nil { + for i, item := range x.Manufacturer { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'manufacturer[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Moiety != nil { + for i, item := range x.Moiety { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'moiety[%d]' is invalid: %w", i, err) + } + } + } + } + if x.MolecularWeight != nil { + for i, item := range x.MolecularWeight { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'molecularWeight[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Name != nil { + for i, item := range x.Name { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'name[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Note != nil { + for i, item := range x.Note { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) + } + } + } + } + if x.NucleicAcid != nil { + if err := x.NucleicAcid.Validate(); err != nil { + return fmt.Errorf("field 'nucleicAcid' is invalid: %w", err) + } + } + if x.Polymer != nil { + if err := x.Polymer.Validate(); err != nil { + return fmt.Errorf("field 'polymer' is invalid: %w", err) + } + } + if x.Property != nil { + for i, item := range x.Property { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'property[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Protein != nil { + if err := x.Protein.Validate(); err != nil { + return fmt.Errorf("field 'protein' is invalid: %w", err) + } + } + if x.ReferenceInformation != nil { + if err := x.ReferenceInformation.Validate(); err != nil { + return fmt.Errorf("field 'referenceInformation' is invalid: %w", err) + } + } + if x.Relationship != nil { + for i, item := range x.Relationship { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'relationship[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "SubstanceDefinition" { + return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinition'") + } + } + if x.SourceMaterial != nil { + if err := x.SourceMaterial.Validate(); err != nil { + return fmt.Errorf("field 'sourceMaterial' is invalid: %w", err) + } + } + if x.Status != nil { + if err := x.Status.Validate(); err != nil { + return fmt.Errorf("field 'status' is invalid: %w", err) + } + } + if x.Structure != nil { + if err := x.Structure.Validate(); err != nil { + return fmt.Errorf("field 'structure' is invalid: %w", err) + } + } + if x.Supplier != nil { + for i, item := range x.Supplier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'supplier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Text != nil { + if err := x.Text.Validate(); err != nil { + return fmt.Errorf("field 'text' is invalid: %w", err) + } + } + if x.Version != nil { + if *x.Version == "" { + return fmt.Errorf("field 'version' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + return nil +} + +// Validate validates a SubstanceDefinitionCharacterization struct against its schema constraints. +func (x *SubstanceDefinitionCharacterization) Validate() error { + if x == nil { + return nil + } + if x.XDescription != nil { + if err := x.XDescription.Validate(); err != nil { + return fmt.Errorf("field '_description' is invalid: %w", err) + } + } + if x.Description != nil { + if !rx_SubstanceDefinitionCharacterization_Description.MatchString(*x.Description) { + return fmt.Errorf("field 'description' does not match pattern '\\s*(\\S|\\s)*'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.File != nil { + for i, item := range x.File { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'file[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Form != nil { + if err := x.Form.Validate(); err != nil { + return fmt.Errorf("field 'form' is invalid: %w", err) + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "SubstanceDefinitionCharacterization" { + return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinitionCharacterization'") + } + } + if x.Technique != nil { + if err := x.Technique.Validate(); err != nil { + return fmt.Errorf("field 'technique' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a SubstanceDefinitionCode struct against its schema constraints. +func (x *SubstanceDefinitionCode) Validate() error { + if x == nil { + return nil + } + if x.XStatusDate != nil { + if err := x.XStatusDate.Validate(); err != nil { + return fmt.Errorf("field '_statusDate' is invalid: %w", err) + } + } + if x.Code != nil { + if err := x.Code.Validate(); err != nil { + return fmt.Errorf("field 'code' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Note != nil { + for i, item := range x.Note { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "SubstanceDefinitionCode" { + return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinitionCode'") + } + } + if x.Source != nil { + for i, item := range x.Source { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'source[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Status != nil { + if err := x.Status.Validate(); err != nil { + return fmt.Errorf("field 'status' is invalid: %w", err) + } + } + if x.StatusDate != nil { + if err := ValidateFhirDateTime(*x.StatusDate); err != nil { + return fmt.Errorf("field 'statusDate' has invalid date-time format: %w", err) + } + } + return nil +} + +// Validate validates a SubstanceDefinitionMoiety struct against its schema constraints. +func (x *SubstanceDefinitionMoiety) Validate() error { + if x == nil { + return nil + } + if x.XAmountString != nil { + if err := x.XAmountString.Validate(); err != nil { + return fmt.Errorf("field '_amountString' is invalid: %w", err) + } + } + if x.XMolecularFormula != nil { + if err := x.XMolecularFormula.Validate(); err != nil { + return fmt.Errorf("field '_molecularFormula' is invalid: %w", err) + } + } + if x.XName != nil { + if err := x.XName.Validate(); err != nil { + return fmt.Errorf("field '_name' is invalid: %w", err) + } + } + if x.AmountQuantity != nil { + if err := x.AmountQuantity.Validate(); err != nil { + return fmt.Errorf("field 'amountQuantity' is invalid: %w", err) + } + } + if x.AmountString != nil { + if *x.AmountString == "" { + return fmt.Errorf("field 'amountString' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.IDentifier != nil { + if err := x.IDentifier.Validate(); err != nil { + return fmt.Errorf("field 'identifier' is invalid: %w", err) + } + } + if x.Links != nil { + } + if x.MeasurementType != nil { + if err := x.MeasurementType.Validate(); err != nil { + return fmt.Errorf("field 'measurementType' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.MolecularFormula != nil { + if *x.MolecularFormula == "" { + return fmt.Errorf("field 'molecularFormula' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Name != nil { + if *x.Name == "" { + return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.OpticalActivity != nil { + if err := x.OpticalActivity.Validate(); err != nil { + return fmt.Errorf("field 'opticalActivity' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "SubstanceDefinitionMoiety" { + return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinitionMoiety'") + } + } + if x.Role != nil { + if err := x.Role.Validate(); err != nil { + return fmt.Errorf("field 'role' is invalid: %w", err) + } + } + if x.Stereochemistry != nil { + if err := x.Stereochemistry.Validate(); err != nil { + return fmt.Errorf("field 'stereochemistry' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a SubstanceDefinitionMolecularWeight struct against its schema constraints. +func (x *SubstanceDefinitionMolecularWeight) Validate() error { + if x == nil { + return nil + } + if x.Amount == nil { + return fmt.Errorf("required field 'amount' is missing") + } + if x.Amount != nil { + if err := x.Amount.Validate(); err != nil { + return fmt.Errorf("field 'amount' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Method != nil { + if err := x.Method.Validate(); err != nil { + return fmt.Errorf("field 'method' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "SubstanceDefinitionMolecularWeight" { + return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinitionMolecularWeight'") + } + } + if x.Type != nil { + if err := x.Type.Validate(); err != nil { + return fmt.Errorf("field 'type' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a SubstanceDefinitionName struct against its schema constraints. +func (x *SubstanceDefinitionName) Validate() error { + if x == nil { + return nil + } + if x.XName != nil { + if err := x.XName.Validate(); err != nil { + return fmt.Errorf("field '_name' is invalid: %w", err) + } + } + if x.XPreferred != nil { + if err := x.XPreferred.Validate(); err != nil { + return fmt.Errorf("field '_preferred' is invalid: %w", err) + } + } + if x.Domain != nil { + for i, item := range x.Domain { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'domain[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Jurisdiction != nil { + for i, item := range x.Jurisdiction { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'jurisdiction[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Language != nil { + for i, item := range x.Language { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'language[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Name != nil { + if *x.Name == "" { + return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Official != nil { + for i, item := range x.Official { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'official[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Preferred != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "SubstanceDefinitionName" { + return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinitionName'") + } + } + if x.Source != nil { + for i, item := range x.Source { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'source[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Status != nil { + if err := x.Status.Validate(); err != nil { + return fmt.Errorf("field 'status' is invalid: %w", err) + } + } + if x.Synonym != nil { + for i, item := range x.Synonym { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'synonym[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Translation != nil { + for i, item := range x.Translation { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'translation[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Type != nil { + if err := x.Type.Validate(); err != nil { + return fmt.Errorf("field 'type' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a SubstanceDefinitionNameOfficial struct against its schema constraints. +func (x *SubstanceDefinitionNameOfficial) Validate() error { + if x == nil { + return nil + } + if x.XDate != nil { + if err := x.XDate.Validate(); err != nil { + return fmt.Errorf("field '_date' is invalid: %w", err) + } + } + if x.Authority != nil { + if err := x.Authority.Validate(); err != nil { + return fmt.Errorf("field 'authority' is invalid: %w", err) + } + } + if x.Date != nil { + if err := ValidateFhirDateTime(*x.Date); err != nil { + return fmt.Errorf("field 'date' has invalid date-time format: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "SubstanceDefinitionNameOfficial" { + return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinitionNameOfficial'") + } + } + if x.Status != nil { + if err := x.Status.Validate(); err != nil { + return fmt.Errorf("field 'status' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a SubstanceDefinitionProperty struct against its schema constraints. +func (x *SubstanceDefinitionProperty) Validate() error { + if x == nil { + return nil + } + if x.XValueBoolean != nil { + if err := x.XValueBoolean.Validate(); err != nil { + return fmt.Errorf("field '_valueBoolean' is invalid: %w", err) + } + } + if x.XValueDate != nil { + if err := x.XValueDate.Validate(); err != nil { + return fmt.Errorf("field '_valueDate' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "SubstanceDefinitionProperty" { + return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinitionProperty'") + } + } + if x.Type == nil { + return fmt.Errorf("required field 'type' is missing") + } + if x.Type != nil { + if err := x.Type.Validate(); err != nil { + return fmt.Errorf("field 'type' is invalid: %w", err) + } + } + if x.ValueAttachment != nil { + if err := x.ValueAttachment.Validate(); err != nil { + return fmt.Errorf("field 'valueAttachment' is invalid: %w", err) + } + } + if x.ValueBoolean != nil { + } + if x.ValueCodeableConcept != nil { + if err := x.ValueCodeableConcept.Validate(); err != nil { + return fmt.Errorf("field 'valueCodeableConcept' is invalid: %w", err) + } + } + if x.ValueDate != nil { + if err := ValidateFhirDate(*x.ValueDate); err != nil { + return fmt.Errorf("field 'valueDate' has invalid date format: %w", err) + } + } + if x.ValueQuantity != nil { + if err := x.ValueQuantity.Validate(); err != nil { + return fmt.Errorf("field 'valueQuantity' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a SubstanceDefinitionRelationship struct against its schema constraints. +func (x *SubstanceDefinitionRelationship) Validate() error { + if x == nil { + return nil + } + if x.XAmountString != nil { + if err := x.XAmountString.Validate(); err != nil { + return fmt.Errorf("field '_amountString' is invalid: %w", err) + } + } + if x.XIsDefining != nil { + if err := x.XIsDefining.Validate(); err != nil { + return fmt.Errorf("field '_isDefining' is invalid: %w", err) + } + } + if x.AmountQuantity != nil { + if err := x.AmountQuantity.Validate(); err != nil { + return fmt.Errorf("field 'amountQuantity' is invalid: %w", err) + } + } + if x.AmountRatio != nil { + if err := x.AmountRatio.Validate(); err != nil { + return fmt.Errorf("field 'amountRatio' is invalid: %w", err) + } + } + if x.AmountString != nil { + if *x.AmountString == "" { + return fmt.Errorf("field 'amountString' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Comparator != nil { + if err := x.Comparator.Validate(); err != nil { + return fmt.Errorf("field 'comparator' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.IsDefining != nil { + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.RatioHighLimitAmount != nil { + if err := x.RatioHighLimitAmount.Validate(); err != nil { + return fmt.Errorf("field 'ratioHighLimitAmount' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "SubstanceDefinitionRelationship" { + return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinitionRelationship'") + } + } + if x.Source != nil { + for i, item := range x.Source { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'source[%d]' is invalid: %w", i, err) + } + } + } + } + if x.SubstanceDefinitionCodeableConcept != nil { + if err := x.SubstanceDefinitionCodeableConcept.Validate(); err != nil { + return fmt.Errorf("field 'substanceDefinitionCodeableConcept' is invalid: %w", err) + } + } + if x.SubstanceDefinitionReference != nil { + if err := x.SubstanceDefinitionReference.Validate(); err != nil { + return fmt.Errorf("field 'substanceDefinitionReference' is invalid: %w", err) + } + } + if x.Type == nil { + return fmt.Errorf("required field 'type' is missing") + } + if x.Type != nil { + if err := x.Type.Validate(); err != nil { + return fmt.Errorf("field 'type' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a SubstanceDefinitionSourceMaterial struct against its schema constraints. +func (x *SubstanceDefinitionSourceMaterial) Validate() error { + if x == nil { + return nil + } + if x.CountryOfOrigin != nil { + for i, item := range x.CountryOfOrigin { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'countryOfOrigin[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Genus != nil { + if err := x.Genus.Validate(); err != nil { + return fmt.Errorf("field 'genus' is invalid: %w", err) + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Part != nil { + if err := x.Part.Validate(); err != nil { + return fmt.Errorf("field 'part' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "SubstanceDefinitionSourceMaterial" { + return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinitionSourceMaterial'") + } + } + if x.Species != nil { + if err := x.Species.Validate(); err != nil { + return fmt.Errorf("field 'species' is invalid: %w", err) + } + } + if x.Type != nil { + if err := x.Type.Validate(); err != nil { + return fmt.Errorf("field 'type' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a SubstanceDefinitionStructure struct against its schema constraints. +func (x *SubstanceDefinitionStructure) Validate() error { + if x == nil { + return nil + } + if x.XMolecularFormula != nil { + if err := x.XMolecularFormula.Validate(); err != nil { + return fmt.Errorf("field '_molecularFormula' is invalid: %w", err) + } + } + if x.XMolecularFormulaByMoiety != nil { + if err := x.XMolecularFormulaByMoiety.Validate(); err != nil { + return fmt.Errorf("field '_molecularFormulaByMoiety' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.MolecularFormula != nil { + if *x.MolecularFormula == "" { + return fmt.Errorf("field 'molecularFormula' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.MolecularFormulaByMoiety != nil { + if *x.MolecularFormulaByMoiety == "" { + return fmt.Errorf("field 'molecularFormulaByMoiety' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.MolecularWeight != nil { + if err := x.MolecularWeight.Validate(); err != nil { + return fmt.Errorf("field 'molecularWeight' is invalid: %w", err) + } + } + if x.OpticalActivity != nil { + if err := x.OpticalActivity.Validate(); err != nil { + return fmt.Errorf("field 'opticalActivity' is invalid: %w", err) + } + } + if x.Representation != nil { + for i, item := range x.Representation { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'representation[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "SubstanceDefinitionStructure" { + return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinitionStructure'") + } + } + if x.SourceDocument != nil { + for i, item := range x.SourceDocument { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'sourceDocument[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Stereochemistry != nil { + if err := x.Stereochemistry.Validate(); err != nil { + return fmt.Errorf("field 'stereochemistry' is invalid: %w", err) + } + } + if x.Technique != nil { + for i, item := range x.Technique { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'technique[%d]' is invalid: %w", i, err) + } + } + } + } + return nil +} + +// Validate validates a SubstanceDefinitionStructureRepresentation struct against its schema constraints. +func (x *SubstanceDefinitionStructureRepresentation) Validate() error { + if x == nil { + return nil + } + if x.XRepresentation != nil { + if err := x.XRepresentation.Validate(); err != nil { + return fmt.Errorf("field '_representation' is invalid: %w", err) + } + } + if x.Document != nil { + if err := x.Document.Validate(); err != nil { + return fmt.Errorf("field 'document' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Format != nil { + if err := x.Format.Validate(); err != nil { + return fmt.Errorf("field 'format' is invalid: %w", err) + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Representation != nil { + if *x.Representation == "" { + return fmt.Errorf("field 'representation' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.ResourceType != nil { + if *x.ResourceType != "SubstanceDefinitionStructureRepresentation" { + return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceDefinitionStructureRepresentation'") + } + } + if x.Type != nil { + if err := x.Type.Validate(); err != nil { + return fmt.Errorf("field 'type' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a SubstanceIngredient struct against its schema constraints. +func (x *SubstanceIngredient) Validate() error { + if x == nil { + return nil + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Quantity != nil { + if err := x.Quantity.Validate(); err != nil { + return fmt.Errorf("field 'quantity' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "SubstanceIngredient" { + return fmt.Errorf("field 'resourceType' must be exactly 'SubstanceIngredient'") + } + } + if x.SubstanceCodeableConcept != nil { + if err := x.SubstanceCodeableConcept.Validate(); err != nil { + return fmt.Errorf("field 'substanceCodeableConcept' is invalid: %w", err) + } + } + if x.SubstanceReference != nil { + if err := x.SubstanceReference.Validate(); err != nil { + return fmt.Errorf("field 'substanceReference' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a Task struct against its schema constraints. +func (x *Task) Validate() error { + if x == nil { + return nil + } + if x.XAuthoredOn != nil { + if err := x.XAuthoredOn.Validate(); err != nil { + return fmt.Errorf("field '_authoredOn' is invalid: %w", err) + } + } + if x.XDescription != nil { + if err := x.XDescription.Validate(); err != nil { + return fmt.Errorf("field '_description' is invalid: %w", err) + } + } + if x.XDoNotPerform != nil { + if err := x.XDoNotPerform.Validate(); err != nil { + return fmt.Errorf("field '_doNotPerform' is invalid: %w", err) + } + } + if x.XImplicitRules != nil { + if err := x.XImplicitRules.Validate(); err != nil { + return fmt.Errorf("field '_implicitRules' is invalid: %w", err) + } + } + if x.XInstantiatesCanonical != nil { + if err := x.XInstantiatesCanonical.Validate(); err != nil { + return fmt.Errorf("field '_instantiatesCanonical' is invalid: %w", err) + } + } + if x.XInstantiatesURI != nil { + if err := x.XInstantiatesURI.Validate(); err != nil { + return fmt.Errorf("field '_instantiatesUri' is invalid: %w", err) + } + } + if x.XIntent != nil { + if err := x.XIntent.Validate(); err != nil { + return fmt.Errorf("field '_intent' is invalid: %w", err) + } + } + if x.XLanguage != nil { + if err := x.XLanguage.Validate(); err != nil { + return fmt.Errorf("field '_language' is invalid: %w", err) + } + } + if x.XLastModified != nil { + if err := x.XLastModified.Validate(); err != nil { + return fmt.Errorf("field '_lastModified' is invalid: %w", err) + } + } + if x.XPriority != nil { + if err := x.XPriority.Validate(); err != nil { + return fmt.Errorf("field '_priority' is invalid: %w", err) + } + } + if x.XStatus != nil { + if err := x.XStatus.Validate(); err != nil { + return fmt.Errorf("field '_status' is invalid: %w", err) + } + } + if x.AuthoredOn != nil { + if err := ValidateFhirDateTime(*x.AuthoredOn); err != nil { + return fmt.Errorf("field 'authoredOn' has invalid date-time format: %w", err) + } + } + if x.BasedOn != nil { + for i, item := range x.BasedOn { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'basedOn[%d]' is invalid: %w", i, err) + } + } + } + } + if x.BusinessStatus != nil { + if err := x.BusinessStatus.Validate(); err != nil { + return fmt.Errorf("field 'businessStatus' is invalid: %w", err) + } + } + if x.Code != nil { + if err := x.Code.Validate(); err != nil { + return fmt.Errorf("field 'code' is invalid: %w", err) + } + } + if x.Contained != nil { + for i, item := range x.Contained { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'contained[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Description != nil { + if *x.Description == "" { + return fmt.Errorf("field 'description' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.DoNotPerform != nil { + } + if x.Encounter != nil { + if err := x.Encounter.Validate(); err != nil { + return fmt.Errorf("field 'encounter' is invalid: %w", err) + } + } + if x.ExecutionPeriod != nil { + if err := x.ExecutionPeriod.Validate(); err != nil { + return fmt.Errorf("field 'executionPeriod' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Focus != nil { + if err := x.Focus.Validate(); err != nil { + return fmt.Errorf("field 'focus' is invalid: %w", err) + } + } + if x.ForFhir != nil { + if err := x.ForFhir.Validate(); err != nil { + return fmt.Errorf("field 'for_fhir' is invalid: %w", err) + } + } + if x.GroupIDentifier != nil { + if err := x.GroupIDentifier.Validate(); err != nil { + return fmt.Errorf("field 'groupIdentifier' is invalid: %w", err) + } + } + if x.ID != nil { + if !rx_Task_ID.MatchString(*x.ID) { + return fmt.Errorf("field 'id' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ID) < 1 { + return fmt.Errorf("field 'id' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ID) > 64 { + return fmt.Errorf("field 'id' is too long (max 64 characters)") + } + } + if x.IDentifier != nil { + for i, item := range x.IDentifier { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'identifier[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ImplicitRules != nil { + } + if x.Input != nil { + for i, item := range x.Input { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'input[%d]' is invalid: %w", i, err) + } + } + } + } + if x.InstantiatesCanonical != nil { + } + if x.InstantiatesURI != nil { + } + if x.Insurance != nil { + for i, item := range x.Insurance { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'insurance[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Intent != nil { + if !rx_Task_Intent.MatchString(*x.Intent) { + return fmt.Errorf("field 'intent' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Language != nil { + if !rx_Task_Language.MatchString(*x.Language) { + return fmt.Errorf("field 'language' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.LastModified != nil { + if err := ValidateFhirDateTime(*x.LastModified); err != nil { + return fmt.Errorf("field 'lastModified' has invalid date-time format: %w", err) + } + } + if x.Links != nil { + } + if x.Location != nil { + if err := x.Location.Validate(); err != nil { + return fmt.Errorf("field 'location' is invalid: %w", err) + } + } + if x.Meta != nil { + if err := x.Meta.Validate(); err != nil { + return fmt.Errorf("field 'meta' is invalid: %w", err) + } + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Note != nil { + for i, item := range x.Note { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'note[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Output != nil { + for i, item := range x.Output { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'output[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Owner != nil { + if err := x.Owner.Validate(); err != nil { + return fmt.Errorf("field 'owner' is invalid: %w", err) + } + } + if x.PartOf != nil { + for i, item := range x.PartOf { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'partOf[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Performer != nil { + for i, item := range x.Performer { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'performer[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Priority != nil { + if !rx_Task_Priority.MatchString(*x.Priority) { + return fmt.Errorf("field 'priority' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Reason != nil { + for i, item := range x.Reason { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'reason[%d]' is invalid: %w", i, err) + } + } + } + } + if x.RelevantHistory != nil { + for i, item := range x.RelevantHistory { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'relevantHistory[%d]' is invalid: %w", i, err) + } + } + } + } + if x.RequestedPerformer != nil { + for i, item := range x.RequestedPerformer { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'requestedPerformer[%d]' is invalid: %w", i, err) + } + } + } + } + if x.RequestedPeriod != nil { + if err := x.RequestedPeriod.Validate(); err != nil { + return fmt.Errorf("field 'requestedPeriod' is invalid: %w", err) + } + } + if x.Requester != nil { + if err := x.Requester.Validate(); err != nil { + return fmt.Errorf("field 'requester' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "Task" { + return fmt.Errorf("field 'resourceType' must be exactly 'Task'") + } + } + if x.Restriction != nil { + if err := x.Restriction.Validate(); err != nil { + return fmt.Errorf("field 'restriction' is invalid: %w", err) + } + } + if x.Status != nil { + if !rx_Task_Status.MatchString(*x.Status) { + return fmt.Errorf("field 'status' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.StatusReason != nil { + if err := x.StatusReason.Validate(); err != nil { + return fmt.Errorf("field 'statusReason' is invalid: %w", err) + } + } + if x.Text != nil { + if err := x.Text.Validate(); err != nil { + return fmt.Errorf("field 'text' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a TaskInput struct against its schema constraints. +func (x *TaskInput) Validate() error { + if x == nil { + return nil + } + if x.XValueBase64Binary != nil { + if err := x.XValueBase64Binary.Validate(); err != nil { + return fmt.Errorf("field '_valueBase64Binary' is invalid: %w", err) + } + } + if x.XValueBoolean != nil { + if err := x.XValueBoolean.Validate(); err != nil { + return fmt.Errorf("field '_valueBoolean' is invalid: %w", err) + } + } + if x.XValueCanonical != nil { + if err := x.XValueCanonical.Validate(); err != nil { + return fmt.Errorf("field '_valueCanonical' is invalid: %w", err) + } + } + if x.XValueCode != nil { + if err := x.XValueCode.Validate(); err != nil { + return fmt.Errorf("field '_valueCode' is invalid: %w", err) + } + } + if x.XValueDate != nil { + if err := x.XValueDate.Validate(); err != nil { + return fmt.Errorf("field '_valueDate' is invalid: %w", err) + } + } + if x.XValueDateTime != nil { + if err := x.XValueDateTime.Validate(); err != nil { + return fmt.Errorf("field '_valueDateTime' is invalid: %w", err) + } + } + if x.XValueDecimal != nil { + if err := x.XValueDecimal.Validate(); err != nil { + return fmt.Errorf("field '_valueDecimal' is invalid: %w", err) + } + } + if x.XValueID != nil { + if err := x.XValueID.Validate(); err != nil { + return fmt.Errorf("field '_valueId' is invalid: %w", err) + } + } + if x.XValueInstant != nil { + if err := x.XValueInstant.Validate(); err != nil { + return fmt.Errorf("field '_valueInstant' is invalid: %w", err) + } + } + if x.XValueInteger != nil { + if err := x.XValueInteger.Validate(); err != nil { + return fmt.Errorf("field '_valueInteger' is invalid: %w", err) + } + } + if x.XValueInteger64 != nil { + if err := x.XValueInteger64.Validate(); err != nil { + return fmt.Errorf("field '_valueInteger64' is invalid: %w", err) + } + } + if x.XValueMarkdown != nil { + if err := x.XValueMarkdown.Validate(); err != nil { + return fmt.Errorf("field '_valueMarkdown' is invalid: %w", err) + } + } + if x.XValueOid != nil { + if err := x.XValueOid.Validate(); err != nil { + return fmt.Errorf("field '_valueOid' is invalid: %w", err) + } + } + if x.XValuePositiveInt != nil { + if err := x.XValuePositiveInt.Validate(); err != nil { + return fmt.Errorf("field '_valuePositiveInt' is invalid: %w", err) + } + } + if x.XValueString != nil { + if err := x.XValueString.Validate(); err != nil { + return fmt.Errorf("field '_valueString' is invalid: %w", err) + } + } + if x.XValueTime != nil { + if err := x.XValueTime.Validate(); err != nil { + return fmt.Errorf("field '_valueTime' is invalid: %w", err) + } + } + if x.XValueUnsignedInt != nil { + if err := x.XValueUnsignedInt.Validate(); err != nil { + return fmt.Errorf("field '_valueUnsignedInt' is invalid: %w", err) + } + } + if x.XValueURI != nil { + if err := x.XValueURI.Validate(); err != nil { + return fmt.Errorf("field '_valueUri' is invalid: %w", err) + } + } + if x.XValueURL != nil { + if err := x.XValueURL.Validate(); err != nil { + return fmt.Errorf("field '_valueUrl' is invalid: %w", err) + } + } + if x.XValueUUID != nil { + if err := x.XValueUUID.Validate(); err != nil { + return fmt.Errorf("field '_valueUuid' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "TaskInput" { + return fmt.Errorf("field 'resourceType' must be exactly 'TaskInput'") + } + } + if x.Type == nil { + return fmt.Errorf("required field 'type' is missing") + } + if x.Type != nil { + if err := x.Type.Validate(); err != nil { + return fmt.Errorf("field 'type' is invalid: %w", err) + } + } + if x.ValueAddress != nil { + if err := x.ValueAddress.Validate(); err != nil { + return fmt.Errorf("field 'valueAddress' is invalid: %w", err) + } + } + if x.ValueAge != nil { + if err := x.ValueAge.Validate(); err != nil { + return fmt.Errorf("field 'valueAge' is invalid: %w", err) + } + } + if x.ValueAnnotation != nil { + if err := x.ValueAnnotation.Validate(); err != nil { + return fmt.Errorf("field 'valueAnnotation' is invalid: %w", err) + } + } + if x.ValueAttachment != nil { + if err := x.ValueAttachment.Validate(); err != nil { + return fmt.Errorf("field 'valueAttachment' is invalid: %w", err) + } + } + if x.ValueAvailability != nil { + if err := x.ValueAvailability.Validate(); err != nil { + return fmt.Errorf("field 'valueAvailability' is invalid: %w", err) + } + } + if x.ValueBase64Binary != nil { + if err := ValidateFhirBinary(*x.ValueBase64Binary); err != nil { + return fmt.Errorf("field 'valueBase64Binary' has invalid binary format: %w", err) + } + } + if x.ValueBoolean != nil { + } + if x.ValueCanonical != nil { + } + if x.ValueCode != nil { + if !rx_TaskInput_ValueCode.MatchString(*x.ValueCode) { + return fmt.Errorf("field 'valueCode' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.ValueCodeableConcept != nil { + if err := x.ValueCodeableConcept.Validate(); err != nil { + return fmt.Errorf("field 'valueCodeableConcept' is invalid: %w", err) + } + } + if x.ValueCodeableReference != nil { + if err := x.ValueCodeableReference.Validate(); err != nil { + return fmt.Errorf("field 'valueCodeableReference' is invalid: %w", err) + } + } + if x.ValueCoding != nil { + if err := x.ValueCoding.Validate(); err != nil { + return fmt.Errorf("field 'valueCoding' is invalid: %w", err) + } + } + if x.ValueContactDetail != nil { + if err := x.ValueContactDetail.Validate(); err != nil { + return fmt.Errorf("field 'valueContactDetail' is invalid: %w", err) + } + } + if x.ValueContactPoint != nil { + if err := x.ValueContactPoint.Validate(); err != nil { + return fmt.Errorf("field 'valueContactPoint' is invalid: %w", err) + } + } + if x.ValueCount != nil { + if err := x.ValueCount.Validate(); err != nil { + return fmt.Errorf("field 'valueCount' is invalid: %w", err) + } + } + if x.ValueDataRequirement != nil { + if err := x.ValueDataRequirement.Validate(); err != nil { + return fmt.Errorf("field 'valueDataRequirement' is invalid: %w", err) + } + } + if x.ValueDate != nil { + if err := ValidateFhirDate(*x.ValueDate); err != nil { + return fmt.Errorf("field 'valueDate' has invalid date format: %w", err) + } + } + if x.ValueDateTime != nil { + if err := ValidateFhirDateTime(*x.ValueDateTime); err != nil { + return fmt.Errorf("field 'valueDateTime' has invalid date-time format: %w", err) + } + } + if x.ValueDecimal != nil { + } + if x.ValueDistance != nil { + if err := x.ValueDistance.Validate(); err != nil { + return fmt.Errorf("field 'valueDistance' is invalid: %w", err) + } + } + if x.ValueDosage != nil { + if err := x.ValueDosage.Validate(); err != nil { + return fmt.Errorf("field 'valueDosage' is invalid: %w", err) + } + } + if x.ValueDuration != nil { + if err := x.ValueDuration.Validate(); err != nil { + return fmt.Errorf("field 'valueDuration' is invalid: %w", err) + } + } + if x.ValueExpression != nil { + if err := x.ValueExpression.Validate(); err != nil { + return fmt.Errorf("field 'valueExpression' is invalid: %w", err) + } + } + if x.ValueExtendedContactDetail != nil { + if err := x.ValueExtendedContactDetail.Validate(); err != nil { + return fmt.Errorf("field 'valueExtendedContactDetail' is invalid: %w", err) + } + } + if x.ValueHumanName != nil { + if err := x.ValueHumanName.Validate(); err != nil { + return fmt.Errorf("field 'valueHumanName' is invalid: %w", err) + } + } + if x.ValueID != nil { + if !rx_TaskInput_ValueID.MatchString(*x.ValueID) { + return fmt.Errorf("field 'valueId' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ValueID) < 1 { + return fmt.Errorf("field 'valueId' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ValueID) > 64 { + return fmt.Errorf("field 'valueId' is too long (max 64 characters)") + } + } + if x.ValueIDentifier != nil { + if err := x.ValueIDentifier.Validate(); err != nil { + return fmt.Errorf("field 'valueIdentifier' is invalid: %w", err) + } + } + if x.ValueInstant != nil { + if err := ValidateFhirDateTime(*x.ValueInstant); err != nil { + return fmt.Errorf("field 'valueInstant' has invalid date-time format: %w", err) + } + } + if x.ValueInteger != nil { + } + if x.ValueInteger64 != nil { + } + if x.ValueMarkdown != nil { + if !rx_TaskInput_ValueMarkdown.MatchString(*x.ValueMarkdown) { + return fmt.Errorf("field 'valueMarkdown' does not match pattern '\\s*(\\S|\\s)*'") + } + } + if x.ValueMeta != nil { + if err := x.ValueMeta.Validate(); err != nil { + return fmt.Errorf("field 'valueMeta' is invalid: %w", err) + } + } + if x.ValueMoney != nil { + if err := x.ValueMoney.Validate(); err != nil { + return fmt.Errorf("field 'valueMoney' is invalid: %w", err) + } + } + if x.ValueOid != nil { + if !rx_TaskInput_ValueOid.MatchString(*x.ValueOid) { + return fmt.Errorf("field 'valueOid' does not match pattern '^urn:oid:[0-2](\\.(0|[1-9][0-9]*))+$'") + } + } + if x.ValueParameterDefinition != nil { + if err := x.ValueParameterDefinition.Validate(); err != nil { + return fmt.Errorf("field 'valueParameterDefinition' is invalid: %w", err) + } + } + if x.ValuePeriod != nil { + if err := x.ValuePeriod.Validate(); err != nil { + return fmt.Errorf("field 'valuePeriod' is invalid: %w", err) + } + } + if x.ValuePositiveInt != nil { + if *x.ValuePositiveInt <= 0.000000 { + return fmt.Errorf("field 'valuePositiveInt' is below exclusive minimum 0.000000") + } + } + if x.ValueQuantity != nil { + if err := x.ValueQuantity.Validate(); err != nil { + return fmt.Errorf("field 'valueQuantity' is invalid: %w", err) + } + } + if x.ValueRange != nil { + if err := x.ValueRange.Validate(); err != nil { + return fmt.Errorf("field 'valueRange' is invalid: %w", err) + } + } + if x.ValueRatio != nil { + if err := x.ValueRatio.Validate(); err != nil { + return fmt.Errorf("field 'valueRatio' is invalid: %w", err) + } + } + if x.ValueRatioRange != nil { + if err := x.ValueRatioRange.Validate(); err != nil { + return fmt.Errorf("field 'valueRatioRange' is invalid: %w", err) + } + } + if x.ValueReference != nil { + if err := x.ValueReference.Validate(); err != nil { + return fmt.Errorf("field 'valueReference' is invalid: %w", err) + } + } + if x.ValueRelatedArtifact != nil { + if err := x.ValueRelatedArtifact.Validate(); err != nil { + return fmt.Errorf("field 'valueRelatedArtifact' is invalid: %w", err) + } + } + if x.ValueSampledData != nil { + if err := x.ValueSampledData.Validate(); err != nil { + return fmt.Errorf("field 'valueSampledData' is invalid: %w", err) + } + } + if x.ValueSignature != nil { + if err := x.ValueSignature.Validate(); err != nil { + return fmt.Errorf("field 'valueSignature' is invalid: %w", err) + } + } + if x.ValueString != nil { + if *x.ValueString == "" { + return fmt.Errorf("field 'valueString' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.ValueTime != nil { + if err := ValidateFhirTime(*x.ValueTime); err != nil { + return fmt.Errorf("field 'valueTime' has invalid time format: %w", err) + } + } + if x.ValueTiming != nil { + if err := x.ValueTiming.Validate(); err != nil { + return fmt.Errorf("field 'valueTiming' is invalid: %w", err) + } + } + if x.ValueTriggerDefinition != nil { + if err := x.ValueTriggerDefinition.Validate(); err != nil { + return fmt.Errorf("field 'valueTriggerDefinition' is invalid: %w", err) + } + } + if x.ValueUnsignedInt != nil { + if *x.ValueUnsignedInt < 0.000000 { + return fmt.Errorf("field 'valueUnsignedInt' is below minimum 0.000000") + } + } + if x.ValueURI != nil { + } + if x.ValueURL != nil { + if utf8.RuneCountInString(*x.ValueURL) < 1 { + return fmt.Errorf("field 'valueUrl' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ValueURL) > 65536 { + return fmt.Errorf("field 'valueUrl' is too long (max 65536 characters)") + } + if err := ValidateFhirURI(*x.ValueURL); err != nil { + return fmt.Errorf("field 'valueUrl' has invalid URI format: %w", err) + } + } + if x.ValueUsageContext != nil { + if err := x.ValueUsageContext.Validate(); err != nil { + return fmt.Errorf("field 'valueUsageContext' is invalid: %w", err) + } + } + if x.ValueUUID != nil { + if err := ValidateFhirUUID(*x.ValueUUID); err != nil { + return fmt.Errorf("field 'valueUuid' has invalid UUID format: %w", err) + } + } + return nil +} + +// Validate validates a TaskOutput struct against its schema constraints. +func (x *TaskOutput) Validate() error { + if x == nil { + return nil + } + if x.XValueBase64Binary != nil { + if err := x.XValueBase64Binary.Validate(); err != nil { + return fmt.Errorf("field '_valueBase64Binary' is invalid: %w", err) + } + } + if x.XValueBoolean != nil { + if err := x.XValueBoolean.Validate(); err != nil { + return fmt.Errorf("field '_valueBoolean' is invalid: %w", err) + } + } + if x.XValueCanonical != nil { + if err := x.XValueCanonical.Validate(); err != nil { + return fmt.Errorf("field '_valueCanonical' is invalid: %w", err) + } + } + if x.XValueCode != nil { + if err := x.XValueCode.Validate(); err != nil { + return fmt.Errorf("field '_valueCode' is invalid: %w", err) + } + } + if x.XValueDate != nil { + if err := x.XValueDate.Validate(); err != nil { + return fmt.Errorf("field '_valueDate' is invalid: %w", err) + } + } + if x.XValueDateTime != nil { + if err := x.XValueDateTime.Validate(); err != nil { + return fmt.Errorf("field '_valueDateTime' is invalid: %w", err) + } + } + if x.XValueDecimal != nil { + if err := x.XValueDecimal.Validate(); err != nil { + return fmt.Errorf("field '_valueDecimal' is invalid: %w", err) + } + } + if x.XValueID != nil { + if err := x.XValueID.Validate(); err != nil { + return fmt.Errorf("field '_valueId' is invalid: %w", err) + } + } + if x.XValueInstant != nil { + if err := x.XValueInstant.Validate(); err != nil { + return fmt.Errorf("field '_valueInstant' is invalid: %w", err) + } + } + if x.XValueInteger != nil { + if err := x.XValueInteger.Validate(); err != nil { + return fmt.Errorf("field '_valueInteger' is invalid: %w", err) + } + } + if x.XValueInteger64 != nil { + if err := x.XValueInteger64.Validate(); err != nil { + return fmt.Errorf("field '_valueInteger64' is invalid: %w", err) + } + } + if x.XValueMarkdown != nil { + if err := x.XValueMarkdown.Validate(); err != nil { + return fmt.Errorf("field '_valueMarkdown' is invalid: %w", err) + } + } + if x.XValueOid != nil { + if err := x.XValueOid.Validate(); err != nil { + return fmt.Errorf("field '_valueOid' is invalid: %w", err) + } + } + if x.XValuePositiveInt != nil { + if err := x.XValuePositiveInt.Validate(); err != nil { + return fmt.Errorf("field '_valuePositiveInt' is invalid: %w", err) + } + } + if x.XValueString != nil { + if err := x.XValueString.Validate(); err != nil { + return fmt.Errorf("field '_valueString' is invalid: %w", err) + } + } + if x.XValueTime != nil { + if err := x.XValueTime.Validate(); err != nil { + return fmt.Errorf("field '_valueTime' is invalid: %w", err) + } + } + if x.XValueUnsignedInt != nil { + if err := x.XValueUnsignedInt.Validate(); err != nil { + return fmt.Errorf("field '_valueUnsignedInt' is invalid: %w", err) + } + } + if x.XValueURI != nil { + if err := x.XValueURI.Validate(); err != nil { + return fmt.Errorf("field '_valueUri' is invalid: %w", err) + } + } + if x.XValueURL != nil { + if err := x.XValueURL.Validate(); err != nil { + return fmt.Errorf("field '_valueUrl' is invalid: %w", err) + } + } + if x.XValueUUID != nil { + if err := x.XValueUUID.Validate(); err != nil { + return fmt.Errorf("field '_valueUuid' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "TaskOutput" { + return fmt.Errorf("field 'resourceType' must be exactly 'TaskOutput'") + } + } + if x.Type == nil { + return fmt.Errorf("required field 'type' is missing") + } + if x.Type != nil { + if err := x.Type.Validate(); err != nil { + return fmt.Errorf("field 'type' is invalid: %w", err) + } + } + if x.ValueAddress != nil { + if err := x.ValueAddress.Validate(); err != nil { + return fmt.Errorf("field 'valueAddress' is invalid: %w", err) + } + } + if x.ValueAge != nil { + if err := x.ValueAge.Validate(); err != nil { + return fmt.Errorf("field 'valueAge' is invalid: %w", err) + } + } + if x.ValueAnnotation != nil { + if err := x.ValueAnnotation.Validate(); err != nil { + return fmt.Errorf("field 'valueAnnotation' is invalid: %w", err) + } + } + if x.ValueAttachment != nil { + if err := x.ValueAttachment.Validate(); err != nil { + return fmt.Errorf("field 'valueAttachment' is invalid: %w", err) + } + } + if x.ValueAvailability != nil { + if err := x.ValueAvailability.Validate(); err != nil { + return fmt.Errorf("field 'valueAvailability' is invalid: %w", err) + } + } + if x.ValueBase64Binary != nil { + if err := ValidateFhirBinary(*x.ValueBase64Binary); err != nil { + return fmt.Errorf("field 'valueBase64Binary' has invalid binary format: %w", err) + } + } + if x.ValueBoolean != nil { + } + if x.ValueCanonical != nil { + } + if x.ValueCode != nil { + if !rx_TaskOutput_ValueCode.MatchString(*x.ValueCode) { + return fmt.Errorf("field 'valueCode' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.ValueCodeableConcept != nil { + if err := x.ValueCodeableConcept.Validate(); err != nil { + return fmt.Errorf("field 'valueCodeableConcept' is invalid: %w", err) + } + } + if x.ValueCodeableReference != nil { + if err := x.ValueCodeableReference.Validate(); err != nil { + return fmt.Errorf("field 'valueCodeableReference' is invalid: %w", err) + } + } + if x.ValueCoding != nil { + if err := x.ValueCoding.Validate(); err != nil { + return fmt.Errorf("field 'valueCoding' is invalid: %w", err) + } + } + if x.ValueContactDetail != nil { + if err := x.ValueContactDetail.Validate(); err != nil { + return fmt.Errorf("field 'valueContactDetail' is invalid: %w", err) + } + } + if x.ValueContactPoint != nil { + if err := x.ValueContactPoint.Validate(); err != nil { + return fmt.Errorf("field 'valueContactPoint' is invalid: %w", err) + } + } + if x.ValueCount != nil { + if err := x.ValueCount.Validate(); err != nil { + return fmt.Errorf("field 'valueCount' is invalid: %w", err) + } + } + if x.ValueDataRequirement != nil { + if err := x.ValueDataRequirement.Validate(); err != nil { + return fmt.Errorf("field 'valueDataRequirement' is invalid: %w", err) + } + } + if x.ValueDate != nil { + if err := ValidateFhirDate(*x.ValueDate); err != nil { + return fmt.Errorf("field 'valueDate' has invalid date format: %w", err) + } + } + if x.ValueDateTime != nil { + if err := ValidateFhirDateTime(*x.ValueDateTime); err != nil { + return fmt.Errorf("field 'valueDateTime' has invalid date-time format: %w", err) + } + } + if x.ValueDecimal != nil { + } + if x.ValueDistance != nil { + if err := x.ValueDistance.Validate(); err != nil { + return fmt.Errorf("field 'valueDistance' is invalid: %w", err) + } + } + if x.ValueDosage != nil { + if err := x.ValueDosage.Validate(); err != nil { + return fmt.Errorf("field 'valueDosage' is invalid: %w", err) + } + } + if x.ValueDuration != nil { + if err := x.ValueDuration.Validate(); err != nil { + return fmt.Errorf("field 'valueDuration' is invalid: %w", err) + } + } + if x.ValueExpression != nil { + if err := x.ValueExpression.Validate(); err != nil { + return fmt.Errorf("field 'valueExpression' is invalid: %w", err) + } + } + if x.ValueExtendedContactDetail != nil { + if err := x.ValueExtendedContactDetail.Validate(); err != nil { + return fmt.Errorf("field 'valueExtendedContactDetail' is invalid: %w", err) + } + } + if x.ValueHumanName != nil { + if err := x.ValueHumanName.Validate(); err != nil { + return fmt.Errorf("field 'valueHumanName' is invalid: %w", err) + } + } + if x.ValueID != nil { + if !rx_TaskOutput_ValueID.MatchString(*x.ValueID) { + return fmt.Errorf("field 'valueId' does not match pattern '^[A-Za-z0-9\\-.]+$'") + } + if utf8.RuneCountInString(*x.ValueID) < 1 { + return fmt.Errorf("field 'valueId' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ValueID) > 64 { + return fmt.Errorf("field 'valueId' is too long (max 64 characters)") + } + } + if x.ValueIDentifier != nil { + if err := x.ValueIDentifier.Validate(); err != nil { + return fmt.Errorf("field 'valueIdentifier' is invalid: %w", err) + } + } + if x.ValueInstant != nil { + if err := ValidateFhirDateTime(*x.ValueInstant); err != nil { + return fmt.Errorf("field 'valueInstant' has invalid date-time format: %w", err) + } + } + if x.ValueInteger != nil { + } + if x.ValueInteger64 != nil { + } + if x.ValueMarkdown != nil { + if !rx_TaskOutput_ValueMarkdown.MatchString(*x.ValueMarkdown) { + return fmt.Errorf("field 'valueMarkdown' does not match pattern '\\s*(\\S|\\s)*'") + } + } + if x.ValueMeta != nil { + if err := x.ValueMeta.Validate(); err != nil { + return fmt.Errorf("field 'valueMeta' is invalid: %w", err) + } + } + if x.ValueMoney != nil { + if err := x.ValueMoney.Validate(); err != nil { + return fmt.Errorf("field 'valueMoney' is invalid: %w", err) + } + } + if x.ValueOid != nil { + if !rx_TaskOutput_ValueOid.MatchString(*x.ValueOid) { + return fmt.Errorf("field 'valueOid' does not match pattern '^urn:oid:[0-2](\\.(0|[1-9][0-9]*))+$'") + } + } + if x.ValueParameterDefinition != nil { + if err := x.ValueParameterDefinition.Validate(); err != nil { + return fmt.Errorf("field 'valueParameterDefinition' is invalid: %w", err) + } + } + if x.ValuePeriod != nil { + if err := x.ValuePeriod.Validate(); err != nil { + return fmt.Errorf("field 'valuePeriod' is invalid: %w", err) + } + } + if x.ValuePositiveInt != nil { + if *x.ValuePositiveInt <= 0.000000 { + return fmt.Errorf("field 'valuePositiveInt' is below exclusive minimum 0.000000") + } + } + if x.ValueQuantity != nil { + if err := x.ValueQuantity.Validate(); err != nil { + return fmt.Errorf("field 'valueQuantity' is invalid: %w", err) + } + } + if x.ValueRange != nil { + if err := x.ValueRange.Validate(); err != nil { + return fmt.Errorf("field 'valueRange' is invalid: %w", err) + } + } + if x.ValueRatio != nil { + if err := x.ValueRatio.Validate(); err != nil { + return fmt.Errorf("field 'valueRatio' is invalid: %w", err) + } + } + if x.ValueRatioRange != nil { + if err := x.ValueRatioRange.Validate(); err != nil { + return fmt.Errorf("field 'valueRatioRange' is invalid: %w", err) + } + } + if x.ValueReference != nil { + if err := x.ValueReference.Validate(); err != nil { + return fmt.Errorf("field 'valueReference' is invalid: %w", err) + } + } + if x.ValueRelatedArtifact != nil { + if err := x.ValueRelatedArtifact.Validate(); err != nil { + return fmt.Errorf("field 'valueRelatedArtifact' is invalid: %w", err) + } + } + if x.ValueSampledData != nil { + if err := x.ValueSampledData.Validate(); err != nil { + return fmt.Errorf("field 'valueSampledData' is invalid: %w", err) + } + } + if x.ValueSignature != nil { + if err := x.ValueSignature.Validate(); err != nil { + return fmt.Errorf("field 'valueSignature' is invalid: %w", err) + } + } + if x.ValueString != nil { + if *x.ValueString == "" { + return fmt.Errorf("field 'valueString' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.ValueTime != nil { + if err := ValidateFhirTime(*x.ValueTime); err != nil { + return fmt.Errorf("field 'valueTime' has invalid time format: %w", err) + } + } + if x.ValueTiming != nil { + if err := x.ValueTiming.Validate(); err != nil { + return fmt.Errorf("field 'valueTiming' is invalid: %w", err) + } + } + if x.ValueTriggerDefinition != nil { + if err := x.ValueTriggerDefinition.Validate(); err != nil { + return fmt.Errorf("field 'valueTriggerDefinition' is invalid: %w", err) + } + } + if x.ValueUnsignedInt != nil { + if *x.ValueUnsignedInt < 0.000000 { + return fmt.Errorf("field 'valueUnsignedInt' is below minimum 0.000000") + } + } + if x.ValueURI != nil { + } + if x.ValueURL != nil { + if utf8.RuneCountInString(*x.ValueURL) < 1 { + return fmt.Errorf("field 'valueUrl' is too short (min 1 characters)") + } + if utf8.RuneCountInString(*x.ValueURL) > 65536 { + return fmt.Errorf("field 'valueUrl' is too long (max 65536 characters)") + } + if err := ValidateFhirURI(*x.ValueURL); err != nil { + return fmt.Errorf("field 'valueUrl' has invalid URI format: %w", err) + } + } + if x.ValueUsageContext != nil { + if err := x.ValueUsageContext.Validate(); err != nil { + return fmt.Errorf("field 'valueUsageContext' is invalid: %w", err) + } + } + if x.ValueUUID != nil { + if err := ValidateFhirUUID(*x.ValueUUID); err != nil { + return fmt.Errorf("field 'valueUuid' has invalid UUID format: %w", err) + } + } + return nil +} + +// Validate validates a TaskPerformer struct against its schema constraints. +func (x *TaskPerformer) Validate() error { + if x == nil { + return nil + } + if x.Actor == nil { + return fmt.Errorf("required field 'actor' is missing") + } + if x.Actor != nil { + if err := x.Actor.Validate(); err != nil { + return fmt.Errorf("field 'actor' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Function != nil { + if err := x.Function.Validate(); err != nil { + return fmt.Errorf("field 'function' is invalid: %w", err) + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ResourceType != nil { + if *x.ResourceType != "TaskPerformer" { + return fmt.Errorf("field 'resourceType' must be exactly 'TaskPerformer'") + } + } + return nil +} + +// Validate validates a TaskRestriction struct against its schema constraints. +func (x *TaskRestriction) Validate() error { + if x == nil { + return nil + } + if x.XRepetitions != nil { + if err := x.XRepetitions.Validate(); err != nil { + return fmt.Errorf("field '_repetitions' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Period != nil { + if err := x.Period.Validate(); err != nil { + return fmt.Errorf("field 'period' is invalid: %w", err) + } + } + if x.Recipient != nil { + for i, item := range x.Recipient { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'recipient[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Repetitions != nil { + if *x.Repetitions <= 0.000000 { + return fmt.Errorf("field 'repetitions' is below exclusive minimum 0.000000") + } + } + if x.ResourceType != nil { + if *x.ResourceType != "TaskRestriction" { + return fmt.Errorf("field 'resourceType' must be exactly 'TaskRestriction'") + } + } + return nil +} + +// Validate validates a Timing struct against its schema constraints. +func (x *Timing) Validate() error { + if x == nil { + return nil + } + if x.XEvent != nil { + for i, item := range x.XEvent { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field '_event[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Code != nil { + if err := x.Code.Validate(); err != nil { + return fmt.Errorf("field 'code' is invalid: %w", err) + } + } + if x.Event != nil { + for i, item := range x.Event { + if err := ValidateFhirDateTime(item); err != nil { + return fmt.Errorf("field 'event[%d]' has invalid date-time format: %w", i, err) + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ModifierExtension != nil { + for i, item := range x.ModifierExtension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'modifierExtension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Repeat != nil { + if err := x.Repeat.Validate(); err != nil { + return fmt.Errorf("field 'repeat' is invalid: %w", err) + } + } + if x.ResourceType != nil { + if *x.ResourceType != "Timing" { + return fmt.Errorf("field 'resourceType' must be exactly 'Timing'") + } + } + return nil +} + +// Validate validates a TimingRepeat struct against its schema constraints. +func (x *TimingRepeat) Validate() error { + if x == nil { + return nil + } + if x.XCount != nil { + if err := x.XCount.Validate(); err != nil { + return fmt.Errorf("field '_count' is invalid: %w", err) + } + } + if x.XCountMax != nil { + if err := x.XCountMax.Validate(); err != nil { + return fmt.Errorf("field '_countMax' is invalid: %w", err) + } + } + if x.XDayOfWeek != nil { + for i, item := range x.XDayOfWeek { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field '_dayOfWeek[%d]' is invalid: %w", i, err) + } + } + } + } + if x.XDuration != nil { + if err := x.XDuration.Validate(); err != nil { + return fmt.Errorf("field '_duration' is invalid: %w", err) + } + } + if x.XDurationMax != nil { + if err := x.XDurationMax.Validate(); err != nil { + return fmt.Errorf("field '_durationMax' is invalid: %w", err) + } + } + if x.XDurationUnit != nil { + if err := x.XDurationUnit.Validate(); err != nil { + return fmt.Errorf("field '_durationUnit' is invalid: %w", err) + } + } + if x.XFrequency != nil { + if err := x.XFrequency.Validate(); err != nil { + return fmt.Errorf("field '_frequency' is invalid: %w", err) + } + } + if x.XFrequencyMax != nil { + if err := x.XFrequencyMax.Validate(); err != nil { + return fmt.Errorf("field '_frequencyMax' is invalid: %w", err) + } + } + if x.XOffset != nil { + if err := x.XOffset.Validate(); err != nil { + return fmt.Errorf("field '_offset' is invalid: %w", err) + } + } + if x.XPeriod != nil { + if err := x.XPeriod.Validate(); err != nil { + return fmt.Errorf("field '_period' is invalid: %w", err) + } + } + if x.XPeriodMax != nil { + if err := x.XPeriodMax.Validate(); err != nil { + return fmt.Errorf("field '_periodMax' is invalid: %w", err) + } + } + if x.XPeriodUnit != nil { + if err := x.XPeriodUnit.Validate(); err != nil { + return fmt.Errorf("field '_periodUnit' is invalid: %w", err) + } + } + if x.XTimeOfDay != nil { + for i, item := range x.XTimeOfDay { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field '_timeOfDay[%d]' is invalid: %w", i, err) + } + } + } + } + if x.XWhen != nil { + for i, item := range x.XWhen { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field '_when[%d]' is invalid: %w", i, err) + } + } + } + } + if x.BoundsDuration != nil { + if err := x.BoundsDuration.Validate(); err != nil { + return fmt.Errorf("field 'boundsDuration' is invalid: %w", err) + } + } + if x.BoundsPeriod != nil { + if err := x.BoundsPeriod.Validate(); err != nil { + return fmt.Errorf("field 'boundsPeriod' is invalid: %w", err) + } + } + if x.BoundsRange != nil { + if err := x.BoundsRange.Validate(); err != nil { + return fmt.Errorf("field 'boundsRange' is invalid: %w", err) + } + } + if x.Count != nil { + if *x.Count <= 0.000000 { + return fmt.Errorf("field 'count' is below exclusive minimum 0.000000") + } + } + if x.CountMax != nil { + if *x.CountMax <= 0.000000 { + return fmt.Errorf("field 'countMax' is below exclusive minimum 0.000000") + } + } + if x.DayOfWeek != nil { + for i, item := range x.DayOfWeek { + if !rx_TimingRepeat_DayOfWeek_items.MatchString(item) { + return fmt.Errorf("field 'dayOfWeek[%d]' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'", i) + } + } + } + if x.Duration != nil { + } + if x.DurationMax != nil { + } + if x.DurationUnit != nil { + if !rx_TimingRepeat_DurationUnit.MatchString(*x.DurationUnit) { + return fmt.Errorf("field 'durationUnit' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Frequency != nil { + if *x.Frequency <= 0.000000 { + return fmt.Errorf("field 'frequency' is below exclusive minimum 0.000000") + } + } + if x.FrequencyMax != nil { + if *x.FrequencyMax <= 0.000000 { + return fmt.Errorf("field 'frequencyMax' is below exclusive minimum 0.000000") + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Offset != nil { + if *x.Offset < 0.000000 { + return fmt.Errorf("field 'offset' is below minimum 0.000000") + } + } + if x.Period != nil { + } + if x.PeriodMax != nil { + } + if x.PeriodUnit != nil { + if !rx_TimingRepeat_PeriodUnit.MatchString(*x.PeriodUnit) { + return fmt.Errorf("field 'periodUnit' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + if x.ResourceType != nil { + if *x.ResourceType != "TimingRepeat" { + return fmt.Errorf("field 'resourceType' must be exactly 'TimingRepeat'") + } + } + if x.TimeOfDay != nil { + for i, item := range x.TimeOfDay { + if err := ValidateFhirTime(item); err != nil { + return fmt.Errorf("field 'timeOfDay[%d]' has invalid time format: %w", i, err) + } + } + } + if x.When != nil { + for i, item := range x.When { + if !rx_TimingRepeat_When_items.MatchString(item) { + return fmt.Errorf("field 'when[%d]' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'", i) + } + } + } + return nil +} + +// Validate validates a TriggerDefinition struct against its schema constraints. +func (x *TriggerDefinition) Validate() error { + if x == nil { + return nil + } + if x.XName != nil { + if err := x.XName.Validate(); err != nil { + return fmt.Errorf("field '_name' is invalid: %w", err) + } + } + if x.XSubscriptionTopic != nil { + if err := x.XSubscriptionTopic.Validate(); err != nil { + return fmt.Errorf("field '_subscriptionTopic' is invalid: %w", err) + } + } + if x.XTimingDate != nil { + if err := x.XTimingDate.Validate(); err != nil { + return fmt.Errorf("field '_timingDate' is invalid: %w", err) + } + } + if x.XTimingDateTime != nil { + if err := x.XTimingDateTime.Validate(); err != nil { + return fmt.Errorf("field '_timingDateTime' is invalid: %w", err) + } + } + if x.XType != nil { + if err := x.XType.Validate(); err != nil { + return fmt.Errorf("field '_type' is invalid: %w", err) + } + } + if x.Code != nil { + if err := x.Code.Validate(); err != nil { + return fmt.Errorf("field 'code' is invalid: %w", err) + } + } + if x.Condition != nil { + if err := x.Condition.Validate(); err != nil { + return fmt.Errorf("field 'condition' is invalid: %w", err) + } + } + if x.Data != nil { + for i, item := range x.Data { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'data[%d]' is invalid: %w", i, err) + } + } + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.Name != nil { + if *x.Name == "" { + return fmt.Errorf("field 'name' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.ResourceType != nil { + if *x.ResourceType != "TriggerDefinition" { + return fmt.Errorf("field 'resourceType' must be exactly 'TriggerDefinition'") + } + } + if x.SubscriptionTopic != nil { + } + if x.TimingDate != nil { + if err := ValidateFhirDate(*x.TimingDate); err != nil { + return fmt.Errorf("field 'timingDate' has invalid date format: %w", err) + } + } + if x.TimingDateTime != nil { + if err := ValidateFhirDateTime(*x.TimingDateTime); err != nil { + return fmt.Errorf("field 'timingDateTime' has invalid date-time format: %w", err) + } + } + if x.TimingReference != nil { + if err := x.TimingReference.Validate(); err != nil { + return fmt.Errorf("field 'timingReference' is invalid: %w", err) + } + } + if x.TimingTiming != nil { + if err := x.TimingTiming.Validate(); err != nil { + return fmt.Errorf("field 'timingTiming' is invalid: %w", err) + } + } + if x.Type != nil { + if !rx_TriggerDefinition_Type.MatchString(*x.Type) { + return fmt.Errorf("field 'type' does not match pattern '^[^\\s]+(\\s[^\\s]+)*$'") + } + } + return nil +} + +// Validate validates a UsageContext struct against its schema constraints. +func (x *UsageContext) Validate() error { + if x == nil { + return nil + } + if x.Code == nil { + return fmt.Errorf("required field 'code' is missing") + } + if x.Code != nil { + if err := x.Code.Validate(); err != nil { + return fmt.Errorf("field 'code' is invalid: %w", err) + } + } + if x.Extension != nil { + for i, item := range x.Extension { + if item != nil { + if err := item.Validate(); err != nil { + return fmt.Errorf("field 'extension[%d]' is invalid: %w", i, err) + } + } + } + } + if x.ID != nil { + if *x.ID == "" { + return fmt.Errorf("field 'id' does not match pattern '[ \\r\\n\\t\\S]+'") + } + } + if x.Links != nil { + } + if x.ResourceType != nil { + if *x.ResourceType != "UsageContext" { + return fmt.Errorf("field 'resourceType' must be exactly 'UsageContext'") + } + } + if x.ValueCodeableConcept != nil { + if err := x.ValueCodeableConcept.Validate(); err != nil { + return fmt.Errorf("field 'valueCodeableConcept' is invalid: %w", err) + } + } + if x.ValueQuantity != nil { + if err := x.ValueQuantity.Validate(); err != nil { + return fmt.Errorf("field 'valueQuantity' is invalid: %w", err) + } + } + if x.ValueRange != nil { + if err := x.ValueRange.Validate(); err != nil { + return fmt.Errorf("field 'valueRange' is invalid: %w", err) + } + } + if x.ValueReference != nil { + if err := x.ValueReference.Validate(); err != nil { + return fmt.Errorf("field 'valueReference' is invalid: %w", err) + } + } + return nil +} From 4640060b12648dd9a1ed6257620c04c46247913e Mon Sep 17 00:00:00 2001 From: matthewpeterkort Date: Sun, 12 Jul 2026 21:02:28 -0700 Subject: [PATCH 05/15] optimize compiler to generate faster AQL --- Makefile | 10 +- README.md | 1 + cmd/arango-fhir-proto/main.go | 25 + cmd/dataframe-profile/main.go | 233 ++++ conformance/compiler/policy_ablation_test.go | 545 ++++++++ docs/AQL_EXECUTION_IMPLEMENTATION_AUDIT.md | 242 ++++ docs/AQL_OPTIMIZATION_WORKLIST.md | 9 +- docs/LUNA_AQL_EXECUTION_ROUND_3.md | 683 ++++++++++ docs/LUNA_AQL_OPTIMIZATION_ROUND_2.md | 342 +++++ docs/LUNA_AQL_RUNTIME_ROUND_4.md | 676 ++++++++++ docs/LUNA_FRONTEND_ENABLEMENT_PART_5.md | 1103 +++++++++++++++++ .../LUNA_FRONTEND_ENABLEMENT_PART_5_PHASE0.md | 30 + graphqlapi/dataframe/datasets.go | 138 +++ graphqlapi/dataframe/datasets_test.go | 110 ++ graphqlapi/dataframe/service.go | 31 +- graphqlapi/dataframe/templates.go | 243 ++++ graphqlapi/dataframe/templates_test.go | 93 ++ graphqlapi/dataframe/types.go | 17 + graphqlapi/dataframe/validation.go | 98 ++ graphqlapi/dataframe/validation_test.go | 80 ++ graphqlapi/errors.go | 56 + graphqlapi/errors_test.go | 59 + internal/catalog/generation_test.go | 25 +- internal/catalog/read_datasets.go | 174 +++ internal/catalog/read_datasets_test.go | 99 ++ internal/catalog/read_references.go | 81 +- internal/catalog/rebuild.go | 142 +++ internal/catalog/relationships.go | 101 ++ internal/catalog/relationships_test.go | 54 + internal/catalog/types.go | 86 +- internal/catalog/write_persist.go | 76 ++ .../compact_batch_tournament_test.go | 205 +++ .../compact_summary_experiment_test.go | 325 +++++ internal/dataframe/compile.go | 11 +- ...endpoint_selector_combo_experiment_test.go | 376 ++++++ .../endpoint_strategy_experiment_test.go | 642 ++++++++++ .../endpoint_strategy_integration_test.go | 172 +++ internal/dataframe/errors.go | 380 ++++++ internal/dataframe/errors_test.go | 134 ++ .../dataframe/full_batch_tournament_test.go | 265 ++++ .../full_identity_tournament_test.go | 263 ++++ internal/dataframe/generic_physical_plan.go | 221 +++- .../dataframe/generic_physical_plan_test.go | 19 +- .../identity_order_experiment_test.go | 308 +++++ .../materialization_tournament_test.go | 201 +++ internal/dataframe/physical_cost.go | 126 +- internal/dataframe/physical_diagnostics.go | 144 ++- .../dataframe/physical_diagnostics_test.go | 49 + internal/dataframe/physical_helpers.go | 47 + internal/dataframe/physical_lowering.go | 10 +- internal/dataframe/physical_optimize.go | 38 +- internal/dataframe/physical_optimize_test.go | 152 ++- internal/dataframe/physical_plan.go | 151 ++- internal/dataframe/physical_render.go | 248 +++- internal/dataframe/physical_render_test.go | 18 +- .../root_endpoint_experiment_test.go | 274 ++++ .../dataframe/root_endpoint_live_gate_test.go | 214 ++++ ...root_endpoint_strategy_integration_test.go | 68 + internal/dataframe/selection_semantics.go | 25 + .../selector_expression_experiment_test.go | 665 ++++++++++ internal/dataframe/selector_mode_test.go | 96 ++ internal/dataframe/selector_render.go | 9 + internal/dataframe/service.go | 18 +- internal/dataframe/storage_route.go | 15 + .../summary_pushdown_experiment_test.go | 262 ++++ internal/dataframe/template/availability.go | 213 ++++ .../dataframe/template/availability_test.go | 66 + internal/dataframe/template/registry.go | 230 ++++ internal/dataframe/template/registry_test.go | 76 ++ internal/dataframe/template/types.go | 233 ++++ internal/dataframe/tournament_pivot_test.go | 409 ++++++ .../dataframe/tournament_sort_order_test.go | 192 +++ .../traversal_projection_experiment_test.go | 629 ++++++++++ internal/dataframe/validation_service.go | 130 ++ internal/dataframe/validation_service_test.go | 102 ++ internal/httpapi/errors.go | 98 ++ internal/httpapi/errors_test.go | 61 + internal/ingest/backend.go | 13 +- internal/ingest/backend_test.go | 14 + internal/ingest/generation_load.go | 68 +- internal/ingest/load.go | 36 +- .../store/arango/profile_integration_test.go | 112 ++ 82 files changed, 14351 insertions(+), 144 deletions(-) create mode 100644 cmd/dataframe-profile/main.go create mode 100644 conformance/compiler/policy_ablation_test.go create mode 100644 docs/AQL_EXECUTION_IMPLEMENTATION_AUDIT.md create mode 100644 docs/LUNA_AQL_EXECUTION_ROUND_3.md create mode 100644 docs/LUNA_AQL_OPTIMIZATION_ROUND_2.md create mode 100644 docs/LUNA_AQL_RUNTIME_ROUND_4.md create mode 100644 docs/LUNA_FRONTEND_ENABLEMENT_PART_5.md create mode 100644 docs/LUNA_FRONTEND_ENABLEMENT_PART_5_PHASE0.md create mode 100644 graphqlapi/dataframe/datasets.go create mode 100644 graphqlapi/dataframe/datasets_test.go create mode 100644 graphqlapi/dataframe/templates.go create mode 100644 graphqlapi/dataframe/templates_test.go create mode 100644 graphqlapi/dataframe/validation.go create mode 100644 graphqlapi/dataframe/validation_test.go create mode 100644 graphqlapi/errors.go create mode 100644 graphqlapi/errors_test.go create mode 100644 internal/catalog/read_datasets.go create mode 100644 internal/catalog/read_datasets_test.go create mode 100644 internal/catalog/rebuild.go create mode 100644 internal/catalog/relationships.go create mode 100644 internal/catalog/relationships_test.go create mode 100644 internal/dataframe/compact_batch_tournament_test.go create mode 100644 internal/dataframe/compact_summary_experiment_test.go create mode 100644 internal/dataframe/endpoint_selector_combo_experiment_test.go create mode 100644 internal/dataframe/endpoint_strategy_experiment_test.go create mode 100644 internal/dataframe/endpoint_strategy_integration_test.go create mode 100644 internal/dataframe/errors.go create mode 100644 internal/dataframe/errors_test.go create mode 100644 internal/dataframe/full_batch_tournament_test.go create mode 100644 internal/dataframe/full_identity_tournament_test.go create mode 100644 internal/dataframe/identity_order_experiment_test.go create mode 100644 internal/dataframe/materialization_tournament_test.go create mode 100644 internal/dataframe/physical_diagnostics_test.go create mode 100644 internal/dataframe/root_endpoint_experiment_test.go create mode 100644 internal/dataframe/root_endpoint_live_gate_test.go create mode 100644 internal/dataframe/root_endpoint_strategy_integration_test.go create mode 100644 internal/dataframe/selector_expression_experiment_test.go create mode 100644 internal/dataframe/selector_mode_test.go create mode 100644 internal/dataframe/summary_pushdown_experiment_test.go create mode 100644 internal/dataframe/template/availability.go create mode 100644 internal/dataframe/template/availability_test.go create mode 100644 internal/dataframe/template/registry.go create mode 100644 internal/dataframe/template/registry_test.go create mode 100644 internal/dataframe/template/types.go create mode 100644 internal/dataframe/tournament_pivot_test.go create mode 100644 internal/dataframe/tournament_sort_order_test.go create mode 100644 internal/dataframe/traversal_projection_experiment_test.go create mode 100644 internal/dataframe/validation_service.go create mode 100644 internal/dataframe/validation_service_test.go create mode 100644 internal/httpapi/errors.go create mode 100644 internal/httpapi/errors_test.go diff --git a/Makefile b/Makefile index 11019e1..dd139d9 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: build build-cli build-server clean compiler-bench compiler-arango-bench dataframe-demo conformance generate-fhir generate-graphql graphql-check gqlgen-check test docker-build docker-run +.PHONY: build build-cli build-server clean compiler-bench compiler-arango-bench dataframe-demo dataframe-profile conformance generate-fhir generate-graphql graphql-check gqlgen-check test docker-build docker-run GO ?= go GOCACHE_DIR ?= $(CURDIR)/.gocache @@ -14,6 +14,8 @@ DATAFRAME_TIMEOUT ?= 5m DATAFRAME_PRINT_RESPONSE ?= false DATAFRAME_QUERY ?= examples/meta_gdc_case_matrix.graphql DATAFRAME_VARIABLES ?= examples/meta_gdc_case_matrix.variables.json +DATAFRAME_PROFILE_VARIABLES ?= examples/meta_gdc_case_matrix.variables.json +DATAFRAME_PROFILE_LIMIT ?= 1000 build: build-cli build-server @@ -66,6 +68,12 @@ dataframe-demo: mkdir -p $(GOCACHE_DIR) GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) run ./cmd/dataframe-query -url $(GRAPHQL_URL) -query $(DATAFRAME_QUERY) -variables $(DATAFRAME_VARIABLES) -repeat $(DATAFRAME_REPEAT) -limit $(DATAFRAME_LIMIT) -timeout $(DATAFRAME_TIMEOUT) -print-response=$(DATAFRAME_PRINT_RESPONSE) +# Requires a loaded META fixture database. Compiles the checked-in GDC fixture, +# writes exact rendered AQL, then runs Arango EXPLAIN and PROFILE 2. +dataframe-profile: + mkdir -p $(GOCACHE_DIR) + GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) run ./cmd/dataframe-profile -variables $(DATAFRAME_PROFILE_VARIABLES) -limit $(DATAFRAME_PROFILE_LIMIT) + conformance: mkdir -p $(GOCACHE_DIR) GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) test $(GOFLAGS) ./conformance/... -count=1 diff --git a/README.md b/README.md index 4aee411..973ffee 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ directory contains the local Arango compose setup. - [Luna Rich Physical Renderer Execution Plan](docs/LUNA_RICH_PHYSICAL_RENDERER_EXECUTION.md) - [Luna Compiler Finalization Plan](docs/LUNA_COMPILER_FINALIZATION_PLAN.md) - [Terra Ultra Parallel Execution Plan](docs/TERRA_ULTRA_EXECUTION_PLAN.md) +- [Part 5 Luna Frontend Enablement Plan](docs/LUNA_FRONTEND_ENABLEMENT_PART_5.md) ## Current Layout diff --git a/cmd/arango-fhir-proto/main.go b/cmd/arango-fhir-proto/main.go index 0a9f526..df90e2c 100644 --- a/cmd/arango-fhir-proto/main.go +++ b/cmd/arango-fhir-proto/main.go @@ -39,6 +39,8 @@ func main() { err = runDiscoverPopulatedReferences(ctx, os.Args[2:]) case "discover-populated-fields": err = runDiscoverPopulatedFields(ctx, os.Args[2:]) + case "rebuild-relationship-catalog": + err = runRebuildRelationshipCatalog(ctx, os.Args[2:]) default: usage() os.Exit(2) @@ -179,6 +181,26 @@ func runDiscoverPopulatedFields(ctx context.Context, args []string) error { return printJSON(results) } +func runRebuildRelationshipCatalog(ctx context.Context, args []string) error { + fs := flag.NewFlagSet("rebuild-relationship-catalog", flag.ExitOnError) + opts := catalog.RelationshipRebuildOptions{} + fs.StringVar(&opts.URL, "url", defaultURL, "Backend base URL") + fs.StringVar(&opts.Database, "database", defaultDatabase, "Arango database") + fs.StringVar(&opts.Project, "project", defaultProject, "Project label") + fs.StringVar(&opts.DatasetGeneration, "dataset-generation", "", "Optional generation; empty selects the legacy namespace") + fs.StringVar(&opts.WriteAPI, "write-api", "import", "Bulk write API: import or document") + fs.IntVar(&opts.CursorBatch, "cursor-batch-size", 1000, "Query cursor batch size") + fs.IntVar(&opts.BatchSize, "batch-size", 1000, "Catalog write batch size") + if err := fs.Parse(args); err != nil { + return err + } + summary, err := catalog.RebuildRelationshipCatalog(ctx, opts) + if err != nil { + return err + } + return printJSON(summary) +} + func parseDiscoverPopulatedReferenceOptions(args []string, errorHandling flag.ErrorHandling) (catalog.PopulatedReferenceOptions, error) { fs := flag.NewFlagSet("discover-populated-references", errorHandling) opts := catalog.PopulatedReferenceOptions{} @@ -187,6 +209,8 @@ func parseDiscoverPopulatedReferenceOptions(args []string, errorHandling flag.Er fs.StringVar(&opts.Project, "project", defaultProject, "Project label") fs.StringVar(&opts.DatasetGeneration, "dataset-generation", "", "Optional generation to inspect; empty selects the legacy namespace and never resolves an active generation") fs.StringVar(&opts.FromType, "from-type", "", "Optional source collection/resource type filter, for example Patient") + fs.StringVar(&opts.NodeType, "node-type", "", "Optional builder node/resource type filter, for example Patient") + fs.StringVar(&opts.Mode, "mode", catalog.TraversalModeStorage, "Traversal discovery mode: storage or builder") fs.IntVar(&opts.CursorBatch, "cursor-batch-size", 1000, "Query cursor batch size") if err := fs.Parse(args); err != nil { return catalog.PopulatedReferenceOptions{}, err @@ -225,6 +249,7 @@ func usage() { arango-fhir-proto load-generation --generation OPAQUE_ID [flags] # immutable complete META directory; no --truncate flag arango-fhir-proto discover-populated-references [flags] arango-fhir-proto discover-populated-fields [flags] + arango-fhir-proto rebuild-relationship-catalog [flags] # explicit fhir_edge repair/backfill `) } diff --git a/cmd/dataframe-profile/main.go b/cmd/dataframe-profile/main.go new file mode 100644 index 0000000..19153ab --- /dev/null +++ b/cmd/dataframe-profile/main.go @@ -0,0 +1,233 @@ +// dataframe-profile compiles one checked-in dataframe fixture and profiles +// the exact rendered AQL directly against ArangoDB. It is intentionally a +// diagnostic command: normal GraphQL execution never enables PROFILE. +package main + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "flag" + "fmt" + "os" + "path/filepath" + "time" + + compilerfixture "github.com/calypr/loom/conformance/compiler" + dataframeapi "github.com/calypr/loom/graphqlapi/dataframe" + "github.com/calypr/loom/graphqlapi/model" + "github.com/calypr/loom/internal/dataframe" + arangostore "github.com/calypr/loom/internal/store/arango" +) + +type profileReport struct { + Fixture string `json:"fixture"` + AQLSHA256 string `json:"aql_sha256"` + ResultSHA256 string `json:"result_sha256,omitempty"` + BindVars map[string]any `json:"bind_vars"` + Rows int `json:"rows"` + Explain explainReport `json:"explain"` + Profile profileReportDetails `json:"profile"` + PlanDiagnostics dataframe.CompilerPlanDiagnostics `json:"plan_diagnostics"` + AQLPath string `json:"aql_path"` + ProfilePath string `json:"profile_path,omitempty"` + ProfileWallSeconds float64 `json:"profile_wall_seconds"` +} + +type explainReport struct { + Plans []arangostore.ExplainPlanEstimate `json:"plans"` + FullCollectionScans []arangostore.ExplainCollectionScan `json:"full_collection_scans"` + Indexes []arangostore.ExplainIndexSummary `json:"indexes"` + OptimizerRules []string `json:"optimizer_rules"` + Warnings []arangostore.ExplainWarning `json:"warnings"` +} + +type profileReportDetails struct { + RuntimeSeconds float64 `json:"runtime_seconds_sum_of_nodes"` + ScannedFull int `json:"scanned_full"` + ScannedIndex int `json:"scanned_index"` + PeakMemory uint64 `json:"peak_memory_bytes"` + Phases arangostore.ProfilePhases `json:"phases"` + ByType []arangostore.ProfileNodeGroup `json:"by_node_type"` + TraversalNodes []arangostore.ProfileNodeSummary `json:"traversal_nodes"` + EnumerateListNodes []arangostore.ProfileNodeSummary `json:"enumerate_list_nodes"` + TopNodes []arangostore.ProfileNodeSummary `json:"top_nodes"` +} + +func main() { + var ( + fixtureDir = flag.String("fixtures", "conformance/compiler/fixtures", "compiler fixture directory") + fixtureID = flag.String("fixture", "gdc-case-matrix", "fixture ID to compile") + variables = flag.String("variables", "", "GraphQL variables JSON; when set, compile its input instead of the fixture builder") + limit = flag.Int("limit", 1000, "root row limit") + url = flag.String("url", "http://127.0.0.1:8529", "ArangoDB URL") + database = flag.String("database", "fhir_proto", "ArangoDB database") + aqlPath = flag.String("aql-out", "", "write exact rendered AQL to this path (default: -.aql)") + reportPath = flag.String("report-out", "", "write JSON profile report to this path") + profile = flag.Int("profile", 2, "Arango profile level") + batchSize = flag.Int("batch-size", 10000, "Arango profile cursor batch size") + ) + flag.Parse() + if *limit <= 0 { + fatalf("limit must be positive") + } + if *profile < 1 || *profile > 2 { + fatalf("profile must be 1 or 2") + } + + var ( + fixture compilerfixture.Fixture + builder dataframe.Builder + label = *fixtureID + ) + if *variables != "" { + data, err := os.ReadFile(*variables) + if err != nil { + fatalf("read variables %q: %v", *variables, err) + } + var payload struct { + Input model.FhirDataframeInput `json:"input"` + } + if err := json.Unmarshal(data, &payload); err != nil { + fatalf("decode GraphQL variables %q: %v", *variables, err) + } + if payload.Input.Project == "" || payload.Input.RootResourceType == "" { + fatalf("GraphQL variables %q do not contain a complete input", *variables) + } + builder = dataframeapi.BuilderFromInput(payload.Input) + label = filepath.Base(*variables) + } else { + fixtures, err := compilerfixture.LoadDir(*fixtureDir) + if err != nil { + fatalf("load fixtures: %v", err) + } + for _, candidate := range fixtures { + if candidate.ID == *fixtureID { + fixture = candidate + break + } + } + if fixture.ID == "" { + fatalf("fixture %q not found in %s", *fixtureID, *fixtureDir) + } + builder = fixture.Builder + } + compiled, err := dataframe.CompileRequest(builder, *limit) + if err != nil { + fatalf("compile GDC request %q: %v", label, err) + } + hash := sha256.Sum256([]byte(compiled.Query)) + aqlHash := hex.EncodeToString(hash[:]) + if *aqlPath == "" { + *aqlPath = filepath.Join("docs", "benchmarks", label+"-"+aqlHash[:16]+".aql") + } + if err := os.WriteFile(*aqlPath, []byte(compiled.Query+"\n"), 0o644); err != nil { + fatalf("write AQL %q: %v", *aqlPath, err) + } + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) + defer cancel() + client, err := arangostore.Open(ctx, *url, *database) + if err != nil { + fatalf("open Arango: %v", err) + } + defer client.Close(ctx) + explain, err := client.Explain(ctx, arangostore.ExplainRequest{Query: compiled.Query, BindVars: compiled.BindVars}) + if err != nil { + fatalf("EXPLAIN: %v", err) + } + started := time.Now() + profileResult, err := client.Profile(ctx, arangostore.ProfileRequest{ + Query: compiled.Query, + BindVars: compiled.BindVars, + BatchSize: *batchSize, + Count: true, + Options: arangostore.ProfileOptions{Profile: *profile}, + }) + if err != nil { + fatalf("PROFILE: %v", err) + } + + assessment := arangostore.AssessExplainResult(explain) + summary := arangostore.SummarizeProfile(profileResult) + topNodes := append([]arangostore.ProfileNodeSummary(nil), summary.Nodes...) + if len(topNodes) > 20 { + topNodes = topNodes[:20] + } + traversalNodes := filterProfileNodes(summary.Nodes, "TraversalNode") + enumerateListNodes := filterProfileNodes(summary.Nodes, "EnumerateListNode") + report := profileReport{ + Fixture: label, + AQLSHA256: aqlHash, + ResultSHA256: canonicalResultHash(profileResult.Result), + BindVars: compiled.BindVars, + Rows: profileResult.Count, + Explain: explainReport{ + Plans: assessment.Plans, + FullCollectionScans: assessment.FullCollectionScans, + Indexes: assessment.Indexes, + OptimizerRules: assessment.AppliedOptimizerRules, + Warnings: assessment.Warnings, + }, + Profile: profileReportDetails{ + RuntimeSeconds: summary.RuntimeSeconds, + ScannedFull: summary.ScannedFull, + ScannedIndex: summary.ScannedIndex, + PeakMemory: summary.PeakMemory, + Phases: profileResult.Extra.Profile, + ByType: summary.ByType, + TraversalNodes: traversalNodes, + EnumerateListNodes: enumerateListNodes, + TopNodes: topNodes, + }, + PlanDiagnostics: compiled.PlanDiagnostics, + AQLPath: *aqlPath, + ProfileWallSeconds: time.Since(started).Seconds(), + } + if *reportPath != "" { + report.ProfilePath = *reportPath + } + encoded, err := json.MarshalIndent(report, "", " ") + if err != nil { + fatalf("encode report: %v", err) + } + if *reportPath != "" { + if err := os.WriteFile(*reportPath, append(encoded, '\n'), 0o644); err != nil { + fatalf("write report %q: %v", *reportPath, err) + } + } + fmt.Println(string(encoded)) +} + +func filterProfileNodes(nodes []arangostore.ProfileNodeSummary, typ string) []arangostore.ProfileNodeSummary { + filtered := make([]arangostore.ProfileNodeSummary, 0) + for _, node := range nodes { + if node.Type == typ { + filtered = append(filtered, node) + } + } + return filtered +} + +func canonicalResultHash(rows []json.RawMessage) string { + hash := sha256.New() + for _, raw := range rows { + var value any + if err := json.Unmarshal(raw, &value); err != nil { + continue + } + canonical, err := json.Marshal(value) + if err != nil { + continue + } + _, _ = hash.Write(canonical) + _, _ = hash.Write([]byte{'\n'}) + } + return hex.EncodeToString(hash.Sum(nil)) +} + +func fatalf(format string, args ...any) { + fmt.Fprintf(os.Stderr, "dataframe-profile: "+format+"\n", args...) + os.Exit(1) +} diff --git a/conformance/compiler/policy_ablation_test.go b/conformance/compiler/policy_ablation_test.go new file mode 100644 index 0000000..70f97f6 --- /dev/null +++ b/conformance/compiler/policy_ablation_test.go @@ -0,0 +1,545 @@ +package compilerfixture + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "os" + "path/filepath" + "sort" + "strings" + "testing" + "time" + + "github.com/calypr/loom/internal/dataframe" + "github.com/calypr/loom/internal/store/arango" +) + +// TestGDCOptimizationPolicyAblationAgainstArango is opt-in because it reads +// the local development database and profiles four complete GDC executions. +// It proves that independent policy switches preserve the same dataframe +// result before a later work package uses the measurements to enable a new +// rewrite. +func TestGDCOptimizationPolicyAblationAgainstArango(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run policy ablation against Arango") + } + fixtures, err := LoadDir(filepath.Join("fixtures")) + if err != nil { + t.Fatal(err) + } + var fixture Fixture + for _, candidate := range fixtures { + if candidate.ID == "gdc-case-matrix" { + fixture = candidate + break + } + } + if fixture.ID == "" { + t.Fatal("gdc-case-matrix fixture is missing") + } + + defaultPolicy := dataframe.DefaultPhysicalOptimizationPolicy() + policies := []struct { + name string + policy dataframe.PhysicalOptimizationPolicy + }{ + {name: "none", policy: dataframe.PhysicalOptimizationPolicy{Enabled: false, MinimumSavings: 1}}, + {name: "sharing-only", policy: defaultPolicy.WithRule(dataframe.PhysicalOptimizationRulePreparedSelectors, false)}, + {name: "prepared-only", policy: defaultPolicy.WithRule(dataframe.PhysicalOptimizationRuleTraversalSharing, false).WithRule(dataframe.PhysicalOptimizationRulePreparedSelectors, true)}, + {name: "defaults", policy: defaultPolicy}, + } + + url := os.Getenv("LOOM_ARANGO_URL") + if url == "" { + url = "http://127.0.0.1:8529" + } + database := os.Getenv("LOOM_ARANGO_DATABASE") + if database == "" { + database = "fhir_proto" + } + project := os.Getenv("LOOM_ARANGO_PROJECT") + if project == "" { + project = "ARANGODB_PROTO" + } + fixture.Builder.Project = project + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) + defer cancel() + opts := arango.ConnectionOptions{URL: url, Database: database} + var expectedHash string + var expectedRows []map[string]any + for _, candidate := range policies { + candidate := candidate + t.Run(candidate.name, func(t *testing.T) { + compiled, err := dataframe.CompileRequestWithPolicy(fixture.Builder, 1000, candidate.policy) + if err != nil { + t.Fatal(err) + } + rows := make([]map[string]any, 0, 1000) + err = dataframe.ExecuteQueryRows(ctx, dataframe.ExecuteQueryOptions{ConnectionOptions: opts, BatchSize: 1000}, compiled.Query, compiled.BindVars, func(row map[string]any) error { + rows = append(rows, row) + return nil + }) + if err != nil { + t.Fatal(err) + } + payload, err := json.Marshal(rows) + if err != nil { + t.Fatal(err) + } + hash := sha256.Sum256(payload) + resultHash := hex.EncodeToString(hash[:]) + if expectedHash == "" { + expectedHash = resultHash + expectedRows = rows + } else if resultHash != expectedHash { + for index := range rows { + if index >= len(expectedRows) { + break + } + // JSON object encoding sorts map keys, making this a stable + // row-level diagnostic even though rows are decoded into maps. + left, _ := json.Marshal(rows[index]) + right, _ := json.Marshal(expectedRows[index]) + if string(left) != string(right) { + t.Logf("first differing row=%d candidate=%s baseline=%s", index, left, right) + break + } + } + t.Fatalf("result hash = %s, want %s", resultHash, expectedHash) + } + profile, err := dataframe.ProfileCompiledQuery(ctx, opts, compiled, 2) + if err != nil { + t.Fatal(err) + } + summary := arango.SummarizeProfile(profile) + topNodes := summary.Nodes + if len(topNodes) > 5 { + topNodes = topNodes[:5] + } + t.Logf("policy=%s rows=%d hash=%s aql_sha256=%x profile_runtime=%0.6fs scanned_full=%d scanned_index=%d lookups=%d peak_memory=%d top_nodes=%#v rule_states=%#v", candidate.name, len(rows), resultHash, sha256.Sum256([]byte(compiled.Query)), summary.RuntimeSeconds, summary.ScannedFull, summary.ScannedIndex, profile.Extra.Stats.DocumentLookups, summary.PeakMemory, topNodes, compiled.PlanDiagnostics.OptimizationPolicy.RuleStates) + }) + } +} + +// TestTraversalSharingAblationAgainstArango profiles focused sibling and +// deep-traversal fixtures with sharing isolated from prepared selectors. The +// fixtures intentionally use an oracle project; this test rewrites only the +// project bind to the loaded local dataset and leaves route semantics intact. +func TestTraversalSharingAblationAgainstArango(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run traversal sharing profile") + } + fixtures, err := LoadDir(filepath.Join("fixtures")) + if err != nil { + t.Fatal(err) + } + byID := make(map[string]Fixture, len(fixtures)) + for _, fixture := range fixtures { + byID[fixture.ID] = fixture + } + url := os.Getenv("LOOM_ARANGO_URL") + if url == "" { + url = "http://127.0.0.1:8529" + } + database := os.Getenv("LOOM_ARANGO_DATABASE") + if database == "" { + database = "fhir_proto" + } + project := os.Getenv("LOOM_ARANGO_PROJECT") + if project == "" { + project = "ARANGODB_PROTO" + } + opts := arango.ConnectionOptions{URL: url, Database: database} + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) + defer cancel() + for _, fixtureID := range []string{"patient-sibling-targets", "patient-deep-filter"} { + fixture, ok := byID[fixtureID] + if !ok { + t.Fatalf("fixture %q is missing", fixtureID) + } + fixture.Builder.Project = project + t.Run(fixtureID, func(t *testing.T) { + policies := []struct { + name string + policy dataframe.PhysicalOptimizationPolicy + }{ + {name: "unshared", policy: dataframe.PhysicalOptimizationPolicy{Enabled: false, MinimumSavings: 1}}, + {name: "sharing", policy: dataframe.DefaultPhysicalOptimizationPolicy().WithRule(dataframe.PhysicalOptimizationRulePreparedSelectors, false)}, + } + var expectedHash string + for _, candidate := range policies { + compiled, err := dataframe.CompileRequestWithPolicy(fixture.Builder, fixture.Limit, candidate.policy) + if err != nil { + t.Fatal(err) + } + var rows []map[string]any + executeSeconds := make([]float64, 0, 5) + var executionHash string + for run := 0; run < 5; run++ { + candidateRows := make([]map[string]any, 0, fixture.Limit) + executeStart := time.Now() + err = dataframe.ExecuteQueryRows(ctx, dataframe.ExecuteQueryOptions{ConnectionOptions: opts, BatchSize: 1000}, compiled.Query, compiled.BindVars, func(row map[string]any) error { + candidateRows = append(candidateRows, row) + return nil + }) + if err != nil { + t.Fatal(err) + } + executeSeconds = append(executeSeconds, time.Since(executeStart).Seconds()) + if run == 0 { + rows = candidateRows + } else if len(candidateRows) != len(rows) { + t.Fatalf("%s run %d rows = %d, want %d", candidate.name, run+1, len(candidateRows), len(rows)) + } + runPayload, err := json.Marshal(candidateRows) + if err != nil { + t.Fatal(err) + } + runHash := sha256.Sum256(runPayload) + if run == 0 { + executionHash = hex.EncodeToString(runHash[:]) + } else if got := hex.EncodeToString(runHash[:]); got != executionHash { + t.Fatalf("%s run %d result hash = %s, want %s", candidate.name, run+1, got, executionHash) + } + } + warm := append([]float64(nil), executeSeconds[1:]...) + sort.Float64s(warm) + warmMedian := warm[len(warm)/2] + payload, err := json.Marshal(rows) + if err != nil { + t.Fatal(err) + } + hash := sha256.Sum256(payload) + resultHash := hex.EncodeToString(hash[:]) + if expectedHash == "" { + expectedHash = resultHash + } else if resultHash != expectedHash { + t.Fatalf("%s result hash = %s, want %s", candidate.name, resultHash, expectedHash) + } + profile, err := dataframe.ProfileCompiledQuery(ctx, opts, compiled, 2) + if err != nil { + t.Fatal(err) + } + summary := arango.SummarizeProfile(profile) + topNodes := summary.Nodes + if len(topNodes) > 10 { + topNodes = topNodes[:10] + } + t.Logf("policy=%s rows=%d hash=%s aql_sha256=%x warm_median=%0.6fs warm_min=%0.6fs runs=%#v profile_runtime=%0.6fs scanned_full=%d scanned_index=%d lookups=%d peak_memory=%d top_nodes=%#v shared=%d", candidate.name, len(rows), resultHash, sha256.Sum256([]byte(compiled.Query)), warmMedian, warm[0], executeSeconds, summary.RuntimeSeconds, summary.ScannedFull, summary.ScannedIndex, profile.Extra.Stats.DocumentLookups, summary.PeakMemory, topNodes, compiled.PlanDiagnostics.SharedTraversalCount) + } + }) + } +} + +// TestPreparedSelectorAblationAgainstArango profiles the prepared selector +// payload independently from traversal sharing. It intentionally covers a +// child aggregate+slice, a child pivot, a nested child, and the full GDC +// dataframe so WP3 can make a generic payload decision instead of relying on +// one resource-specific query. +func TestPreparedSelectorAblationAgainstArango(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run prepared-selector profile") + } + fixtures, err := LoadDir(filepath.Join("fixtures")) + if err != nil { + t.Fatal(err) + } + byID := make(map[string]Fixture, len(fixtures)) + for _, fixture := range fixtures { + byID[fixture.ID] = fixture + } + url := os.Getenv("LOOM_ARANGO_URL") + if url == "" { + url = "http://127.0.0.1:8529" + } + database := os.Getenv("LOOM_ARANGO_DATABASE") + if database == "" { + database = "fhir_proto" + } + project := os.Getenv("LOOM_ARANGO_PROJECT") + if project == "" { + project = "ARANGODB_PROTO" + } + opts := arango.ConnectionOptions{URL: url, Database: database} + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) + defer cancel() + for _, fixtureID := range []string{"specimen-aggregate-slice", "patient-observation-pivot", "patient-deep-filter", "gdc-case-matrix"} { + fixture, ok := byID[fixtureID] + if !ok { + t.Fatalf("fixture %q is missing", fixtureID) + } + fixture.Builder.Project = project + t.Run(fixtureID, func(t *testing.T) { + policies := []struct { + name string + policy dataframe.PhysicalOptimizationPolicy + }{ + {name: "direct", policy: dataframe.PhysicalOptimizationPolicy{Enabled: false, MinimumSavings: 1}}, + {name: "prepared", policy: dataframe.DefaultPhysicalOptimizationPolicy().WithRule(dataframe.PhysicalOptimizationRuleTraversalSharing, false)}, + } + var expectedHash string + for _, candidate := range policies { + compiled, err := dataframe.CompileRequestWithPolicy(fixture.Builder, fixture.Limit, candidate.policy) + if err != nil { + t.Fatal(err) + } + var rows []map[string]any + executeSeconds := make([]float64, 0, 5) + var executionHash string + var responseBytes int + for run := 0; run < 5; run++ { + candidateRows := make([]map[string]any, 0, fixture.Limit) + executeStart := time.Now() + err = dataframe.ExecuteQueryRows(ctx, dataframe.ExecuteQueryOptions{ConnectionOptions: opts, BatchSize: 1000}, compiled.Query, compiled.BindVars, func(row map[string]any) error { + candidateRows = append(candidateRows, row) + return nil + }) + if err != nil { + t.Fatal(err) + } + executeSeconds = append(executeSeconds, time.Since(executeStart).Seconds()) + payload, err := json.Marshal(candidateRows) + if err != nil { + t.Fatal(err) + } + result := sha256.Sum256(payload) + runHash := hex.EncodeToString(result[:]) + if run == 0 { + rows = candidateRows + responseBytes = len(payload) + executionHash = runHash + } else if runHash != executionHash { + t.Fatalf("%s run %d result hash = %s, want %s", candidate.name, run+1, runHash, executionHash) + } + } + if expectedHash == "" { + expectedHash = executionHash + } else if executionHash != expectedHash { + t.Fatalf("%s result hash = %s, want %s", candidate.name, executionHash, expectedHash) + } + warm := append([]float64(nil), executeSeconds[1:]...) + sort.Float64s(warm) + profile, err := dataframe.ProfileCompiledQuery(ctx, opts, compiled, 2) + if err != nil { + t.Fatal(err) + } + summary := arango.SummarizeProfile(profile) + topNodes := summary.Nodes + if len(topNodes) > 10 { + topNodes = topNodes[:10] + } + explain, err := dataframe.ExplainCompiledQuery(ctx, opts, compiled) + if err != nil { + t.Fatal(err) + } + assessment := arango.AssessExplainResult(explain) + preparedFields := strings.Count(compiled.Query, "__loom_prepared_") + t.Logf("policy=%s rows=%d response_bytes=%d hash=%s aql_sha256=%x prepared_tokens=%d warm_median=%0.6fs warm_min=%0.6fs runs=%#v profile_runtime=%0.6fs scanned_full=%d scanned_index=%d lookups=%d peak_memory=%d indexes=%#v top_nodes=%#v", candidate.name, len(rows), responseBytes, executionHash, sha256.Sum256([]byte(compiled.Query)), preparedFields, warm[len(warm)/2], warm[0], executeSeconds, summary.RuntimeSeconds, summary.ScannedFull, summary.ScannedIndex, profile.Extra.Stats.DocumentLookups, summary.PeakMemory, assessment.Indexes, topNodes) + } + }) + } +} + +// TestRichConsumerReuseProfileAgainstArango records the baseline work for +// WP4's proposed rich-consumer fusion. It deliberately uses the production +// default (prepared selectors disabled after WP3) and reports the physical +// reuse groups plus the rendered loop count. There is no fused candidate in +// this test: fusion must be added only after a compatible group and a profile +// benefit are demonstrated. +func TestRichConsumerReuseProfileAgainstArango(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run rich-consumer profile") + } + fixtures, err := LoadDir(filepath.Join("fixtures")) + if err != nil { + t.Fatal(err) + } + byID := make(map[string]Fixture, len(fixtures)) + for _, fixture := range fixtures { + byID[fixture.ID] = fixture + } + url := os.Getenv("LOOM_ARANGO_URL") + if url == "" { + url = "http://127.0.0.1:8529" + } + database := os.Getenv("LOOM_ARANGO_DATABASE") + if database == "" { + database = "fhir_proto" + } + project := os.Getenv("LOOM_ARANGO_PROJECT") + if project == "" { + project = "ARANGODB_PROTO" + } + opts := arango.ConnectionOptions{URL: url, Database: database} + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) + defer cancel() + for _, fixtureID := range []string{"specimen-aggregate-slice", "gdc-case-matrix"} { + fixture, ok := byID[fixtureID] + if !ok { + t.Fatalf("fixture %q is missing", fixtureID) + } + fixture.Builder.Project = project + t.Run(fixtureID, func(t *testing.T) { + policy := dataframe.DefaultPhysicalOptimizationPolicy().WithRule(dataframe.PhysicalOptimizationRulePreparedSelectors, false) + compiled, err := dataframe.CompileRequestWithPolicy(fixture.Builder, fixture.Limit, policy) + if err != nil { + t.Fatal(err) + } + var rows []map[string]any + executeSeconds := make([]float64, 0, 5) + var resultHash string + var responseBytes int + for run := 0; run < 5; run++ { + candidateRows := make([]map[string]any, 0, fixture.Limit) + start := time.Now() + err = dataframe.ExecuteQueryRows(ctx, dataframe.ExecuteQueryOptions{ConnectionOptions: opts, BatchSize: 1000}, compiled.Query, compiled.BindVars, func(row map[string]any) error { + candidateRows = append(candidateRows, row) + return nil + }) + if err != nil { + t.Fatal(err) + } + executeSeconds = append(executeSeconds, time.Since(start).Seconds()) + payload, err := json.Marshal(candidateRows) + if err != nil { + t.Fatal(err) + } + hash := sha256.Sum256(payload) + gotHash := hex.EncodeToString(hash[:]) + if run == 0 { + rows = candidateRows + responseBytes = len(payload) + resultHash = gotHash + } else if gotHash != resultHash { + t.Fatalf("run %d result hash = %s, want %s", run+1, gotHash, resultHash) + } + } + warm := append([]float64(nil), executeSeconds[1:]...) + sort.Float64s(warm) + profile, err := dataframe.ProfileCompiledQuery(ctx, opts, compiled, 2) + if err != nil { + t.Fatal(err) + } + summary := arango.SummarizeProfile(profile) + topNodes := summary.Nodes + if len(topNodes) > 10 { + topNodes = topNodes[:10] + } + explain, err := dataframe.ExplainCompiledQuery(ctx, opts, compiled) + if err != nil { + t.Fatal(err) + } + assessment := arango.AssessExplainResult(explain) + t.Logf("rows=%d response_bytes=%d hash=%s aql_sha256=%x warm_median=%0.6fs warm_min=%0.6fs runs=%#v rich_source_reuse=%#v rich_consumer_groups=%#v aql_for_loops=%d profile_runtime=%0.6fs scanned_full=%d scanned_index=%d lookups=%d peak_memory=%d indexes=%#v top_nodes=%#v", len(rows), responseBytes, resultHash, sha256.Sum256([]byte(compiled.Query)), warm[len(warm)/2], warm[0], executeSeconds, compiled.PlanDiagnostics.RichSourceReuse, compiled.PlanDiagnostics.RichConsumerGroups, strings.Count(compiled.Query, "FOR "), summary.RuntimeSeconds, summary.ScannedFull, summary.ScannedIndex, profile.Extra.Stats.DocumentLookups, summary.PeakMemory, assessment.Indexes, topNodes) + }) + } +} + +// TestCompactSetProjectionAblationAgainstArango compares full stored nodes +// with the typed identity-safe set projection while keeping traversal sharing +// and prepared selectors fixed. It is the WP5 evidence gate. +func TestCompactSetProjectionAblationAgainstArango(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run compact-set profile") + } + fixtures, err := LoadDir(filepath.Join("fixtures")) + if err != nil { + t.Fatal(err) + } + byID := make(map[string]Fixture, len(fixtures)) + for _, fixture := range fixtures { + byID[fixture.ID] = fixture + } + url := os.Getenv("LOOM_ARANGO_URL") + if url == "" { + url = "http://127.0.0.1:8529" + } + database := os.Getenv("LOOM_ARANGO_DATABASE") + if database == "" { + database = "fhir_proto" + } + project := os.Getenv("LOOM_ARANGO_PROJECT") + if project == "" { + project = "ARANGODB_PROTO" + } + opts := arango.ConnectionOptions{URL: url, Database: database} + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) + defer cancel() + for _, fixtureID := range []string{"specimen-aggregate-slice", "patient-specimen-file", "patient-deep-filter", "gdc-case-matrix"} { + fixture, ok := byID[fixtureID] + if !ok { + t.Fatalf("fixture %q is missing", fixtureID) + } + fixture.Builder.Project = project + t.Run(fixtureID, func(t *testing.T) { + limit := fixture.Limit + if fixtureID == "gdc-case-matrix" { + limit = 1000 + } + basePolicy := dataframe.DefaultPhysicalOptimizationPolicy().WithRule(dataframe.PhysicalOptimizationRulePreparedSelectors, false) + policies := []struct { + name string + policy dataframe.PhysicalOptimizationPolicy + }{ + {name: "full", policy: basePolicy.WithRule(dataframe.PhysicalOptimizationRuleCompactProjection, false)}, + {name: "compact", policy: basePolicy.WithRule(dataframe.PhysicalOptimizationRuleCompactProjection, true)}, + } + var expectedHash string + for _, candidate := range policies { + compiled, err := dataframe.CompileRequestWithPolicy(fixture.Builder, limit, candidate.policy) + if err != nil { + t.Fatal(err) + } + var rows []map[string]any + executeSeconds := make([]float64, 0, 5) + var resultHash string + var responseBytes int + for run := 0; run < 5; run++ { + candidateRows := make([]map[string]any, 0, limit) + start := time.Now() + err = dataframe.ExecuteQueryRows(ctx, dataframe.ExecuteQueryOptions{ConnectionOptions: opts, BatchSize: 1000}, compiled.Query, compiled.BindVars, func(row map[string]any) error { + candidateRows = append(candidateRows, row) + return nil + }) + if err != nil { + t.Fatal(err) + } + executeSeconds = append(executeSeconds, time.Since(start).Seconds()) + payload, err := json.Marshal(candidateRows) + if err != nil { + t.Fatal(err) + } + hash := sha256.Sum256(payload) + gotHash := hex.EncodeToString(hash[:]) + if run == 0 { + rows = candidateRows + responseBytes = len(payload) + resultHash = gotHash + } else if gotHash != resultHash { + t.Fatalf("%s run %d result hash = %s, want %s", candidate.name, run+1, gotHash, resultHash) + } + } + if expectedHash == "" { + expectedHash = resultHash + } else if resultHash != expectedHash { + t.Fatalf("%s result hash = %s, want %s", candidate.name, resultHash, expectedHash) + } + warm := append([]float64(nil), executeSeconds[1:]...) + sort.Float64s(warm) + profile, err := dataframe.ProfileCompiledQuery(ctx, opts, compiled, 2) + if err != nil { + t.Fatal(err) + } + summary := arango.SummarizeProfile(profile) + explain, err := dataframe.ExplainCompiledQuery(ctx, opts, compiled) + if err != nil { + t.Fatal(err) + } + assessment := arango.AssessExplainResult(explain) + t.Logf("policy=%s rows=%d response_bytes=%d hash=%s aql_sha256=%x warm_median=%0.6fs warm_min=%0.6fs runs=%#v profile_runtime=%0.6fs scanned_full=%d scanned_index=%d lookups=%d peak_memory=%d indexes=%#v compact_rule=%t", candidate.name, len(rows), responseBytes, resultHash, sha256.Sum256([]byte(compiled.Query)), warm[len(warm)/2], warm[0], executeSeconds, summary.RuntimeSeconds, summary.ScannedFull, summary.ScannedIndex, profile.Extra.Stats.DocumentLookups, summary.PeakMemory, assessment.Indexes, candidate.policy.RuleEnabled(dataframe.PhysicalOptimizationRuleCompactProjection)) + } + }) + } +} diff --git a/docs/AQL_EXECUTION_IMPLEMENTATION_AUDIT.md b/docs/AQL_EXECUTION_IMPLEMENTATION_AUDIT.md new file mode 100644 index 0000000..1c9b74a --- /dev/null +++ b/docs/AQL_EXECUTION_IMPLEMENTATION_AUDIT.md @@ -0,0 +1,242 @@ +# AQL execution implementation audit + +## Conclusion + +The compiler has two real production optimizations, but it is not close to a +fully optimized physical translation. Generic sibling traversal sharing and +compact set projection are enabled and measurable. Most other named +optimizer rules are experiments, diagnostics, or policy switches with no +production rewrite behind them. + +The concern about `LUNA_AQL_EXECUTION_ROUND_3.md` is justified. Its prepared +selector package largely repeats a previously rejected second-pass prepared +set, and its fusion package starts from a classifier that currently finds no +real candidates. Those packages may reduce some selector work after a major +redesign, but they are unlikely to be the first large reduction in the +5.9-second Arango phase. + +The highest-confidence missing translation is index-aware edge lowering. The +actual query's four native traversal nodes all use the default `_to` edge +index while existing endpoint-first compound indexes remain unused. The next +largest architectural gap is that Loom materializes payload-bearing child +arrays and only then performs rich shaping in separate loops. + +## Plan versus production code + +| Capability | Plan/document claim | Current code truth | Production effect | +|---|---|---|---| +| Physical compiler/renderer | complete | complete; the physical compiler is the execution path | required foundation | +| Root scope/window | complete | project/generation/auth before `_key` sort and limit | root index selected; not the bottleneck | +| Generic sibling traversal sharing | complete | implemented in `sharePhysicalSetGroup`; enabled by default | large win: roughly 7.4s unoptimized to 5.6–5.9s current | +| Compact set projection | complete | implemented and enabled by default | modest runtime win; meaningful memory reduction | +| Prepared selectors | described as complete in old status text | implemented as an optional second prepared array; disabled by default | previously slower and about 303 MB more memory at 1,000 rows | +| Rich-consumer fusion | described as complete in old status text | diagnostics classify only byte-identical expressions; no fusion rewrite/rendering exists | no AQL change | +| Nested traversal sharing | named rule | no optimizer implementation; prior corpus had no repeated nested candidate | no AQL change | +| Required-match reuse | complete | identical required matches are deduplicated and counted | useful, but absent from this optional-only GDC shape | +| Endpoint-first indexes | declared and Explain-tested | native traversal still selects only default edge `_to`; explicit filtered-edge probes select compound indexes | unused by production translation | +| Relationship cardinality catalog | complete | used for discovery/validation; `EdgeCount` is not carried into semantic/physical planning | no cost-aware strategy selection | +| Durable profile tooling | mostly complete | exact variables input, AQL/result hashes, Explain/Profile artifacts now exist | diagnostic only | +| Cost policy | complete structurally | estimates operation counts, not cardinality, fan-out, retained width, or selected index | cannot choose the cheapest physical strategy reliably | + +The old `AQL_OPTIMIZATION_WORKLIST.md` execution-status section is therefore +stale where it calls prepared reuse and aggregate/pivot/slice fusion complete. +Prepared references exist, but their current rendering was rejected for +production. Fusion is diagnostics-only. + +## What the current AQL actually does + +The exact 1,000-row GDC query contains: + +| Rendered operation | Count | +|---|---:| +| `UNIQUE` materializations/expressions | 8 | +| `SORT` clauses | 11 | +| native graph traversals | 4 | +| post-materialization `FOR __item IN child_set` loops | 7 | +| child sets retaining `payload` | 6 | + +The query first materializes a broad Patient-neighbor array, derives typed +arrays, materializes three nested arrays, and then re-enumerates those arrays +for aggregates, slices, and the pivot. Representative slices sort an array +that was already sorted during set materialization; when the requested sort +is `_key`, the renderer currently emits `_key` twice as the primary key and +tie-breaker. + +This is correct AQL, but it is a general-purpose materialize-then-shape plan, +not an optimized query plan. + +## Profile-backed bottlenecks + +The exact request profile reports 475,876 indexed items, no full scans, and +269,844,480 bytes peak memory. The root `Patient(project, _key)` index is +working. The remaining traversal fan-out is: + +| Region | Node | Items | Filtered | Cumulative runtime | +|---|---:|---:|---:|---:| +| shared first hop | 12 | 34,852 | 11,622 | 1.079s | +| Specimen → DocumentReference | 55 | 14,334 | 60,944 | 2.888s | +| Specimen → Group | 79 | 22,950 | 52,328 | 4.124s | +| Group → DocumentReference | 103 | 12,074 | 11,074 | 5.673s | + +These runtimes overlap, but the calls/items/filtered counts are decisive: the +renderer asks native traversal to retrieve broad endpoint adjacency and then +filters label, type, project, generation, and auth. `EXPLAIN` shows only the +default `_to` edge index. The endpoint-first compound index is proven usable +only by explicit edge-filter AQL. + +The other large node family is payload list enumeration. The same selector is +often recomputed for distinct aggregation, a representative slice, or a +pivot. The current prepared-set experiment addresses this by creating another +array that also retains `payload` and `__loom_prepared_node`, which explains +its memory and runtime regression. + +## Assessment of Round 3 + +### Prepared selector unions + +Do not execute the existing package unchanged. The repository already has a +selector-union collector and prepared renderer. Previous live evidence showed +it was slower because it performs a second pass and duplicates payload-bearing +objects. + +The useful replacement is **traversal-time shaping projection**: compute the +union of required selector values in the child traversal's `RETURN` object, +along with only `_id`, `_key`, and fields required for nested navigation. This +removes payload before it enters the materialized array and avoids the second +prepared pass entirely. + +### Compatible aggregate/slice/pivot fusion + +Do not implement the current identical-expression classifier as a renderer. +The real query contains unlike consumers over the same source—count, distinct +values, slice, and pivot—not repeated identical expressions. The classifier +correctly produces singleton groups, so enabling its rule cannot change this +query. + +Fusion becomes useful only as **leaf-set summary pushdown**: after identity +deduplication, a leaf relationship subquery should return both its bounded +slice and aggregate/pivot summary without first returning a payload array to +the outer root projection. That is a different physical operation from the +current diagnostics group. + +### Explicit endpoint-filter traversal + +Keep and expand this package. It is the only Round 3 proposal directly aimed +at the profile's largest proven work. It must compare four strategies, because +the current sibling-sharing win can conflict with compound-index equality: + +1. native shared multi-type traversal; +2. native independent typed traversals; +3. explicit shared multi-type edge lookup; and +4. explicit independent typed edge lookups using endpoint/type equality. + +The inbound multi-type `IN` probe previously fell back to the default edge +index, while equality selected the compound index. A production choice cannot +assume that sharing remains cheaper after endpoint filtering. + +## Missing work, reordered by expected impact + +### P1 — index-aware traversal strategy selection + +Add a typed physical strategy for native traversal versus explicit edge/node +lookup. Prototype nested equality routes first, then the shared root route. +Require the endpoint-first compound index, exact parity, and at least a 10% +whole-query median win before production enablement. + +This is the highest-confidence package because it targets the observed +filtered adjacency work and an already-proven usable index. + +### P2 — traversal-time shaping projection + +Replace post-set prepared arrays with a typed projection attached to the +relationship set itself. Compute repeated selector arrays once while each node +is in scope. Retain `payload` only for an unprepared fallback or unsupported +consumer; retain `_id` only when a nested traversal needs it. + +This package should delete or replace the current harmful prepared-set +rendering rather than layering another representation on top of it. + +### P3 — leaf-set summary pushdown + +For a materialized child with no navigated descendants, lower aggregate, +pivot, and representative-slice outputs into a typed summary subquery. The +summary should perform identity deduplication once, then emit named outputs. +The outer root `RETURN` reads the summary object instead of repeatedly looping +over a child payload array. + +This is the production form of useful “fusion.” It must preserve count, +distinct ordering, pivot collision reduction, and sort-before-limit. + +### P4 — identity, deduplication, and ordering plan + +Model identity uniqueness and ordering as physical properties rather than +emitting `UNIQUE` plus `SORT` for every set and another `SORT` for each slice. +Prove whether `_id`/`_key` deduplication can replace object-level `UNIQUE`, and +whether a sorted/deduplicated source satisfies a slice's order. + +Do not start with the duplicated `_key` text cleanup alone; it is correct but +unlikely to move the whole query. The package matters only if it removes +materialization/sort executor work. + +### P5 — batch-oriented root execution prototype + +If P1–P4 do not bring the warm query below roughly three seconds, prototype a +set-oriented plan: materialize the 1,000-root window once, perform edge/node +lookups for the root set, group by root identity, and assemble rows afterward. +The current compiler is correlated root-by-root; no prior work package tested +a batch join/aggregation strategy. + +This is higher-risk but has more upside than additional expression-level +fusion. It must remain an experiment until auth/generation and row-order +parity are proven. + +### P6 — catalog-backed physical costing + +Carry relationship counts from validated catalog references into compilation +as read-only statistics. Use them to choose shared versus independent and +native versus explicit traversal, and to bound retained-set width. Statistics +must never change semantics and must have a deterministic no-statistics +fallback. + +This package enables correct strategy choice; it does not count as a speedup +unless it selects a measurably faster rendered plan. + +## Recommended execution order + +```text +Wave 1, parallel experiments: + P1 endpoint lookup: nested paths and root shared/unshared matrix + P2 traversal-time projection: selector/retention prototype + P4 identity/order: prove which sorts/UNIQUE operations are removable + +Wave 2, serialized compiler merges: + P1 production strategy + P2 production projection + P3 leaf summary pushdown + P4 proven ordering/dedup changes + +Wave 3: + re-profile exact GDC and generic corpus + implement P5 only if the execution phase remains above the target + add P6 when more than one physical strategy has survived profiling +``` + +Rich fusion and prepared selectors should not remain standalone production +goals. They should be absorbed into traversal-time projection and leaf summary +pushdown, where they can remove an actual materialization boundary. + +## Completion target + +The next round should target more than “below the old 6.34-second baseline.” +That gate has already been met. A meaningful next milestone is: + +- exact result and scope parity; +- zero full scans; +- endpoint-first indexes selected where expected; +- no more than 200 MB peak memory for this request; and +- five-run warm Arango median below 4.5 seconds after P1/P2, with a stretch + target below 3 seconds after leaf pushdown or batch-oriented execution. + +Any package that cannot identify removed scanned items, removed payload +materialization, or removed sort/list work is not an AQL translation +optimization and should not be merged as one. diff --git a/docs/AQL_OPTIMIZATION_WORKLIST.md b/docs/AQL_OPTIMIZATION_WORKLIST.md index dd465e8..c77eac0 100644 --- a/docs/AQL_OPTIMIZATION_WORKLIST.md +++ b/docs/AQL_OPTIMIZATION_WORKLIST.md @@ -507,8 +507,13 @@ As of the current execution pass: decomposition-proven plans. - **Complete:** WP3b recursive nested object rendering and recursive object cycle validation. -- **Complete:** WP3/WP4 prepared-set reuse and aggregate/pivot/slice - consumer fusion for eligible child sets. +- **Experimental and disabled:** WP3 prepared-set reuse has a physical operation + and renderer, but the live GDC profile was slower and used substantially more + memory. It is not part of the production-default optimization policy. +- **Diagnostics only:** WP4 can classify byte-identical rich consumers, but no + fusion lowering or renderer path currently executes fused aggregate, pivot, + or slice consumers. The GDC profile also produced no eligible multi-consumer + groups under that classifier. - **Complete:** WP6 profile-driven Explain/index corpus harness (live execution remains opt-in with `LOOM_COMPILER_ARANGO_INTEGRATION=1`). - **Complete:** WP5 required-match reuse: duplicate required EXISTS routes are diff --git a/docs/LUNA_AQL_EXECUTION_ROUND_3.md b/docs/LUNA_AQL_EXECUTION_ROUND_3.md new file mode 100644 index 0000000..8f9cedb --- /dev/null +++ b/docs/LUNA_AQL_EXECUTION_ROUND_3.md @@ -0,0 +1,683 @@ +# Luna execution plan: AQL execution optimization round 3 + +## Mission + +Reduce the Arango execution time and retained memory of Loom's generic FHIR +dataframe AQL. Optimize the generic physical translation, not the example +schema or the Go/GraphQL request path. + +This plan replaces the earlier prepared-selector and byte-identical-consumer +fusion plan. The current compiler already proved those formulations do not +justify production work: + +- the second prepared array was slower and added roughly 303 MB of peak memory; +- the rich-consumer classifier found no multi-consumer group in the GDC query; +- native traversals ignore Loom's endpoint-first compound edge indexes; and +- payload-bearing sets are materialized, deduplicated, sorted, and then scanned + again for aggregates, pivots, and slices. + +The work below is ordered around removal of those measured costs. A work +package is not complete merely because it adds an IR type, optimizer rule, or +passing unit test. It must either prove a material profile improvement or be +rejected and removed. + +Read `docs/AQL_EXECUTION_IMPLEMENTATION_AUDIT.md` completely before starting +any package. + +## Current baseline and invariant input + +The invariant benchmark is the real GraphQL request formed by: + +- `examples/meta_gdc_case_matrix.graphql` +- `examples/meta_gdc_case_matrix.variables.json` +- limit 1,000 +- project `ARANGODB_PROTO` +- database `fhir_proto` + +Checked-in baseline artifacts: + +- `docs/benchmarks/meta_gdc_case_matrix-profile.aql` +- `docs/benchmarks/meta_gdc_case_matrix-profile.json` +- `docs/benchmarks/GDC_AQL_PROFILE.md` + +| Measure | Baseline | +|---|---:| +| AQL hash | `c0b39eb0ec0f29a09b1661c78fc377159881aae81214e505a5427495c8a7e07c` | +| canonical result hash | `17faea7ac3ee7f308b37223f376530a0660f8068d5e015cc573cf99ccb4045ca` | +| Arango executing phase | 5.928s | +| indexed items scanned | 475,876 | +| full scans | 0 | +| peak memory | 269,844,480 bytes | +| `UNIQUE` expressions | 8 | +| `SORT` clauses | 11 | +| native traversals | 4 | +| post-materialization set loops | 7 | +| child sets retaining payload | 6 | + +The baseline numbers are reference evidence, not permission to compare results +from a different database state. WP0 must recapture a same-session baseline +before every experiment series. + +## Global semantic contracts + +Every work package must preserve: + +1. one row per root and ascending root `_key` order; +2. root project, generation, authorization, and required filters before the + root `SORT/LIMIT` window; +3. optional child shaping after the root window; +4. project, exact generation, and authorization checks on every traversed edge + and node; +5. route direction, edge label, endpoint discriminator, and target type from + `resolveStorageRoute` and generated `fhirschema` data only; +6. bind-backed values and collection binds; no interpolated user values; +7. exact null versus empty-array behavior, output column names, array order, + `SORTED_UNIQUE`, pivot collision selection, and representative-slice + sort-before-limit semantics; +8. duplicate-edge identity semantics and deterministic tie-breaking; +9. inbound and proven outbound traversal behavior, notably + `ResearchSubject -> ResearchStudy`; and +10. a deterministic correct fallback when statistics or a specialized + strategy are unavailable. + +Production code must never branch on `Patient`, GDC, a `child_set_N` variable, +an example column name, or a known example edge label. + +## Required evidence and promotion gate + +Every experiment and production packet records: + +- commit/worktree hash and hashes of every owned file before editing; +- exact command, policy environment, database, project, limit, and run time; +- rendered AQL hash and canonical result hash; +- five raw warm client and Arango execution times, median, and minimum; +- response rows and bytes; +- scanned full/index items and peak memory; +- traversal calls/items/filtered/runtime and selected index names/fields; +- top ten profile nodes by cumulative runtime and by item count; +- counts of `UNIQUE`, `SORT`, traversal, materialized-set, payload-retaining, + and post-materialization enumeration operations; +- the structural reason the candidate should improve the plan; and +- an `enable`, `cost-gate`, or `reject` decision. + +Use: + +```bash +make dataframe-demo \ + DATAFRAME_LIMIT=1000 \ + DATAFRAME_REPEAT=5 \ + DATAFRAME_PRINT_RESPONSE=false + +make dataframe-profile \ + DATAFRAME_PROFILE_LIMIT=1000 +``` + +A production rewrite is promotable only when: + +- result hashes match at limits 25 and 1,000; +- there are zero full collection scans; +- scope and route parity tests pass; +- the same-session five-run warm median improves by at least 10%; or the + targeted profile region loses at least 25% of its work while the whole query + improves by at least 5%; +- peak memory does not regress by more than 5%; and +- protected scalar-root, single-child, aggregate, pivot, slice, deep traversal, + sibling traversal, required-match, auth, generation, and outbound cases do + not regress by more than 5%. + +An experiment with no measurable benefit is a successful rejection. Do not +leave its production switch, alternate renderer, or unused IR behind. + +## Ownership and parallel execution + +The following files are shared compiler files. Only the integration +coordinator may edit them: + +- `internal/dataframe/physical_plan.go` +- `internal/dataframe/generic_physical_plan.go` +- `internal/dataframe/physical_optimize.go` +- `internal/dataframe/physical_render.go` +- `internal/dataframe/physical_cost.go` +- `internal/dataframe/physical_diagnostics.go` +- `internal/dataframe/physical_execution.go` + +Experiment workers may add isolated `*_experiment_test.go` files under +`internal/dataframe/` or `internal/store/arango/`, add benchmark artifacts +under their assigned `docs/benchmarks/round3//` directory, and extend +`cmd/dataframe-profile/` only when their package explicitly owns it. They may +not patch shared production behavior. + +```text +Wave 0, serialized: + WP0 baseline lock and parity harness + +Wave 1, parallel experiments: + WP1 endpoint/index strategy matrix + WP3 traversal-time shaping projection + WP6 identity/order/dedup property proof + +Wave 2, serialized coordinator merges: + WP2 endpoint-aware traversal lowering, only if WP1 passes + WP4 traversal-time shaping, only if WP3 passes + WP7 physical identity/order properties, only for WP6-proven changes + +Wave 3, after WP4: + WP5 leaf summary pushdown + +Wave 4, conditional parallel investigations: + WP8 batch-root execution, only if warm median remains above 3s + WP9 catalog-backed costing, only after at least two strategies survive + +Wave 5, serialized: + WP10 integration, cleanup, and final profile +``` + +No worker may write a shared file while another worker or coordinator owns it. +Stop when an unowned IR change is required and hand the coordinator a typed IR +proposal instead. + +## WP0 - lock baseline, parity, and profile accounting + +**Purpose:** make every later speedup attributable and reproducible. + +**Owner:** coordinator. **May edit:** `cmd/dataframe-profile/`, focused profile +tests, `docs/benchmarks/round3/wp0/`, and Makefile profile targets. Do not alter +compiler output. + +### Tasks + +1. Verify the exact GraphQL request and variables are used by both demo and + profile commands. Record the effective limit and every bind variable without + logging authorization secrets. +2. Capture a fresh five-run warm baseline and raw `PROFILE` result. Preserve + raw artifacts, not only a Markdown summary. +3. Make canonical result hashing insensitive only to JSON object key order. It + must remain sensitive to row order, array order, nulls, empty arrays, scalar + types, and values. +4. Add or verify structural AQL accounting for the operation counts required by + the evidence contract. +5. Add a comparison command or test that accepts baseline/candidate profile + artifacts and reports absolute and percentage changes. It must not sum + nested cumulative profile runtimes. +6. Run the protected generic compiler corpus once and record its commands and + current hashes. + +### Acceptance + +- two unchanged consecutive captures have identical result and AQL hashes; +- their warm medians are within 10%, otherwise diagnose environmental noise; +- comparison output identifies selected edge indexes and the four current + traversal regions; and +- no production AQL changes. + +**Artifact:** `docs/benchmarks/round3/wp0/BASELINE.md` plus raw JSON/AQL. + +## WP1 - endpoint/index traversal strategy experiment + +**Purpose:** determine which generic traversal shape eliminates the largest +measured filtered-adjacency work. + +**Owner:** experiment worker. **May edit:** new +`internal/dataframe/*endpoint_strategy_experiment_test.go`, new +`internal/store/arango/*endpoint_strategy_experiment_test.go`, and +`docs/benchmarks/round3/wp1/`. **Must not edit shared compiler files or create +or remove persistent indexes.** + +### Strategy matrix + +For each route, compare these four shapes independently: + +1. shared native traversal over multiple typed sibling routes; +2. independent native typed traversals; +3. shared explicit edge lookup with endpoint equality and multiple types; and +4. independent explicit edge lookups with endpoint and type equality. + +Test the three expensive nested regions first, then the shared root region. +Replace only one region per candidate so its effect is attributable. + +### Tasks + +1. Obtain direction, edge collection, target collection, endpoint field, + discriminator field, label, and target type from `resolveStorageRoute`. +2. Generate test-only candidate AQL by a structured helper or narrowly replace + one identified physical region. Do not use resource-specific string + replacement. +3. For INBOUND, compare edge `_to == parent._id`, the route's from-type + discriminator, and the `_from` node join. For OUTBOUND, compare `_from`, the + to-type discriminator, and `_to` node join. +4. Apply edge project/generation/auth scope before joining the node. Apply node + project/generation/auth/resource-type scope before returning it. +5. Preserve current identity deduplication, ordering, child predicates, output + shape, and compact retained fields. +6. Capture `EXPLAIN` before executing each candidate. Reject any explicit + candidate that does not select the intended endpoint-first compound index. +7. Test equality and multi-type `IN` separately; do not infer that an index + chosen for equality will be chosen for `IN`. +8. Cover root parent, nested parent set, zero/one/many neighbors, duplicate + edges, restricted/unrestricted auth, null/named generation, and the proven + outbound route. + +### Required decision table + +For each structural route class, report native/shared, native/independent, +explicit/shared, and explicit/independent median, scanned items, filtered +items, memory, index, and parity. Identify whether sharing becomes a loss once +typed equality enables the compound index. + +### Stop conditions + +- stop if a candidate needs a new persistent index; +- stop if scope must move after node materialization; +- reject a candidate that selects only the default edge index; +- reject resource-specific wins that cannot be expressed using route metadata; +- do not propose required-match lowering in this packet. + +### Acceptance and handoff + +Pass only if at least one route-generic explicit strategy satisfies the global +promotion gate. Hand off a typed `PhysicalTraversalStrategy` proposal, exact +filter ordering, supported route classes, unsupported cases, and profile +evidence. Do not implement it in production. + +## WP2 - production endpoint-aware traversal lowering + +**Purpose:** add the WP1-winning strategy without weakening native traversal +fallbacks. + +**Owner:** coordinator. **Depends on:** WP1 pass. **Owns:** shared compiler +files, relevant focused tests, and `docs/benchmarks/round3/wp2/`. + +### IR contract + +Add a typed strategy to `PhysicalTraversal`; do not store AQL fragments. It +must describe: + +- native graph versus explicit endpoint lookup; +- direction and endpoint field; +- edge-to-node join field; +- edge type discriminator field/value; +- route/collection binds already validated by `resolveStorageRoute`; and +- a reason/cost decision visible in diagnostics. + +### Tasks + +1. Extend physical validation to reject inconsistent endpoint/direction/join + combinations and undefined collection binds. +2. Lower only the route classes proven by WP1. Required matches, variable-depth + traversal, `ANY`, and unproven route shapes remain native. +3. Render edge scope before node lookup and node scope before child predicates. +4. Preserve duplicate-edge `UNIQUE`, deterministic order, compact projection, + nested parent correlation, and outbound direction. +5. Add an independent rule switch for ablation. Default-enable it only if the + generic protected corpus and GDC gate pass. +6. Report native versus endpoint decision, selected index expectation, and + rejection reason in physical diagnostics. + +### Tests + +- plan validation for every legal/illegal direction combination; +- exact AQL shape and bind tests for inbound and outbound; +- duplicate edge, optional empty, child predicate, auth, and generation parity; +- live Explain asserts the endpoint-first index for enabled candidates; +- live result parity and five-run ablation profile. + +### Acceptance + +Meet WP1's measured gate in the production execution path. If only a structural +subset wins, use a deterministic structural gate; do not install a broad +heuristic based on FHIR type names. + +## WP3 - traversal-time shaping projection experiment + +**Purpose:** prove that selector values can be computed while the child node is +in scope, eliminating payload retention and the harmful second prepared array. + +**Owner:** experiment worker. **May edit:** new +`internal/dataframe/*traversal_projection_experiment_test.go` and +`docs/benchmarks/round3/wp3/`. **Must not edit shared compiler files.** + +### Candidate shape + +One child-set item should retain only the union actually required downstream: + +- `_id` only when a nested traversal consumes the node; +- `_key` or an explicit stable identity/order key when required; +- route/type fields only when a downstream operation needs them; and +- named selector arrays/scalars computed from the node payload in the traversal + `RETURN` object. + +It must not create a second prepared array, copy `payload`, or retain an +original-node escape hatch unless a specific unsupported consumer requires a +mixed fallback plan. + +### Tasks + +1. Walk all consumers of each physical set and collect selector requirements + from aggregate values/predicates, pivot key/value, slice predicate/sort/ + projections, filters, derived expressions, and descendant navigation. +2. Canonicalize a projected selector by resource type, selector path, + cardinality, fallback semantics, and evaluation scope. Never merge selectors + that merely render similar text. +3. Classify retention as identity, navigation, ordering, projected selector, + or unsupported payload fallback. Report the reason for every retained field. +4. Prototype the GDC child sets with one shaped object produced in the original + set subquery. Rewire test-only consumers to read that same object. +5. Measure the candidate alone and combined with the WP1 winner, keeping the + two improvements separately attributable. +6. Cover scalar and array selectors, repeated coding paths, null/missing + intermediate objects, fallback chains, child filters, nested navigation, + and mixed supported/unsupported consumers. + +### Stop conditions + +- reject any design that materializes both shaped and payload-bearing copies; +- do not silently disable a fallback selector; +- stop and propose an IR contract if consumer scope cannot be represented; +- do not count fewer AQL characters as a benefit. + +### Acceptance and handoff + +Pass if payload-retaining sets and repeated payload enumeration materially fall, +peak memory does not regress, exact parity holds, and the global performance +gate passes. Hand off a typed set-item projection contract, consumer rewiring +map, retention-reason schema, unsupported-case fallback, and evidence. + +## WP4 - production traversal-time shaping + +**Purpose:** replace prepared-set post-processing with the WP3-proven single +materialization shape. + +**Owner:** coordinator. **Depends on:** WP3 pass. **Owns:** shared compiler +files, focused tests, and `docs/benchmarks/round3/wp4/`. + +### Tasks + +1. Add typed projected fields and retention requirements to the physical set + item contract. Stable field names derive from canonical selector identity. +2. Build requirements after all consumers and descendants are known, then + render them in the set's original `RETURN` object. +3. Rewire eligible extract, aggregate, pivot, slice, predicate, sort, and + derived-field reads to projected fields. +4. Retain `_id` only for descendant traversal, identity only when dedup/order + requires it, and payload only for an explicitly diagnosed unsupported + consumer. +5. Remove or supersede `PhysicalPreparedSet` and its renderer when all supported + uses migrate. Do not maintain two production representations. +6. Validate every projected reference is defined by its source set and cannot + be read outside its item scope. +7. Add diagnostics listing projected selectors, retained fields/reasons, + fallback consumers, estimated item width, and removed payload retention. + +### Tests + +- selector canonicalization and stable names; +- nested-navigation `_id` retention and leaf omission; +- aggregate/pivot/slice/filter/derived rewiring; +- fallback and mixed-consumer behavior; +- duplicate edge and ordering parity; +- live result/profile ablation with rule on/off. + +### Acceptance + +Meet the WP3 gate in production. Delete the rejected second prepared-array path +and its switches/tests once no production use remains. A rule that normally +retains payload is not accepted as traversal-time shaping. + +## WP5 - leaf-set summary pushdown + +**Purpose:** compute leaf aggregate, pivot, and representative-slice outputs +inside one child subquery instead of repeatedly scanning a materialized set. + +**Owner:** coordinator. **Depends on:** WP4. **Owns:** shared compiler files, +focused tests, and `docs/benchmarks/round3/wp5/`. + +### Eligibility + +A set is initially eligible only when it has no navigated descendants and all +of its consumers can be represented by shaped selectors. A summary may contain +different consumers of the same source; byte-identical expression grouping is +not the eligibility rule. + +### IR contract + +Add a typed summary operation with: + +- source identity/dedup contract; +- named aggregate outputs; +- named pivot outputs with key/value/collision semantics; +- named bounded slices with predicate, sort, tie-break, limit, and projections; +- explicit ordering requirements; and +- a fallback reason when a consumer remains outside the summary. + +### Tasks + +1. Group consumers by source set and compatible source identity/predicate scope, + not by identical full expression text. +2. Deduplicate source identity once. Preserve aggregate-specific predicates and + null filtering inside each named result. +3. Keep `COUNT` as direct set cardinality where possible. Preserve + `COUNT_DISTINCT`, `DISTINCT_VALUES`, `MIN`, `MAX`, `FIRST`, and `EXISTS` + semantics exactly. +4. Preserve pivot allowed columns, sparse keys, key/value array behavior, + sorted collision selection, and grouped values. +5. Preserve slice filter, sort-before-limit, stable tie-break, and per-item + projection. A bounded slice must not force an unbounded summary array. +6. Return one typed summary object and have the root projection read named + fields without re-enumerating the child set. +7. Compare summary pushdown alone against WP4 and report incremental benefit. + +### Tests + +- each aggregate operation and null/empty behavior; +- count plus distinct values over one source; +- aggregate plus slice; aggregate plus pivot; all three together; +- same source with different predicates remains semantically independent; +- pivot collision/sparse columns; slice ties/limits; duplicate edges; +- high fan-out and empty leaf sets; auth/generation parity; +- live profile proves fewer post-materialization loops. + +### Acceptance + +Require at least 5% incremental whole-query improvement over WP4 and at least +15% combined improvement over WP0, with no memory regression. Otherwise reject +the operation and remove its unused IR instead of calling diagnostics fusion. + +## WP6 - identity, ordering, and deduplication proof + +**Purpose:** identify exactly which `UNIQUE` and `SORT` operations are redundant +without guessing about AQL executor order. + +**Owner:** experiment worker. **May edit:** isolated experiment tests and +`docs/benchmarks/round3/wp6/`. **Must not edit shared compiler files.** + +### Tasks + +1. Inventory every current `UNIQUE` and `SORT`, its source set, consumer, key, + tie-break, and semantic reason. +2. Model candidate properties on paper/test helpers: + - identity unique by node `_id` or `_key`; + - stable ascending order by an exact key tuple; + - unordered; + - bounded by a known limit; and + - property invalidation by filter, projection, union, traversal, or grouping. +3. Prove duplicate-edge behavior when replacing object-level `UNIQUE` with + identity-key deduplication. Payload/object equality is not identity equality. +4. Test whether set materialization order can satisfy a slice's exact sort and + tie-break. Do not assume traversal order or `UNIQUE` output order. +5. Detect and remove duplicated sort keys such as `_key, _key` only as a + correctness cleanup; measure separately from executor-level sort removal. +6. Prototype removal of one operation at a time and capture parity/profile + evidence. Include high fan-out and intentionally duplicated edges. + +### Acceptance and handoff + +Pass only individual property rules that remove executor sort/dedup work and +meet the targeted/whole-query gate. Hand off transfer/invalidation rules and a +list of proven removals. Reject any rule dependent on undocumented traversal +order. + +## WP7 - production physical properties + +**Purpose:** encode only WP6-proven identity/order facts and use them to avoid +redundant work. + +**Owner:** coordinator. **Depends on:** WP6 pass. **Owns:** shared compiler +files, focused tests, and `docs/benchmarks/round3/wp7/`. + +### Tasks + +1. Add explicit physical properties for identity uniqueness, ordered key tuple, + and bound. Unknown is the safe default. +2. Define property transfer and invalidation for every physical operation. +3. Make dedup and sort requirements explicit consumers of those properties; + suppress an operation only when the input proves the exact requirement. +4. Normalize duplicate sort keys without changing requested direction or null + behavior. +5. Emit diagnostics for every retained and removed sort/dedup operation with + its proof. +6. Add rule-level ablation and profile independently from WP2/WP4/WP5. + +### Acceptance + +All WP6 semantic cases pass, diagnostics contain a proof for every removal, and +the production profile reproduces the measured benefit. An unknown property +must render the current conservative operation. + +## WP8 - conditional batch-root execution experiment + +**Purpose:** test whether processing the root window as a set is materially +faster than executing correlated child work once per root. + +**Run only if:** the five-run warm median remains above 3 seconds after all +accepted WP2/WP4/WP5/WP7 changes. + +**Owner:** experiment worker. **May edit:** isolated experiment tests and +`docs/benchmarks/round3/wp8/`. No shared production edits. + +### Candidate shape + +1. Materialize the scoped, sorted, limited root window exactly once. +2. Look up relevant scoped edges for the complete root identity set. +3. Join scoped child nodes, preserving root identity on every row. +4. Group/deduplicate/shape by root identity. +5. Reassemble output in original root-window order, including roots with no + optional children. + +### Tasks and risks + +- compare correlated and batched shapes at limits 25, 100, and 1,000; +- profile edge-index behavior for `IN root_ids` versus per-root equality; +- prove auth and generation scope before grouping; +- prove duplicate-edge and optional-empty behavior; +- bound intermediate cardinality and memory; and +- test one-hop and nested paths separately before composing them. + +Reject batching if `IN` loses the compound index, memory grows above the global +gate, optional roots disappear, or improvement exists only at one hard-coded +limit/resource. + +### Acceptance and handoff + +Require at least 15% additional whole-query improvement at limit 1,000 and no +more than 5% regression at 25/100. Hand off a typed root-batch/subplan proposal +and evidence; do not productionize in this package. + +## WP9 - conditional catalog-backed physical costing + +**Purpose:** choose among proven physical strategies using real generic +cardinality/width evidence. + +**Run only if:** at least two production-safe strategies have shape-dependent +winners. Statistics are not useful when there is no choice to make. + +**Owner:** coordinator or isolated investigator followed by coordinator merge. + +### Tasks + +1. Trace current `catalog.PopulatedReference.EdgeCount` production ownership and + define a read-only compilation statistics snapshot keyed by validated route, + project, generation, and authorization visibility where available. +2. Never query discovery repeatedly during rendering. Fetch/cache statistics at + the request/compiler boundary with an explicit freshness policy. +3. Estimate root count, edge fan-out, selectivity, retained item width, and + expected materialized rows. Record unknown separately from zero. +4. Use statistics only to choose among strategies already proven semantically + equivalent: shared/independent, native/endpoint, shaped/fallback, or + correlated/batched. +5. Provide a deterministic no-statistics fallback matching a proven production + policy. Statistics never change result semantics. +6. Emit the inputs, estimate, selected strategy, and reason in diagnostics. +7. Test missing, stale, zero, extreme, and contradictory statistics and verify + they cannot cause invalid IR. + +### Acceptance + +The cost policy must select the faster strategy across a route/cardinality +corpus with no protected-case regression. Merely plumbing `EdgeCount` without a +measured strategy-selection win is not completion. + +## WP10 - final integration, deletion, and report + +**Purpose:** retain only proven generic translations and leave one coherent +production compiler. + +**Owner:** coordinator only. **Depends on:** every accepted package. + +### Tasks + +1. Rebase decisions on a fresh WP0 same-session baseline. +2. Run each accepted rule independently and cumulatively at limits 25, 100, and + 1,000. Detect interactions where two individually useful rewrites regress in + combination. +3. Run the full generic unit suite, physical renderer/validator suite, result + parity suite, live Arango Explain/profile suite, auth/generation cases, and + proven outbound route. +4. Save final raw AQL/profile artifacts and a comparison table against WP0. +5. Delete rejected experiments, dead switches, stale diagnostics, unused IR, + the superseded prepared-array path, and documentation claims contradicted by + production code. +6. Confirm no FHIR resource, route, example set variable, or example column is + hard-coded in production optimizer logic. +7. Run `go test ./... -count=1` and the exact five-run demo/profile commands. + +### Final acceptance target + +- exact result parity and zero full scans; +- endpoint-first index selected wherever the accepted strategy requires it; +- peak memory below 200 MB; +- five-run warm Arango median below 4.5 seconds after endpoint/projection work; +- stretch median below 3 seconds after summary/property or batch work; and +- a plain explanation of which physical rewrite removed which scanned items, + payload materialization, set loop, dedup, or sort. + +If the target is not met, report the remaining top profile region honestly. Do +not label added compiler machinery as an optimization without disappeared +runtime work. + +## Luna work-package prompt template + +Use this prompt for each worker, replacing the placeholders exactly: + +```text +Execute in Loom. + +Read docs/LUNA_AQL_EXECUTION_ROUND_3.md and +docs/AQL_EXECUTION_IMPLEMENTATION_AUDIT.md completely, then read every source +file named by the package. Own only . Do not edit shared compiler +files unless this package designates you as coordinator. + +Before editing, record git status and SHA-256 hashes for every owned existing +file. Preserve unrelated dirty changes. Use fhirschema and +resolveStorageRoute; never hard-code a FHIR resource, edge, child_set variable, +or GDC column. Preserve every global semantic contract. + +Run the package baseline first. Implement only this package. Run its named +unit/live tests and produce its required evidence directory. Report changed +files, before/after hashes, raw profile metrics, rejected experiments, the +enable/cost-gate/reject decision, and coordinator decisions required. + +Stop rather than guess if an unowned IR change is required, an owned file +changes concurrently, baseline hashes/results differ unexpectedly, scope or +ordering semantics would change, the intended index is not selected, or the +required profile benefit is absent. +``` diff --git a/docs/LUNA_AQL_OPTIMIZATION_ROUND_2.md b/docs/LUNA_AQL_OPTIMIZATION_ROUND_2.md new file mode 100644 index 0000000..7b297fe --- /dev/null +++ b/docs/LUNA_AQL_OPTIMIZATION_ROUND_2.md @@ -0,0 +1,342 @@ +# Luna High execution plan: AQL optimization round two + +## Mission + +Reduce Loom's warm rich-dataframe AQL time without changing results, +authorization, generation isolation, supported FHIR routes, or GraphQL. The +physical compiler is the only production path. Do not restore compatibility +code or add resource-specific optimizer rules. + +Current live GDC baseline over loaded `META`, database `fhir_proto`, project +`ARANGODB_PROTO`: + +| Measure | Baseline | +|---|---:| +| rows / response | 1,000 / 3,303,295 bytes | +| mean / warm HTTP | 6.364s / 6.339s | +| Arango query | 6.301s | +| warm preparation / compilation | 0.075ms / 1.212ms | +| row materialization / HTTP overhead | 1.748ms / about 35ms | +| traversal sets / eliminated traversals | 4 / 2 | + +The warm bottleneck is Arango, not Go compilation. The first request still +spends about 10.75s in relationship discovery; WP7 addresses that separately. + +Baseline command: + +```bash +make dataframe-demo DATAFRAME_LIMIT=1000 DATAFRAME_REPEAT=3 DATAFRAME_PRINT_RESPONSE=false +``` + +## Read first + +- `docs/AQL_OPTIMIZATION_WORKLIST.md` +- `docs/benchmarks/AQL_PROFILE_CORPUS.md` +- `conformance/compiler/fixtures/gdc-case-matrix.json` +- `examples/meta_gdc_case_matrix.graphql` +- `internal/dataframe/physical_plan.go` +- `internal/dataframe/physical_optimize.go` +- `internal/dataframe/physical_render.go` +- `internal/dataframe/physical_prefix.go` +- `internal/dataframe/physical_cost.go` +- `internal/dataframe/profile.go` +- `internal/store/arango/profile.go` +- `internal/ingest/backend.go` + +Already complete: generic physical lowering, scoped graph traversal, root +windowing, required semi-joins, sibling sharing, aggregates, pivots, slices, +nested objects, prepared sets, structural cost reporting, opt-in profile, and +compatibility renderer deletion. Do not rebuild these foundations. + +## Global contracts + +Every package preserves: + +1. One row per root in stable `_key` order. +2. Columns, row count, null/empty behavior, array order, distinct behavior, + pivot collision behavior, and representative slice choice. +3. Required matching before root `SORT/LIMIT`; optional shaping after it. +4. Project, generation, and authorization checks on every root, node, and edge. +5. Bind-backed request values and names; no request interpolation into AQL. +6. Routes accepted by `resolveStorageRoute` only. +7. Generic physical-property rules only: no production Patient, Specimen, + Observation, GDC, or fixture-label special cases. +8. Disable/remove a rule when parity is unproven or live profile is slower. + +## Evidence required from every optimization + +Publish fixture/data scope, limit, batch size, complete rule policy, canonical +result SHA-256, rows, response bytes, AQL hash, every execution time, five-run +warm median/minimum, profile work counters, peak memory, top ten runtime nodes, +selected indexes, and a conclusion: enable, cost-gate, disable, or remove. + +Object key order must not affect hashes; array order must. Compare identical +database state and binds while changing one rule only. + +## Shared-file ownership + +Only the coordinator merges edits to: + +- `internal/dataframe/physical_plan.go` +- `internal/dataframe/physical_optimize.go` +- `internal/dataframe/physical_render.go` +- `internal/dataframe/physical_cost.go` +- `internal/dataframe/physical_diagnostics.go` + +Workers prepare tests/reports/proposed patches. Never let two workers edit +these files concurrently. Maintain independent developer switches for current +sharing, nested sharing, prepared selectors, rich fusion, and compact set +projection. + +## WP0 — Reproducible baseline and profile attribution + +**Owner:** benchmark worker. **Owns:** `cmd/dataframe-query/`, conformance, +examples, and benchmark docs. No physical compiler edits. + +Implement: + +1. Compile a fixture, execute it, then `EXPLAIN` and profile level 2 using the + same AQL and binds. +2. Support limits 25/100/1,000 and repetitions 1/5. +3. Canonicalize JSON results and calculate SHA-256. +4. Attribute profile nodes to root window, every set/prepared set, aggregate, + pivot, slice, and return. +5. Record scalar-root, optional-child, aggregate+slice, pivot, deep traversal, + sibling, required-match, and GDC baselines. +6. Store optimizer policy and AQL hash in every artifact. + +Acceptance: repeated hashes match; GDC returns 1,000 rows and approximately +3.3MB; top nodes map to physical regions; `go test ./conformance/compiler +./cmd/dataframe-query -count=1` passes. Handoff artifact schema, fixture IDs, +hashes, commands, and the three most expensive regions. + +## WP1 — Independent optimizer-rule ablation + +**Owner:** coordinator. **Depends on:** WP0. + +Implement: + +1. Typed independent decisions for current sharing and prepared selectors; + disabled entries for nested sharing, fusion, and compact projection. +2. Keep `CompileRequest` production-only; add internal/test + `CompileRequestWithPolicy` rather than environment-only control. +3. Report each rule's state, estimate, and rejection reason. +4. Compile the same request while changing exactly one rule. +5. Label every artifact with the full policy. + +Acceptance: live GDC hashes match for no optional rewrites, sharing only, +prepared only, and defaults; `go test ./internal/dataframe +./conformance/compiler -count=1` passes. WP1 enables no new rule. + +## WP2 — Traversal fan-out and nested-prefix optimization + +**Owner:** traversal worker; coordinator merges shared files. **Depends on:** +WP0/WP1. + +Investigate before coding: + +1. Profile sibling sharing on/off for focused fixtures and GDC. +2. Per traversal record parents, edge-index items, node lookups, filtered and + returned items, and runtime. +3. Compare broad multi-type traversal with independent typed traversals. +4. Test whether `POSITION(@target_types, edge type, true)` changes index choice + versus equality. +5. Profile deep paths separately. +6. Find repeated nested prefixes using `DecomposePhysicalTraversalPrefix`. + +Candidate A: cost-aware sibling sharing. Estimate union-neighbor versus +independent typed work from catalog/profile counts; reject broad sharing when +it loses selectivity; report exact inputs/reason. + +Candidate B: nested sharing, only with profile evidence. Require equal parent, +direction, label, scope, and optionality; alpha-rename captures; materialize in +the same parent scope; derive consumer subsets; never move a semi-join after +the root window. + +Tests: zero/one/many neighbors, skewed type distribution, inbound and proven +outbound routes, three-hop equivalence, and rejection for differing auth, +generation, direction, label, or parent. Enable only with identical hashes, no +full scan, reduced targeted work, and at least 5% warm-median improvement. + +## WP3 — Prepared-selector cost and payload minimization + +**Owner:** prepared-set worker; coordinator merges shared files. **Depends on:** +WP0/WP1. May investigate with WP2. + +First profile prepared on/off for aggregate+slice, pivot, deep-child, and GDC. +Record selector calls, prepared items, memory, runtime, and hashes at child +cardinality 0/1/10/100/high-fan-out. + +Implement: + +1. Compute selector union for aggregate values/predicates, pivot key/value, + slice predicate/sort, and slice fields. +2. Project each eligible selector once. +3. Add explicit typed `RetainNode`; retain full nodes only for nested traversal + or an unprepared consumer. +4. Keep single-use selectors direct unless profile proves value. +5. Cost-gate on consumer count, child estimate, field count, and node retention. +6. Keep ordered fallback chains direct until preparation preserves all fallbacks. + +Tests: direct/prepared null, empty, multi-value, distinct, slice ordering, +pivot collisions, shared-subset prepared definitions, bind correctness, and +corpus hashes. Prepared mode must improve focused fixtures and be neutral or +better for GDC; otherwise cost-gate/disable it. + +## WP4 — Fuse compatible rich consumers + +**Owner:** rich-expression worker; coordinator merges IR/renderer. **Depends +on:** WP1 and WP3 evidence. + +Implement a typed consumer group keyed by source, identical predicate, +ordering needs, and prepared schema. Classify count/exists, distinct/min/max, +pivot grouping, and bounded slices. Group only identical semantics. Render one +typed shaping subquery and project columns from its object. Preserve +sort-before-limit, pivot allowed columns/collisions/distinctness, and lexical +scope. Keep disabled until profile passes. + +Tests: identical counts fuse, different predicates do not, count+distinct, +aggregate+slice, aggregate+pivot, empty/null/duplicate/multi-value selectors, +nested scope, and live hash parity. Keep only if loops/items and focused +runtime improve without GDC regression; remove if Arango already fuses it. + +## WP5 — Compact intermediate set projection + +**Owner:** projection worker; coordinator merges renderer. **Depends on:** WP0. + +Implement: + +1. Compute required set properties from downstream selectors, endpoint + identity, `_key`, typing, ordering, and uniqueness. +2. Define typed set output; keep document/full node only for later traversal. +3. Preserve `_key` and run scope predicates before compact projection. +4. Compare full-object `UNIQUE` with identity uniqueness only under + duplicate-edge parity tests. +5. Measure intermediate memory separately from requested response size. + +Tests: nested traversal handle, duplicate edges, ordering/slices, requested +columns, auth/generation ordering, and compact/full hashes. Require lower peak +memory or copied work and neutral/better runtime; otherwise disable/remove. + +## WP6 — Profile-driven Arango index audit + +**Owner:** index worker. **Owns:** `internal/ingest/backend.go`, Arango +explain/profile tests, index docs. No renderer edits. **Depends on:** WP0 and a +repeat after WP2--WP5 stabilize. + +1. Inventory installed indexes, field order, selectivity, and corpus usage. +2. Verify INBOUND `_to,project,dataset_generation,label,from_type` and OUTBOUND + `_from,project,dataset_generation,label,to_type` indexes. +3. Determine whether multi-type sharing uses compound or default edge indexes. +4. Test alternative orders only with disposable named indexes. +5. Compare equality-per-type and multi-type traversal. +6. Verify root scope plus `_key` sort avoids unrelated roots. +7. Record ingest time, index size, runtime, and scanned work. Add no speculative + index and remove none without corpus proof. + +Acceptance: checked-in shape/index matrix, no execution full scans, documented +tradeoffs, and `go test ./internal/ingest ./internal/store/arango -count=1`. + +## WP7 — Ingest-time relationship catalog + +**Owner:** catalog/ingest worker. **Owns:** catalog, ingest, loader command, and +related tests/docs. No physical compiler edits. May run with WP2--WP6. + +Create an ingest-owned relationship catalog keyed by project, generation, +auth path, from type, label, to type, and edge count. + +1. Bootstrap indexed builder lookup by project/generation/to-type and storage + lookup by project/generation/from-type, with auth where required. +2. Count successfully committed edges, not attempted rows. +3. Define legacy rebuild and immutable-generation behavior. +4. Read discovery from catalog; retain direct edge aggregation only as explicit + repair/backfill, never request fallback. +5. Add rebuild command for the existing 14.5-million-edge database. +6. Invalidate memory cache only after successful import/rebuild. +7. Preserve restricted authorization aggregation. + +Tests: empty data, two projects/generations, restricted/unrestricted auth, +idempotent rebuild, failed writes, builder orientation, and catalog/direct +parity. Gate: cold discovery performs no edge scan, GDC preparation below +250ms, and `go test ./internal/catalog ./internal/ingest +./cmd/arango-fhir-proto -count=1`. + +## WP8 — Durable parity/profile regression gates + +**Owner:** conformance worker. **Depends on:** WP0 and consumes WP2--WP7. + +1. Audit that every supplied bind is referenced and every AQL bind has a + value, correctly handling `@@collection` and prefix collisions. +2. Audit physical set/prepared variable definitions and lexical uses. +3. Compare canonical hashes across WP1 ablations. +4. Add opt-in live gates for indexes, `scannedFull == 0`, rows, and hashes. +5. Use generous timing ceilings; fail primarily on structural regressions. +6. Assert discovery uses the catalog, never direct aggregation. +7. Document exact 25/100/1,000 and profile commands. + +Acceptance: tests catch historical missing `child_set_1_prepared` and unused +`child_set_2_label`; corpus hashes match; `go test ./... -count=1` passes +offline; opt-in live suite passes. + +## WP9 — Integrate proven rules and publish baseline + +**Owner:** coordinator. **Depends on:** WP2--WP8 evidence. + +Review hashes, work counters, warm median, memory, and regressions. Classify +each rule as default, shape-cost-gated, experimental, or rejected. Delete +rejected prototype code. Run full unit/conformance/live suites and +25/100/1,000 plus cold discovery benchmarks. Publish hashes, AQL hashes, +profiles, and timings. + +Done: no normal execution/discovery full scans, cold preparation below 250ms, +all correctness contracts pass, and warm GDC median is below 6.34s. If it does +not improve, document the profile-proven irreducible fan-out and next physical +strategy rather than claiming success. + +## Parallel waves + +Wave 1, concurrent: Luna A WP0; Luna B WP6 investigation; Luna C WP7; +coordinator WP1. Merge WP0 contract before WP1 controls. WP7 is independent. + +Wave 2 after WP0/WP1, concurrent without shared-file edits: Luna D WP2; Luna E +WP3; Luna F WP5; Luna B repeat WP6. Workers deliver tests/reports/proposed +patches. Coordinator integrates one candidate, profiles, retains/removes, then +takes the next. + +Wave 3 after WP3 decision: Luna G WP4; Luna H WP8; Luna B final WP6; +coordinator sequential integration. + +Wave 4: coordinator executes WP9 alone. No new optimizer design during final +integration. + +## Copy-paste worker prompt + +```text +Execute in Loom. + +Read docs/LUNA_AQL_OPTIMIZATION_ROUND_2.md completely, then the package files +it lists. Own only . Do not edit physical_plan.go, +physical_optimize.go, physical_render.go, physical_cost.go, or +physical_diagnostics.go unless designated coordinator. + +Preserve every global contract. Use fhirschema and resolveStorageRoute; never +hard-code a FHIR type/route. Preserve unrelated dirty changes. Use apply_patch +and prefix shell commands with rtk. + +Run baseline tests, implement only this package, run named unit/live tests, +produce the required evidence artifact, and report changed files, hashes, +profile metrics, rejected experiments, and coordinator decisions needed. + +Stop rather than guess if an unowned IR change is required, hashes differ, +scope semantics change, profile benefit is absent, or an owned file changed +concurrently. +``` + +## Coordinator merge checklist + +For each candidate: reject resource-specific logic; run focused tests and +`go test ./... -count=1`; compile optimized/ablated AQL from the same request; +verify binds and lexical variables; compare hashes at 25/1,000 rows; confirm +indexes/no full scan; compare five warm runs and profiles; record median, work, +and memory; then enable, cost-gate, or remove. + diff --git a/docs/LUNA_AQL_RUNTIME_ROUND_4.md b/docs/LUNA_AQL_RUNTIME_ROUND_4.md new file mode 100644 index 0000000..08ae69a --- /dev/null +++ b/docs/LUNA_AQL_RUNTIME_ROUND_4.md @@ -0,0 +1,676 @@ +# Luna multi-agent execution plan: AQL runtime round 4 + +## Mission + +Reduce the real GDC dataframe operation from its current roughly 5.7-second +Arango execution median to **1–3 seconds for 1,000 rows**, while preserving +generic FHIR semantics, authorization, generation isolation, deterministic +output, and bounded memory. + +This round is runtime-first. A memory reduction is valuable, but it does not +qualify as the principal result of a work package unless runtime also improves. +Compiler construction time, GraphQL input mapping, AQL planning, query +execution, row transfer, JSON materialization, and optional export are measured +separately so frontend turnaround can be predicted honestly. + +The target represents the first execution of a newly requested dataframe +shape. Do not use Arango's result cache to meet it. Repeated identical queries +may be reported as additional evidence, but cached results are not the product +SLO. + +Read these files completely before starting any package: + +- `docs/AQL_EXECUTION_IMPLEMENTATION_AUDIT.md` +- `docs/LUNA_AQL_EXECUTION_ROUND_3.md` +- `docs/benchmarks/round3/WP10_REPORT.md` +- `docs/benchmarks/round3/wp4/production.aql` +- `docs/benchmarks/round3/wp4/production.json` + +## Invariant request and current baseline + +Every promotion decision uses the actual frontend input path: + +- GraphQL document: `examples/meta_gdc_case_matrix.graphql` +- GraphQL variables: `examples/meta_gdc_case_matrix.variables.json` +- mapping: `graphqlapi/dataframe.BuilderFromInput` +- project: `ARANGODB_PROTO` +- database: `fhir_proto` +- root limit: 1,000 + +The compiler fixture `conformance/compiler/fixtures/gdc-case-matrix.json` is +useful for unit coverage but is not interchangeable with the real GraphQL +input and cannot provide promotion evidence. + +Current production facts: + +| Measure | Value | +|---|---:| +| result SHA-256 | `17faea7ac3ee7f308b37223f376530a0660f8068d5e015cc573cf99ccb4045ca` | +| production AQL SHA-256 | `4081527f4d893c7fc8b4957ad75ffbf51a975a8b646c315f01d09093444aad68` | +| five-run Arango executing median | approximately 5.67s | +| indexed items | 475,876 | +| full scans | 0 | +| peak memory | 194,117,632 bytes | +| native traversals | 4 | +| native traversal edge index | default `fhir_edge(_to)` | +| child-set materializations | 6 typed sets plus one broad shared set | +| child-set sorts | 7 plus three representative-slice sorts | +| repeated projected-set consumer loops | at least 7 | + +The root index and root limit are already effective. The remaining work is +dominated by traversal adjacency, correlated child materialization, selector +enumeration, deduplication, sorting, aggregate/pivot/slice consumers, and final +row construction. + +## Product SLO and promotion thresholds + +### Primary target + +- exact 1,000-row result; +- five alternating, non-result-cached candidate/control runs; +- candidate Arango `executing` median between 1 and 3 seconds; +- end-to-end GraphQL median below 4 seconds when the local API is available; +- peak Arango memory at or below 200 MB; +- zero full collection scans; and +- no authorization, generation, ordering, null, pivot, slice, or duplicate-edge + semantic drift. + +### Incremental package gate + +A package can merge before the final target only if it produces one of: + +1. at least 10% lower whole-query Arango median; or +2. at least 25% lower target-region indexed/items/calculation work and at least + 5% lower whole-query median; or +3. at least 15% lower end-to-end time for a previously dominant non-Arango + stage, without moving work out of the measured boundary. + +Memory must not regress by more than 10%. A candidate that improves runtime by +20% or more may use up to 225 MB temporarily, but it must carry an explicit +memory follow-up before default enablement. + +### Stop rule + +Reject a package when it changes only AQL text, estimated cost, or optimizer +diagnostics without removing measured runtime work. Do not retain alternate IR, +renderer branches, environment switches, or indexes for rejected candidates. + +## Benchmark protocol + +WP0 owns the protocol. Every worker consumes its artifacts unchanged. + +1. Record Arango version, edition, CPU allocation, container memory, database + document/edge counts, active index definitions, index cache state, and Loom + git/worktree hashes. +2. Disable query result caching for benchmark requests. Record whether plan + caching exists and whether the first execution populated it. +3. Alternate control and candidate: `C1, N1, C2, N2 ... C5, N5`. Do not run all + controls and then all candidates. +4. Use identical binds, limit, cursor batch size, database state, and output + consumption. Consume every result row. +5. Record both Arango `PROFILE` and ordinary query timings. `PROFILE` is not a + substitute for client wall time. +6. Record AQL/result hashes, response rows, uncompressed JSON bytes, compressed + bytes if relevant, and serialization throughput. If output transfer alone + exceeds the SLO, report that ceiling explicitly. +7. Record phase times: input mapping, semantic plan, physical plan, rendering, + Arango parsing/planning/executing/finalizing, cursor transfer, Go row + materialization, GraphQL result assembly, and optional NDJSON/Elasticsearch + export. +8. Record selected indexes, optimizer rules, scanned full/index, document + lookups, peak memory, calls/items/filtered/runtime for traversal, index, + calculation, list, collect, sort, limit, and return nodes. +9. Count rendered native traversals, explicit edge loops, `LET` child arrays, + `UNIQUE`, `COLLECT`, `SORT`, projected-set consumer loops, selector + subqueries, and retained payloads. +10. Preserve raw AQL and raw profile JSON under the package evidence directory. + +The profile comparator must not sum cumulative nested node runtimes. Use the +Arango executing phase and client wall clock for whole-query decisions. + +## Global semantic contracts + +Every candidate preserves: + +1. one row per root and exact ascending root `_key` order; +2. project, dataset-generation, authorization, and required root membership + before root `SORT/LIMIT`; +3. optional child shaping after the root window; +4. project, exact generation, and authorization checks on every edge and node; +5. routes exclusively from `resolveStorageRoute` and generated `fhirschema`; +6. inbound and proven outbound behavior, including + `ResearchSubject -> ResearchStudy`; +7. bind-backed user values and validated collection/index metadata; +8. duplicate-edge node identity semantics; +9. exact output columns, values, types, null/empty behavior, array ordering, + `SORTED_UNIQUE`, pivot collision selection, and slice sort-before-limit; +10. deterministic fallback when an index, statistic, server capability, or + specialized strategy is unavailable; and +11. no production branch on GDC, `Patient`, `child_set_N`, example aliases, or + example field names. + +## Shared-file ownership + +Only the coordinator may edit these shared production files: + +- `internal/dataframe/physical_plan.go` +- `internal/dataframe/generic_physical_plan.go` +- `internal/dataframe/physical_optimize.go` +- `internal/dataframe/physical_render.go` +- `internal/dataframe/physical_cost.go` +- `internal/dataframe/physical_diagnostics.go` +- `internal/dataframe/physical_helpers.go` +- `internal/dataframe/physical_execution.go` +- `internal/dataframe/compile.go` +- `internal/dataframe/storage_route.go` + +Experiment workers may add isolated `*_experiment_test.go` files and evidence +under `docs/benchmarks/round4//`. They stop and hand off a typed IR proposal +when production changes are required. + +WP0 alone may edit `cmd/dataframe-profile/`, `cmd/dataframe-query/`, and the +benchmark targets in `Makefile`. Index-definition changes are owned by the +index coordinator and require an explicit before/after index inventory; no +worker may create or remove indexes implicitly from a test. + +## Parallel execution graph + +```text +Wave 0, serialized: + WP0 benchmark integrity and capability lock + +Wave 1, four independent experiments (maximum three workers concurrently): + WP1 native traversal OPTIONS matrix + WP2 explicit endpoint full-query substitution + WP3 identity-first dedup-before-shaping + WP4 selector/expression lowering + +Wave 2, serialized coordinator production merges: + WP5 traversal strategy production integration (WP1/WP2 winners only) + WP6 identity-first set production integration (WP3 winner only) + WP7 expression lowering integration (WP4 winner only) + +Wave 3, three parallel architectural experiments against the new baseline: + WP8 leaf summary pushdown + WP9 batch-root/set-oriented execution + WP10 output materialization and export throughput + +Wave 4, serialized: + WP11 production integration and structural cost policy + WP12 combined 1–3 second gate, cleanup, and report +``` + +Wave 1 workers do not wait on each other. With four total agent slots, keep the +coordinator free and start WP1, WP2, and WP3 first; start WP4 when the first +worker slot becomes available. This is a scheduling constraint, not a data +dependency. Wave 2 is serialized because each merge changes the physical +baseline. Wave 3 starts only after all accepted Wave 2 changes are re-profiled +together. In Wave 3, WP8, WP9, and WP10 may occupy all three worker slots while +the coordinator protects shared production files. + +## Official Arango references + +Workers must verify syntax and version support against the server reported by +WP0. These are the primary references for this round: + +- query optimization and optimizer rules: + +- traversal execution options, including `parallelism`, `maxProjections`, + `indexHint`, and `useCache`: + +- profiling and execution-node statistics: + + +The optimizer is cost-based, but it cannot be credited with inventing Loom's +semantic batching, selector reuse, identity-first shaping, or consumer fusion. +Those transformations must be represented explicitly and proven by profiles. + +## WP0 — benchmark integrity and Arango capability lock + +**Owner:** coordinator. **May edit:** profiling commands, benchmark Makefile +targets, focused profiling tests, and `docs/benchmarks/round4/wp0/`. + +### Tasks + +1. Prove the benchmark command uses `BuilderFromInput` on the actual variables + file. Include the effective semantic/physical plan hash in the report. +2. Query and record the exact Arango server version. Mark support for traversal + `indexHint`, `parallelism`, `maxProjections`, `useCache`, collection index + hints, stored values, query plan cache, and result-cache controls. +3. Inventory all `fhir_edge` indexes with name, ID, fields, direction + applicability, selectivity, cache configuration, stored values, and size. +4. Verify inbound compound coverage begins with `_to` and outbound coverage + begins with `_from`. Record missing symmetric indexes without creating them. +5. Add alternating control/candidate execution and output-byte accounting to + the profile harness. +6. Add `-cache=false`, cursor batch size, ordinary-run count, and raw artifact + directory flags where the Arango API supports them. +7. Capture five alternating baseline pairs to quantify normal variance. +8. Measure compilation separately. If semantic+physical+rendering exceeds + 100ms, create a compiler-only follow-up; do not mix it into AQL execution. +9. Measure uncompressed result bytes and local cursor transfer throughput. State + whether 1–3 seconds is physically plausible for the current output size. + +### Acceptance + +- identical AQL/result hashes across unchanged runs; +- median pair variance below 10%, or a documented environment fix; +- exact Arango capability and index inventory; +- result cache proven disabled; and +- raw baseline artifacts in `docs/benchmarks/round4/wp0/`. + +## WP1 — native traversal OPTIONS matrix + +**Purpose:** determine whether Arango's native traversal can use existing +vertex-centric indexes and multiple cores without switching to explicit joins. + +**Owner:** traversal-options worker. **May edit:** isolated experiment tests +under `internal/dataframe/` or `internal/store/arango/` and +`docs/benchmarks/round4/wp1/`. No shared production files or indexes. + +### Candidate matrix + +Test one traversal region at a time, starting with the most expensive nested +region. Compare: + +1. current native traversal; +2. native plus compound vertex-centric `indexHint`; +3. native plus `parallelism` values 2, 4, and 8 bounded by available CPUs; +4. native plus index hint and each useful parallelism value; +5. useful candidates with `maxProjections` values 5, 8, and an explicit full + document threshold; and +6. `useCache` true/false only to diagnose cache pollution, not as the primary + speed mechanism. + +### Tasks + +1. Obtain edge collection, direction, route discriminator, and expected index + from validated route/index metadata. Hard-coded index names are allowed only + in isolated AQL probes and must be replaced by a typed metadata contract in + the handoff. +2. Test inbound and outbound index-hint syntax separately. Confirm the index is + eligible and actually selected by `EXPLAIN`; a hint is not assumed to be + forced. +3. Test the root shared multi-type traversal and each nested single-type route. + Multi-type `IN` and equality must have separate evidence. +4. Preserve all edge/node scope and deterministic post-traversal order. +5. Record CPU utilization and whether parallelism reduces wall time or merely + increases contention/memory. +6. Run isolated region tests and the full actual GDC query. Region-only wins do + not promote a production default. + +### Stop conditions + +- reject a hint if `EXPLAIN` still selects only the default edge index; +- reject parallelism if whole-query runtime or memory regresses; +- do not use `PRUNE` to change a depth-one result filter; +- do not force an index unsupported by the active server version; and +- stop if dynamic edge collection/index metadata cannot be represented without + a shared IR change. + +### Acceptance and handoff + +Pass only a generic structural strategy meeting the incremental gate on the +full query. Hand off traversal option fields, capability checks, index metadata +requirements, exact AQL, and default/fallback policy. + +## WP2 — explicit endpoint full-query substitution + +**Purpose:** determine whether explicit indexed edge equality beats native +traversal in the actual correlated dataframe plan. + +**Owner:** endpoint worker. **May edit:** isolated experiment tests and +`docs/benchmarks/round4/wp2/`. No shared production files or indexes. + +### Tasks + +1. Begin from the exact WP0 production AQL/binds. Replace exactly one nested + traversal region at a time with explicit endpoint equality. +2. For INBOUND, filter edge `_to == parent._id` plus project, generation, label, + and `from_type` equality before `DOCUMENT(edge._from)` or an indexed node + join. OUTBOUND uses `_from`, `to_type`, and `_to`. +3. Compare `DOCUMENT(endpoint)` with a primary-index collection join. Record + document lookups and memory for both. +4. Preserve auth on both edge and node, node type verification, duplicate-edge + identity, child filters, sorting, and compact projection. +5. Test the three actual nested GDC routes, then combinations of two and all + three. Region interactions must be measured; isolated percentages cannot be + added together. +6. Test shared explicit `IN` only as a control. Previous evidence shows it can + be fast while still missing the compound index. +7. Run five alternating full-query pairs for every promotable combination. + +### Acceptance and handoff + +Pass when endpoint equality selects the compound index, exact parity holds, +and the full query meets the incremental gate without unacceptable memory. +Hand off a typed native/explicit strategy proposal and supported route classes. + +## WP3 — identity-first deduplication before shaping + +**Purpose:** stop applying object-level `UNIQUE` to identity-plus-selector +objects containing arrays. + +**Owner:** identity worker. **May edit:** isolated experiment tests and +`docs/benchmarks/round4/wp3/`. No shared production files. + +### Candidate shapes + +Compare the current shape against: + +1. deduplicate scoped nodes by `_id` before selector extraction, then sort and + shape; +2. `COLLECT node_id = node._id INTO group` followed by deterministic node + selection and shaping; +3. `RETURN DISTINCT node._id` followed by primary lookup and shaping; and +4. identity-key object projection followed by selector projection. + +### Tasks + +1. Prove scope runs before identity deduplication. +2. Use duplicate-edge fixtures where one node appears through multiple edges. +3. Preserve one stable node document per `_id`; never deduplicate solely by + payload or shaped object equality. +4. Sort after any operation whose output order is unspecified. Do not rely on + traversal, `UNIQUE`, or `COLLECT` order. +5. Apply one region at a time and report removed object width, calculation + nodes, collect/unique work, memory, and whole-query runtime. +6. Include shared subsets, nested sets, empty sets, auth/generation, and + outbound routes. + +### Acceptance and handoff + +Pass only the identity operation that removes measured work and satisfies the +incremental gate. Hand off explicit identity/order properties and invalidation +rules; do not propose general sort removal. + +## WP4 — selector and expression lowering + +**Purpose:** reduce calculation/list-node work caused by generic singleton +selector subqueries and repeated selector enumeration. + +**Owner:** expression worker. **May edit:** isolated experiment tests and +`docs/benchmarks/round4/wp4/`. No shared production files. + +### Tasks + +1. Inventory every selector expression in the actual AQL and classify: + - direct scalar path; + - optional scalar path; + - fixed index; + - repeated array path; + - predicate-bearing selector; + - fallback chain; and + - derived/nested object expression. +2. Compare current `FOR __root IN [payload]` lowering against direct attribute + access for schema-proven scalar selectors. +3. Compare conditional array expansion against current nested subqueries for + schema-proven repeated paths. +4. Compute each selector union once per shaped child item and verify every + consumer reads the same field. Count remaining projected-set loops. +5. Test common-subexpression `LET` placement within the child loop versus outer + correlated expressions. +6. Preserve missing/null, array, fallback, filter quantifier, primitive type, + and FHIR choice-field behavior using `fhirschema`; no path heuristics. +7. Measure calculation/list nodes and whole-query time. Reduced AQL length is + not evidence. + +### Acceptance and handoff + +Pass only schema-proven lowering families meeting the incremental gate across +the protected selector corpus and actual query. Hand off typed selector +execution modes, never raw AQL fragments. + +## WP5 — production traversal strategy integration + +**Owner:** coordinator. **Depends on:** WP1 and/or WP2 passing. + +### Tasks + +1. Add typed traversal execution fields for native options and/or explicit + endpoint lookup. Store no raw AQL. +2. Validate direction, endpoint, discriminator, collection, index metadata, + server capability, and fallback strategy. +3. Render only experiment-approved route classes. +4. Add deterministic rule ablation and diagnostics showing selected strategy, + index expectation, parallelism, estimated/observed fan-out, and rejection + reason. +5. Preserve required matches and unsupported traversal forms on their existing + correct path. +6. Re-run actual full-query parity/profile after each accepted strategy rather + than merging all changes before measurement. + +### Acceptance + +The production execution path must reproduce the experiment's full-query win, +selected index, memory bound, and all semantic tests. + +## WP6 — production identity-first set integration + +**Owner:** coordinator. **Depends on:** WP3 passing. + +### Tasks + +1. Add typed identity/dedup/order requirements to `PhysicalSet`. +2. Apply scope before dedup, dedup before selector projection, and explicit sort + after any order-invalidating operation. +3. Render only the winning dedup shape. +4. Diagnose identity key, dedup strategy, order proof, shaped width avoided, + and retained fallback. +5. Add duplicate-edge, auth/generation, nested, outbound, and rich-shape parity + tests plus full-query ablation. + +### Acceptance + +Production must reproduce WP3's runtime improvement. Unknown identity/order +properties retain the current conservative behavior. + +## WP7 — production selector/expression integration + +**Owner:** coordinator. **Depends on:** WP4 passing. + +### Tasks + +1. Add typed selector execution modes derived from generated schema metadata. +2. Render direct scalar/array access only for proven-safe selector shapes. +3. Retain generic subquery lowering for predicates, fallbacks, unsupported + choices, and unknown cardinality. +4. Validate mode/path/cardinality consistency in physical IR. +5. Add diagnostics and ablation for each lowering family. +6. Run the generic selector conformance corpus and actual full-query profile. + +### Acceptance + +Each enabled family independently passes parity and the incremental gate. Do +not default-enable a combined family whose individual contribution is unknown. + +## WP8 — leaf summary pushdown + +**Purpose:** replace repeated aggregate, pivot, and slice scans over one shaped +leaf set with one summary-producing subquery. + +**Owner:** summary worker. **May edit:** isolated experiment tests and +`docs/benchmarks/round4/wp8/` until coordinator promotion. + +### Tasks + +1. Identify leaf sets with no navigated descendants and no unsupported escaping + consumer. +2. Deduplicate identity once, then compute named outputs in one correlated + summary contract: + - count; + - count distinct/distinct values/min/max/first/exists; + - bounded pivot pairs and collision reduction; and + - representative slice with exact predicate, sort, tie-break, limit, and + projection. +3. Compare one summary object against current independent loops. Do not create + a larger unbounded intermediate array. +4. Test each operation alone, compatible mixtures, incompatible predicates, + empty/high-fanout sets, duplicate edges, and auth/generation. +5. Apply to the actual diagnosis, sample, file, group-file, and observation + sets; report incremental wins per source. +6. Count eliminated child-set enumerations and calculation nodes. + +### Acceptance and handoff + +Require at least 10% additional whole-query improvement from the post-Wave-2 +baseline. Hand off a typed `PhysicalSetSummary` proposal with named outputs and +fallback reasons. + +## WP9 — batch-root/set-oriented execution + +**Purpose:** replace 1,000 correlated root-by-root child pipelines with batched +edge/node work over the complete root window. + +**Owner:** batch worker. **May edit:** isolated experiment tests and +`docs/benchmarks/round4/wp9/` until coordinator promotion. + +### Candidate shape + +1. materialize the scoped, sorted, limited root window once; +2. create a root identity set; +3. retrieve scoped edges for all root IDs using indexed endpoint access; +4. join scoped nodes and retain root identity; +5. deduplicate/shape/group by root identity; and +6. left-join summaries back to the root window in exact root order, preserving + roots with no optional children. + +### Tasks + +1. Compare per-root equality, batched `IN`, chunked root IDs, and grouped edge + scans. Record whether compound indexes remain selected. +2. Test root batch sizes 25, 100, 250, 500, and 1,000. Bound intermediate + cardinality and memory. +3. Start with one relationship and one output, then add nested paths. Attribute + each step. +4. Preserve optional-left-join semantics, root ordering, duplicate-edge + identity, auth/generation, and outbound direction. +5. Compare batch execution to the best accepted correlated plan, not Round 3. +6. Reject any shape that requires loading all project edges before the root + limit or loses the endpoint compound index. + +### Acceptance and handoff + +Require at least 20% additional whole-query improvement at 1,000 rows and no +more than 5% regression at 25/100 rows. Hand off typed batch/subplan/grouping +IR only after parity and memory pass. + +## WP10 — output materialization and export throughput + +**Purpose:** ensure the frontend-visible turnaround is not dominated by cursor +transfer, JSON assembly, or export after AQL reaches the target. + +**Owner:** runtime pipeline worker. **May edit:** isolated benchmark commands, +tests, and `docs/benchmarks/round4/wp10/`; no compiler semantics. + +### Tasks + +1. Measure AQL execution, cursor fetch, RawMessage decoding, GraphQL assembly, + response encoding, NDJSON/CSV encoding, and Elasticsearch bulk-body creation + separately for the exact 1,000 rows. +2. Record response bytes and rows/MB per second. +3. Compare cursor batch sizes without changing query results or memory bounds. +4. Test streaming rows directly into NDJSON/Elasticsearch bulk format instead + of retaining the full result in Go, if the existing API boundary permits it. +5. Do not hide AQL work in asynchronous background processing when measuring + "dataframe created". Report accepted/queued and fully-created latency + separately if a job API is proposed. +6. Do not use response compression to claim lower server computation time; + report transport benefit separately. + +### Acceptance + +The non-Arango pipeline should add less than one second for 1,000 rows on the +local development server, or produce a concrete throughput/output-size limit +that changes the product SLO. + +## WP11 — production integration and cost policy + +**Owner:** coordinator. **Depends on:** passing WP8 and/or WP9 plus accepted +Wave-2 production changes. + +### Tasks + +1. Add only experiment-proven summary/batch IR. +2. Integrate accepted strategies sequentially and re-profile after each. +3. Carry route cardinality, root limit, projected width, fan-out, server + capability, and available index metadata into deterministic structural + choices. +4. Statistics may choose only among semantically equivalent proven strategies. + Unknown statistics use the safest measured fallback. +5. Emit a decision trace suitable for frontend/admin diagnostics without + exposing authorization values. +6. Remove superseded prepared-array, rejected alternate renderers, stale rule + switches, and test-only production hooks. + +### Acceptance + +Combined production AQL reproduces individual wins, exact parity, and the +memory gate. If two individually useful rules regress together, keep the faster +combination and remove the loser. + +## WP12 — 1–3 second final gate and cleanup + +**Owner:** coordinator only. + +### Tasks + +1. Capture fresh alternating controls for the final production policy and every + accepted rule ablation at limits 25, 100, and 1,000. +2. Run the full Go suite, conformance/compiler suite, live Arango parity, + Explain/index, auth/generation, duplicate-edge, deep traversal, required + match, inbound, outbound, aggregate, pivot, slice, fallback, and derived + field cases. +3. Save final AQL, raw profiles, result hashes, response bytes, end-to-end + timings, selected indexes, CPU, and memory. +4. Delete rejected experiments from production code and update all stale + completion claims. +5. Report contribution by rewrite; do not attribute the combined win to all + packages equally. + +### Final decision + +The round succeeds when the actual 1,000-row request has: + +- five-run non-cached Arango median at or below 3.0 seconds; +- stretch median near 1.0–2.0 seconds; +- exact canonical result hash; +- zero full scans; +- peak memory at or below 200 MB; and +- end-to-end local API median below 4.0 seconds. + +If execution remains above three seconds, the final report identifies the +largest remaining node family and answers whether the limit is query shape, +edge/storage layout, output size, or available CPU. Do not close the round with +"more optimization may be possible." + +## Luna worker prompt template + +```text +Execute from docs/LUNA_AQL_RUNTIME_ROUND_4.md. + +Read the Round 4 plan, AQL implementation audit, Round 3 plan, Round 3 final +report, and every file named by this package completely. Own only . Do not edit shared compiler files unless designated coordinator. + +Before editing, record git status and SHA-256 hashes of owned existing files. +Preserve unrelated dirty changes. Use apply_patch and prefix shell commands +with rtk. Use the real examples/meta_gdc_case_matrix.variables.json through +BuilderFromInput for performance evidence; compiler fixtures are unit coverage +only. Use fhirschema and resolveStorageRoute and never hard-code a FHIR type, +route, child_set variable, example alias, or index name in production. + +Run WP0's alternating, cache-disabled baseline first. Implement only this +package. Preserve every global semantic contract. Run named unit/live tests and +write raw AQL/profile evidence under docs/benchmarks/round4//. + +Report changed files and hashes, exact commands, five raw alternating times, +medians, AQL/result hashes, response bytes, scanned items, document lookups, +peak memory, selected indexes, top profile nodes, structural work removed, +rejected candidates, and enable/cost-gate/reject decision. + +Stop rather than guess if an unowned IR change is required, an owned file +changes concurrently, the result hash differs, the intended index is not +selected, scope/order semantics change, server capability is absent, output is +not fully consumed, or the required runtime benefit is missing. +``` diff --git a/docs/LUNA_FRONTEND_ENABLEMENT_PART_5.md b/docs/LUNA_FRONTEND_ENABLEMENT_PART_5.md new file mode 100644 index 0000000..b9b9448 --- /dev/null +++ b/docs/LUNA_FRONTEND_ENABLEMENT_PART_5.md @@ -0,0 +1,1103 @@ +# Part 5: Luna frontend-enablement execution plan + +## Mission + +Build the thin product API needed for a nontechnical frontend without moving +FHIR knowledge, graph safety, AQL generation, authorization, or dataset +generation logic into the browser. + +This part starts from a working compiler and execution service. It does not +redesign the physical compiler. It adds six frontend-facing capabilities: + +1. dataset and root-resource discovery; +2. guided dataframe templates; +3. compile/validate without execution; +4. structured frontend errors; +5. stable preview paging; +6. streaming NDJSON and CSV export. + +The resulting primary flow is: + +```text +list datasets + -> choose a guided template + -> inspect available fields, filters, traversals, and pivots + -> validate and normalize the request + -> preview bounded pages + -> stream NDJSON or CSV +``` + +Saved recipes, durable jobs, Elasticsearch delivery, a large frontend, and +additional AQL optimization tournaments are outside Part 5. + +## Repository facts Luna must preserve + +Read these files before changing code: + +- `README.md` +- `docs/QUICKSTART.md` +- `docs/DEVELOPER_ARCHITECTURE.md` +- `docs/FORMAL_GAP_ANALYSIS.md` +- `graphqlapi/schema.graphqls` +- `graphqlapi/handler.go` +- `graphqlapi/schema.resolvers.go` +- `graphqlapi/output_mapping.go` +- `graphqlapi/dataframe/service.go` +- `graphqlapi/dataframe/introspection.go` +- `graphqlapi/dataframe/input_resolution.go` +- `graphqlapi/dataframe/input_mapping.go` +- `internal/dataframe/service.go` +- `internal/dataframe/execution.go` +- `internal/dataframe/compile.go` +- `internal/dataframe/builder_types.go` +- `internal/catalog/types.go` +- `internal/catalog/read_fields.go` +- `internal/catalog/read_references.go` +- `internal/dataset/active_resolver.go` +- `internal/dataset/manifest.go` +- `internal/httpapi/server.go` +- `internal/httpapi/routes.go` +- `cmd/arango-fhir-server/main.go` +- `fhirschema/` +- `examples/meta_gdc_case_matrix.graphql` +- `examples/meta_gdc_case_matrix.variables.json` + +Current, real foundations: + +- `dataframeBuilderIntrospection` exposes populated fields, references, + distinct values, pivot candidates, and relationship cardinality. +- `runFhirDataframe` resolves `fieldRef` values, validates the request, lowers + through the physical compiler, executes AQL, and returns flattened rows. +- `dataframe.Service.Stream` already delivers flattened rows without retaining + the entire result in Loom memory. +- active immutable dataset generation resolution is available through + `dataset.ActiveManifestResolver`. +- request principal and authorization-path resolution already exist in + `internal/authscope`. +- the compiler owns FHIR selectors and routes through `fhirschema` and + `resolveStorageRoute`. + +Do not duplicate any of these foundations in a new product package. + +## Global contracts + +Every work package must preserve the following: + +1. The browser never constructs AQL and never decides whether a FHIR route is + physically safe. +2. Public field choices use stable `fieldRef` values. Raw selectors may be + returned for diagnostics but are not required by the primary UI. +3. Project, active generation, and resolved authorization scope are selected + once per request and propagated into every catalog, validation, preview, + and export operation. +4. A restricted caller with no surviving auth-resource paths receives no data; + an empty list must never be reinterpreted as unrestricted. +5. Only READY active generations are advertised in generation-aware mode. +6. Legacy mutable META mode remains supported deliberately. Its generation is + represented consistently as absent/null, not invented. +7. Requests and cursor tokens never embed raw AQL, credentials, or unvalidated + collection names. +8. Output row semantics, column names, pivot flattening, stable root ordering, + and null/array behavior remain identical between preview and export. +9. All lists returned to the frontend have deterministic ordering. +10. No Patient-, Observation-, GDC-, fixture-, or edge-label-specific branch is + allowed in compiler, catalog, pagination, or export code. +11. Template definitions may name FHIR resource types and semantic field + preferences because they are product metadata, but availability must be + proven from the current catalog and `fhirschema`. +12. GraphQL generated files are generated, never manually edited. +13. Preserve unrelated dirty-worktree changes. Stop if an owned file changes + concurrently. + +## Part 5 public API target + +The coordinator should freeze this semantic API before workers begin. Exact +GraphQL naming can change during schema review, but the information and +behavior must remain stable. + +```graphql +type Query { + dataframeDatasets: [DataframeDataset!]! + + dataframeTemplates( + input: DataframeTemplateOptionsInput! + ): [DataframeTemplateAvailability!]! + + dataframeBuilderIntrospection( + input: DataframeBuilderIntrospectionInput! + ): DataframeBuilderIntrospection! + + validateFhirDataframe( + input: FhirDataframeInput! + ): FhirDataframeValidation! +} + +type Mutation { + previewFhirDataframe( + input: FhirDataframeInput! + first: Int = 25 + after: String + ): FhirDataframePage! +} +``` + +`runFhirDataframe` may remain temporarily as the compatibility name during +Part 5, but it must call the same preview service. Do not maintain two +compilation or execution implementations. + +Streaming export is an authenticated HTTP endpoint because GraphQL JSON should +not buffer large row sets: + +```text +POST /api/v1/dataframes/export +Content-Type: application/json +Accept: application/x-ndjson | text/csv +``` + +The request body contains one `FhirDataframeInput`-equivalent request plus an +explicit format. The HTTP adapter must call the same preparation and streaming +service as GraphQL. + +## Shared-file ownership and coordination + +Only the Part 5 coordinator may edit or regenerate: + +- `graphqlapi/schema.graphqls` +- `graphqlapi/generated.go` +- `graphqlapi/model/models.go` +- `graphqlapi/schema.resolvers.go` +- `graphqlapi/resolver.go` +- `graphqlapi/handler.go` +- `graphqlapi/output_mapping.go` +- `cmd/arango-fhir-server/main.go` +- `internal/httpapi/server.go` +- `internal/httpapi/routes.go` +- `README.md` +- `docs/QUICKSTART.md` + +Workers implement typed Go services behind coordinator-frozen interfaces and +submit schema wiring requirements as handoff notes. Do not allow multiple +workers to run `make generate-graphql` concurrently. + +The coordinator performs GraphQL generation once after WP1-WP5 service +contracts are integrated, then again only if the schema changes during final +review. + +## Baseline required before implementation + +Run and record: + +```bash +GOCACHE="$(pwd)/.gocache" GOTOOLCHAIN=auto go test ./graphqlapi ./graphqlapi/dataframe ./internal/dataframe ./internal/catalog ./internal/dataset/... ./internal/httpapi -count=1 +GOCACHE="$(pwd)/.gocache" GOTOOLCHAIN=auto go test ./conformance/compiler -count=1 +make dataframe-demo DATAFRAME_LIMIT=25 DATAFRAME_REPEAT=1 DATAFRAME_PRINT_RESPONSE=false +``` + +Record the loaded database, project, generation mode, result hash, row count, +and current GraphQL schema hash. A failing baseline is a coordinator decision; +workers must not silently fix unrelated failures. + +--- + +## WP1 — Dataset and root-resource discovery + +### Goal + +Let a frontend discover what can be queried before it knows a project or root +resource type. Return only datasets and resource types visible to the current +principal. + +### Owner and files + +**Owner:** dataset-discovery worker. + +Owned production files: + +- new `internal/catalog/read_datasets.go` +- new `internal/catalog/read_datasets_test.go` +- additive types in `internal/catalog/types.go` +- new `graphqlapi/dataframe/datasets.go` +- new `graphqlapi/dataframe/datasets_test.go` +- additive service dependencies in `graphqlapi/dataframe/service.go` +- additive response types in `graphqlapi/dataframe/types.go` + +Coordinator-owned integration: + +- GraphQL schema, generated output, resolver, output mapping, server wiring. + +### Contract + +Define persistence-neutral read types: + +```go +type DatasetSummaryOptions struct { + arangostore.ConnectionOptions + ProjectAllowlist []string + CursorBatch int +} + +type DatasetSummary struct { + Project string + DatasetGeneration string + State string + ResourceTypes []ResourceTypeSummary +} + +type ResourceTypeSummary struct { + ResourceType string + DocumentCount int64 + PopulatedFieldCount int + PivotCandidateCount int +} +``` + +Names may be adjusted to match repository conventions, but do not expose +Arango documents or collection names publicly. + +### Implementation + +1. Determine the caller's allowed projects from the existing principal and + authorizer contract. Never discover all projects and filter them only in the + browser. +2. In generation-aware mode, resolve each allowed project's active READY + manifest. Exclude projects without a valid active READY generation and + report them only through server logs/diagnostics. +3. In legacy mode, aggregate dataset summaries from catalog rows whose + generation is null/absent. +4. Obtain resource types from `fhir_field_catalog`, not Arango collection names. + This avoids advertising system, edge, lifecycle, or generated collections. +5. Aggregate per resource type: + - maximum or otherwise semantically correct document count from catalog + facts; + - populated field count; + - pivot-candidate count. +6. Apply generation and authorization scope before aggregation. A restricted + user must not infer resource types that exist only outside their scope. +7. Sort datasets by project and resource types by resource type. +8. Add a cache keyed by principal scope, project, active generation, and + analysis/catalog version only if profiling proves the query needs it. Do not + key only by project. +9. Provide a GraphQL service method that returns DTOs without exposing catalog + persistence types. +10. Keep project selection explicit for deployments whose authorization layer + cannot enumerate projects. In that case accept a configured project list; + do not fall back to unrestricted catalog scanning. + +### Tests + +- legacy null-generation dataset; +- READY active generation; +- project with no active generation; +- active pointer naming a non-READY generation; +- two resource types with deterministic ordering; +- restricted scope hiding one resource type entirely; +- restricted-empty scope returns no resources; +- no leakage between projects or generations; +- catalog contains duplicate auth-path rows but counts are not multiplied; +- no field catalog rows returns an empty list, not null. + +### Acceptance + +- A caller can reach the first frontend screen without hardcoded root types. +- Every advertised resource type has at least one visible populated catalog + fact. +- No raw collection discovery or hardcoded FHIR resource list is used. +- Focused unit, GraphQL integration, and live META tests pass. +- Live query completes below 250 ms warm for the current META fixture. + +### Handoff + +Report exact DTOs, authorization behavior, AQL hash, selected indexes, live +latency, and GraphQL fields required from the coordinator. + +--- + +## WP2 — Guided dataframe template registry + +### Goal + +Implement the backend answer to “What are you making?” without building a +general saved-recipe system. + +Initial template families: + +- patient cohort; +- specimen inventory; +- file manifest; +- diagnoses; +- labs/observations; +- study enrollment. + +### Owner and files + +**Owner:** template worker. + +Owned files: + +- new `internal/dataframe/template/types.go` +- new `internal/dataframe/template/registry.go` +- new `internal/dataframe/template/availability.go` +- new `internal/dataframe/template/registry_test.go` +- new `internal/dataframe/template/availability_test.go` +- new `graphqlapi/dataframe/templates.go` +- new `graphqlapi/dataframe/templates_test.go` + +Read-only dependencies: + +- `fhirschema/` +- `internal/catalog` +- existing dataframe input/semantic types. + +Coordinator owns GraphQL schema and mappings. + +### Template definition + +Each template is immutable product metadata: + +```go +type Definition struct { + ID string + Version int + Label string + Description string + RootCandidates []string + SuggestedColumns []ColumnSuggestion + SuggestedTraversals []TraversalSuggestion + SuggestedPivots []PivotSuggestion +} +``` + +Suggestions must use semantic preferences rather than raw AQL. A column may +contain ordered `fieldRef` alternatives so the registry can adapt to different +FHIR encodings: + +```go +type ColumnSuggestion struct { + ID string + Label string + FieldRefAlternatives []string + DefaultSelected bool + Advanced bool +} +``` + +Traversal suggestions name FHIR source/target types and a semantic route +preference. Availability resolution must match them against discovered +references and `fhirschema`; it must not invent edge labels. + +### Implementation + +1. Freeze stable IDs and version `1` for all six families. +2. Keep definitions deterministic and side-effect free. No database calls from + `registry.go`. +3. Resolve availability against the WP1 dataset summary and existing builder + introspection: + - viable root types; + - available suggested columns; + - unavailable optional suggestions; + - required missing capabilities; + - viable traversals and pivots. +4. Return one of `AVAILABLE`, `PARTIAL`, or `UNAVAILABLE` with machine-readable + reasons. +5. Return `commonColumns` before `advancedColumns` and preserve registry order. +6. Never claim a field is available because it exists in the FHIR schema alone; + it must be populated and visible in the current dataset catalog. +7. Produce a starter `FhirDataframeInput`-equivalent DTO containing only + suggestions proven available. Do not persist it. +8. Use the existing `fieldRef` resolution path when materializing the starter + request; do not copy selector parsing. +9. Keep synonyms and friendly labels in the template package. The compiler + remains unaware of “file manifest” or “patient cohort.” +10. Document how a seventh template can be added without editing GraphQL or the + compiler. + +### Minimum semantic intent + +The exact available fields vary by dataset, but definitions should express: + +- patient cohort: Patient grain, identifiers/demographics, optional Condition + and enrollment relationships; +- specimen inventory: Specimen grain, identifiers, specimen type, subject and + container/collection facts when populated; +- file manifest: DocumentReference grain or a viable root leading to it, + attachment name/URL/size/content type and related subject/specimen IDs; +- diagnoses: Condition grain or Patient cohort with Condition aggregation; +- labs/observations: Observation grain or subject grain with bounded + Observation pivots; +- study enrollment: ResearchSubject grain with proven ResearchStudy and + subject relationships. + +These are product preferences, not assumptions that every dataset contains the +same paths. + +### Tests + +- all six IDs unique and stable; +- deterministic registry order; +- complete, partial, and unavailable datasets; +- alternative fieldRef selection; +- suggested traversal absent from catalog; +- schema-known but unpopulated field remains unavailable; +- pivot template with zero, one, and many bounded columns; +- restricted scope changes availability without leaking hidden facts; +- generated starter input passes the real WP3 validator; +- no template source imports Arango or renderer packages. + +### Acceptance + +- The frontend can render six choices without understanding FHIR routes. +- Every enabled suggestion is accepted by real input preparation. +- Unavailable templates explain which capability is missing. +- Adding a template requires registry data and tests, not compiler branches. + +### Handoff + +Report template IDs/version, availability DTO, starter request DTO, missing +capability reason codes, and coordinator GraphQL requirements. + +--- + +## WP3 — Compile and validate without execution + +### Goal + +Validate, normalize, and compile a dataframe request without opening an Arango +result cursor. Give the frontend actionable output before Preview. + +### Owner and files + +**Owner:** validation worker. + +Owned files: + +- new `internal/dataframe/validation.go` +- new `internal/dataframe/validation_test.go` +- additive types in `internal/dataframe/builder_types.go` +- additive service methods in `internal/dataframe/service.go` +- new `graphqlapi/dataframe/validation.go` +- new `graphqlapi/dataframe/validation_test.go` + +Coordinator owns GraphQL schema, resolver, and output mapping. + +### Internal contract + +Add one service operation that shares preparation and compilation with Run: + +```go +func (s *Service) Validate(ctx context.Context, req ValidateRequest) (ValidationResult, error) +``` + +The result should include: + +- `Valid`; +- normalized public request or normalized builder DTO; +- root row grain and stable root identity field; +- ordered output columns; +- bounded pivot-expanded columns when known; +- warnings; +- compiler plan diagnostics; +- request fingerprint used by WP5 cursor paging; +- limits/capabilities such as preview allowed and export allowed. + +Do not expose raw rendered AQL by default. A development-only diagnostic may +return its hash and plan facts. + +### Implementation + +1. Refactor the existing `prepareSpec` and `CompileRequest` call sequence into a + shared internal method used by Validate, Run, and Stream. +2. Validation must perform the same: + - project authorization; + - active generation resolution; + - auth-resource-path intersection; + - populated field/reference validation; + - pivot-column expansion and bounding; + - semantic and physical compilation. +3. Validation must never call `ExecuteQueryRows`, create an Arango cursor, or + profile the query. +4. Return the exact ordered columns that preview/export will produce. Include + flattened pivot columns based on bounded columns rather than waiting to see + runtime object keys. +5. Define warning codes for valid but potentially surprising shapes: + - no selected data columns; + - template suggestion unavailable; + - high traversal fanout; + - truncated distinct values; + - truncated pivot candidates; + - preview limit capped; + - export recommended instead of preview. +6. Define a deterministic request fingerprint from canonical normalized + semantics, project, generation, resolved scope mode/paths, output ordering, + and compiler-relevant request values. Do not hash arbitrary JSON map order. +7. The fingerprint must exclude the page cursor and page size, but include + filters and row grain. +8. Add configurable preview/export cost policy as a service dependency with + conservative defaults. Start with structural facts already available in + plan diagnostics; do not pretend Arango estimates are measured runtime. +9. Keep validation idempotent: validating an already-normalized request yields + the same normalized result and fingerprint. +10. `runFhirDataframe`, future preview, and export must fail if their prepared + fingerprint differs from a supplied validated fingerprint. + +### Tests + +- valid root-only request; +- nested traversal, aggregate, slice, and pivot request; +- unknown fieldRef and unavailable populated field; +- unsafe/unknown traversal; +- unbounded pivot; +- unauthorized project and restricted-empty scope; +- active generation changes between requests; +- Validate never invokes the execution dependency; +- Validate and Run produce identical columns and plan diagnostics; +- canonical equivalent inputs produce the same fingerprint; +- changed field, filter, scope, generation, traversal, or pivot column changes + the fingerprint; +- deterministic warning and column ordering. + +### Acceptance + +- The frontend can validate every editable request without executing AQL. +- Validation uses the production compiler, not a reduced validator. +- No execution cursor is opened. +- The GDC request validates in under 100 ms warm, excluding a deliberately cold + catalog cache. +- Existing Run and Stream behavior remains unchanged. + +### Handoff + +Report normalized DTO, fingerprint algorithm/version, warning schema, cost +policy defaults, benchmarks, and GraphQL requirements. + +--- + +## WP4 — Structured frontend error contract + +### Goal + +Give GraphQL, preview, and export one stable error taxonomy that the frontend +can map to controls and user messages. + +### Owner and files + +**Owner:** error-contract worker. + +Owned files: + +- new `internal/dataframe/errors.go` +- new `internal/dataframe/errors_test.go` +- new `graphqlapi/errors.go` +- new `graphqlapi/errors_test.go` +- additive reusable HTTP error mapping in `internal/httpapi/errors.go` +- new `internal/httpapi/errors_test.go` + +Coordinator integrates the GraphQL error presenter in `graphqlapi/handler.go` +and reconciles `internal/httpapi/server.go`. + +### Error shape + +Define an interface or typed error carrying: + +```go +type UserError interface { + error + Code() string + FieldPath() []string + Details() map[string]any + Retryable() bool +} +``` + +Do not expose internal errors, AQL text, bind variables, collection names, +filesystem paths, or stack traces through `Details`. + +Minimum stable codes: + +- `PROJECT_REQUIRED` +- `ROOT_RESOURCE_TYPE_REQUIRED` +- `UNAUTHORIZED_PROJECT` +- `UNKNOWN_FIELD` +- `FIELD_NOT_POPULATED` +- `INVALID_TRAVERSAL` +- `UNSAFE_TRAVERSAL_ROUTE` +- `INVALID_FILTER` +- `UNBOUNDED_PIVOT` +- `INVALID_PIVOT_COLUMN` +- `INVALID_SLICE` +- `PLAN_TOO_EXPENSIVE` +- `INVALID_CURSOR` +- `STALE_CURSOR` +- `DATASET_GENERATION_CHANGED` +- `UNSUPPORTED_EXPORT_FORMAT` +- `CLIENT_CANCELED` +- `BACKEND_UNAVAILABLE` +- `INTERNAL_ERROR` + +### Implementation + +1. Inventory public errors emitted by GraphQL input resolution, dataframe + preparation, catalog validation, semantic lowering, cursor decode, and + export adapters. +2. Wrap errors at their semantic owner. Do not classify by parsing error text + in the GraphQL layer. +3. Preserve `errors.Is`/`errors.As` behavior and root causes for server logs. +4. Return GraphQL errors with extensions: + + ```json + { + "code": "UNKNOWN_FIELD", + "fieldPath": ["rootFields", "2", "fieldRef"], + "retryable": false, + "details": {"fieldRef": "Patient.missing"}, + "requestId": "..." + } + ``` + +5. Reuse the same code/message/detail mapper for REST export errors before + response streaming begins. +6. Once streaming has started, log the structured error and terminate the + stream; do not attempt to replace a partial CSV/NDJSON body with JSON. +7. Map context cancellation separately from backend timeout/unavailability. +8. Unknown errors become `INTERNAL_ERROR` externally and retain the full cause + only in structured server logs. +9. Document which codes are user-correctable, retryable, or operator failures. +10. Add a compatibility test preventing accidental code renames. + +### Tests + +- every minimum code is unique and documented; +- GraphQL extensions contain code/path/request ID; +- REST envelope uses the same code; +- internal AQL and bind values are redacted; +- wrapped errors preserve `errors.Is`/`errors.As`; +- cancellation, deadline, and Arango connection failures map differently; +- validation locates root field, nested field, pivot, filter, and traversal + errors at the corresponding input path; +- unknown panic/error returns a generic external message. + +### Acceptance + +- The frontend never needs to parse an English message to identify an error. +- The same semantic failure has the same code across validation, preview, and + export. +- Existing request IDs remain available. +- No sensitive query or scope data leaks. + +### Handoff + +Report the frozen code registry, Go interface, GraphQL extension shape, REST +shape, redaction rules, and coordinator integration steps. + +--- + +## WP5 — Stable preview paging + +### Goal + +Replace the unused GraphQL cursor field with keyset paging over the stable root +grain. Preview pages must not use offsets and must not repeat or skip roots +within one immutable dataset generation. + +### Owner and files + +**Owner:** paging worker. + +Owned files: + +- new `internal/dataframe/cursor.go` +- new `internal/dataframe/cursor_test.go` +- new `internal/dataframe/paging.go` +- new `internal/dataframe/paging_test.go` +- additive semantic/physical paging fields in coordinator-approved dataframe + files only; +- new `graphqlapi/dataframe/preview.go` +- new `graphqlapi/dataframe/preview_test.go` + +The paging worker must stop and request coordinator approval before editing +shared physical files such as `physical_plan.go`, `physical_render.go`, or +`generic_physical_plan.go`. + +Coordinator owns GraphQL schema and generated files. + +### Cursor contract + +Use an opaque, versioned, authenticated token. Minimum payload: + +```go +type CursorV1 struct { + Version int + RequestFingerprint string + Project string + DatasetGeneration string + RootResourceType string + LastRootKey string +} +``` + +Sign the canonical payload with HMAC-SHA-256 using server configuration. Do not +accept unsigned base64 JSON in production. Provide an explicit insecure test +codec only in tests. + +### Implementation + +1. Add a preview request with `first` and `after`; cap `first` using configured + minimum/default/maximum values, initially 1/25/1,000. +2. Decode and verify the cursor before compiling AQL. +3. Recompute WP3's request fingerprint and reject a cursor from a different + request, root type, project, scope, or generation. +4. Add the root-key predicate before root `SORT` and `LIMIT`: + + ```aql + FILTER root._key > @after_root_key + SORT root._key ASC + LIMIT @page_fetch_limit + ``` + +5. Fetch `first + 1` rows to calculate `hasNextPage`, then return at most + `first` rows. +6. Construct `endCursor` from the last returned root `_key`; never derive it + from a child resource or output field selected by the user. +7. Keep `_key` available as hidden execution metadata even if the user does not + select it as an output column. Remove hidden metadata before delivering rows. +8. Preserve required-match filtering before paging. Optional child shaping + remains after the root window. +9. Do not implement backward paging or offset paging in Part 5. +10. Cancel and close the Arango cursor when the request context ends. Confirm + the current driver path does so; add explicit close behavior if required. +11. Return page info: + - `hasNextPage`; + - `endCursor` or null for an empty page; + - requested/effective page size; + - request fingerprint/version. +12. Keep `runFhirDataframe(limit:)` as a thin first-page compatibility adapter + during migration. + +### Tests + +- empty, one-row, exact-page, and page-plus-one datasets; +- multiple pages concatenate to the same ordered rows as one unpaged request; +- no duplicate or skipped root keys; +- required filter applied before page window; +- optional child fanout does not alter page boundaries; +- invalid signature, malformed token, unsupported version; +- cursor from another project, scope, generation, root type, or request; +- generation activation between pages produces `STALE_CURSOR` or + `DATASET_GENERATION_CHANGED`; +- page size zero, negative, and above maximum; +- cancellation closes cursor resources; +- root `_key` is not leaked unless requested as a column; +- live META paging for the GDC shape with exact concatenated result hash. + +### Acceptance + +- The GraphQL cursor field is no longer decorative. +- Page concatenation has exact parity with the equivalent stable unpaged + result. +- Explain uses the scoped root index and keyset predicate with no full scan. +- Page memory is bounded by effective page size, not total result size. +- Cursor tampering and stale generations fail with structured WP4 errors. + +### Handoff + +Report cursor wire version, key rotation/configuration decision, fingerprint +dependency, AQL/Explain evidence, parity hashes, and GraphQL page DTO. + +--- + +## WP6 — Streaming NDJSON and CSV export transport + +### Goal + +Expose the existing validated `dataframe.Service.Stream` path as an +authenticated, cancellation-aware HTTP export without buffering the full +dataframe in GraphQL or server memory. + +This is synchronous streaming export only. Durable jobs, artifact storage, +resume, and Elasticsearch are separate future work. + +### Owner and files + +**Owner:** export worker. + +Owned files: + +- new `internal/export/types.go` +- new `internal/export/ndjson.go` +- new `internal/export/csv.go` +- new `internal/export/ndjson_test.go` +- new `internal/export/csv_test.go` +- new `internal/httpapi/dataframe_export.go` +- new `internal/httpapi/dataframe_export_test.go` + +Coordinator owns shared HTTP config/routes and server command wiring. + +### Request and response contract + +Proposed request: + +```json +{ + "format": "ndjson", + "dataframe": { "...": "FhirDataframeInput-equivalent JSON" }, + "validatedFingerprint": "optional fingerprint returned by WP3" +} +``` + +Response behavior: + +- NDJSON: `Content-Type: application/x-ndjson; charset=utf-8`; +- CSV: `Content-Type: text/csv; charset=utf-8`; +- attachment filename is sanitized and contains project, root type, and a UTC + timestamp, never an auth path; +- `Cache-Control: no-store`; +- `X-Content-Type-Options: nosniff`; +- optional safe headers for request fingerprint and generation; +- no `Content-Length` requirement for streaming responses. + +### Implementation + +1. Define a small sink interface receiving ordered columns and flattened rows. +2. NDJSON writes one canonical JSON object and one newline per row. +3. CSV writes the header once using validated ordered columns, then writes every + value with RFC 4180-compatible quoting through `encoding/csv`. +4. Define deterministic CSV encoding: + - null -> empty field; + - string/number/bool -> scalar text; + - arrays/objects -> compact canonical JSON in one CSV cell; + - timestamps remain the compiler-delivered string representation. +5. Never derive CSV column order from Go map iteration. Use WP3's compiled + ordered columns, including bounded flattened pivot columns. +6. Call the same GraphQL input preparation/fieldRef resolution and + `dataframe.Service.Stream` path. Extract a transport-neutral request adapter + if necessary; do not duplicate GraphQL-only parsing rules. +7. Resolve authorization and active generation before writing HTTP headers so + validation failures can return a normal structured error response. +8. If `validatedFingerprint` is supplied, require exact equality with the + freshly prepared request. +9. Flush periodically or per configured row batch. Do not flush every cell. +10. Stop promptly when the request context is canceled or the client + disconnects; propagate cancellation to Arango. +11. Record rows and bytes written in structured logs. Do not log row contents. +12. Enforce configurable export row and duration limits for synchronous mode. + Return `PLAN_TOO_EXPENSIVE` before streaming if the request requires a + durable job that Part 5 does not provide. +13. Do not write temporary files, artifact metadata, job collections, or + Elasticsearch documents in this package. +14. Register `POST /api/v1/dataframes/export` behind the existing authentication + middleware and project authorization contract. + +### Tests + +- NDJSON exact rows and newline behavior; +- CSV header order, commas, quotes, newlines, Unicode, nulls, arrays, objects, + and pivot-expanded columns; +- preview and both export formats decode to identical logical rows; +- large fake stream proves bounded memory; +- writer failure and client cancellation stop upstream execution; +- error before headers returns WP4 JSON envelope; +- error after streaming starts terminates and logs without appending JSON error + material to CSV/NDJSON; +- unsupported `Accept`/format returns `UNSUPPORTED_EXPORT_FORMAT`; +- unauthorized project and restricted-empty scope; +- generation changes and validated-fingerprint mismatch; +- live META GDC export at 1,000 rows with row/hash parity; +- response headers prevent caching and content sniffing. + +### Acceptance + +- 100,000 generated test rows export with memory bounded independently of row + count. +- Live 1,000-row GDC NDJSON and CSV exports contain the same logical rows as + preview. +- Disconnect/cancellation stops Arango work. +- No GraphQL JSON buffering is used for export. +- No durable-job or Elasticsearch scaffolding is introduced. + +### Handoff + +Report sink interface, CSV value rules, endpoint request/headers, cancellation +evidence, memory benchmark, row hashes, and coordinator wiring steps. + +--- + +## Parallel execution plan + +### Phase 0 — Coordinator contract freeze + +One coordinator performs a read-only audit and freezes: + +- GraphQL semantic field names; +- shared DTOs between GraphQL and REST input adapters; +- WP4 error interface and initial code list; +- WP3 normalized-request and fingerprint boundary; +- shared-file hashes and worker ownership. + +No generated GraphQL edit occurs yet. + +### Phase 1 — Four parallel workers + +These packages can start concurrently after Phase 0: + +| Lane | Work | May edit | +| --- | --- | --- | +| A | WP1 catalog dataset summaries | catalog read files and dataset DTO/service files | +| B | WP2 pure template registry | `internal/dataframe/template` only initially | +| C | WP3 validation core | dataframe validation/service files | +| D | WP4 error taxonomy | new error files and tests | + +Coordination rules: + +- Lane B uses fake availability inputs until WP1's response interface lands. +- Lane C returns typed internal errors compatible with Lane D's frozen + interface. If the interface is insufficient, stop and request a coordinator + decision. +- No lane edits GraphQL schema/generated files. +- WP1 and WP3 must not independently refactor authorization or active generation + resolution; they reuse existing services. + +### Phase 2 — Two parallel workers plus integration + +After WP3's normalized request/fingerprint contract and WP4 errors are merged: + +| Lane | Work | Dependency | +| --- | --- | --- | +| E | WP5 cursor codec and paging | WP3 + WP4 | +| F | WP6 export sinks and handler | WP3 + WP4; may use current Stream immediately | +| Coordinator | WP1-WP4 GraphQL schema integration | stable service DTOs | + +WP5 and WP6 may run concurrently because paging owns compiler/page execution +and export owns streaming formats/HTTP adapter. They must not both edit shared +dataframe service files; any shared extraction is coordinator-owned. + +### Phase 3 — Single coordinator integration + +The coordinator: + +1. integrates service dependencies into the server command; +2. edits `graphqlapi/schema.graphqls` once for WP1-WP5; +3. runs `make generate-graphql` once; +4. wires resolvers and output mapping; +5. wires the WP6 HTTP route/configuration; +6. updates README and Quickstart examples; +7. resolves API naming and generated-code conflicts; +8. runs the complete Part 5 test matrix. + +### Phase 4 — Parallel verification + +After integration, three read-mostly verification workers may run concurrently: + +- authorization/generation isolation across all six operations; +- GraphQL/REST contract and error compatibility; +- live META performance, paging parity, streaming memory, and cancellation. + +Only the coordinator fixes shared production files. Verification workers add +focused tests/evidence or propose patches. + +## Dependency graph + +```text +Phase 0 contract freeze + ├── WP1 dataset discovery ───────┐ + ├── WP2 template registry ───────┼── GraphQL integration + ├── WP3 validate/fingerprint ─┬──┤ + └── WP4 structured errors ────┤ │ + ├── WP5 preview paging ─┐ + └── WP6 export ─────────┼── final integration + └── system verification +``` + +WP2's availability adapter depends on WP1 and existing introspection, but its +registry can be built independently. WP5 and WP6 require the final WP3/WP4 +contracts. Export does not depend on paging. + +## Coordinator merge order + +Merge in this order even if workers finish differently: + +1. WP4 internal error contract; +2. WP3 validation and fingerprint contract; +3. WP1 dataset summary service; +4. WP2 template registry and availability adapter; +5. WP5 paging; +6. WP6 export; +7. GraphQL generation and server wiring; +8. docs and system evidence. + +This order prevents WP3/WP5/WP6 from inventing incompatible error or +fingerprint representations. + +## Required system tests + +Add a Part 5 system suite covering one complete user flow: + +1. load or use the checked-in META dataset; +2. list visible datasets and resource types; +3. list templates; +4. select an available template and starter request; +5. introspect fields and distinct filter values; +6. validate the request; +7. preview at least two pages; +8. concatenate pages and verify row identity/order; +9. export NDJSON and CSV; +10. decode both exports and prove logical row parity; +11. repeat with restricted and restricted-empty scopes; +12. activate a different generation and prove the old cursor/fingerprint is + rejected. + +The system suite must include: + +- Patient-root GDC matrix with nested traversals, aggregates, slices, and + Observation pivot; +- a non-Patient root; +- a dataset where at least one of the six templates is partial/unavailable; +- malformed input and cursor cases; +- cancellation during streaming export. + +## Final acceptance gate + +Part 5 is complete when: + +1. The frontend needs no hardcoded project resource types for the first screen. +2. Six guided template families are returned with data-backed availability. +3. Every starter request is accepted by the production validator or explicitly + marked unavailable. +4. Validation opens no result cursor and returns stable columns, warnings, + diagnostics, and fingerprint. +5. Every user-correctable failure has a stable structured code and input path. +6. Preview cursor paging has exact concatenation parity and stable root order. +7. NDJSON and CSV stream through the production dataframe service with bounded + memory and cancellation. +8. Preview/export preserve project, generation, and auth-scope isolation. +9. Existing GDC result hashes and compiler conformance remain unchanged. +10. No frontend-specific FHIR route or AQL logic enters the compiler. +11. No saved-recipe, durable-job, artifact, or Elasticsearch scaffolding is + added. +12. README and Quickstart contain copy-pasteable calls for dataset discovery, + template selection, validation, paged preview, and both export formats. + +## Luna worker prompt template + +```text +Execute WP from docs/LUNA_FRONTEND_ENABLEMENT_PART_5.md. + +Read the entire Part 5 plan, then every file listed under that WP. Own only the +exact paths assigned to the WP. Do not edit GraphQL schema/generated files, +server wiring, shared physical compiler files, README, or Quickstart unless you +are the designated coordinator. + +Preserve all global contracts, especially project/generation/auth isolation, +stable fieldRef behavior, exact preview/export row semantics, deterministic +ordering, and no FHIR/AQL logic in the frontend layer. Reuse fhirschema, +resolveStorageRoute, catalog discovery, dataframe.Service, and +dataset.ActiveManifestResolver. Never hardcode a fixture route in generic code. + +Record baseline hashes. Implement only this package, run the named unit/live +tests, and produce the required handoff. Report changed files, test commands, +API/type decisions, hashes, latency/memory metrics, rejected approaches, and +coordinator decisions required. + +Stop rather than guess if a shared contract must change, an owned file changed +concurrently, authorization semantics differ, active-generation semantics are +unclear, result parity fails, or a generated/shared file edit is required. +``` + diff --git a/docs/LUNA_FRONTEND_ENABLEMENT_PART_5_PHASE0.md b/docs/LUNA_FRONTEND_ENABLEMENT_PART_5_PHASE0.md new file mode 100644 index 0000000..e4271fb --- /dev/null +++ b/docs/LUNA_FRONTEND_ENABLEMENT_PART_5_PHASE0.md @@ -0,0 +1,30 @@ +# Part 5 Phase 0 contract freeze + +This file records the coordinator freeze used for Phase 1. It is intentionally +an internal-service contract; GraphQL schema changes and generated code remain +coordinator-owned and are deferred until the service lanes have completed. + +## Frozen boundaries + +- Catalog discovery returns persistence-neutral dataset summaries and never + scans without an explicit project allowlist. +- Template availability consumes a catalog-backed capability snapshot and + returns semantic starter intent; it does not emit AQL or collection names. +- `dataframe.Service.Validate` shares the exact preparation and compiler + boundary with `Run`, returns a normalized builder, a request fingerprint, + plan metadata, warnings, and timing diagnostics, and never executes rows. +- User-facing errors use the stable code registry in + `internal/dataframe/errors.go`. GraphQL and HTTP adapters map the same + semantic error without exposing backend details. +- Project, active generation, and authorization scope are resolved once by + the request adapter and propagated to every catalog and compiler call. +- Generated GraphQL files, schema, route registration, and server wiring are + coordinator-owned. Phase 1 workers must report those wiring requirements + rather than editing shared files. + +## Phase 1 acceptance gate + +Each lane must provide focused unit tests, deterministic ordering and defensive +copy behavior where applicable, `git diff --check` output, and a list of +coordinator wiring decisions. No lane may introduce a FHIR-type-, project-, +fixture-, or edge-label-specific production branch. diff --git a/graphqlapi/dataframe/datasets.go b/graphqlapi/dataframe/datasets.go new file mode 100644 index 0000000..fdb55f3 --- /dev/null +++ b/graphqlapi/dataframe/datasets.go @@ -0,0 +1,138 @@ +package dataframeapi + +import ( + "context" + "log" + "sort" + "strings" + + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/dataset" +) + +// DiscoverDatasets returns the projects and populated FHIR resource types +// visible to the request principal. Project discovery is intentionally +// allowlist-based: the service never scans the catalog to invent project +// names for a caller that has not supplied an explicit project source. +func (s *Service) DiscoverDatasets(ctx context.Context) ([]DatasetSummary, error) { + if s == nil || s.discoverDatasets == nil { + return []DatasetSummary{}, nil + } + principal, _ := authscope.PrincipalFromContext(ctx) + projects := datasetDiscoveryProjects(principal, s.datasetProjectAllowlist) + if len(projects) == 0 { + return []DatasetSummary{}, nil + } + + generations := make(map[string]string, len(projects)) + states := make(map[string]string, len(projects)) + selectedProjects := make([]string, 0, len(projects)) + for _, project := range projects { + generation := "" + state := "LEGACY" + if s.activeManifestResolver != nil { + manifest, err := dataset.ResolveReadyActiveManifest(ctx, s.activeManifestResolver, project) + if err != nil { + // A project without a valid active READY generation is not an + // advertised dataset. Discovery is best-effort per project so one + // stale active pointer does not hide unrelated visible projects. + log.Printf("dataframe dataset discovery: skip project %q: %v", project, err) + continue + } + generation = manifest.Dataset.Generation + state = string(manifest.State) + } + generations[project] = generation + states[project] = state + selectedProjects = append(selectedProjects, project) + } + if len(selectedProjects) == 0 { + return []DatasetSummary{}, nil + } + + scopes := make(map[string]catalog.DatasetAuthScope, len(selectedProjects)) + for _, project := range selectedProjects { + scope, err := s.resolveReadScopeForGeneration(ctx, principal, project, generations[project], nil) + if err != nil { + return nil, err + } + scopes[project] = catalog.DatasetAuthScope{ + AuthResourcePaths: cloneStrings(scope.AuthResourcePaths), + Unrestricted: scope.Unrestricted(), + } + } + + catalogSummaries, err := s.discoverDatasets(ctx, catalog.DatasetSummaryOptions{ + ConnectionOptions: s.connOpts, + ProjectAllowlist: selectedProjects, + DatasetGenerationByProject: generations, + AuthScopesByProject: scopes, + DatasetStateByProject: states, + CursorBatch: 1000, + }) + if err != nil { + return nil, err + } + result := make([]DatasetSummary, 0, len(catalogSummaries)) + for _, summary := range catalogSummaries { + resourceTypes := make([]ResourceTypeSummary, 0, len(summary.ResourceTypes)) + for _, resource := range summary.ResourceTypes { + resourceTypes = append(resourceTypes, ResourceTypeSummary{ + ResourceType: resource.ResourceType, + DocumentCount: resource.DocumentCount, + PopulatedFieldCount: resource.PopulatedFieldCount, + PivotCandidateCount: resource.PivotCandidateCount, + }) + } + sort.Slice(resourceTypes, func(i, j int) bool { return resourceTypes[i].ResourceType < resourceTypes[j].ResourceType }) + result = append(result, DatasetSummary{ + Project: summary.Project, + DatasetGeneration: summary.DatasetGeneration, + State: summary.State, + ResourceTypes: resourceTypes, + }) + } + sort.Slice(result, func(i, j int) bool { return result[i].Project < result[j].Project }) + return result, nil +} + +func datasetDiscoveryProjects(principal *authscope.Principal, configured []string) []string { + configured = normalizedProjects(configured) + if principal == nil || len(principal.Projects) == 0 { + return configured + } + principalProjects := normalizedProjects(principal.Projects) + if len(configured) == 0 { + return principalProjects + } + allowed := make(map[string]struct{}, len(principalProjects)) + for _, project := range principalProjects { + allowed[project] = struct{}{} + } + result := make([]string, 0, len(configured)) + for _, project := range configured { + if _, ok := allowed[project]; ok { + result = append(result, project) + } + } + return result +} + +func normalizedProjects(projects []string) []string { + seen := make(map[string]struct{}, len(projects)) + result := make([]string, 0, len(projects)) + for _, project := range projects { + project = strings.TrimSpace(project) + if project == "" { + continue + } + if _, ok := seen[project]; ok { + continue + } + seen[project] = struct{}{} + result = append(result, project) + } + sort.Strings(result) + return result +} diff --git a/graphqlapi/dataframe/datasets_test.go b/graphqlapi/dataframe/datasets_test.go new file mode 100644 index 0000000..bc31c07 --- /dev/null +++ b/graphqlapi/dataframe/datasets_test.go @@ -0,0 +1,110 @@ +package dataframeapi + +import ( + "context" + "errors" + "testing" + + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/dataset" +) + +type datasetDiscoveryManifestResolver struct { + manifests map[string]dataset.Manifest + errors map[string]error +} + +func (r datasetDiscoveryManifestResolver) ResolveActiveManifest(_ context.Context, project string) (dataset.Manifest, error) { + if err := r.errors[project]; err != nil { + return dataset.Manifest{}, err + } + manifest, ok := r.manifests[project] + if !ok { + return dataset.Manifest{}, errors.New("no active generation") + } + return manifest.Clone(), nil +} + +func TestDiscoverDatasetsUsesPrincipalProjectsAndGenerationScope(t *testing.T) { + manifest := builderReadyManifest(t, "P1", "generation-1") + var got catalog.DatasetSummaryOptions + service := NewService(Config{ + ActiveManifestResolver: datasetDiscoveryManifestResolver{manifests: map[string]dataset.Manifest{"P1": manifest}}, + DiscoverDatasets: func(_ context.Context, options catalog.DatasetSummaryOptions) ([]catalog.DatasetSummary, error) { + got = options + return []catalog.DatasetSummary{{ + Project: "P1", DatasetGeneration: "generation-1", State: "READY", + ResourceTypes: []catalog.ResourceTypeSummary{{ResourceType: "Patient", DocumentCount: 4, PopulatedFieldCount: 2, PivotCandidateCount: 1}}, + }}, nil + }, + }) + ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{ + Projects: []string{"P1"}, + AuthResourcePaths: []string{"path-a"}, + }) + result, err := service.DiscoverDatasets(ctx) + if err != nil { + t.Fatalf("DiscoverDatasets() error = %v", err) + } + if len(result) != 1 || result[0].Project != "P1" || result[0].DatasetGeneration != "generation-1" || len(result[0].ResourceTypes) != 1 { + t.Fatalf("result = %#v", result) + } + if got.ProjectAllowlist[0] != "P1" || got.DatasetGenerationByProject["P1"] != "generation-1" || got.DatasetStateByProject["P1"] != "READY" { + t.Fatalf("dataset selection = %+v", got) + } + scope := got.AuthScopesByProject["P1"] + if scope.Unrestricted || len(scope.AuthResourcePaths) != 1 || scope.AuthResourcePaths[0] != "path-a" { + t.Fatalf("dataset auth scope = %+v", scope) + } +} + +func TestDiscoverDatasetsIntersectsConfiguredProjectsAndSkipsInvalidActive(t *testing.T) { + called := false + service := NewService(Config{ + DatasetProjectAllowlist: []string{"P2", "P1", "P3"}, + ActiveManifestResolver: datasetDiscoveryManifestResolver{ + manifests: map[string]dataset.Manifest{"P1": builderReadyManifest(t, "P1", "generation-1")}, + errors: map[string]error{"P2": errors.New("active pointer missing")}, + }, + DiscoverDatasets: func(_ context.Context, options catalog.DatasetSummaryOptions) ([]catalog.DatasetSummary, error) { + called = true + if len(options.ProjectAllowlist) != 1 || options.ProjectAllowlist[0] != "P1" { + t.Fatalf("selected projects = %#v", options.ProjectAllowlist) + } + return []catalog.DatasetSummary{}, nil + }, + }) + ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{Projects: []string{"P1", "P2"}}) + if _, err := service.DiscoverDatasets(ctx); err != nil { + t.Fatalf("DiscoverDatasets() error = %v", err) + } + if !called { + t.Fatal("catalog discovery was not called for surviving project") + } +} + +func TestDiscoverDatasetsDoesNotScanCatalogWithoutExplicitProjects(t *testing.T) { + called := false + service := NewService(Config{ + DiscoverDatasets: func(context.Context, catalog.DatasetSummaryOptions) ([]catalog.DatasetSummary, error) { + called = true + return nil, nil + }, + }) + result, err := service.DiscoverDatasets(context.Background()) + if err != nil { + t.Fatalf("DiscoverDatasets() error = %v", err) + } + if called || result == nil || len(result) != 0 { + t.Fatalf("result=%#v catalogCalled=%v", result, called) + } +} + +func TestDatasetDiscoveryProjectsAreDeterministic(t *testing.T) { + got := datasetDiscoveryProjects(&authscope.Principal{Projects: []string{" P2", "P1", "P2"}}, []string{"P3", "P1", "P2"}) + want := []string{"P1", "P2"} + if len(got) != len(want) || got[0] != want[0] || got[1] != want[1] { + t.Fatalf("projects = %#v, want %#v", got, want) + } +} diff --git a/graphqlapi/dataframe/service.go b/graphqlapi/dataframe/service.go index 8c715e2..9fda7db 100644 --- a/graphqlapi/dataframe/service.go +++ b/graphqlapi/dataframe/service.go @@ -13,12 +13,14 @@ import ( ) type Service struct { - connOpts arangostore.ConnectionOptions - discoverReferences func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) - discoverFields func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) - dataframes *dataframe.Service - scopeResolver *authscope.ScopeResolver - activeManifestResolver dataset.ActiveManifestResolver + connOpts arangostore.ConnectionOptions + discoverReferences func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) + discoverFields func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) + dataframes *dataframe.Service + scopeResolver *authscope.ScopeResolver + activeManifestResolver dataset.ActiveManifestResolver + discoverDatasets func(context.Context, catalog.DatasetSummaryOptions) ([]catalog.DatasetSummary, error) + datasetProjectAllowlist []string } type Config struct { @@ -31,13 +33,24 @@ type Config struct { // discovery and recipe preparation resolve one READY active generation // before inspecting any fields or relationship routes. ActiveManifestResolver dataset.ActiveManifestResolver + // DatasetProjectAllowlist is the explicit project source used when a + // principal does not carry a project list. An empty value never triggers an + // unrestricted catalog scan. + DatasetProjectAllowlist []string + DiscoverDatasets func(context.Context, catalog.DatasetSummaryOptions) ([]catalog.DatasetSummary, error) } func NewService(cfg Config) *Service { service := &Service{ - connOpts: cfg.ConnectionOptions, - scopeResolver: cfg.ScopeResolver, - activeManifestResolver: cfg.ActiveManifestResolver, + connOpts: cfg.ConnectionOptions, + scopeResolver: cfg.ScopeResolver, + activeManifestResolver: cfg.ActiveManifestResolver, + datasetProjectAllowlist: cloneStrings(cfg.DatasetProjectAllowlist), + } + if cfg.DiscoverDatasets != nil { + service.discoverDatasets = cfg.DiscoverDatasets + } else { + service.discoverDatasets = catalog.DiscoverDatasetSummaries } if cfg.DiscoverReferences != nil { service.discoverReferences = cfg.DiscoverReferences diff --git a/graphqlapi/dataframe/templates.go b/graphqlapi/dataframe/templates.go new file mode 100644 index 0000000..012220b --- /dev/null +++ b/graphqlapi/dataframe/templates.go @@ -0,0 +1,243 @@ +package dataframeapi + +import ( + "context" + "fmt" + "strings" + + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/catalog" + dataframetemplate "github.com/calypr/loom/internal/dataframe/template" +) + +// TemplateOptions is the transport-neutral input for guided template +// discovery. GraphQL schema ownership remains with the Part 5 coordinator. +type TemplateOptions struct { + Project string + AuthResourcePaths []string + TemplateID string +} + +type TemplateColumn struct { + ID string + Label string + FieldRef string + Advanced bool +} + +type TemplateTraversal struct { + ID string + Label string + SemanticRole string + FromType string + EdgeLabel string + ToType string + Advanced bool +} + +type TemplatePivot struct { + ID string + Label string + FieldRef string + Columns []string + Advanced bool +} + +type TemplateMissingCapability struct { + SuggestionID string + Kind string + Label string + Code string +} + +type TemplateStarterRequest struct { + RootResourceType string + RowGrain string + Fields []TemplateColumn + Traversals []TemplateTraversal + Pivots []TemplatePivot +} + +// TemplateAvailability is the GraphQL-dataframe service DTO. It contains no +// catalog persistence documents or raw selectors/AQL. +type TemplateAvailability struct { + ID string + Version int + Label string + Description string + Status string + RootResourceType string + CommonColumns []TemplateColumn + AdvancedColumns []TemplateColumn + Traversals []TemplateTraversal + Pivots []TemplatePivot + Missing []TemplateMissingCapability + Reasons []string + Starter TemplateStarterRequest +} + +// ListTemplates resolves all or one guided template against the current +// project's visible catalog. The active generation and effective auth scope +// are selected before any catalog reads. +func (s *Service) ListTemplates(ctx context.Context, req TemplateOptions) ([]TemplateAvailability, error) { + if strings.TrimSpace(req.Project) == "" { + return nil, fmt.Errorf("project is required") + } + principal, _ := authscope.PrincipalFromContext(ctx) + if err := authorizeProject(principal, req.Project, s.scopeResolver != nil); err != nil { + return nil, err + } + generation, err := s.resolveActiveGeneration(ctx, req.Project) + if err != nil { + return nil, err + } + scope, err := s.resolveReadScopeForGeneration(ctx, principal, req.Project, generation, req.AuthResourcePaths) + if err != nil { + return nil, err + } + + registry := dataframetemplate.DefaultRegistry() + definitions := registry.Definitions() + if id := strings.TrimSpace(req.TemplateID); id != "" { + definition, ok := registry.Definition(id) + if !ok { + return []TemplateAvailability{}, nil + } + definitions = []dataframetemplate.Definition{definition} + } + snapshot, err := s.templateCapabilities(ctx, definitions, req.Project, generation, scope) + if err != nil { + return nil, err + } + result := make([]TemplateAvailability, 0, len(definitions)) + for _, definition := range definitions { + result = append(result, templateAvailabilityDTO(dataframetemplate.Resolve(definition, snapshot))) + } + return result, nil +} + +// Templates is a short compatibility alias for callers that prefer the +// noun-shaped service method while the GraphQL operation is being integrated. +func (s *Service) Templates(ctx context.Context, req TemplateOptions) ([]TemplateAvailability, error) { + return s.ListTemplates(ctx, req) +} + +func (s *Service) templateCapabilities(ctx context.Context, definitions []dataframetemplate.Definition, project, generation string, scope authscope.ReadScope) (dataframetemplate.CapabilitySnapshot, error) { + resourceTypes := make(map[string]struct{}) + for _, definition := range definitions { + for _, resourceType := range definition.RootCandidates { + resourceTypes[resourceType] = struct{}{} + } + for _, suggestion := range definition.SuggestedTraversals { + for _, resourceType := range suggestion.FromResourceTypes { + resourceTypes[resourceType] = struct{}{} + } + for _, resourceType := range suggestion.ToResourceTypes { + resourceTypes[resourceType] = struct{}{} + } + } + } + + orderedTypes := make([]string, 0, len(resourceTypes)) + for resourceType := range resourceTypes { + orderedTypes = append(orderedTypes, resourceType) + } + // Definitions are product ordered; sorting resource types makes catalog + // call order and resulting snapshots deterministic across map iteration. + sortStrings(orderedTypes) + + snapshot := dataframetemplate.CapabilitySnapshot{Resources: []dataframetemplate.ResourceCapability{}, Relationships: []dataframetemplate.RelationshipCapability{}} + seenRelationships := map[string]struct{}{} + for _, resourceType := range orderedTypes { + fields, err := s.discoverFields(ctx, catalog.PopulatedFieldOptions{ + ConnectionOptions: s.connOpts, Project: project, DatasetGeneration: generation, + AuthResourcePathsUnrestricted: catalog.ExplicitAuthResourcePathsUnrestricted(scope.Unrestricted()), + AuthResourcePaths: cloneStrings(scope.AuthResourcePaths), ResourceType: resourceType, + }) + if err != nil { + return dataframetemplate.CapabilitySnapshot{}, err + } + fieldCapabilities := make([]dataframetemplate.FieldCapability, 0, len(fields)) + for _, field := range fields { + fieldCapabilities = append(fieldCapabilities, dataframetemplate.FieldCapability{ + ResourceType: field.ResourceType, FieldRef: defaultFieldRef(resourceType, field.Path), + PivotCandidate: field.PivotCandidate, PivotColumns: cloneStrings(field.PivotColumns), + PivotFamily: field.PivotFamily, PivotColumnSelect: field.PivotColumnSelect, + PivotValueSelect: field.PivotValueSelect, + }) + } + // A resource is advertised only when catalog evidence proves it is + // visible. Schema presence alone is intentionally insufficient. + resource := dataframetemplate.ResourceCapability{ResourceType: resourceType, Present: len(fields) > 0, Fields: fieldCapabilities} + refs, err := s.discoverReferences(ctx, catalog.PopulatedReferenceOptions{ + ConnectionOptions: s.connOpts, Project: project, DatasetGeneration: generation, + AuthResourcePathsUnrestricted: catalog.ExplicitAuthResourcePathsUnrestricted(scope.Unrestricted()), + AuthResourcePaths: cloneStrings(scope.AuthResourcePaths), NodeType: resourceType, + Mode: catalog.TraversalModeBuilder, + }) + if err != nil { + return dataframetemplate.CapabilitySnapshot{}, err + } + for _, ref := range refs { + if ref.FromType == resourceType { + resource.Present = true + } + key := ref.FromType + "\x00" + ref.Label + "\x00" + ref.ToType + if _, ok := seenRelationships[key]; ok { + continue + } + seenRelationships[key] = struct{}{} + snapshot.Relationships = append(snapshot.Relationships, dataframetemplate.RelationshipCapability{FromType: ref.FromType, Label: ref.Label, ToType: ref.ToType, EdgeCount: ref.EdgeCount}) + } + snapshot.Resources = append(snapshot.Resources, resource) + } + return snapshot, nil +} + +func templateAvailabilityDTO(in dataframetemplate.Availability) TemplateAvailability { + out := TemplateAvailability{ + ID: in.ID, Version: in.Version, Label: in.Label, Description: in.Description, + Status: string(in.Status), RootResourceType: in.RootResourceType, + CommonColumns: templateColumns(in.CommonColumns), AdvancedColumns: templateColumns(in.AdvancedColumns), + Traversals: templateTraversals(in.Traversals), Pivots: templatePivots(in.Pivots), + Missing: make([]TemplateMissingCapability, 0, len(in.Missing)), Reasons: cloneStrings(in.Reasons), + Starter: TemplateStarterRequest{RootResourceType: in.Starter.RootResourceType, RowGrain: in.Starter.RowGrain, + Fields: templateColumns(in.Starter.Fields), Traversals: templateTraversals(in.Starter.Traversals), Pivots: templatePivots(in.Starter.Pivots)}, + } + for _, missing := range in.Missing { + out.Missing = append(out.Missing, TemplateMissingCapability{SuggestionID: missing.SuggestionID, Kind: missing.Kind, Label: missing.Label, Code: missing.Code}) + } + return out +} + +func templateColumns(in []dataframetemplate.SelectedColumn) []TemplateColumn { + out := make([]TemplateColumn, 0, len(in)) + for _, item := range in { + out = append(out, TemplateColumn{ID: item.ID, Label: item.Label, FieldRef: item.FieldRef, Advanced: item.Advanced}) + } + return out +} + +func templateTraversals(in []dataframetemplate.SelectedTraversal) []TemplateTraversal { + out := make([]TemplateTraversal, 0, len(in)) + for _, item := range in { + out = append(out, TemplateTraversal{ID: item.ID, Label: item.Label, SemanticRole: item.SemanticRole, FromType: item.FromType, EdgeLabel: item.EdgeLabel, ToType: item.ToType, Advanced: item.Advanced}) + } + return out +} + +func templatePivots(in []dataframetemplate.SelectedPivot) []TemplatePivot { + out := make([]TemplatePivot, 0, len(in)) + for _, item := range in { + out = append(out, TemplatePivot{ID: item.ID, Label: item.Label, FieldRef: item.FieldRef, Columns: cloneStrings(item.Columns), Advanced: item.Advanced}) + } + return out +} + +func sortStrings(values []string) { + for i := 1; i < len(values); i++ { + for j := i; j > 0 && values[j] < values[j-1]; j-- { + values[j], values[j-1] = values[j-1], values[j] + } + } +} diff --git a/graphqlapi/dataframe/templates_test.go b/graphqlapi/dataframe/templates_test.go new file mode 100644 index 0000000..98bff83 --- /dev/null +++ b/graphqlapi/dataframe/templates_test.go @@ -0,0 +1,93 @@ +package dataframeapi + +import ( + "context" + "testing" + + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/catalog" +) + +func TestListTemplatesUsesCatalogEvidenceAndScope(t *testing.T) { + var fieldOptions []catalog.PopulatedFieldOptions + var referenceOptions []catalog.PopulatedReferenceOptions + service := NewService(Config{ + DiscoverFields: func(_ context.Context, options catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + fieldOptions = append(fieldOptions, options) + switch options.ResourceType { + case "Patient": + return []catalog.PopulatedField{ + {ResourceType: "Patient", Path: "identifier[].value"}, + {ResourceType: "Patient", Path: "gender"}, + {ResourceType: "Patient", Path: "birthDate"}, + }, nil + default: + return []catalog.PopulatedField{}, nil + } + }, + DiscoverReferences: func(_ context.Context, options catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + referenceOptions = append(referenceOptions, options) + if options.NodeType == "Patient" { + return []catalog.PopulatedReference{{FromType: "Patient", Label: "subject_Patient", ToType: "Condition", EdgeCount: 3}}, nil + } + return []catalog.PopulatedReference{}, nil + }, + }) + ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{Subject: "u1", Projects: []string{"P1"}, AuthResourcePaths: []string{"scope/a"}}) + got, err := service.ListTemplates(ctx, TemplateOptions{Project: "P1", AuthResourcePaths: []string{"scope/a"}}) + if err != nil { + t.Fatal(err) + } + if len(got) != 6 || got[0].ID != "patient-cohort" || got[5].ID != "study-enrollment" { + t.Fatalf("unexpected template order/result: %#v", got) + } + patient := got[0] + if patient.Status != "PARTIAL" || patient.RootResourceType != "Patient" { + t.Fatalf("patient availability = %#v", patient) + } + if len(patient.Starter.Fields) != 3 || patient.Starter.Fields[0].FieldRef != "Patient.identifier_value" { + t.Fatalf("patient starter = %#v", patient.Starter) + } + if len(fieldOptions) == 0 || len(referenceOptions) == 0 { + t.Fatalf("expected catalog calls, fields=%d references=%d", len(fieldOptions), len(referenceOptions)) + } + for _, options := range fieldOptions { + if options.Project != "P1" || options.AuthResourcePathsUnrestricted == nil || *options.AuthResourcePathsUnrestricted { + t.Fatalf("field scope was not explicit/restricted: %+v", options) + } + } + for _, options := range referenceOptions { + if options.Project != "P1" || options.Mode != catalog.TraversalModeBuilder || options.AuthResourcePaths[0] != "scope/a" { + t.Fatalf("reference scope was not propagated: %+v", options) + } + } +} + +func TestListTemplatesFiltersUnknownTemplateWithoutCatalogReads(t *testing.T) { + fieldCalls := 0 + service := NewService(Config{ + DiscoverFields: func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + fieldCalls++ + return nil, nil + }, + DiscoverReferences: func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + t.Fatal("unexpected reference discovery for unknown template") + return nil, nil + }, + }) + got, err := service.ListTemplates(context.Background(), TemplateOptions{Project: "P1", TemplateID: "not-a-template"}) + if err != nil { + t.Fatal(err) + } + if len(got) != 0 || fieldCalls != 0 { + t.Fatalf("unknown template result=%#v fieldCalls=%d", got, fieldCalls) + } +} + +func TestListTemplatesRejectsUnauthorizedProject(t *testing.T) { + service := NewService(Config{}) + ctx := authscope.ContextWithPrincipal(context.Background(), &authscope.Principal{Subject: "u1", Projects: []string{"P1"}}) + if _, err := service.ListTemplates(ctx, TemplateOptions{Project: "P2"}); err == nil { + t.Fatal("expected project authorization error") + } +} diff --git a/graphqlapi/dataframe/types.go b/graphqlapi/dataframe/types.go index ff6de69..47372b2 100644 --- a/graphqlapi/dataframe/types.go +++ b/graphqlapi/dataframe/types.go @@ -32,3 +32,20 @@ type RelatedResourceHints struct { EdgeCount int64 Target ResourceHints } + +// DatasetSummary is the frontend-facing discovery DTO. It deliberately +// contains catalog facts rather than persistence documents or collection +// names. +type DatasetSummary struct { + Project string + DatasetGeneration string + State string + ResourceTypes []ResourceTypeSummary +} + +type ResourceTypeSummary struct { + ResourceType string + DocumentCount int64 + PopulatedFieldCount int + PivotCandidateCount int +} diff --git a/graphqlapi/dataframe/validation.go b/graphqlapi/dataframe/validation.go new file mode 100644 index 0000000..b06c65c --- /dev/null +++ b/graphqlapi/dataframe/validation.go @@ -0,0 +1,98 @@ +package dataframeapi + +import ( + "context" + + "github.com/calypr/loom/graphqlapi/model" + "github.com/calypr/loom/internal/dataframe" +) + +// ValidationResult is the transport-neutral dataframe adapter result used by +// the future GraphQL resolver. It intentionally contains the normalized input +// and compiler metadata, but never rendered AQL or bind variables. +type ValidationResult struct { + Valid bool + NormalizedInput model.FhirDataframeInput + Project string + DatasetGeneration string + RootResourceType string + Limit int + Columns []string + PivotFields []string + RowIdentity *dataframe.RowIdentity + RequestFingerprint string + Warnings []dataframe.ValidationWarning + Plan dataframe.CompilerPlanDiagnostics + PreviewAllowed bool + ExportAllowed bool + Diagnostics dataframe.QueryDiagnostics +} + +// Validate resolves public fieldRefs, pins generation/scope, and delegates to +// the same internal preparation/compiler boundary used by Run. It never opens +// an Arango cursor or invokes row execution. +func (s *Service) Validate(ctx context.Context, input model.FhirDataframeInput) (ValidationResult, error) { + normalized, scope, generation, err := s.prepareRunInput(ctx, input) + if err != nil { + return ValidationResult{}, err + } + builder := BuilderFromInput(normalized) + builder.DatasetGeneration = generation + builder.AuthScopeMode = scope.Mode + limit := 0 + if normalized.Limit != nil { + limit = *normalized.Limit + } + validated, err := s.dataframes.Validate(ctx, dataframe.ValidateRequest{Builder: builder, Limit: limit}) + if err != nil { + return ValidationResult{}, err + } + validatedWarnings := cloneValidationWarnings(validated.Warnings) + // The internal service owns the normalized builder. Keep the adapter's + // public normalized input as the fieldRef-resolved model so a caller can + // display or persist it without learning compiler selectors. + return ValidationResult{ + Valid: validated.Valid, + NormalizedInput: normalized, + Project: validated.Project, + DatasetGeneration: validated.DatasetGeneration, + RootResourceType: validated.RootResourceType, + Limit: validated.Limit, + Columns: cloneStrings(validated.Columns), + PivotFields: cloneStrings(validated.PivotFields), + RowIdentity: cloneRowIdentity(validated.RowIdentity), + RequestFingerprint: validated.RequestFingerprint, + Warnings: validatedWarnings, + Plan: validated.Plan, + PreviewAllowed: validated.PreviewAllowed, + ExportAllowed: validated.ExportAllowed, + Diagnostics: validated.Diagnostics, + }, nil +} + +func cloneValidationWarnings(in []dataframe.ValidationWarning) []dataframe.ValidationWarning { + if len(in) == 0 { + return nil + } + out := make([]dataframe.ValidationWarning, len(in)) + for i, warning := range in { + out[i] = warning + out[i].Path = append([]string(nil), warning.Path...) + if warning.Details != nil { + out[i].Details = make(map[string]any, len(warning.Details)) + for key, value := range warning.Details { + out[i].Details[key] = value + } + } + } + return out +} + +func cloneRowIdentity(in *dataframe.RowIdentity) *dataframe.RowIdentity { + if in == nil { + return nil + } + out := *in + out.Fields = cloneStrings(in.Fields) + return &out +} diff --git a/graphqlapi/dataframe/validation_test.go b/graphqlapi/dataframe/validation_test.go new file mode 100644 index 0000000..f4be208 --- /dev/null +++ b/graphqlapi/dataframe/validation_test.go @@ -0,0 +1,80 @@ +package dataframeapi + +import ( + "context" + "testing" + + "github.com/calypr/loom/graphqlapi/model" + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/dataframe" +) + +func TestValidateUsesProductionCompilerWithoutExecutingRows(t *testing.T) { + executed := false + discoverFields := func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + return []catalog.PopulatedField{}, nil + } + discoverReferences := func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + return []catalog.PopulatedReference{}, nil + } + inner := dataframe.NewService(dataframe.ServiceConfig{ + DiscoverFields: discoverFields, + DiscoverReferences: discoverReferences, + ExecuteRows: func(context.Context, dataframe.ExecuteQueryOptions, string, map[string]any, func(map[string]any) error) error { + executed = true + return nil + }, + }) + service := NewService(Config{Dataframes: inner, DiscoverFields: discoverFields, DiscoverReferences: discoverReferences}) + result, err := service.Validate(context.Background(), model.FhirDataframeInput{ + Project: "P1", + RootResourceType: "Patient", + Limit: intPtr(25), + }) + if err != nil { + t.Fatalf("Validate() error = %v", err) + } + if !result.Valid || result.Project != "P1" || result.RootResourceType != "Patient" { + t.Fatalf("unexpected validation result: %#v", result) + } + if result.Limit != 25 || result.RequestFingerprint == "" || len(result.Columns) == 0 { + t.Fatalf("validation result omitted compiler metadata: %#v", result) + } + if executed { + t.Fatal("Validate executed rows") + } + if result.NormalizedInput.Project != "P1" || result.NormalizedInput.RootResourceType != "Patient" { + t.Fatalf("normalized input was not returned: %#v", result.NormalizedInput) + } +} + +func TestValidateResolvesFieldRefsBeforeCompilation(t *testing.T) { + discoverFields := func(_ context.Context, options catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + return []catalog.PopulatedField{{ResourceType: options.ResourceType, Path: "gender"}}, nil + } + discoverReferences := func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + return []catalog.PopulatedReference{}, nil + } + inner := dataframe.NewService(dataframe.ServiceConfig{ + DiscoverFields: discoverFields, + DiscoverReferences: discoverReferences, + }) + service := NewService(Config{Dataframes: inner, DiscoverFields: discoverFields, DiscoverReferences: discoverReferences}) + fieldRef := "Patient.gender" + result, err := service.Validate(context.Background(), model.FhirDataframeInput{ + Project: "P1", + RootResourceType: "Patient", + RootFields: []*model.FhirFieldSelectInput{{Name: "gender", FieldRef: &fieldRef}}, + }) + if err != nil { + t.Fatalf("Validate() error = %v", err) + } + if len(result.NormalizedInput.RootFields) != 1 || result.NormalizedInput.RootFields[0].Selector == nil { + t.Fatalf("fieldRef was not resolved: %#v", result.NormalizedInput.RootFields) + } + if len(result.Columns) < 2 { + t.Fatalf("compiled columns = %#v", result.Columns) + } +} + +func intPtr(value int) *int { return &value } diff --git a/graphqlapi/errors.go b/graphqlapi/errors.go new file mode 100644 index 0000000..f01edff --- /dev/null +++ b/graphqlapi/errors.go @@ -0,0 +1,56 @@ +package graphqlapi + +import ( + "errors" + + "github.com/calypr/loom/internal/dataframe" + "github.com/vektah/gqlparser/v2/gqlerror" +) + +// PresentError converts a service error to the GraphQL error shape used by +// the frontend. The original error remains attached to gqlerror.Error.Err so +// server logging and errors.Is/errors.As retain their normal behavior. +func PresentError(err error, requestID string) *gqlerror.Error { + if err == nil { + return nil + } + userErr := dataframe.Normalize(err) + return &gqlerror.Error{ + Err: err, + Message: dataframe.PublicMessage(userErr), + Extensions: ExtensionsForError(userErr, requestID), + } +} + +// GraphQLError is an error-returning convenience for resolver code. +func GraphQLError(err error, requestID string) error { + return PresentError(err, requestID) +} + +// ExtensionsForError returns a fresh map suitable for a GraphQL error +// response. It deliberately exposes only the stable semantic contract. +func ExtensionsForError(err error, requestID string) map[string]any { + userErr := dataframe.Normalize(err) + if userErr == nil { + return nil + } + extensions := map[string]any{ + "code": userErr.Code(), + "fieldPath": append([]string(nil), userErr.FieldPath()...), + "retryable": userErr.Retryable(), + } + if details := userErr.Details(); len(details) > 0 { + extensions["details"] = details + } + if requestID != "" { + extensions["requestId"] = requestID + } + return extensions +} + +// IsUserError is useful to adapters that need to preserve the semantic error +// while adding transport context. +func IsUserError(err error) bool { + var userErr dataframe.UserError + return errors.As(err, &userErr) +} diff --git a/graphqlapi/errors_test.go b/graphqlapi/errors_test.go new file mode 100644 index 0000000..8648e58 --- /dev/null +++ b/graphqlapi/errors_test.go @@ -0,0 +1,59 @@ +package graphqlapi + +import ( + "errors" + "testing" + + "github.com/calypr/loom/internal/dataframe" +) + +func TestPresentErrorUsesStableExtensions(t *testing.T) { + err := dataframe.NewError( + dataframe.CodeUnknownField, + "secret internal selector detail", + dataframe.WithFieldPath("rootFields", "2", "fieldRef"), + dataframe.WithDetails(map[string]any{"fieldRef": "Patient.missing", "aql": "FOR p IN Patient RETURN p"}), + ) + graphqlErr := PresentError(err, "request-123") + if graphqlErr == nil { + t.Fatal("PresentError returned nil") + } + if graphqlErr.Message != "the selected field is not recognized" { + t.Fatalf("message = %q", graphqlErr.Message) + } + if graphqlErr.Extensions["code"] != string(dataframe.CodeUnknownField) { + t.Fatalf("extensions = %#v", graphqlErr.Extensions) + } + if graphqlErr.Extensions["requestId"] != "request-123" { + t.Fatalf("request ID missing: %#v", graphqlErr.Extensions) + } + if _, ok := graphqlErr.Extensions["aql"]; ok { + t.Fatalf("AQL extension leaked: %#v", graphqlErr.Extensions) + } + if !errors.Is(graphqlErr, err) { + t.Fatal("GraphQL error did not preserve original cause") + } +} + +func TestPresentErrorRedactsUnknownErrors(t *testing.T) { + graphqlErr := PresentError(errors.New("AQL FOR p IN Patient bind=@token"), "request-456") + if graphqlErr.Message != "internal server error" { + t.Fatalf("unknown message = %q", graphqlErr.Message) + } + if graphqlErr.Extensions["code"] != string(dataframe.CodeInternalError) { + t.Fatalf("unknown extensions = %#v", graphqlErr.Extensions) + } + if graphqlErr.Extensions["details"] != nil { + t.Fatalf("unknown details leaked: %#v", graphqlErr.Extensions) + } +} + +func TestExtensionsForErrorOmitsEmptyRequestID(t *testing.T) { + extensions := ExtensionsForError(dataframe.NewError(dataframe.CodeInvalidCursor, ""), "") + if _, ok := extensions["requestId"]; ok { + t.Fatalf("empty request ID should be omitted: %#v", extensions) + } + if extensions["fieldPath"] == nil { + t.Fatal("fieldPath extension should remain present for stable shape") + } +} diff --git a/internal/catalog/generation_test.go b/internal/catalog/generation_test.go index 70810ac..e910ae6 100644 --- a/internal/catalog/generation_test.go +++ b/internal/catalog/generation_test.go @@ -22,6 +22,16 @@ func TestCatalogGenerationBindsUseExactOrLegacyNullNamespace(t *testing.T) { if got := references["dataset_generation"]; got != "generation-a" { t.Fatalf("reference dataset_generation bind = %#v, want generation-a", got) } + builderReferences := populatedReferencesBindVars(PopulatedReferenceOptions{ + Project: "P1", + NodeType: "Patient", + }, TraversalModeBuilder) + if _, ok := builderReferences["from_type"]; ok { + t.Fatalf("builder reference binds retained storage-only from_type: %#v", builderReferences) + } + if _, ok := builderReferences["mode"]; ok { + t.Fatalf("reference binds retained obsolete mode parameter: %#v", builderReferences) + } legacyFields := populatedFieldsBindVars(PopulatedFieldOptions{Project: "P1"}) if got, present := legacyFields["dataset_generation"]; !present || got != nil { @@ -32,13 +42,16 @@ func TestCatalogGenerationBindsUseExactOrLegacyNullNamespace(t *testing.T) { t.Fatalf("legacy reference dataset_generation bind = %#v (present=%t), want explicit nil", got, present) } - for name, query := range map[string]string{ - "fields": populatedFieldsAQL, - "references": populatedReferencesAQL, - "auth paths": existingAuthResourcePathsAQL, + for name, query := range map[string]struct { + query string + prefix string + }{ + "fields": {query: populatedFieldsAQL, prefix: "d"}, + "references": {query: relationshipCatalogBuilderAQL, prefix: "d"}, + "auth paths": {query: existingAuthResourcePathsAQL, prefix: "d"}, } { - if !strings.Contains(query, "FILTER "+map[string]string{"fields": "d", "references": "e", "auth paths": "d"}[name]+".dataset_generation == @dataset_generation") { - t.Fatalf("%s query is missing exact dataset-generation predicate:\n%s", name, query) + if !strings.Contains(query.query, "FILTER "+query.prefix+".dataset_generation == @dataset_generation") { + t.Fatalf("%s query is missing exact dataset-generation predicate:\n%s", name, query.query) } } } diff --git a/internal/catalog/read_datasets.go b/internal/catalog/read_datasets.go new file mode 100644 index 0000000..49460ed --- /dev/null +++ b/internal/catalog/read_datasets.go @@ -0,0 +1,174 @@ +package catalog + +import ( + "context" + "fmt" + "sort" + "strings" + "time" + + arangostore "github.com/calypr/loom/internal/store/arango" +) + +// datasetSummariesAQL deliberately reads only the ingest-owned field catalog. +// The first COLLECT removes duplicate rows for the same visible resource +// type/path (for example, one row per auth resource path); the second groups +// those field facts by resource type without multiplying counts. +const datasetSummariesAQL = ` +FOR d IN fhir_field_catalog + FILTER d.project == @project + FILTER d.dataset_generation == @dataset_generation + FILTER @auth_resource_paths_unrestricted == true OR d.auth_resource_path IN @auth_resource_paths + COLLECT resource_type = d.resource_type, path = d.path + AGGREGATE document_count = MAX(d.doc_count), pivot_candidate = MAX(d.pivot_candidate ? 1 : 0) + COLLECT resource_type = resource_type + AGGREGATE document_count = MAX(document_count), populated_field_count = COUNT(), pivot_candidate_count = SUM(pivot_candidate) + SORT resource_type + RETURN { + resource_type, + document_count, + populated_field_count, + pivot_candidate_count + } +` + +type datasetRowsQuery func(context.Context, string, int, map[string]any, arangostore.RowVisitor) error + +// DiscoverDatasetSummaries returns only projects explicitly supplied by the +// caller. It opens one Arango client for the whole read, while each project +// retains its own generation and authorization bind values. +func DiscoverDatasetSummaries(ctx context.Context, opts DatasetSummaryOptions) ([]DatasetSummary, error) { + projects := normalizedProjectAllowlist(opts.ProjectAllowlist) + if len(projects) == 0 { + return []DatasetSummary{}, nil + } + if opts.CursorBatch <= 0 { + opts.CursorBatch = 1000 + } + client, err := arangostore.Open(ctx, opts.URL, opts.Database) + if err != nil { + return nil, err + } + defer client.Close(ctx) + + results := make([]DatasetSummary, 0, len(projects)) + for _, project := range projects { + generation := NormalizeDatasetGeneration(opts.DatasetGenerationByProject[project]) + scope, hasScope := opts.AuthScopesByProject[project] + if !hasScope { + // Discovery callers must pass a scope for every project. Keeping this + // default explicit preserves compatibility for direct catalog users + // without turning an omitted path list into an implicit restriction. + scope = DatasetAuthScope{Unrestricted: true} + } + state := strings.TrimSpace(opts.DatasetStateByProject[project]) + if state == "" { + if generation == "" { + state = "LEGACY" + } else { + state = "READY" + } + } + + start := time.Now() + emit("go_discovery_start", map[string]any{ + "database": opts.Database, + "project": project, + "dataset_generation": DatasetGenerationBindValue(generation), + "auth_resource_paths": scope.AuthResourcePaths, + "cursor_batch_size": opts.CursorBatch, + "query": "dataset_summaries", + }) + + bindVars := map[string]any{ + "project": project, + "dataset_generation": DatasetGenerationBindValue(generation), + "auth_resource_paths": cloneStrings(scope.AuthResourcePaths), + "auth_resource_paths_unrestricted": scope.Unrestricted, + } + rows, err := readDatasetResourceTypes(ctx, client.QueryRows, opts.CursorBatch, bindVars, project) + if err != nil { + return nil, err + } + if len(rows) == 0 { + emit("go_discovery_complete", map[string]any{ + "database": opts.Database, + "project": project, + "dataset_generation": DatasetGenerationBindValue(generation), + "auth_resource_paths": scope.AuthResourcePaths, + "rows": 0, + "seconds": secondsSince(start), + "query": "dataset_summaries", + }) + continue + } + sort.Slice(rows, func(i, j int) bool { return rows[i].ResourceType < rows[j].ResourceType }) + results = append(results, DatasetSummary{ + Project: project, + DatasetGeneration: generation, + State: state, + ResourceTypes: rows, + }) + emit("go_discovery_complete", map[string]any{ + "database": opts.Database, + "project": project, + "dataset_generation": DatasetGenerationBindValue(generation), + "auth_resource_paths": scope.AuthResourcePaths, + "rows": len(rows), + "seconds": secondsSince(start), + "query": "dataset_summaries", + }) + } + return results, nil +} + +func readDatasetResourceTypes(ctx context.Context, query datasetRowsQuery, batchSize int, bindVars map[string]any, project string) ([]ResourceTypeSummary, error) { + rows := make([]ResourceTypeSummary, 0, 16) + if err := query(ctx, datasetSummariesAQL, batchSize, bindVars, func(row map[string]any) error { + resourceType := stringValue(row["resource_type"]) + if resourceType == "" { + return fmt.Errorf("dataset summary returned an empty resource type for project %q", project) + } + documentCount, err := int64Value(row["document_count"]) + if err != nil { + return fmt.Errorf("decode document_count for %s/%s: %w", project, resourceType, err) + } + populatedFields, err := int64Value(row["populated_field_count"]) + if err != nil { + return fmt.Errorf("decode populated_field_count for %s/%s: %w", project, resourceType, err) + } + pivotCandidates, err := int64Value(row["pivot_candidate_count"]) + if err != nil { + return fmt.Errorf("decode pivot_candidate_count for %s/%s: %w", project, resourceType, err) + } + rows = append(rows, ResourceTypeSummary{ + ResourceType: resourceType, + DocumentCount: documentCount, + PopulatedFieldCount: int(populatedFields), + PivotCandidateCount: int(pivotCandidates), + }) + return nil + }); err != nil { + return nil, err + } + sort.Slice(rows, func(i, j int) bool { return rows[i].ResourceType < rows[j].ResourceType }) + return rows, nil +} + +func normalizedProjectAllowlist(projects []string) []string { + seen := make(map[string]struct{}, len(projects)) + result := make([]string, 0, len(projects)) + for _, project := range projects { + project = strings.TrimSpace(project) + if project == "" { + continue + } + if _, ok := seen[project]; ok { + continue + } + seen[project] = struct{}{} + result = append(result, project) + } + sort.Strings(result) + return result +} diff --git a/internal/catalog/read_datasets_test.go b/internal/catalog/read_datasets_test.go new file mode 100644 index 0000000..ddc397a --- /dev/null +++ b/internal/catalog/read_datasets_test.go @@ -0,0 +1,99 @@ +package catalog + +import ( + "context" + "strings" + "testing" + + arangostore "github.com/calypr/loom/internal/store/arango" +) + +func TestNormalizedProjectAllowlistSortsDeduplicatesAndTrims(t *testing.T) { + got := normalizedProjectAllowlist([]string{" P2 ", "P1", "", "P2", "P1"}) + want := []string{"P1", "P2"} + if len(got) != len(want) { + t.Fatalf("normalized projects = %#v, want %#v", got, want) + } + for i := range want { + if got[i] != want[i] { + t.Fatalf("normalized projects = %#v, want %#v", got, want) + } + } +} + +func TestReadDatasetResourceTypesDecodesRowsAndPreservesScopeBinds(t *testing.T) { + var gotQuery string + var gotBatch int + var gotBinds map[string]any + query := datasetRowsQuery(func(_ context.Context, query string, batch int, binds map[string]any, visit arangostore.RowVisitor) error { + gotQuery = query + gotBatch = batch + gotBinds = binds + if err := visit(map[string]any{ + "resource_type": "Specimen", + "document_count": int64(7), + "populated_field_count": int64(3), + "pivot_candidate_count": int64(1), + }); err != nil { + return err + } + return visit(map[string]any{ + "resource_type": "Patient", + "document_count": float64(9), + "populated_field_count": float64(4), + "pivot_candidate_count": float64(0), + }) + }) + + rows, err := readDatasetResourceTypes(context.Background(), query, 37, map[string]any{ + "project": "P1", + "dataset_generation": nil, + "auth_resource_paths": []string{}, + "auth_resource_paths_unrestricted": false, + }, "P1") + if err != nil { + t.Fatalf("readDatasetResourceTypes() error = %v", err) + } + if gotBatch != 37 || gotBinds["dataset_generation"] != nil || gotBinds["auth_resource_paths_unrestricted"] != false { + t.Fatalf("query contract batch=%d binds=%#v", gotBatch, gotBinds) + } + if !strings.Contains(gotQuery, "COLLECT resource_type = d.resource_type, path = d.path") || !strings.Contains(gotQuery, "pivot_candidate_count") { + t.Fatalf("dataset query does not preserve deduplicating aggregation: %s", gotQuery) + } + if len(rows) != 2 || rows[0].ResourceType != "Patient" || rows[1].ResourceType != "Specimen" { + t.Fatalf("rows = %#v, want deterministic resource ordering", rows) + } + if rows[0].DocumentCount != 9 || rows[0].PopulatedFieldCount != 4 || rows[1].PivotCandidateCount != 1 { + t.Fatalf("decoded rows = %#v", rows) + } +} + +func TestReadDatasetResourceTypesRejectsMalformedRows(t *testing.T) { + tests := []struct { + name string + row map[string]any + }{ + {name: "missing resource type", row: map[string]any{"document_count": int64(1), "populated_field_count": int64(1), "pivot_candidate_count": int64(0)}}, + {name: "invalid count", row: map[string]any{"resource_type": "Patient", "document_count": "one", "populated_field_count": int64(1), "pivot_candidate_count": int64(0)}}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + query := datasetRowsQuery(func(_ context.Context, _ string, _ int, _ map[string]any, visit arangostore.RowVisitor) error { + return visit(test.row) + }) + if _, err := readDatasetResourceTypes(context.Background(), query, 1, nil, "P1"); err == nil { + t.Fatal("expected malformed row error") + } + }) + } +} + +func TestDiscoverDatasetSummariesRequiresExplicitProjects(t *testing.T) { + rows, err := DiscoverDatasetSummaries(context.Background(), DatasetSummaryOptions{}) + if err != nil { + t.Fatalf("DiscoverDatasetSummaries() error = %v", err) + } + if rows == nil || len(rows) != 0 { + t.Fatalf("empty project allowlist result = %#v, want non-nil empty", rows) + } +} diff --git a/internal/catalog/read_references.go b/internal/catalog/read_references.go index ba24ab3..1f2f8b3 100644 --- a/internal/catalog/read_references.go +++ b/internal/catalog/read_references.go @@ -8,25 +8,48 @@ import ( arangostore "github.com/calypr/loom/internal/store/arango" ) -const populatedReferencesAQL = ` -FOR e IN fhir_edge - FILTER e.project == @project - FILTER e.dataset_generation == @dataset_generation - FILTER @auth_resource_paths_unrestricted == true OR e.auth_resource_path IN @auth_resource_paths - FILTER ( - @mode == "builder" && (@node_type == null || e.to_type == @node_type) - ) || ( - @mode != "builder" && (@from_type == null || e.from_type == @from_type) - ) +// relationshipCatalogBuilderAQL is the indexed runtime discovery path. The +// builder asks for edges entering a node type, so the persisted edge +// orientation is reversed in the dataframe-facing result (the same contract +// as the direct repair query above). +const relationshipCatalogBuilderAQL = ` +FOR d IN fhir_relationship_catalog + FILTER d.project == @project + FILTER d.dataset_generation == @dataset_generation + FILTER @auth_resource_paths_unrestricted == true OR d.auth_resource_path IN @auth_resource_paths + FILTER @node_type == null OR d.to_type == @node_type COLLECT - dataset_generation = e.dataset_generation, - from_type = (@mode == "builder" ? @node_type : e.from_type), - label = e.label, - to_type = (@mode == "builder" ? e.from_type : e.to_type) - WITH COUNT INTO edge_count + from_type = d.to_type, + label = d.label, + to_type = d.from_type + AGGREGATE edge_count = SUM(d.edge_count) SORT from_type, edge_count DESC, label, to_type RETURN { - dataset_generation, + dataset_generation: @dataset_generation, + from_type, + label, + to_type, + edge_count + } +` + +// relationshipCatalogStorageAQL keeps the physical edge orientation for +// storage traversal discovery. Both runtime paths read only the compact +// ingest-owned catalog; fhir_edge aggregation remains an explicit rebuild. +const relationshipCatalogStorageAQL = ` +FOR d IN fhir_relationship_catalog + FILTER d.project == @project + FILTER d.dataset_generation == @dataset_generation + FILTER @auth_resource_paths_unrestricted == true OR d.auth_resource_path IN @auth_resource_paths + FILTER @from_type == null OR d.from_type == @from_type + COLLECT + from_type = d.from_type, + label = d.label, + to_type = d.to_type + AGGREGATE edge_count = SUM(d.edge_count) + SORT from_type, edge_count DESC, label, to_type + RETURN { + dataset_generation: @dataset_generation, from_type, label, to_type, @@ -61,11 +84,15 @@ func DiscoverPopulatedReferences(ctx context.Context, opts PopulatedReferenceOpt if mode == "" { mode = TraversalModeStorage } + query := relationshipCatalogStorageAQL + if mode == TraversalModeBuilder { + query = relationshipCatalogBuilderAQL + } bindVars := populatedReferencesBindVars(opts, mode) results := make([]PopulatedReference, 0, 64) - err = client.QueryRows(ctx, populatedReferencesAQL, opts.CursorBatch, bindVars, func(row map[string]any) error { + err = client.QueryRows(ctx, query, opts.CursorBatch, bindVars, func(row map[string]any) error { ref := PopulatedReference{ DatasetGeneration: stringValue(row["dataset_generation"]), FromType: stringValue(row["from_type"]), @@ -104,17 +131,19 @@ func populatedReferencesBindVars(opts PopulatedReferenceOptions, mode string) ma "dataset_generation": DatasetGenerationBindValue(opts.DatasetGeneration), "auth_resource_paths": cloneStrings(opts.AuthResourcePaths), "auth_resource_paths_unrestricted": EffectiveAuthResourcePathsUnrestricted(opts.AuthResourcePaths, opts.AuthResourcePathsUnrestricted), - "mode": mode, } - if opts.FromType != "" { - bindVars["from_type"] = opts.FromType - } else { - bindVars["from_type"] = nil - } - if opts.NodeType != "" { - bindVars["node_type"] = opts.NodeType + if mode == TraversalModeBuilder { + if opts.NodeType != "" { + bindVars["node_type"] = opts.NodeType + } else { + bindVars["node_type"] = nil + } } else { - bindVars["node_type"] = nil + if opts.FromType != "" { + bindVars["from_type"] = opts.FromType + } else { + bindVars["from_type"] = nil + } } return bindVars } diff --git a/internal/catalog/rebuild.go b/internal/catalog/rebuild.go new file mode 100644 index 0000000..3f589e6 --- /dev/null +++ b/internal/catalog/rebuild.go @@ -0,0 +1,142 @@ +package catalog + +import ( + "context" + "time" + + arangostore "github.com/calypr/loom/internal/store/arango" +) + +// RelationshipRebuildOptions describes the explicit repair path. Normal +// discovery never uses this scan; operators call it after an old dataset was +// loaded before the relationship catalog existed or after a repair. +type RelationshipRebuildOptions struct { + arangostore.ConnectionOptions + Project string + DatasetGeneration string + AuthResourcePaths []string + AuthResourcePathsUnrestricted *bool + CursorBatch int + BatchSize int + WriteAPI string +} + +type RelationshipRebuildSummary struct { + Project string `json:"project"` + DatasetGeneration string `json:"dataset_generation,omitempty"` + Rows int `json:"rows"` + EdgeCount int64 `json:"edge_count"` + Seconds float64 `json:"seconds"` +} + +const relationshipRebuildAQL = ` +FOR e IN fhir_edge + FILTER e.project == @project + FILTER e.dataset_generation == @dataset_generation + FILTER @auth_resource_paths_unrestricted == true OR e.auth_resource_path IN @auth_resource_paths + COLLECT + project = e.project, + dataset_generation = e.dataset_generation, + auth_resource_path = e.auth_resource_path, + from_type = e.from_type, + label = e.label, + to_type = e.to_type + WITH COUNT INTO edge_count + RETURN { + project, + dataset_generation, + auth_resource_path, + from_type, + label, + to_type, + edge_count + } +` + +const relationshipClearAQL = ` +FOR d IN fhir_relationship_catalog + FILTER d.project == @project + FILTER d.dataset_generation == @dataset_generation + FILTER @auth_resource_paths_unrestricted == true OR d.auth_resource_path IN @auth_resource_paths + REMOVE d IN fhir_relationship_catalog + RETURN 1 +` + +// RebuildRelationshipCatalog performs the only supported direct fhir_edge +// aggregation. It clears the selected namespace first, then writes a +// deterministic compact catalog, making repeated rebuilds idempotent. +func RebuildRelationshipCatalog(ctx context.Context, opts RelationshipRebuildOptions) (RelationshipRebuildSummary, error) { + if opts.CursorBatch <= 0 { + opts.CursorBatch = 1000 + } + if opts.BatchSize <= 0 { + opts.BatchSize = 1000 + } + if opts.WriteAPI == "" { + opts.WriteAPI = "import" + } + client, err := arangostore.Open(ctx, opts.URL, opts.Database) + if err != nil { + return RelationshipRebuildSummary{}, err + } + defer client.Close(ctx) + if err := client.Bootstrap(ctx, arangostore.BootstrapSpec{Collections: []arangostore.CollectionSpec{{ + Name: RelationshipCatalogCollection, + Indexes: [][]string{ + {"project", "dataset_generation", "to_type"}, + {"project", "dataset_generation", "auth_resource_path", "to_type"}, + {"project", "dataset_generation", "from_type"}, + {"project", "dataset_generation", "auth_resource_path", "from_type"}, + }, + }}}); err != nil { + return RelationshipRebuildSummary{}, err + } + bindVars := relationshipRebuildBindVars(opts) + if err := client.QueryRows(ctx, relationshipClearAQL, opts.CursorBatch, bindVars, func(map[string]any) error { return nil }); err != nil { + return RelationshipRebuildSummary{}, err + } + counts := make(map[RelationshipKey]int64) + start := time.Now() + if err := client.QueryRows(ctx, relationshipRebuildAQL, opts.CursorBatch, bindVars, func(row map[string]any) error { + count, err := int64Value(row["edge_count"]) + if err != nil { + return err + } + key := RelationshipKey{ + Project: stringValue(row["project"]), + DatasetGeneration: stringValue(row["dataset_generation"]), + AuthResourcePath: stringValue(row["auth_resource_path"]), + FromType: stringValue(row["from_type"]), + Label: stringValue(row["label"]), + ToType: stringValue(row["to_type"]), + } + counts[key] = count + return nil + }); err != nil { + return RelationshipRebuildSummary{}, err + } + docs := RelationshipCatalogDocuments(counts) + if err := WriteRelationshipCatalog(ctx, client, docs, opts.BatchSize, true, opts.WriteAPI, nil); err != nil { + return RelationshipRebuildSummary{}, err + } + var edgeCount int64 + for _, count := range counts { + edgeCount += count + } + return RelationshipRebuildSummary{ + Project: opts.Project, + DatasetGeneration: NormalizeDatasetGeneration(opts.DatasetGeneration), + Rows: len(docs), + EdgeCount: edgeCount, + Seconds: time.Since(start).Seconds(), + }, nil +} + +func relationshipRebuildBindVars(opts RelationshipRebuildOptions) map[string]any { + return map[string]any{ + "project": opts.Project, + "dataset_generation": DatasetGenerationBindValue(opts.DatasetGeneration), + "auth_resource_paths": cloneStrings(opts.AuthResourcePaths), + "auth_resource_paths_unrestricted": EffectiveAuthResourcePathsUnrestricted(opts.AuthResourcePaths, opts.AuthResourcePathsUnrestricted), + } +} diff --git a/internal/catalog/relationships.go b/internal/catalog/relationships.go new file mode 100644 index 0000000..2e72a4c --- /dev/null +++ b/internal/catalog/relationships.go @@ -0,0 +1,101 @@ +package catalog + +import ( + "encoding/json" + "fmt" + "sort" + + "github.com/bytedance/sonic" +) + +const relationshipCatalogKeyPrefix = "rfc_" + +// rawRelationshipEdge is the small subset of an edge document needed to +// build the ingest-owned relationship catalog. It deliberately does not +// depend on a generated FHIR type: graph edge routing is schema-owned and the +// persisted edge contract is stable across generated and generic loaders. +type rawRelationshipEdge struct { + Project string `json:"project"` + DatasetGeneration string `json:"dataset_generation"` + AuthResourcePath string `json:"auth_resource_path"` + FromType string `json:"from_type"` + Label string `json:"label"` + ToType string `json:"to_type"` +} + +// RelationshipCountsFromRawEdges counts only complete, routable edge +// documents. Callers add these counts to their committed-write result only +// after InsertBatchRaw succeeds, so failed batches can never advertise facts +// that are absent from Arango. +func RelationshipCountsFromRawEdges(docs []json.RawMessage) (map[RelationshipKey]int64, error) { + counts := make(map[RelationshipKey]int64) + for index, raw := range docs { + var edge rawRelationshipEdge + if err := sonic.Unmarshal(raw, &edge); err != nil { + return nil, fmt.Errorf("decode relationship edge %d: %w", index, err) + } + if edge.Project == "" || edge.FromType == "" || edge.Label == "" || edge.ToType == "" { + return nil, fmt.Errorf("relationship edge %d is missing project/from_type/label/to_type", index) + } + key := RelationshipKey{ + Project: edge.Project, + DatasetGeneration: NormalizeDatasetGeneration(edge.DatasetGeneration), + AuthResourcePath: edge.AuthResourcePath, + FromType: edge.FromType, + Label: edge.Label, + ToType: edge.ToType, + } + counts[key]++ + } + return counts, nil +} + +func MergeRelationshipCounts(dst, src map[RelationshipKey]int64) { + for key, count := range src { + dst[key] += count + } +} + +func RelationshipCatalogDocuments(counts map[RelationshipKey]int64) []RelationshipCatalogDocument { + keys := make([]RelationshipKey, 0, len(counts)) + for key, count := range counts { + if count > 0 { + keys = append(keys, key) + } + } + sort.Slice(keys, func(i, j int) bool { + left, right := keys[i], keys[j] + for _, pair := range [][2]string{{left.Project, right.Project}, {left.DatasetGeneration, right.DatasetGeneration}, {left.AuthResourcePath, right.AuthResourcePath}, {left.FromType, right.FromType}, {left.Label, right.Label}, {left.ToType, right.ToType}} { + if pair[0] != pair[1] { + return pair[0] < pair[1] + } + } + return false + }) + docs := make([]RelationshipCatalogDocument, 0, len(keys)) + for _, key := range keys { + docs = append(docs, RelationshipCatalogDocument{ + Key: relationshipCatalogKey(key), + Project: key.Project, + DatasetGeneration: NormalizeDatasetGeneration(key.DatasetGeneration), + AuthResourcePath: key.AuthResourcePath, + FromType: key.FromType, + Label: key.Label, + ToType: key.ToType, + EdgeCount: counts[key], + }) + } + return docs +} + +func relationshipCatalogKey(key RelationshipKey) string { + return relationshipCatalogKeyPrefix + catalogIdentityDigest( + "relationship-catalog/v1", + key.Project, + NormalizeDatasetGeneration(key.DatasetGeneration), + key.AuthResourcePath, + key.FromType, + key.Label, + key.ToType, + ) +} diff --git a/internal/catalog/relationships_test.go b/internal/catalog/relationships_test.go new file mode 100644 index 0000000..82ca14e --- /dev/null +++ b/internal/catalog/relationships_test.go @@ -0,0 +1,54 @@ +package catalog + +import ( + "encoding/json" + "reflect" + "strings" + "testing" +) + +func TestRelationshipCountsRequireCompleteCommittedEdgeShape(t *testing.T) { + docs := []json.RawMessage{ + json.RawMessage(`{"project":"P1","from_type":"Patient","label":"subject","to_type":"Specimen"}`), + json.RawMessage(`{"project":"P1","from_type":"Patient","label":"subject","to_type":"Specimen"}`), + } + counts, err := RelationshipCountsFromRawEdges(docs) + if err != nil { + t.Fatal(err) + } + want := map[RelationshipKey]int64{{Project: "P1", FromType: "Patient", Label: "subject", ToType: "Specimen"}: 2} + if !reflect.DeepEqual(counts, want) { + t.Fatalf("counts = %#v, want %#v", counts, want) + } + if _, err := RelationshipCountsFromRawEdges([]json.RawMessage{json.RawMessage(`{"project":"P1","from_type":"Patient"}`)}); err == nil { + t.Fatal("incomplete edge was accepted") + } +} + +func TestRelationshipCatalogDocumentsHaveStableGenerationSafeKeys(t *testing.T) { + counts := map[RelationshipKey]int64{ + {Project: "P1", DatasetGeneration: "gen/a", AuthResourcePath: "path", FromType: "Patient", Label: "subject", ToType: "Specimen"}: 3, + } + docs := RelationshipCatalogDocuments(counts) + if len(docs) != 1 || !strings.HasPrefix(docs[0].Key, relationshipCatalogKeyPrefix) { + t.Fatalf("documents = %#v", docs) + } + if docs[0].DatasetGeneration != "gen/a" || docs[0].EdgeCount != 3 { + t.Fatalf("document = %#v", docs[0]) + } + other := RelationshipCatalogDocuments(map[RelationshipKey]int64{ + {Project: "P1", DatasetGeneration: "gen a", AuthResourcePath: "path", FromType: "Patient", Label: "subject", ToType: "Specimen"}: 3, + }) + if docs[0].Key == other[0].Key { + t.Fatal("distinct generations collided in relationship key") + } +} + +func TestRuntimeReferenceDiscoveryUsesCatalogAndKeepsRepairExplicit(t *testing.T) { + if !strings.Contains(relationshipCatalogBuilderAQL, "FOR d IN fhir_relationship_catalog") || !strings.Contains(relationshipCatalogStorageAQL, "FOR d IN fhir_relationship_catalog") { + t.Fatal("runtime relationship queries do not use the catalog") + } + if !strings.Contains(relationshipRebuildAQL, "FOR e IN fhir_edge") || strings.Contains(relationshipCatalogBuilderAQL, "fhir_edge") || strings.Contains(relationshipCatalogStorageAQL, "fhir_edge") { + t.Fatal("direct edge aggregation leaked into runtime discovery") + } +} diff --git a/internal/catalog/types.go b/internal/catalog/types.go index 83956bb..a582874 100644 --- a/internal/catalog/types.go +++ b/internal/catalog/types.go @@ -7,16 +7,17 @@ import ( ) const ( - FieldCatalogCollection = "fhir_field_catalog" - fieldCatalogDistinctCap = 50 - fieldCatalogPivotCap = 50 - fieldKindScalar = "scalar" - fieldKindObject = "object" - fieldKindArray = "array" - fieldKindCodeableConcept = "codeable_concept" - fieldKindCoding = "coding" - pivotKindCodeableConcept = "codeable_concept_display_value" - pivotKindObservation = "observation_code_value" + FieldCatalogCollection = "fhir_field_catalog" + RelationshipCatalogCollection = "fhir_relationship_catalog" + fieldCatalogDistinctCap = 50 + fieldCatalogPivotCap = 50 + fieldKindScalar = "scalar" + fieldKindObject = "object" + fieldKindArray = "array" + fieldKindCodeableConcept = "codeable_concept" + fieldKindCoding = "coding" + pivotKindCodeableConcept = "codeable_concept_display_value" + pivotKindObservation = "observation_code_value" ) const ( @@ -68,6 +69,48 @@ type PopulatedFieldOptions struct { CursorBatch int } +// DatasetSummaryOptions describes one scoped dataset-discovery read. The +// reader accepts an explicit project allowlist; an empty allowlist means no +// projects are queried. Callers may select a different immutable generation +// and authorization scope for every project in the allowlist. +type DatasetSummaryOptions struct { + arangostore.ConnectionOptions + ProjectAllowlist []string + DatasetGenerationByProject map[string]string + AuthScopesByProject map[string]DatasetAuthScope + DatasetStateByProject map[string]string + CursorBatch int +} + +// DatasetAuthScope is the catalog-facing form of an effective read scope. +// Unrestricted is authoritative even when AuthResourcePaths is empty, so a +// restricted caller with no surviving paths cannot be widened accidentally. +type DatasetAuthScope struct { + AuthResourcePaths []string + Unrestricted bool +} + +// DatasetSummary is the persistence-neutral summary advertised to frontend +// callers. It contains only catalog facts and never exposes Arango collection +// names or raw catalog documents. +type DatasetSummary struct { + Project string + DatasetGeneration string + State string + ResourceTypes []ResourceTypeSummary +} + +// ResourceTypeSummary contains the visible, populated catalog facts for one +// FHIR resource type. DocumentCount is the maximum populated field count; +// this avoids multiplying the estimate when several field paths describe the +// same documents. +type ResourceTypeSummary struct { + ResourceType string + DocumentCount int64 + PopulatedFieldCount int + PivotCandidateCount int +} + type PopulatedField struct { Project string `json:"project"` DatasetGeneration string `json:"dataset_generation,omitempty"` @@ -120,6 +163,29 @@ type PopulatedReference struct { EdgeCount int64 `json:"edge_count"` } +// RelationshipCatalogDocument is the ingest-owned edge cardinality row used +// by builder and storage reference discovery. Auth paths remain part of the +// identity so restricted readers can aggregate only authorized edges. +type RelationshipCatalogDocument struct { + Key string `json:"_key"` + Project string `json:"project"` + DatasetGeneration string `json:"dataset_generation,omitempty"` + AuthResourcePath string `json:"auth_resource_path,omitempty"` + FromType string `json:"from_type"` + Label string `json:"label"` + ToType string `json:"to_type"` + EdgeCount int64 `json:"edge_count"` +} + +type RelationshipKey struct { + Project string + DatasetGeneration string + AuthResourcePath string + FromType string + Label string + ToType string +} + // Write-side field profiling state. type Profiler struct { project string diff --git a/internal/catalog/write_persist.go b/internal/catalog/write_persist.go index 71c4652..7101e6e 100644 --- a/internal/catalog/write_persist.go +++ b/internal/catalog/write_persist.go @@ -39,3 +39,79 @@ func WriteFieldCatalog(ctx context.Context, client *arangostore.Client, collecti } return nil } + +// WriteRelationshipCatalog persists the committed edge cardinalities for a +// load. The caller must invoke it only after all graph batches have succeeded. +func WriteRelationshipCatalog(ctx context.Context, client *arangostore.Client, docs []RelationshipCatalogDocument, batchSize int, overwrite bool, writeAPI string, timings map[string]float64) error { + if len(docs) == 0 { + return nil + } + if batchSize <= 0 { + batchSize = 1000 + } + start := time.Now() + rawDocs := make([]json.RawMessage, 0, len(docs)) + for _, doc := range docs { + data, err := sonic.ConfigFastest.Marshal(&doc) + if err != nil { + return err + } + rawDocs = append(rawDocs, json.RawMessage(data)) + } + if timings != nil { + timings["relationship_catalog_marshal"] += time.Since(start).Seconds() + } + for i := 0; i < len(rawDocs); i += batchSize { + end := i + batchSize + if end > len(rawDocs) { + end = len(rawDocs) + } + insertStart := time.Now() + if err := client.InsertBatchRaw(ctx, RelationshipCatalogCollection, rawDocs[i:end], overwrite, writeAPI); err != nil { + return err + } + if timings != nil { + timings["relationship_catalog_insert"] += time.Since(insertStart).Seconds() + } + } + return nil +} + +// AccumulateRelationshipCatalog atomically adds committed edge counts to an +// existing legacy catalog. This is the append/import counterpart to +// WriteRelationshipCatalog; it avoids replacing counts from earlier resource +// files when the mutable loader runs with --truncate=false. +func AccumulateRelationshipCatalog(ctx context.Context, client *arangostore.Client, docs []RelationshipCatalogDocument, timings map[string]float64) error { + if len(docs) == 0 { + return nil + } + rows := make([]map[string]any, 0, len(docs)) + for _, doc := range docs { + rows = append(rows, map[string]any{ + "_key": doc.Key, + "project": doc.Project, + "dataset_generation": DatasetGenerationBindValue(doc.DatasetGeneration), + "auth_resource_path": doc.AuthResourcePath, + "from_type": doc.FromType, + "label": doc.Label, + "to_type": doc.ToType, + "edge_count": doc.EdgeCount, + }) + } + start := time.Now() + const query = ` +FOR d IN @docs + UPSERT { _key: d._key } + INSERT d + UPDATE { edge_count: OLD.edge_count + d.edge_count } + IN fhir_relationship_catalog + RETURN 1 +` + if err := client.QueryRows(ctx, query, len(rows), map[string]any{"docs": rows}, func(map[string]any) error { return nil }); err != nil { + return err + } + if timings != nil { + timings["relationship_catalog_accumulate"] += time.Since(start).Seconds() + } + return nil +} diff --git a/internal/dataframe/compact_batch_tournament_test.go b/internal/dataframe/compact_batch_tournament_test.go new file mode 100644 index 0000000..e04ebb6 --- /dev/null +++ b/internal/dataframe/compact_batch_tournament_test.go @@ -0,0 +1,205 @@ +package dataframe_test + +// Tournament F is an isolated compact batch experiment. It freezes the +// endpoint-first plus typed-selector incumbent and batches the child_set_3 +// edge lookup per root. Only identity, scope fields, and selector projections +// are retained in the grouped result; no FHIR payload is carried through the +// batch. No production compiler or index files are changed. + +import ( + "context" + "encoding/json" + "fmt" + "os" + "path/filepath" + "runtime" + "strings" + "testing" + "time" + + dataframe "github.com/calypr/loom/internal/dataframe" + arangostore "github.com/calypr/loom/internal/store/arango" +) + +func TestCompactBatchTournamentCandidateBuilds(t *testing.T) { + compiled := compileActualGDC(t, 1000) + candidate, err := compactBatchChildSet3(compiled.Query) + if err != nil { + t.Fatal(err) + } + for _, fragment := range []string{ + "LET child_set_3_by_parent = (", + "FILTER child_set_3_edge._to IN child_set_2[*]._id", + "COLLECT __loom_child_set_3_parent_id = child_set_3_edge._to", + "LET __loom_compact_child_set_3 = {", + "nodes: __loom_child_set_3_rows[*].__loom_compact_child_set_3", + "LET child_set_3 = UNIQUE((", + } { + if !strings.Contains(candidate, fragment) { + t.Fatalf("compact batch candidate missing %q", fragment) + } + } + if strings.Contains(candidate, "FOR __loom_physical_parent_set_4 IN child_set_2\n FOR child_set_3_edge") { + t.Fatal("candidate retained the per-parent edge loop") + } + if strings.Contains(candidate, "payload: child_set_3") || strings.Contains(candidate, "RETURN child_set_3_node") { + t.Fatal("candidate appears to retain a full child payload") + } +} + +func TestCompactBatchTournamentProfilesActualGDC(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run compact batch tournament against Arango") + } + compiled := compileActualGDC(t, 1000) + candidate, err := compactBatchChildSet3(compiled.Query) + if err != nil { + t.Fatal(err) + } + url, database, _ := compilerArangoTarget() + client, err := arangostore.Open(context.Background(), url, database) + if err != nil { + t.Fatal(err) + } + defer client.Close(context.Background()) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) + defer cancel() + controlTimes := make([]float64, 0, 5) + candidateTimes := make([]float64, 0, 5) + controlBytes := make([]int, 0, 5) + candidateBytes := make([]int, 0, 5) + var controlHash, candidateHash string + for run := 0; run < 5; run++ { + controlQuery, controlBinds := cacheBust(compiled.Query, compiled.BindVars, 51000+run) + candidateQuery, candidateBinds := cacheBust(candidate, compiled.BindVars, 52000+run) + controlDuration, bytes, hash, err := executeOrdinary(ctx, client, controlQuery, controlBinds) + if err != nil { + t.Fatalf("control run %d: %v", run+1, err) + } + candidateDuration, candidateSize, candidateResultHash, err := executeOrdinary(ctx, client, candidateQuery, candidateBinds) + if err != nil { + t.Fatalf("candidate run %d: %v", run+1, err) + } + controlTimes = append(controlTimes, controlDuration) + candidateTimes = append(candidateTimes, candidateDuration) + controlBytes = append(controlBytes, bytes) + candidateBytes = append(candidateBytes, candidateSize) + controlHash, candidateHash = hash, candidateResultHash + } + if controlHash != candidateHash { + t.Fatalf("result parity mismatch control=%s candidate=%s", controlHash, candidateHash) + } + controlProfileQuery, controlProfileBinds := cacheBust(compiled.Query, compiled.BindVars, 51999) + candidateProfileQuery, candidateProfileBinds := cacheBust(candidate, compiled.BindVars, 52999) + controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: controlProfileQuery, BindVars: controlProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + t.Fatalf("control PROFILE: %v", err) + } + candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidateProfileQuery, BindVars: candidateProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + t.Fatalf("candidate PROFILE: %v", err) + } + if hashRawRows(controlProfile.Result) != hashRawRows(candidateProfile.Result) { + t.Fatalf("PROFILE result parity mismatch control=%s candidate=%s", hashRawRows(controlProfile.Result), hashRawRows(candidateProfile.Result)) + } + controlExplain, err := client.Explain(ctx, arangostore.ExplainRequest{Query: controlProfileQuery, BindVars: controlProfileBinds}) + if err != nil { + t.Fatalf("control EXPLAIN: %v", err) + } + candidateExplain, err := client.Explain(ctx, arangostore.ExplainRequest{Query: candidateProfileQuery, BindVars: candidateProfileBinds}) + if err != nil { + t.Fatalf("candidate EXPLAIN: %v", err) + } + controlSummary := arangostore.SummarizeProfile(controlProfile) + candidateSummary := arangostore.SummarizeProfile(candidateProfile) + t.Logf("compact batch control median=%.6f candidate median=%.6f control profile=%+v candidate profile=%+v bytes=%v/%v", median(controlTimes), median(candidateTimes), controlSummary, candidateSummary, controlBytes, candidateBytes) + writeCompactBatchEvidence(t, compiled, candidate, controlTimes, candidateTimes, controlBytes, candidateBytes, controlHash, candidateHash, controlProfile, candidateProfile, controlExplain, candidateExplain) + if median(candidateTimes) > median(controlTimes)*1.05 || candidateSummary.PeakMemory > 225*1024*1024 { + t.Logf("compact batch candidate rejected by hard runtime/memory gate") + } +} + +func compactBatchChildSet3(query string) (string, error) { + start := strings.Index(query, " LET child_set_3 = UNIQUE((") + end := strings.Index(query, " LET child_set_4 = UNIQUE((") + if start < 0 || end < 0 || end <= start { + return "", fmt.Errorf("child_set_3/child_set_4 markers not found") + } + block := query[start:end] + returnIndex := strings.Index(block, " RETURN {") + if returnIndex < 0 { + return "", fmt.Errorf("child_set_3 projection return not found") + } + projection := block[returnIndex+len(" RETURN "):] + if closeIndex := strings.Index(projection, "\n ))"); closeIndex >= 0 { + projection = projection[:closeIndex] + } + prefix := block[:returnIndex] + edgeIndex := strings.Index(prefix, "FOR child_set_3_edge IN @@child_set_3_edge_collection") + if edgeIndex < 0 { + return "", fmt.Errorf("child_set_3 edge loop not found") + } + edgePrefix := prefix[edgeIndex:] + if strings.Contains(edgePrefix, "FOR __loom_physical_parent_set_4 IN child_set_2") { + return "", fmt.Errorf("parent loop unexpectedly inside edge prefix") + } + edgePrefix = strings.Replace(edgePrefix, "FILTER child_set_3_edge._to == __loom_physical_parent_set_4._id", "FILTER child_set_3_edge._to IN child_set_2[*]._id", 1) + edgePrefix = strings.Replace(edgePrefix, " SORT child_set_3_node._key\n", "", 1) + if !strings.Contains(edgePrefix, "FILTER child_set_3_edge._to IN child_set_2[*]._id") { + return "", fmt.Errorf("child_set_3 endpoint filter was not replaced") + } + // Strip the final edge-loop indentation only for readability; AQL ignores + // whitespace. The projection object is compact and contains no payload key. + batch := " LET child_set_3_by_parent = (\n " + strings.ReplaceAll(edgePrefix, "\n", "\n ") + + " LET __loom_compact_child_set_3 = " + projection + "\n" + + " COLLECT __loom_child_set_3_parent_id = child_set_3_edge._to INTO __loom_child_set_3_rows\n" + + " RETURN {root_id: root._id, parent_id: __loom_child_set_3_parent_id, nodes: __loom_child_set_3_rows[*].__loom_compact_child_set_3}\n" + + " )\n" + + " LET child_set_3 = UNIQUE((\n" + + " FOR __loom_physical_parent_set_4 IN child_set_2\n" + + " LET __loom_child_set_3_group = FIRST((\n" + + " FOR __loom_group IN child_set_3_by_parent\n" + + " FILTER __loom_group.root_id == root._id AND __loom_group.parent_id == __loom_physical_parent_set_4._id\n" + + " RETURN __loom_group\n" + + " ))\n" + + " FOR child_set_3_item IN (__loom_child_set_3_group ? __loom_child_set_3_group.nodes : [])\n" + + " SORT child_set_3_item._key\n" + + " RETURN child_set_3_item\n" + + " ))\n" + return query[:start] + batch + query[end:], nil +} + +func writeCompactBatchEvidence(t *testing.T, compiled dataframe.CompiledQuery, candidate string, controlTimes, candidateTimes []float64, controlBytes, candidateBytes []int, controlHash, candidateHash string, controlProfile, candidateProfile arangostore.ProfileResult, controlExplain, candidateExplain arangostore.ExplainResult) { + _, source, _, _ := runtime.Caller(0) + directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "tournament_compact_batch") + if err := os.MkdirAll(directory, 0o755); err != nil { + t.Fatalf("create compact batch evidence directory: %v", err) + } + writeJSON := func(name string, value any) { + data, err := json.MarshalIndent(value, "", " ") + if err != nil { + t.Fatalf("encode %s: %v", name, err) + } + if err := os.WriteFile(filepath.Join(directory, name), append(data, '\n'), 0o644); err != nil { + t.Fatalf("write %s: %v", name, err) + } + } + if err := os.WriteFile(filepath.Join(directory, "control.aql"), []byte(compiled.Query+"\n"), 0o644); err != nil { + t.Fatalf("write control AQL: %v", err) + } + if err := os.WriteFile(filepath.Join(directory, "candidate.aql"), []byte(candidate+"\n"), 0o644); err != nil { + t.Fatalf("write candidate AQL: %v", err) + } + writeJSON("control.profile.json", controlProfile) + writeJSON("candidate.profile.json", candidateProfile) + writeJSON("evidence.json", map[string]any{ + "fixture": "examples/meta_gdc_case_matrix.variables.json", "limit": 1000, + "control_aql_sha256": sha256Hex(compiled.Query), "candidate_aql_sha256": sha256Hex(candidate), + "control_result_sha256": controlHash, "candidate_result_sha256": candidateHash, + "control_seconds": controlTimes, "candidate_seconds": candidateTimes, + "control_bytes": controlBytes, "candidate_bytes": candidateBytes, + "control_profile": arangostore.SummarizeProfile(controlProfile), "candidate_profile": arangostore.SummarizeProfile(candidateProfile), + "control_explain": arangostore.AssessExplainResult(controlExplain), "candidate_explain": arangostore.AssessExplainResult(candidateExplain), + "decision": "pending-threshold-review", + }) +} diff --git a/internal/dataframe/compact_summary_experiment_test.go b/internal/dataframe/compact_summary_experiment_test.go new file mode 100644 index 0000000..9900937 --- /dev/null +++ b/internal/dataframe/compact_summary_experiment_test.go @@ -0,0 +1,325 @@ +package dataframe_test + +// Read-only candidate E tournament. The incumbent is the frozen current +// root-endpoint plus selector-lowering AQL. The candidate adds one compact +// summary for a structurally selected leaf set with two distinct-value +// consumers and a representative slice. No production compiler files are +// touched. + +import ( + "context" + "encoding/json" + "fmt" + "os" + "path/filepath" + "regexp" + "runtime" + "sort" + "strings" + "testing" + "time" + + arangostore "github.com/calypr/loom/internal/store/arango" +) + +const compactSummaryIncumbentSHA = "2c5c598d96f161ac74129b532d2d05d8933a348d3032666d5b5262b7a654704d" + +type compactSummaryRun struct { + Name string `json:"name"` + QuerySHA256 string `json:"query_sha256"` + ResultSHA256 string `json:"result_sha256"` + Rows int `json:"rows"` + Bytes []int `json:"bytes"` + WarmSeconds []float64 `json:"warm_seconds"` + MedianSeconds float64 `json:"median_seconds"` + MinSeconds float64 `json:"min_seconds"` + Explain arangostore.ExplainAssessment `json:"explain"` + Profile compactSummaryProfile `json:"profile"` + RawProfile arangostore.ProfileResult `json:"-"` +} + +type compactSummaryProfile struct { + ScannedFull int `json:"scanned_full"` + ScannedIndex int `json:"scanned_index"` + PeakMemoryBytes uint64 `json:"peak_memory_bytes"` + Phases arangostore.ProfilePhases `json:"phases"` + TopNodes []arangostore.ProfileNodeSummary `json:"top_nodes"` +} + +type compactSummaryRewrite struct { + SetVariable string `json:"set_variable"` + Fields []string `json:"fields"` + BeforeLoops int `json:"before_loops"` + AfterLoops int `json:"after_loops"` +} + +func TestCompactSummaryCandidateStructure(t *testing.T) { + incumbent, _ := loadCompactSummaryIncumbent(t) + candidate, rewrite, err := buildCompactSummaryCandidate(incumbent) + if err != nil { + t.Fatal(err) + } + if len(rewrite.Fields) < 2 || rewrite.BeforeLoops < 2 || rewrite.AfterLoops >= rewrite.BeforeLoops { + t.Fatalf("summary did not select a rich leaf or remove consumers: %+v", rewrite) + } + if !strings.Contains(candidate, "COLLECT AGGREGATE") { + t.Fatalf("candidate omitted typed summary aggregation") + } + if !strings.Contains(candidate, "representative_files_limit") && !strings.Contains(candidate, "representative_samples_limit") && !strings.Contains(candidate, "representative_diagnoses_limit") { + t.Fatalf("candidate removed representative slice") + } + t.Logf("summary candidate bindings:\n%s", compactSummaryLines(candidate)) + t.Logf("compact summary structure: %+v", rewrite) +} + +func compactSummaryLines(query string) string { + lines := strings.Split(query, "\n") + selected := make([]string, 0, 20) + for _, line := range lines { + if strings.Contains(line, "__loom_summary") || strings.Contains(line, "__loom_physical_projection_10_name") || strings.Contains(line, "__loom_physical_projection_11_name") || strings.Contains(line, "__loom_physical_projection_12_name") { + selected = append(selected, line) + } + } + return strings.Join(selected, "\n") +} + +func TestCompactSummaryProfilesAgainstCurrentIncumbent(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run compact summary tournament against Arango") + } + incumbent, binds := loadCompactSummaryIncumbent(t) + candidate, rewrite, err := buildCompactSummaryCandidate(incumbent) + if err != nil { + t.Fatal(err) + } + url, database, _ := compilerArangoTarget() + client, err := arangostore.Open(context.Background(), url, database) + if err != nil { + t.Fatal(err) + } + defer client.Close(context.Background()) + ctx, cancel := context.WithTimeout(context.Background(), 20*time.Minute) + defer cancel() + control, candidateRun, err := runCompactSummaryAlternating(ctx, client, incumbent, candidate, binds) + if err != nil { + t.Fatal(err) + } + if control.ResultSHA256 != candidateRun.ResultSHA256 { + t.Fatalf("summary result parity mismatch control=%s candidate=%s", control.ResultSHA256, candidateRun.ResultSHA256) + } + if candidateRun.Profile.PeakMemoryBytes > 225000000 { + t.Fatalf("summary candidate exceeds 225 MB gate: %d", candidateRun.Profile.PeakMemoryBytes) + } + if candidateRun.MedianSeconds >= control.MedianSeconds*0.95 { + t.Logf("compact summary rejected: control=%.6fs candidate=%.6fs improvement=%.2f%% rewrite=%+v", control.MedianSeconds, candidateRun.MedianSeconds, 100*(control.MedianSeconds-candidateRun.MedianSeconds)/control.MedianSeconds, rewrite) + } else { + t.Logf("compact summary passes runtime gate: control=%.6fs candidate=%.6fs improvement=%.2f%% rewrite=%+v", control.MedianSeconds, candidateRun.MedianSeconds, 100*(control.MedianSeconds-candidateRun.MedianSeconds)/control.MedianSeconds, rewrite) + } + writeCompactSummaryArtifacts(t, incumbent, candidate, binds, rewrite, control, candidateRun) +} + +func loadCompactSummaryIncumbent(t *testing.T) (string, map[string]any) { + _, source, _, _ := runtime.Caller(0) + root := filepath.Join(filepath.Dir(source), "..", "..") + queryBytes, err := os.ReadFile(filepath.Join(root, "docs", "benchmarks", "round4", "tournament_root_endpoint", "candidate.aql")) + if err != nil { + t.Fatalf("read compact-summary incumbent: %v", err) + } + query := strings.TrimSuffix(strings.TrimSuffix(string(queryBytes), "\n"), "\r") + if sha256Hex(query) != compactSummaryIncumbentSHA { + t.Fatalf("compact-summary incumbent hash changed: got %s want %s", sha256Hex(query), compactSummaryIncumbentSHA) + } + reportBytes, err := os.ReadFile(filepath.Join(root, "docs", "benchmarks", "round4", "wp2", "integrated.json")) + if err != nil { + t.Fatalf("read compact-summary bind report: %v", err) + } + var report struct { + BindVars map[string]any `json:"bind_vars"` + } + if err := json.Unmarshal(reportBytes, &report); err != nil { + t.Fatalf("decode compact-summary bind report: %v", err) + } + return query, report.BindVars +} + +var compactSetRE = regexp.MustCompile(`(?ms)^ LET ([A-Za-z0-9_]+) = UNIQUE\(\(.*?^ {2,}\)\)\n`) +var compactConsumerRE = regexp.MustCompile(`SORTED_UNIQUE\(FLATTEN\(\(FOR __loom_prepared_value IN ([A-Za-z0-9_]+) RETURN __loom_prepared_value\.([A-Za-z0-9_]+)\)\)\)`) + +func buildCompactSummaryCandidate(control string) (string, compactSummaryRewrite, error) { + blocks := compactSetRE.FindAllStringSubmatchIndex(control, -1) + if len(blocks) == 0 { + return "", compactSummaryRewrite{}, fmt.Errorf("no child-set materializations found") + } + returnStart := strings.LastIndex(control, "\nRETURN ") + if returnStart < 0 { + return "", compactSummaryRewrite{}, fmt.Errorf("no root RETURN found") + } + returnText := control[returnStart:] + chosenSet := "" + fieldSet := map[string]bool{} + for _, block := range blocks { + setVariable := control[block[2]:block[3]] + for _, match := range compactConsumerRE.FindAllStringSubmatch(returnText, -1) { + if match[1] == setVariable { + fieldSet[match[2]] = true + } + } + if len(fieldSet) >= 2 { + chosenSet = setVariable + break + } + fieldSet = map[string]bool{} + } + if chosenSet == "" { + return "", compactSummaryRewrite{}, fmt.Errorf("no leaf set has two distinct-value consumers") + } + fields := make([]string, 0, len(fieldSet)) + for field := range fieldSet { + fields = append(fields, field) + } + sort.Strings(fields) + parts := make([]string, 0, len(fields)) + outputs := make([]string, 0, len(fields)) + defaults := make([]string, 0, len(fields)) + for index, field := range fields { + parts = append(parts, fmt.Sprintf(" __loom_summary_%d = UNIQUE(__loom_summary_item.%s)", index, field)) + outputs = append(outputs, fmt.Sprintf("values_%d: SORTED_UNIQUE(FLATTEN(__loom_summary_%d))", index, index)) + defaults = append(defaults, fmt.Sprintf("values_%d: []", index)) + } + summaryVariable := "__loom_summary_" + chosenSet + summary := fmt.Sprintf(" LET %s = FIRST((\n FOR __loom_summary_item IN %s\n COLLECT AGGREGATE\n __loom_summary_count = COUNT(),\n%s\n RETURN { count: __loom_summary_count, %s }\n )) || { count: 0, %s }\n", summaryVariable, chosenSet, strings.Join(parts, ",\n"), strings.Join(outputs, ", "), strings.Join(defaults, ", ")) + chosenBlock := -1 + for index, block := range blocks { + if control[block[2]:block[3]] == chosenSet { + chosenBlock = index + break + } + } + if chosenBlock < 0 { + return "", compactSummaryRewrite{}, fmt.Errorf("selected set block disappeared") + } + insertAt := blocks[chosenBlock][1] + candidate := control[:insertAt] + summary + control[insertAt:] + candidateReturnStart := strings.LastIndex(candidate, "\nRETURN ") + candidateReturn := candidate[candidateReturnStart:] + candidateReturn = strings.ReplaceAll(candidateReturn, "LENGTH("+chosenSet+")", summaryVariable+".count") + for index, field := range fields { + old := "SORTED_UNIQUE(FLATTEN((FOR __loom_prepared_value IN " + chosenSet + " RETURN __loom_prepared_value." + field + ")))" + candidateReturn = strings.ReplaceAll(candidateReturn, old, fmt.Sprintf("%s.values_%d", summaryVariable, index)) + } + candidate = candidate[:candidateReturnStart] + candidateReturn + return candidate, compactSummaryRewrite{SetVariable: chosenSet, Fields: fields, BeforeLoops: strings.Count(returnText, "FOR __loom_prepared_value IN "+chosenSet), AfterLoops: strings.Count(candidateReturn, "FOR __loom_prepared_value IN "+chosenSet)}, nil +} + +func runCompactSummaryAlternating(ctx context.Context, client *arangostore.Client, control, candidate string, baseBinds map[string]any) (compactSummaryRun, compactSummaryRun, error) { + controlRun := compactSummaryRun{Name: "endpoint_selector_incumbent", QuerySHA256: sha256Hex(control)} + candidateRun := compactSummaryRun{Name: "compact_leaf_summary", QuerySHA256: sha256Hex(candidate)} + for i := 0; i < 5; i++ { + controlQuery, controlBinds := cacheBust(control, baseBinds, 15000+i) + candidateQuery, candidateBinds := cacheBust(candidate, baseBinds, 16000+i) + controlSeconds, controlBytes, controlHash, err := executeOrdinary(ctx, client, controlQuery, controlBinds) + if err != nil { + return controlRun, candidateRun, fmt.Errorf("control run %d: %w", i+1, err) + } + candidateSeconds, candidateBytes, candidateHash, err := executeOrdinary(ctx, client, candidateQuery, candidateBinds) + if err != nil { + return controlRun, candidateRun, fmt.Errorf("candidate run %d: %w", i+1, err) + } + controlRun.WarmSeconds = append(controlRun.WarmSeconds, controlSeconds) + controlRun.Bytes = append(controlRun.Bytes, controlBytes) + controlRun.ResultSHA256 = controlHash + controlRun.Rows = 1000 + candidateRun.WarmSeconds = append(candidateRun.WarmSeconds, candidateSeconds) + candidateRun.Bytes = append(candidateRun.Bytes, candidateBytes) + candidateRun.ResultSHA256 = candidateHash + candidateRun.Rows = 1000 + } + controlRun.MedianSeconds, controlRun.MinSeconds = median(controlRun.WarmSeconds), minCompact(controlRun.WarmSeconds) + candidateRun.MedianSeconds, candidateRun.MinSeconds = median(candidateRun.WarmSeconds), minCompact(candidateRun.WarmSeconds) + controlProfileQuery, controlProfileBinds := cacheBust(control, baseBinds, 17001) + candidateProfileQuery, candidateProfileBinds := cacheBust(candidate, baseBinds, 17002) + controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: controlProfileQuery, BindVars: controlProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + return controlRun, candidateRun, err + } + candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidateProfileQuery, BindVars: candidateProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + return controlRun, candidateRun, err + } + controlRun.Explain, err = explainCompact(ctx, client, control, baseBinds) + if err != nil { + return controlRun, candidateRun, err + } + candidateRun.Explain, err = explainCompact(ctx, client, candidate, baseBinds) + if err != nil { + return controlRun, candidateRun, err + } + controlRun.RawProfile, candidateRun.RawProfile = controlProfile, candidateProfile + controlRun.Profile, candidateRun.Profile = summarizeCompact(controlProfile), summarizeCompact(candidateProfile) + return controlRun, candidateRun, nil +} + +func explainCompact(ctx context.Context, client *arangostore.Client, query string, binds map[string]any) (arangostore.ExplainAssessment, error) { + explain, err := client.Explain(ctx, arangostore.ExplainRequest{Query: query, BindVars: binds}) + if err != nil { + return arangostore.ExplainAssessment{}, err + } + assessment := arangostore.AssessExplainResult(explain) + if len(assessment.FullCollectionScans) != 0 { + return assessment, fmt.Errorf("summary candidate introduced full scans: %#v", assessment.FullCollectionScans) + } + return assessment, nil +} + +func summarizeCompact(profile arangostore.ProfileResult) compactSummaryProfile { + summary := arangostore.SummarizeProfile(profile) + nodes := append([]arangostore.ProfileNodeSummary(nil), summary.Nodes...) + if len(nodes) > 20 { + nodes = nodes[:20] + } + return compactSummaryProfile{ScannedFull: summary.ScannedFull, ScannedIndex: summary.ScannedIndex, PeakMemoryBytes: summary.PeakMemory, Phases: profile.Extra.Profile, TopNodes: nodes} +} + +func minCompact(values []float64) float64 { + if len(values) == 0 { + return 0 + } + minimum := values[0] + for _, value := range values[1:] { + if value < minimum { + minimum = value + } + } + return minimum +} + +func writeCompactSummaryArtifacts(t *testing.T, incumbent, candidate string, binds map[string]any, rewrite compactSummaryRewrite, control, candidateRun compactSummaryRun) { + _, source, _, _ := runtime.Caller(0) + root := filepath.Join(filepath.Dir(source), "..", "..") + directory := filepath.Join(root, "docs", "benchmarks", "round4", "tournament_summaries") + if err := os.MkdirAll(directory, 0o755); err != nil { + t.Fatal(err) + } + for name, query := range map[string]string{"incumbent.aql": incumbent, "candidate.aql": candidate} { + if err := os.WriteFile(filepath.Join(directory, name), []byte(query+"\n"), 0o644); err != nil { + t.Fatal(err) + } + } + for name, profile := range map[string]arangostore.ProfileResult{"incumbent.profile.json": control.RawProfile, "candidate.profile.json": candidateRun.RawProfile} { + encoded, err := json.MarshalIndent(profile, "", " ") + if err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(directory, name), append(encoded, '\n'), 0o644); err != nil { + t.Fatal(err) + } + } + payload := map[string]any{"incumbent": control, "candidate": candidateRun, "bind_vars": binds, "rewrite": rewrite} + encoded, err := json.MarshalIndent(payload, "", " ") + if err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(directory, "RESULTS.json"), append(encoded, '\n'), 0o644); err != nil { + t.Fatal(err) + } +} diff --git a/internal/dataframe/compile.go b/internal/dataframe/compile.go index 77a1a1b..c409bc2 100644 --- a/internal/dataframe/compile.go +++ b/internal/dataframe/compile.go @@ -30,17 +30,24 @@ type CompiledQuery struct { // applies semantics-preserving physical rewrites, and renders parameterized // AQL. Unsupported shapes fail explicitly. func CompileRequest(builder Builder, limit int) (CompiledQuery, error) { + return CompileRequestWithPolicy(builder, limit, DefaultPhysicalOptimizationPolicy()) +} + +// CompileRequestWithPolicy is the explicit ablation entrypoint used by +// compiler tests and benchmark tooling. Normal service execution uses +// CompileRequest and the production default policy. +func CompileRequestWithPolicy(builder Builder, limit int, policy PhysicalOptimizationPolicy) (CompiledQuery, error) { semantic, err := BuildSemanticPlan(builder) if err != nil { return CompiledQuery{}, err } // The physical route owns navigation-only requests directly from semantic // meaning. - physical, err := BuildPhysicalPlan(semantic) + physical, err := BuildPhysicalPlanWithPolicy(semantic, policy) if err != nil { return CompiledQuery{}, fmt.Errorf("unsupported physical dataframe shape: %w", err) } - physical, err = OptimizePhysicalPlan(physical) + physical, err = OptimizePhysicalPlanWithPolicy(physical, policy) if err != nil { return CompiledQuery{}, fmt.Errorf("optimize physical plan: %w", err) } diff --git a/internal/dataframe/endpoint_selector_combo_experiment_test.go b/internal/dataframe/endpoint_selector_combo_experiment_test.go new file mode 100644 index 0000000..b30d5b2 --- /dev/null +++ b/internal/dataframe/endpoint_selector_combo_experiment_test.go @@ -0,0 +1,376 @@ +package dataframe_test + +// This is a read-only, opt-in tournament harness. It composes the two +// previously measured test-only rewrites (WP2 endpoint equality and WP4 +// selector lowering) after compiling the real GraphQL input through +// BuilderFromInput. It does not alter compiler IR or production rendering. + +import ( + "context" + "encoding/json" + "fmt" + "os" + "path/filepath" + "regexp" + "runtime" + "strings" + "testing" + "time" + + dataframe "github.com/calypr/loom/internal/dataframe" + arangostore "github.com/calypr/loom/internal/store/arango" +) + +type endpointSelectorComboRun struct { + Name string `json:"name"` + QuerySHA256 string `json:"query_sha256"` + ResultSHA256 string `json:"result_sha256"` + Rows int `json:"rows"` + Bytes []int `json:"bytes"` + WarmSeconds []float64 `json:"warm_seconds"` + MedianSeconds float64 `json:"median_seconds"` + MinSeconds float64 `json:"min_seconds"` + Explain arangostore.ExplainAssessment `json:"explain"` + Profile endpointSelectorProfileSummary `json:"profile"` +} + +type endpointSelectorProfileSummary struct { + ScannedFull int `json:"scanned_full"` + ScannedIndex int `json:"scanned_index"` + PeakMemoryBytes uint64 `json:"peak_memory_bytes"` + Phases arangostore.ProfilePhases `json:"phases"` + TopNodes []arangostore.ProfileNodeSummary `json:"top_nodes"` +} + +// TestEndpointSelectorComboRendersActualGDC is compile-safe and does not need +// Arango. It proves the composition starts with BuilderFromInput, rewrites all +// three eligible nested routes, and retains bind-backed AQL. +func TestEndpointSelectorComboRendersActualGDC(t *testing.T) { + compiled := compileActualGDC(t, 1000) + compiled = pinComboControlIfCompilerMoved(t, compiled) + endpointOnly, routes, err := prepareEndpointSelectorBase(compiled.Query) + if err != nil { + t.Fatal(err) + } + if len(routes) != 3 { + t.Fatalf("rewrote %d nested routes, want 3: %#v", len(routes), routes) + } + combo, lowering, err := lowerRenderedSelectorExpressions(endpointOnly) + if err != nil { + t.Fatalf("lower selectors after endpoint rewrite: %v", err) + } + if lowering.LoweredSubqueries == 0 { + t.Fatalf("combined candidate lowered no selectors: %+v", lowering) + } + if strings.Contains(combo, "IN 1..1 INBOUND __loom_physical_parent_set") || strings.Contains(combo, "IN 1..1 OUTBOUND __loom_physical_parent_set") { + t.Fatalf("combined candidate retained a nested native traversal:\n%s", combo) + } + if !strings.Contains(combo, "FILTER child_set_3_edge._to == __loom_physical_parent_set_4._id") || + !strings.Contains(combo, "FILTER child_set_4_edge._to == __loom_physical_parent_set_5._id") || + !strings.Contains(combo, "FILTER child_set_5_edge._to == __loom_physical_parent_set_6._id") { + t.Fatalf("combined candidate omitted one endpoint equality routes=%#v has3=%t has4=%t has5=%t\n%s", routes, strings.Contains(combo, "FILTER child_set_3_edge._to == __loom_physical_parent_set_4._id"), strings.Contains(combo, "FILTER child_set_4_edge._to == __loom_physical_parent_set_5._id"), strings.Contains(combo, "FILTER child_set_5_edge._to == __loom_physical_parent_set_6._id"), combo[:minComboLen(len(combo), 7000)]) + } + if !strings.Contains(combo, "@@child_set_3_edge_collection") || !strings.Contains(combo, "@project") { + t.Fatalf("combined candidate lost collection or value binds") + } +} + +func minComboLen(length, maximum int) int { + if length < maximum { + return length + } + return maximum +} + +// pinComboControlIfCompilerMoved protects this experiment from concurrent +// production renderer work. BuilderFromInput is still executed first; when +// its AQL no longer matches the locked WP2 control, the exact previously +// profiled AQL and bind variables are used so the comparison does not mix +// compiler baselines. +func pinComboControlIfCompilerMoved(t *testing.T, compiled dataframe.CompiledQuery) dataframe.CompiledQuery { + const expectedAQLSHA = "4081527f4d893c7fc8b4957ad75ffbf51a975a8b646c315f01d09093444aad68" + const integratedAQLSHA = "988775e708a0f836ed34de0815e74cdbf38172e75c12a80149a9ce6096b48925" + if sha256Hex(compiled.Query) == expectedAQLSHA || sha256Hex(compiled.Query) == integratedAQLSHA { + return compiled + } + t.Logf("BuilderFromInput control AQL changed during concurrent integration (got %s); pinning WP2 control %s", sha256Hex(compiled.Query), expectedAQLSHA) + _, source, _, _ := runtime.Caller(0) + root := filepath.Join(filepath.Dir(source), "..", "..") + queryPath := filepath.Join(root, "docs", "benchmarks", "round4", "wp2", "production.aql") + reportPath := filepath.Join(root, "docs", "benchmarks", "round4", "wp2", "production.json") + queryBytes, err := os.ReadFile(queryPath) + if err != nil { + t.Fatalf("read pinned control AQL: %v", err) + } + query := strings.TrimSuffix(strings.TrimSuffix(string(queryBytes), "\n"), "\r") + if sha256Hex(query) != expectedAQLSHA { + t.Fatalf("pinned control AQL hash changed: got %s want %s", sha256Hex(query), expectedAQLSHA) + } + reportBytes, err := os.ReadFile(reportPath) + if err != nil { + t.Fatalf("read pinned control bind vars: %v", err) + } + var report struct { + BindVars map[string]any `json:"bind_vars"` + } + if err := json.Unmarshal(reportBytes, &report); err != nil { + t.Fatalf("decode pinned control bind vars: %v", err) + } + return dataframe.CompiledQuery{Query: query, BindVars: report.BindVars, Limit: 1000} +} + +// TestEndpointSelectorComboProfilesActualGDC is deliberately opt-in. It +// alternates unchanged production control and the composed candidate, consumes +// every row, then captures Explain/Profile and raw artifacts. The endpoint-only +// median is run separately to answer whether selector lowering compounds the +// proven WP2 4.211s result. +func TestEndpointSelectorComboProfilesActualGDC(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run endpoint/selector combo against Arango") + } + compiled := compileActualGDC(t, 1000) + compiled = pinComboControlIfCompilerMoved(t, compiled) + endpointOnly, routes, err := prepareEndpointSelectorBase(compiled.Query) + if err != nil { + t.Fatal(err) + } + if len(routes) != 3 { + t.Fatalf("rewrote %d nested routes, want 3: %#v", len(routes), routes) + } + combo, lowering, err := lowerRenderedSelectorExpressions(endpointOnly) + if err != nil { + t.Fatal(err) + } + url, database, _ := compilerArangoTarget() + client, err := arangostore.Open(context.Background(), url, database) + if err != nil { + t.Fatal(err) + } + defer client.Close(context.Background()) + ctx, cancel := context.WithTimeout(context.Background(), 20*time.Minute) + defer cancel() + + control, candidate, err := runAlternatingCombo(ctx, client, compiled.Query, combo, compiled.BindVars, "control", "endpoint_selector_combo") + if err != nil { + t.Fatal(err) + } + endpoint, err := runShapeFive(ctx, client, endpointOnly, compiled.BindVars, "endpoint_only") + if err != nil { + t.Fatal(err) + } + if control.ResultSHA256 != candidate.ResultSHA256 || control.ResultSHA256 != endpoint.ResultSHA256 { + t.Fatalf("result parity mismatch control=%s endpoint=%s combo=%s", control.ResultSHA256, endpoint.ResultSHA256, candidate.ResultSHA256) + } + if candidate.MedianSeconds >= endpoint.MedianSeconds { + t.Logf("combined selector lowering did not beat endpoint-only: endpoint=%.6fs combo=%.6fs", endpoint.MedianSeconds, candidate.MedianSeconds) + } + if candidate.MedianSeconds >= control.MedianSeconds { + t.Fatalf("combined candidate regressed control: control=%.6fs combo=%.6fs", control.MedianSeconds, candidate.MedianSeconds) + } + + writeEndpointSelectorComboArtifacts(t, compiled, endpointOnly, combo, routes, lowering, control, endpoint, candidate) + t.Logf("WP2+WP4 control=%.6fs endpoint_only=%.6fs combo=%.6fs improvement_vs_control=%.2f%% improvement_vs_endpoint=%.2f%% control_profile=%.6fs combo_profile=%.6fs", control.MedianSeconds, endpoint.MedianSeconds, candidate.MedianSeconds, 100*(control.MedianSeconds-candidate.MedianSeconds)/control.MedianSeconds, 100*(endpoint.MedianSeconds-candidate.MedianSeconds)/endpoint.MedianSeconds, control.Profile.Phases.Executing, candidate.Profile.Phases.Executing) +} + +func runAlternatingCombo(ctx context.Context, client *arangostore.Client, controlQuery, candidateQuery string, baseBinds map[string]any, controlName, candidateName string) (endpointSelectorComboRun, endpointSelectorComboRun, error) { + control := endpointSelectorComboRun{Name: controlName, QuerySHA256: sha256Hex(controlQuery)} + candidate := endpointSelectorComboRun{Name: candidateName, QuerySHA256: sha256Hex(candidateQuery)} + for i := 0; i < 5; i++ { + controlQueryRun, controlBinds := cacheBust(controlQuery, baseBinds, 7000+i) + candidateQueryRun, candidateBinds := cacheBust(candidateQuery, baseBinds, 8000+i) + controlSeconds, controlBytes, controlHash, err := executeOrdinary(ctx, client, controlQueryRun, controlBinds) + if err != nil { + return control, candidate, fmt.Errorf("control run %d: %w", i+1, err) + } + candidateSeconds, candidateBytes, candidateHash, err := executeOrdinary(ctx, client, candidateQueryRun, candidateBinds) + if err != nil { + return control, candidate, fmt.Errorf("candidate run %d: %w", i+1, err) + } + control.WarmSeconds = append(control.WarmSeconds, controlSeconds) + control.Bytes = append(control.Bytes, controlBytes) + control.Rows = 1000 + control.ResultSHA256 = controlHash + candidate.WarmSeconds = append(candidate.WarmSeconds, candidateSeconds) + candidate.Bytes = append(candidate.Bytes, candidateBytes) + candidate.Rows = 1000 + candidate.ResultSHA256 = candidateHash + } + control.MedianSeconds, control.MinSeconds = median(control.WarmSeconds), minFloat(control.WarmSeconds) + candidate.MedianSeconds, candidate.MinSeconds = median(candidate.WarmSeconds), minFloat(candidate.WarmSeconds) + controlProfileQuery, controlProfileBinds := cacheBust(controlQuery, baseBinds, 9001) + candidateProfileQuery, candidateProfileBinds := cacheBust(candidateQuery, baseBinds, 9002) + controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: controlProfileQuery, BindVars: controlProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + return control, candidate, fmt.Errorf("control PROFILE: %w", err) + } + candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidateProfileQuery, BindVars: candidateProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + return control, candidate, fmt.Errorf("candidate PROFILE: %w", err) + } + control.Explain, err = explainShape(ctx, client, controlQuery, baseBinds) + if err != nil { + return control, candidate, err + } + candidate.Explain, err = explainShape(ctx, client, candidateQuery, baseBinds) + if err != nil { + return control, candidate, err + } + control.Profile = summarizeComboProfile(controlProfile) + candidate.Profile = summarizeComboProfile(candidateProfile) + return control, candidate, nil +} + +func runShapeFive(ctx context.Context, client *arangostore.Client, query string, baseBinds map[string]any, name string) (endpointSelectorComboRun, error) { + run := endpointSelectorComboRun{Name: name, QuerySHA256: sha256Hex(query)} + for i := 0; i < 5; i++ { + queryRun, binds := cacheBust(query, baseBinds, 10000+i) + seconds, bytes, hash, err := executeOrdinary(ctx, client, queryRun, binds) + if err != nil { + return run, fmt.Errorf("%s run %d: %w", name, i+1, err) + } + run.WarmSeconds = append(run.WarmSeconds, seconds) + run.Bytes = append(run.Bytes, bytes) + run.Rows = 1000 + run.ResultSHA256 = hash + } + run.MedianSeconds, run.MinSeconds = median(run.WarmSeconds), minFloat(run.WarmSeconds) + profileQuery, profileBinds := cacheBust(query, baseBinds, 11001) + profile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: profileQuery, BindVars: profileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + return run, fmt.Errorf("%s PROFILE: %w", name, err) + } + run.Explain, err = explainShape(ctx, client, query, baseBinds) + if err != nil { + return run, err + } + run.Profile = summarizeComboProfile(profile) + return run, nil +} + +func explainShape(ctx context.Context, client *arangostore.Client, query string, binds map[string]any) (arangostore.ExplainAssessment, error) { + explain, err := client.Explain(ctx, arangostore.ExplainRequest{Query: query, BindVars: binds}) + if err != nil { + return arangostore.ExplainAssessment{}, err + } + assessment := arangostore.AssessExplainResult(explain) + if len(assessment.FullCollectionScans) != 0 { + return assessment, fmt.Errorf("candidate introduced full collection scans: %#v", assessment.FullCollectionScans) + } + return assessment, nil +} + +func summarizeComboProfile(profile arangostore.ProfileResult) endpointSelectorProfileSummary { + summary := arangostore.SummarizeProfile(profile) + nodes := append([]arangostore.ProfileNodeSummary(nil), summary.Nodes...) + if len(nodes) > 20 { + nodes = nodes[:20] + } + return endpointSelectorProfileSummary{ScannedFull: summary.ScannedFull, ScannedIndex: summary.ScannedIndex, PeakMemoryBytes: summary.PeakMemory, Phases: profile.Extra.Profile, TopNodes: nodes} +} + +func minFloat(values []float64) float64 { + if len(values) == 0 { + return 0 + } + minimum := values[0] + for _, value := range values[1:] { + if value < minimum { + minimum = value + } + } + return minimum +} + +type endpointSelectorRouteRewrite struct { + Node string `json:"node"` + Edge string `json:"edge"` + Parent string `json:"parent"` + Direction string `json:"direction"` + Collection string `json:"collection"` +} + +var nestedEndpointHeaderRE = regexp.MustCompile(`(?m)^(\s*)FOR ([A-Za-z_][A-Za-z0-9_]*)_node, ([A-Za-z_][A-Za-z0-9_]*)_edge IN 1\.\.1 (INBOUND|OUTBOUND) ([A-Za-z_][A-Za-z0-9_]*) (@@[A-Za-z_][A-Za-z0-9_]*_edge_collection)\n`) + +func rewriteNestedEndpointTraversals(query string) (string, []endpointSelectorRouteRewrite, error) { + matches := nestedEndpointHeaderRE.FindAllStringSubmatchIndex(query, -1) + var builder strings.Builder + last := 0 + routes := make([]endpointSelectorRouteRewrite, 0, len(matches)) + for _, match := range matches { + node := query[match[4]:match[5]] + "_node" + edge := query[match[6]:match[7]] + "_edge" + direction := query[match[8]:match[9]] + parent := query[match[10]:match[11]] + collection := query[match[12]:match[13]] + if !strings.HasPrefix(parent, "__loom_physical_parent_set_") { + continue + } + endpoint, target := "_to", "_from" + if direction == "OUTBOUND" { + endpoint, target = "_from", "_to" + } + builder.WriteString(query[last:match[0]]) + builder.WriteString("FOR " + edge + " IN " + collection + "\n") + builder.WriteString(" FILTER " + edge + "." + endpoint + " == " + parent + "._id\n") + builder.WriteString(" LET " + node + " = DOCUMENT(" + edge + "." + target + ")\n") + last = match[1] + routes = append(routes, endpointSelectorRouteRewrite{Node: node, Edge: edge, Parent: parent, Direction: direction, Collection: collection}) + } + if len(routes) == 0 { + return query, nil, fmt.Errorf("no nested physical traversal headers found") + } + builder.WriteString(query[last:]) + return builder.String(), routes, nil +} + +var explicitEndpointHeaderRE = regexp.MustCompile(`(?m)^\s*FOR ([A-Za-z_][A-Za-z0-9_]*)_edge IN (@@[A-Za-z_][A-Za-z0-9_]*_edge_collection)\n\s+FILTER ([A-Za-z_][A-Za-z0-9_]*)_edge\.(\w+) == ([A-Za-z_][A-Za-z0-9_]*)\._id`) + +// prepareEndpointSelectorBase uses the test-only WP2 rewrite for the pinned +// native control. If the coordinator has already enabled WP2 in production, +// the current integrated AQL is itself the endpoint-only control and is used +// unchanged. This keeps the selector comparison meaningful while the shared +// compiler is moving. +func prepareEndpointSelectorBase(query string) (string, []endpointSelectorRouteRewrite, error) { + endpointOnly, routes, err := rewriteNestedEndpointTraversals(query) + if err == nil { + return endpointOnly, routes, nil + } + if sha256Hex(query) != "988775e708a0f836ed34de0815e74cdbf38172e75c12a80149a9ce6096b48925" { + return query, nil, err + } + matches := explicitEndpointHeaderRE.FindAllStringSubmatch(query, -1) + if len(matches) != 3 { + return query, nil, fmt.Errorf("integrated endpoint control has %d explicit nested routes, want 3", len(matches)) + } + routes = make([]endpointSelectorRouteRewrite, 0, len(matches)) + for _, match := range matches { + direction := "INBOUND" + if match[4] == "_from" { + direction = "OUTBOUND" + } + routes = append(routes, endpointSelectorRouteRewrite{Node: match[1] + "_node", Edge: match[1] + "_edge", Parent: match[5], Direction: direction, Collection: match[2]}) + } + return query, routes, nil +} + +func writeEndpointSelectorComboArtifacts(t *testing.T, compiled dataframe.CompiledQuery, endpointOnly, combo string, routes []endpointSelectorRouteRewrite, lowering selectorLoweringReport, control, endpoint, candidate endpointSelectorComboRun) { + _, source, _, _ := runtime.Caller(0) + root := filepath.Join(filepath.Dir(source), "..", "..") + directory := filepath.Join(root, "docs", "benchmarks", "round4", "wp2_selector_combo") + if err := os.MkdirAll(directory, 0o755); err != nil { + t.Fatal(err) + } + for name, query := range map[string]string{"production.aql": compiled.Query, "endpoint_only.aql": endpointOnly, "candidate.aql": combo} { + if err := os.WriteFile(filepath.Join(directory, name), []byte(query+"\n"), 0o644); err != nil { + t.Fatal(err) + } + } + payload := map[string]any{"control": control, "endpoint_only": endpoint, "candidate": candidate, "routes": routes, "selector_lowering": lowering, "compiled_columns": compiled.Columns} + encoded, err := json.MarshalIndent(payload, "", " ") + if err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(directory, "RESULTS.json"), append(encoded, '\n'), 0o644); err != nil { + t.Fatal(err) + } +} diff --git a/internal/dataframe/endpoint_strategy_experiment_test.go b/internal/dataframe/endpoint_strategy_experiment_test.go new file mode 100644 index 0000000..77acc93 --- /dev/null +++ b/internal/dataframe/endpoint_strategy_experiment_test.go @@ -0,0 +1,642 @@ +package dataframe + +// This file is an opt-in experiment harness, not a production lowering. It +// discovers routes from fhir_edge, resolves them through generated schema +// metadata, and compares four generic AQL shapes without touching compiler IR. + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "fmt" + "os" + "path/filepath" + "sort" + "strings" + "testing" + "time" + + "github.com/calypr/loom/fhirschema" + arangostore "github.com/calypr/loom/internal/store/arango" +) + +type endpointExperimentMode string + +const ( + endpointNativeShared endpointExperimentMode = "native_shared" + endpointNativeIndependent endpointExperimentMode = "native_independent" + endpointExplicitShared endpointExperimentMode = "explicit_shared" + endpointExplicitIndependent endpointExperimentMode = "explicit_independent" +) + +type endpointExperimentRoute struct { + ParentType string `json:"parent_type"` + Label string `json:"label"` + TargetType string `json:"target_type"` + EdgeCount int `json:"edge_count"` + Route storageRoute +} + +type endpointExperimentGroup struct { + ParentType string + Label string + Direction PhysicalTraversalDirection + Routes []endpointExperimentRoute +} + +type endpointRouteRow struct { + FromType string `json:"from_type"` + ToType string `json:"to_type"` + Label string `json:"label"` + Count int `json:"edge_count"` +} + +type endpointExperimentRun struct { + Mode endpointExperimentMode `json:"mode"` + QueryHash string `json:"query_hash"` + ResultHash string `json:"result_hash"` + Rows int `json:"rows"` + Bytes int `json:"bytes"` + WarmSeconds []float64 `json:"warm_seconds"` + MedianSeconds float64 `json:"median_seconds"` + MinSeconds float64 `json:"min_seconds"` + Explain arangoExplainExperiment `json:"explain"` + Profile arangoProfileExperiment `json:"profile"` +} + +type arangoExplainExperiment struct { + FullScans []arangostore.ExplainCollectionScan `json:"full_scans"` + Indexes []arangostore.ExplainIndexSummary `json:"indexes"` + Plans []arangostore.ExplainPlanEstimate `json:"plans"` +} + +type arangoProfileExperiment struct { + ScannedFull int `json:"scanned_full"` + ScannedIndex int `json:"scanned_index"` + PeakMemory uint64 `json:"peak_memory"` + Runtime float64 `json:"profile_runtime_seconds"` + TopNodes []arangostore.ProfileNodeSummary `json:"top_nodes"` + TopItemNodes []arangostore.ProfileNodeSummary `json:"top_item_nodes"` +} + +func TestRenderEndpointExperimentQueryShapes(t *testing.T) { + group := endpointExperimentGroup{ + ParentType: "RootCollection", + Label: "generated_label", + Direction: PhysicalInbound, + Routes: []endpointExperimentRoute{ + {ParentType: "RootCollection", Label: "generated_label", TargetType: "TargetA"}, + {ParentType: "RootCollection", Label: "generated_label", TargetType: "TargetB"}, + }, + } + for _, mode := range []endpointExperimentMode{endpointNativeShared, endpointNativeIndependent, endpointExplicitShared, endpointExplicitIndependent} { + query, bindVars, err := renderEndpointExperimentQuery(group, "project", 1000, mode) + if err != nil { + t.Fatalf("render %s: %v", mode, err) + } + if !strings.Contains(query, "@@root_collection") || !strings.Contains(query, "@@edge_collection") { + t.Fatalf("render %s omitted collection binds:\n%s", mode, query) + } + if strings.Contains(query, "TargetA") || strings.Contains(query, "TargetB") { + t.Fatalf("render %s interpolated a target type:\n%s", mode, query) + } + if mode == endpointNativeShared || mode == endpointExplicitShared { + if !strings.Contains(query, "IN @target_types") { + t.Fatalf("render %s omitted shared type predicate:\n%s", mode, query) + } + } else if !strings.Contains(query, "== @target_type_0") || !strings.Contains(query, "== @target_type_1") { + t.Fatalf("render %s omitted independent type predicates:\n%s", mode, query) + } + if mode == endpointNativeShared || mode == endpointExplicitShared { + if _, ok := bindVars["target_types"]; !ok { + t.Fatalf("render %s omitted target_types bind", mode) + } + } else if _, ok := bindVars["target_types"]; ok { + t.Fatalf("render %s retained unused target_types bind", mode) + } + } +} + +// TestEndpointStrategyMatrixAgainstArango is opt-in because it reads the +// provisioned META database. It never creates indexes or mutates documents. +func TestEndpointStrategyMatrixAgainstArango(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run endpoint strategy experiment") + } + url, database, project := compilerArangoTarget() + client, err := arangostore.Open(context.Background(), url, database) + if err != nil { + t.Fatalf("open Arango: %v", err) + } + defer client.Close(context.Background()) + + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute) + defer cancel() + routes, err := discoverEndpointExperimentRoutes(ctx, client, project) + if err != nil { + t.Fatalf("discover endpoint experiment routes: %v", err) + } + groups := groupEndpointExperimentRoutes(routes) + if len(groups) == 0 { + t.Skip("loaded database has no generated route group with multiple target types") + } + sort.SliceStable(groups, func(i, j int) bool { return groupEdgeCount(groups[i]) > groupEdgeCount(groups[j]) }) + if len(groups) > 4 { + groups = groups[:4] + } + limit := experimentLimit() + for index, group := range groups { + group := group + t.Run(fmt.Sprintf("group_%02d_%s_%s", index, group.ParentType, group.Label), func(t *testing.T) { + runs, err := runEndpointExperimentGroup(ctx, client, project, limit, group) + if err != nil { + t.Fatalf("run endpoint strategy matrix: %v", err) + } + for _, run := range runs { + t.Logf("mode=%s query_hash=%s result_hash=%s median=%0.6fs min=%0.6fs rows=%d scanned_index=%d peak_memory=%d indexes=%#v", run.Mode, run.QueryHash, run.ResultHash, run.MedianSeconds, run.MinSeconds, run.Rows, run.Profile.ScannedIndex, run.Profile.PeakMemory, run.Explain.Indexes) + if len(run.Explain.FullScans) != 0 { + t.Errorf("mode=%s used full collection scan: %#v", run.Mode, run.Explain.FullScans) + } + } + if err := writeEndpointExperimentEvidence(project, limit, index, group, runs); err != nil { + t.Fatalf("write endpoint experiment evidence: %v", err) + } + }) + } +} + +// TestEndpointSingletonStrategyMatrixAgainstArango isolates the nested +// single-target paths that a sibling-union benchmark cannot expose. It uses +// the same generated route discovery, but runs one parent collection at a +// time, comparing native traversal with explicit endpoint equality. This is +// intentionally a route-region benchmark: it does not pretend to reproduce +// the parent-set correlation of the complete GDC dataframe. +func TestEndpointSingletonStrategyMatrixAgainstArango(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run singleton endpoint experiment") + } + url, database, project := compilerArangoTarget() + client, err := arangostore.Open(context.Background(), url, database) + if err != nil { + t.Fatalf("open Arango: %v", err) + } + defer client.Close(context.Background()) + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute) + defer cancel() + routes, err := discoverEndpointExperimentRoutes(ctx, client, project) + if err != nil { + t.Fatalf("discover endpoint experiment routes: %v", err) + } + groups := singletonEndpointExperimentGroups(routes) + if len(groups) == 0 { + t.Skip("loaded database has no generated singleton route") + } + limit := experimentLimit() + for index, group := range groups { + group := group + t.Run(fmt.Sprintf("route_%02d_%s_%s_%s", index, group.ParentType, group.Label, group.Routes[0].TargetType), func(t *testing.T) { + runs, err := runEndpointExperimentModes(ctx, client, project, limit, group, []endpointExperimentMode{endpointNativeIndependent, endpointExplicitIndependent}) + if err != nil { + t.Fatalf("run singleton endpoint strategy matrix: %v", err) + } + for _, run := range runs { + t.Logf("mode=%s query_hash=%s result_hash=%s median=%0.6fs min=%0.6fs rows=%d scanned_index=%d peak_memory=%d indexes=%#v", run.Mode, run.QueryHash, run.ResultHash, run.MedianSeconds, run.MinSeconds, run.Rows, run.Profile.ScannedIndex, run.Profile.PeakMemory, run.Explain.Indexes) + if len(run.Explain.FullScans) != 0 { + t.Errorf("mode=%s used full collection scan: %#v", run.Mode, run.Explain.FullScans) + } + } + if err := writeEndpointExperimentEvidenceNamed(project, limit, "singleton", index, group, runs); err != nil { + t.Fatalf("write singleton endpoint experiment evidence: %v", err) + } + }) + } +} + +func singletonEndpointExperimentGroups(routes []endpointExperimentRoute) []endpointExperimentGroup { + if len(routes) == 0 { + return nil + } + // A parent that is itself a target of another generated route is a nested + // parent in the loaded graph. Prefer those regions, then fall back to the + // highest fan-out routes when the fixture has no deeper chain. + targetTypes := map[string]bool{} + for _, route := range routes { + targetTypes[route.TargetType] = true + } + preferred := make([]endpointExperimentRoute, 0, len(routes)) + for _, route := range routes { + if targetTypes[route.ParentType] { + preferred = append(preferred, route) + } + } + if len(preferred) == 0 { + preferred = append(preferred, routes...) + } + sort.SliceStable(preferred, func(i, j int) bool { + if preferred[i].EdgeCount != preferred[j].EdgeCount { + return preferred[i].EdgeCount > preferred[j].EdgeCount + } + if preferred[i].ParentType != preferred[j].ParentType { + return preferred[i].ParentType < preferred[j].ParentType + } + if preferred[i].Label != preferred[j].Label { + return preferred[i].Label < preferred[j].Label + } + return preferred[i].TargetType < preferred[j].TargetType + }) + seen := map[string]bool{} + seenParents := map[string]bool{} + groups := make([]endpointExperimentGroup, 0, 4) + // First cover distinct nested parent collections so a high-fanout resource + // cannot crowd out deeper regions such as Group -> DocumentReference. + for _, route := range preferred { + if seenParents[route.ParentType] { + continue + } + seenParents[route.ParentType] = true + key := fmt.Sprintf("%s\x00%s\x00%s", route.ParentType, route.Label, route.TargetType) + seen[key] = true + groups = append(groups, endpointExperimentGroup{ParentType: route.ParentType, Label: route.Label, Direction: route.Route.Direction, Routes: []endpointExperimentRoute{route}}) + if len(groups) == 4 { + return groups + } + } + for _, route := range preferred { + key := fmt.Sprintf("%s\x00%s\x00%s", route.ParentType, route.Label, route.TargetType) + if seen[key] { + continue + } + seen[key] = true + groups = append(groups, endpointExperimentGroup{ParentType: route.ParentType, Label: route.Label, Direction: route.Route.Direction, Routes: []endpointExperimentRoute{route}}) + if len(groups) == 4 { + break + } + } + return groups +} + +func experimentLimit() int { + if value := strings.TrimSpace(os.Getenv("DATAFRAME_PROFILE_LIMIT")); value != "" { + var limit int + if _, err := fmt.Sscanf(value, "%d", &limit); err == nil && limit > 0 { + return limit + } + } + return 1000 +} + +func discoverEndpointExperimentRoutes(ctx context.Context, client *arangostore.Client, project string) ([]endpointExperimentRoute, error) { + query := `FOR edge IN fhir_edge + FILTER edge.project == @project + COLLECT from_type = edge.from_type, to_type = edge.to_type, label = edge.label WITH COUNT INTO edge_count + RETURN {from_type, to_type, label, edge_count}` + rows := make([]endpointRouteRow, 0) + if err := client.QueryRows(ctx, query, 1000, map[string]any{"project": project}, func(row map[string]any) error { + encoded, err := json.Marshal(row) + if err != nil { + return err + } + var decoded endpointRouteRow + if err := json.Unmarshal(encoded, &decoded); err != nil { + return err + } + rows = append(rows, decoded) + return nil + }); err != nil { + return nil, err + } + + seen := map[string]bool{} + out := make([]endpointExperimentRoute, 0, len(rows)) + for _, edge := range rows { + if !fhirschema.HasResource(edge.FromType) || !fhirschema.HasResource(edge.ToType) || strings.TrimSpace(edge.Label) == "" { + continue + } + // Normal FHIR references are stored child _from -> parent _to. Try the + // generated parent->child tuple first, then the proven forward tuple. + candidates := [][2]string{{edge.ToType, edge.FromType}, {edge.FromType, edge.ToType}} + for _, candidate := range candidates { + route, err := resolveStorageRoute(candidate[0], edge.Label, candidate[1]) + if err != nil { + continue + } + key := fmt.Sprintf("%s\x00%s\x00%s\x00%s", candidate[0], edge.Label, candidate[1], route.Direction) + if seen[key] { + continue + } + seen[key] = true + out = append(out, endpointExperimentRoute{ParentType: candidate[0], Label: edge.Label, TargetType: candidate[1], EdgeCount: edge.Count, Route: route}) + } + } + sort.Slice(out, func(i, j int) bool { + if out[i].ParentType != out[j].ParentType { + return out[i].ParentType < out[j].ParentType + } + if out[i].Label != out[j].Label { + return out[i].Label < out[j].Label + } + return out[i].TargetType < out[j].TargetType + }) + return out, nil +} + +func groupEndpointExperimentRoutes(routes []endpointExperimentRoute) []endpointExperimentGroup { + groups := map[string]endpointExperimentGroup{} + for _, route := range routes { + key := fmt.Sprintf("%s\x00%s\x00%s", route.ParentType, route.Label, route.Route.Direction) + group := groups[key] + group.ParentType = route.ParentType + group.Label = route.Label + group.Direction = route.Route.Direction + group.Routes = append(group.Routes, route) + groups[key] = group + } + out := make([]endpointExperimentGroup, 0, len(groups)) + for _, group := range groups { + seen := map[string]bool{} + unique := group.Routes[:0] + for _, route := range group.Routes { + if seen[route.TargetType] { + continue + } + seen[route.TargetType] = true + unique = append(unique, route) + } + group.Routes = unique + if len(group.Routes) >= 2 { + out = append(out, group) + } + } + sort.Slice(out, func(i, j int) bool { + if out[i].ParentType != out[j].ParentType { + return out[i].ParentType < out[j].ParentType + } + return out[i].Label < out[j].Label + }) + return out +} + +func groupEdgeCount(group endpointExperimentGroup) int { + total := 0 + for _, route := range group.Routes { + total += route.EdgeCount + } + return total +} + +func runEndpointExperimentGroup(ctx context.Context, client *arangostore.Client, project string, limit int, group endpointExperimentGroup) ([]endpointExperimentRun, error) { + modes := []endpointExperimentMode{endpointNativeShared, endpointNativeIndependent, endpointExplicitShared, endpointExplicitIndependent} + return runEndpointExperimentModes(ctx, client, project, limit, group, modes) +} + +func runEndpointExperimentModes(ctx context.Context, client *arangostore.Client, project string, limit int, group endpointExperimentGroup, modes []endpointExperimentMode) ([]endpointExperimentRun, error) { + runs := make([]endpointExperimentRun, 0, len(modes)) + for _, mode := range modes { + query, bindVars, err := renderEndpointExperimentQuery(group, project, limit, mode) + if err != nil { + return nil, err + } + explain, err := client.Explain(ctx, arangostore.ExplainRequest{Query: query, BindVars: bindVars}) + if err != nil { + return nil, fmt.Errorf("explain %s: %w\nAQL:\n%s", mode, err, query) + } + assessment := arangostore.AssessExplainResult(explain) + resultHashes := make([]string, 0, 5) + warm := make([]float64, 0, 5) + rowsCount, bytesCount := 0, 0 + for run := 0; run < 5; run++ { + started := time.Now() + rows := make([]map[string]any, 0, limit) + if err := client.QueryRows(ctx, query, 1000, bindVars, func(row map[string]any) error { + rows = append(rows, row) + return nil + }); err != nil { + return nil, fmt.Errorf("execute %s run %d: %w", mode, run+1, err) + } + warm = append(warm, time.Since(started).Seconds()) + encoded, err := json.Marshal(rows) + if err != nil { + return nil, err + } + resultHashes = append(resultHashes, hashBytes(encoded)) + if run == 0 { + rowsCount, bytesCount = len(rows), len(encoded) + } + } + for _, hash := range resultHashes[1:] { + if hash != resultHashes[0] { + return nil, fmt.Errorf("mode %s changed result hash between warm runs: %v", mode, resultHashes) + } + } + profile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: query, BindVars: bindVars, BatchSize: 1000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + return nil, fmt.Errorf("profile %s: %w", mode, err) + } + profileSummary := arangostore.SummarizeProfile(profile) + sort.Float64s(warm) + runs = append(runs, endpointExperimentRun{ + Mode: mode, QueryHash: hashBytes([]byte(query)), ResultHash: resultHashes[0], Rows: rowsCount, Bytes: bytesCount, + WarmSeconds: warm, MedianSeconds: warm[len(warm)/2], MinSeconds: warm[0], + Explain: arangoExplainExperiment{FullScans: assessment.FullCollectionScans, Indexes: assessment.Indexes, Plans: assessment.Plans}, + Profile: arangoProfileExperiment{ScannedFull: profileSummary.ScannedFull, ScannedIndex: profileSummary.ScannedIndex, PeakMemory: profileSummary.PeakMemory, Runtime: profileSummary.RuntimeSeconds, TopNodes: topProfileNodesByRuntime(profileSummary.Nodes, 10), TopItemNodes: topProfileNodesByItems(profileSummary.Nodes, 10)}, + }) + } + return runs, nil +} + +func renderEndpointExperimentQuery(group endpointExperimentGroup, project string, limit int, mode endpointExperimentMode) (string, map[string]any, error) { + if len(group.Routes) == 0 { + return "", nil, fmt.Errorf("endpoint experiment group requires at least one target route") + } + if (mode == endpointNativeShared || mode == endpointExplicitShared) && len(group.Routes) < 2 { + return "", nil, fmt.Errorf("shared endpoint experiment requires at least two target routes") + } + endpoint, targetEndpoint, discriminator, direction := endpointFields(group.Direction) + types := make([]string, 0, len(group.Routes)) + for _, route := range group.Routes { + types = append(types, route.TargetType) + } + bindVars := map[string]any{ + "@root_collection": group.ParentType, + "@edge_collection": "fhir_edge", + "project": project, + "dataset_generation": "", + "auth_resource_paths_unrestricted": true, + "auth_resource_paths": []string{}, + "limit": limit, + "label": group.Label, + } + var childExpr string + if mode == endpointNativeShared { + bindVars["target_types"] = types + childExpr = fmt.Sprintf(`FOR node, edge IN 1..1 %s root @@edge_collection + FILTER edge.project == @project + FILTER @dataset_generation == "" OR edge.dataset_generation == @dataset_generation + FILTER @auth_resource_paths_unrestricted == true OR edge.auth_resource_path IN @auth_resource_paths + FILTER edge.label == @label + FILTER edge.%s IN @target_types + FILTER node.project == @project + FILTER @dataset_generation == "" OR node.dataset_generation == @dataset_generation + FILTER @auth_resource_paths_unrestricted == true OR node.auth_resource_path IN @auth_resource_paths + FILTER node.resourceType IN @target_types + SORT node._key + RETURN node._key`, direction, discriminator) + } else if mode == endpointExplicitShared { + bindVars["target_types"] = types + childExpr = fmt.Sprintf(`FOR edge IN @@edge_collection + FILTER edge.%s == root._id + FILTER edge.project == @project + FILTER @dataset_generation == "" OR edge.dataset_generation == @dataset_generation + FILTER @auth_resource_paths_unrestricted == true OR edge.auth_resource_path IN @auth_resource_paths + FILTER edge.label == @label + FILTER edge.%s IN @target_types + LET node = DOCUMENT(edge.%s) + FILTER node != null + FILTER node.project == @project + FILTER @dataset_generation == "" OR node.dataset_generation == @dataset_generation + FILTER @auth_resource_paths_unrestricted == true OR node.auth_resource_path IN @auth_resource_paths + FILTER node.resourceType IN @target_types + SORT node._key + RETURN node._key`, endpoint, discriminator, targetEndpoint) + } else { + children := make([]string, 0, len(group.Routes)) + for index, route := range group.Routes { + bindKey := fmt.Sprintf("target_type_%d", index) + bindVars[bindKey] = route.TargetType + if mode == endpointNativeIndependent { + children = append(children, fmt.Sprintf(`FOR node, edge IN 1..1 %s root @@edge_collection + FILTER edge.project == @project + FILTER @dataset_generation == "" OR edge.dataset_generation == @dataset_generation + FILTER @auth_resource_paths_unrestricted == true OR edge.auth_resource_path IN @auth_resource_paths + FILTER edge.label == @label + FILTER edge.%s == @%s + FILTER node.project == @project + FILTER @dataset_generation == "" OR node.dataset_generation == @dataset_generation + FILTER @auth_resource_paths_unrestricted == true OR node.auth_resource_path IN @auth_resource_paths + FILTER node.resourceType == @%s + SORT node._key + RETURN node._key`, direction, discriminator, bindKey, bindKey)) + } else { + children = append(children, fmt.Sprintf(`FOR edge IN @@edge_collection + FILTER edge.%s == root._id + FILTER edge.project == @project + FILTER @dataset_generation == "" OR edge.dataset_generation == @dataset_generation + FILTER @auth_resource_paths_unrestricted == true OR edge.auth_resource_path IN @auth_resource_paths + FILTER edge.label == @label + FILTER edge.%s == @%s + LET node = DOCUMENT(edge.%s) + FILTER node != null + FILTER node.project == @project + FILTER @dataset_generation == "" OR node.dataset_generation == @dataset_generation + FILTER @auth_resource_paths_unrestricted == true OR node.auth_resource_path IN @auth_resource_paths + FILTER node.resourceType == @%s + SORT node._key + RETURN node._key`, endpoint, discriminator, bindKey, targetEndpoint, bindKey)) + } + } + wrapped := make([]string, 0, len(children)) + for _, child := range children { + wrapped = append(wrapped, "("+child+")") + } + combined := wrapped[0] + for _, child := range wrapped[1:] { + // APPEND accepts one array at a time. Nesting it keeps this + // experiment valid for groups with more than two sibling types. + combined = fmt.Sprintf("APPEND(%s, %s, true)", combined, child) + } + childExpr = "SORTED_UNIQUE(" + combined + ")" + } + query := fmt.Sprintf(`FOR root IN @@root_collection + FILTER root.project == @project + FILTER @dataset_generation == "" OR root.dataset_generation == @dataset_generation + FILTER @auth_resource_paths_unrestricted == true OR root.auth_resource_path IN @auth_resource_paths + SORT root._key + LIMIT @limit + LET children = (%s) + RETURN {"_key": root._key, "children": children}`, childExpr) + return query, bindVars, nil +} + +func endpointFields(direction PhysicalTraversalDirection) (endpoint, targetEndpoint, discriminator, aqlDirection string) { + if direction == PhysicalOutbound { + return "_from", "_to", "to_type", "OUTBOUND" + } + return "_to", "_from", "from_type", "INBOUND" +} + +func topProfileNodesByRuntime(nodes []arangostore.ProfileNodeSummary, limit int) []arangostore.ProfileNodeSummary { + ordered := append([]arangostore.ProfileNodeSummary(nil), nodes...) + sort.SliceStable(ordered, func(i, j int) bool { + if ordered[i].Runtime != ordered[j].Runtime { + return ordered[i].Runtime > ordered[j].Runtime + } + return ordered[i].ID < ordered[j].ID + }) + if len(ordered) > limit { + ordered = ordered[:limit] + } + return ordered +} + +func topProfileNodesByItems(nodes []arangostore.ProfileNodeSummary, limit int) []arangostore.ProfileNodeSummary { + ordered := append([]arangostore.ProfileNodeSummary(nil), nodes...) + sort.SliceStable(ordered, func(i, j int) bool { + if ordered[i].Items != ordered[j].Items { + return ordered[i].Items > ordered[j].Items + } + return ordered[i].ID < ordered[j].ID + }) + if len(nodes) > limit { + ordered = ordered[:limit] + } + return ordered +} + +func writeEndpointExperimentEvidence(project string, limit, index int, group endpointExperimentGroup, runs []endpointExperimentRun) error { + return writeEndpointExperimentEvidenceNamed(project, limit, "group", index, group, runs) +} + +func writeEndpointExperimentEvidenceNamed(project string, limit int, prefix string, index int, group endpointExperimentGroup, runs []endpointExperimentRun) error { + directory := filepath.Join(round3BenchmarkRoot(), "docs", "benchmarks", "round3", "wp1") + if err := os.MkdirAll(directory, 0o755); err != nil { + return err + } + name := fmt.Sprintf("%s_%02d_%s_%s", prefix, index, group.ParentType, group.Label) + name = strings.NewReplacer("/", "_", "\\", "_", " ", "_").Replace(name) + payload := map[string]any{"generated_at": time.Now().UTC().Format(time.RFC3339Nano), "git_sha": gitSHAForEvidence(), "project": project, "limit": limit, "group": group, "runs": runs} + encoded, err := json.MarshalIndent(payload, "", " ") + if err != nil { + return err + } + return os.WriteFile(filepath.Join(directory, name+".json"), append(encoded, '\n'), 0o644) +} + +func round3BenchmarkRoot() string { + directory, err := os.Getwd() + if err != nil { + return "." + } + for { + if _, err := os.Stat(filepath.Join(directory, "go.mod")); err == nil { + return directory + } + parent := filepath.Dir(directory) + if parent == directory { + return "." + } + directory = parent + } +} + +func gitSHAForEvidence() string { + if value := strings.TrimSpace(os.Getenv("GIT_COMMIT")); value != "" { + return value + } + return "unknown" +} + +func hashBytes(value []byte) string { + sum := sha256.Sum256(value) + return hex.EncodeToString(sum[:]) +} diff --git a/internal/dataframe/endpoint_strategy_integration_test.go b/internal/dataframe/endpoint_strategy_integration_test.go new file mode 100644 index 0000000..12a81b2 --- /dev/null +++ b/internal/dataframe/endpoint_strategy_integration_test.go @@ -0,0 +1,172 @@ +package dataframe_test + +import ( + "context" + "encoding/json" + "os" + "path/filepath" + "runtime" + "strings" + "testing" + "time" + + dataframe "github.com/calypr/loom/internal/dataframe" + arangostore "github.com/calypr/loom/internal/store/arango" +) + +func TestEndpointStrategyUsesTypedLookupForNestedGDCAndFallsBack(t *testing.T) { + compiled := compileActualGDC(t, 1000) + if !strings.Contains(compiled.Query, "FOR child_set_3_edge IN @@child_set_3_edge_collection") { + t.Fatalf("default generic plan did not render endpoint lookup for nested route:\n%s", compiled.Query) + } + if !strings.Contains(compiled.Query, "FILTER child_set_3_edge._to == __loom_physical_parent_set_4._id") || !strings.Contains(compiled.Query, "DOCUMENT(child_set_3_edge._from)") { + t.Fatalf("endpoint lookup lost inbound endpoint/join fields:\n%s", compiled.Query) + } + + nativePolicy := dataframe.DefaultPhysicalOptimizationPolicy().WithRule(dataframe.PhysicalOptimizationRuleEndpointTraversal, false) + native, err := dataframe.CompileRequestWithPolicy(dataframe.Builder{ + Project: "ARANGODB_PROTO", RootResourceType: "Patient", + Traversals: []dataframe.TraversalStep{{Label: "subject_Patient", ToResourceType: "Specimen", Alias: "specimen", Traversals: []dataframe.TraversalStep{{Label: "subject_Specimen", ToResourceType: "DocumentReference", Alias: "file"}}}}, + }, 25, nativePolicy) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(native.Query, "INBOUND __loom_physical_parent_2 @@traversal_2_edge_collection") { + t.Fatalf("disabled endpoint policy did not retain native traversal:\n%s", native.Query) + } +} + +func TestEndpointStrategySupportsProvenResearchSubjectStudyOutbound(t *testing.T) { + builder := dataframe.Builder{ + Project: "ARANGODB_PROTO", RootResourceType: "ResearchSubject", + Traversals: []dataframe.TraversalStep{{Label: "study", ToResourceType: "ResearchStudy", Alias: "study"}}, + } + semantic, err := dataframe.BuildSemanticPlan(builder) + if err != nil { + t.Fatal(err) + } + physical, err := dataframe.BuildPhysicalPlanWithPolicy(semantic, dataframe.DefaultPhysicalOptimizationPolicy()) + if err != nil { + t.Fatal(err) + } + for _, operation := range physical.Operations { + if operation.Traversal != nil { + t.Logf("outbound physical strategy=%q endpoint=%q join=%q index=%#v", operation.Traversal.Strategy, operation.Traversal.EndpointField, operation.Traversal.EndpointJoinField, operation.Traversal.EndpointIndexFields) + } + } + compiled, err := dataframe.CompileRequestWithPolicy(builder, 25, dataframe.DefaultPhysicalOptimizationPolicy()) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(compiled.Query, "FOR edge_1 IN @@traversal_1_edge_collection") { + t.Fatalf("outbound route did not use typed endpoint lookup:\n%s", compiled.Query) + } + for _, want := range []string{ + "FILTER edge_1._from == root._id", + "FILTER edge_1.to_type == @traversal_1_target_type", + "LET node_1 = DOCUMENT(edge_1._to)", + "FILTER node_1.resourceType == @traversal_1_target_type", + } { + if !strings.Contains(compiled.Query, want) { + t.Fatalf("outbound endpoint lookup missing %q:\n%s", want, compiled.Query) + } + } +} + +func TestEndpointStrategyProfilesActualGDCAgainstArango(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run endpoint strategy live gate") + } + native := compileActualGDCWithEndpointRule(t, false) + candidate := compileActualGDCWithEndpointRule(t, true) + url, database, _ := compilerArangoTarget() + client, err := arangostore.Open(context.Background(), url, database) + if err != nil { + t.Fatalf("open Arango: %v", err) + } + defer client.Close(context.Background()) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) + defer cancel() + controlTimes, candidateTimes := make([]float64, 0, 5), make([]float64, 0, 5) + var controlHash, candidateHash string + for run := 0; run < 5; run++ { + controlQuery, controlBinds := cacheBust(native.Query, native.BindVars, 51000+run) + candidateQuery, candidateBinds := cacheBust(candidate.Query, candidate.BindVars, 52000+run) + seconds, _, hash, err := executeOrdinary(ctx, client, controlQuery, controlBinds) + if err != nil { + t.Fatalf("native control run %d: %v", run+1, err) + } + controlTimes = append(controlTimes, seconds) + controlHash = hash + seconds, _, hash, err = executeOrdinary(ctx, client, candidateQuery, candidateBinds) + if err != nil { + t.Fatalf("endpoint candidate run %d: %v", run+1, err) + } + candidateTimes = append(candidateTimes, seconds) + candidateHash = hash + } + if controlHash != candidateHash { + t.Fatalf("endpoint result parity mismatch control=%s candidate=%s", controlHash, candidateHash) + } + controlExplain, err := client.Explain(ctx, arangostore.ExplainRequest{Query: native.Query, BindVars: native.BindVars}) + if err != nil { + t.Fatalf("native Explain: %v", err) + } + candidateExplain, err := client.Explain(ctx, arangostore.ExplainRequest{Query: candidate.Query, BindVars: candidate.BindVars}) + if err != nil { + t.Fatalf("endpoint Explain: %v", err) + } + controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: native.Query, BindVars: native.BindVars, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + t.Fatalf("native PROFILE: %v", err) + } + candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidate.Query, BindVars: candidate.BindVars, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + t.Fatalf("endpoint PROFILE: %v", err) + } + t.Logf("endpoint live control_hash=%s candidate_hash=%s control_median=%.6f candidate_median=%.6f control_explain=%+v candidate_explain=%+v control_profile=%+v candidate_profile=%+v", controlHash, candidateHash, median(controlTimes), median(candidateTimes), arangostore.AssessExplainResult(controlExplain), arangostore.AssessExplainResult(candidateExplain), arangostore.SummarizeProfile(controlProfile), arangostore.SummarizeProfile(candidateProfile)) + writeEndpointIntegrationEvidence(t, native, candidate, controlHash, candidateHash, controlTimes, candidateTimes, controlExplain, candidateExplain, controlProfile, candidateProfile) +} + +func compileActualGDCWithEndpointRule(t *testing.T, enabled bool) dataframe.CompiledQuery { + old, present := os.LookupEnv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL") + if enabled { + _ = os.Unsetenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL") + } else { + _ = os.Setenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL", "off") + } + defer func() { + if present { + _ = os.Setenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL", old) + } else { + _ = os.Unsetenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL") + } + }() + return compileActualGDC(t, 1000) +} + +func writeEndpointIntegrationEvidence(t *testing.T, control, candidate dataframe.CompiledQuery, controlHash, candidateHash string, controlTimes, candidateTimes []float64, controlExplain, candidateExplain arangostore.ExplainResult, controlProfile, candidateProfile arangostore.ProfileResult) { + _, source, _, _ := runtime.Caller(0) + directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "wp2") + if err := os.WriteFile(filepath.Join(directory, "integration-control.aql"), []byte(control.Query+"\n"), 0o644); err != nil { + t.Fatalf("write endpoint control AQL: %v", err) + } + if err := os.WriteFile(filepath.Join(directory, "integration-candidate.aql"), []byte(candidate.Query+"\n"), 0o644); err != nil { + t.Fatalf("write endpoint candidate AQL: %v", err) + } + payload := map[string]any{ + "control_aql_sha256": sha256Hex(control.Query), "candidate_aql_sha256": sha256Hex(candidate.Query), + "control_result_sha256": controlHash, "candidate_result_sha256": candidateHash, + "control_seconds": controlTimes, "candidate_seconds": candidateTimes, + "control_explain": controlExplain, "candidate_explain": candidateExplain, + "control_profile": controlProfile, "candidate_profile": candidateProfile, + "decision": "pending-coordinator-threshold-review", + } + data, err := json.MarshalIndent(payload, "", " ") + if err != nil { + t.Fatalf("encode endpoint integration evidence: %v", err) + } + if err := os.WriteFile(filepath.Join(directory, "integration-evidence.json"), append(data, '\n'), 0o644); err != nil { + t.Fatalf("write endpoint integration evidence: %v", err) + } +} diff --git a/internal/dataframe/errors.go b/internal/dataframe/errors.go new file mode 100644 index 0000000..2b1b5f1 --- /dev/null +++ b/internal/dataframe/errors.go @@ -0,0 +1,380 @@ +package dataframe + +import ( + "context" + "errors" + "fmt" + "reflect" + "strings" +) + +// ErrorCode is the stable, transport-neutral identifier for a dataframe +// request failure. Clients should branch on this value, not on Error(). +type ErrorCode string + +const ( + CodeProjectRequired ErrorCode = "PROJECT_REQUIRED" + CodeRootResourceTypeRequired ErrorCode = "ROOT_RESOURCE_TYPE_REQUIRED" + CodeUnauthorizedProject ErrorCode = "UNAUTHORIZED_PROJECT" + CodeUnknownField ErrorCode = "UNKNOWN_FIELD" + CodeFieldNotPopulated ErrorCode = "FIELD_NOT_POPULATED" + CodeInvalidTraversal ErrorCode = "INVALID_TRAVERSAL" + CodeUnsafeTraversalRoute ErrorCode = "UNSAFE_TRAVERSAL_ROUTE" + CodeInvalidFilter ErrorCode = "INVALID_FILTER" + CodeUnboundedPivot ErrorCode = "UNBOUNDED_PIVOT" + CodeInvalidPivotColumn ErrorCode = "INVALID_PIVOT_COLUMN" + CodeInvalidSlice ErrorCode = "INVALID_SLICE" + CodePlanTooExpensive ErrorCode = "PLAN_TOO_EXPENSIVE" + CodeInvalidCursor ErrorCode = "INVALID_CURSOR" + CodeStaleCursor ErrorCode = "STALE_CURSOR" + CodeDatasetGenerationChanged ErrorCode = "DATASET_GENERATION_CHANGED" + CodeUnsupportedExportFormat ErrorCode = "UNSUPPORTED_EXPORT_FORMAT" + CodeClientCanceled ErrorCode = "CLIENT_CANCELED" + CodeBackendUnavailable ErrorCode = "BACKEND_UNAVAILABLE" + CodeInternalError ErrorCode = "INTERNAL_ERROR" +) + +// AllErrorCodes is the compatibility registry. Keep its order stable when +// adding a code: it is used by contract tests and generated documentation. +var AllErrorCodes = []ErrorCode{ + CodeProjectRequired, + CodeRootResourceTypeRequired, + CodeUnauthorizedProject, + CodeUnknownField, + CodeFieldNotPopulated, + CodeInvalidTraversal, + CodeUnsafeTraversalRoute, + CodeInvalidFilter, + CodeUnboundedPivot, + CodeInvalidPivotColumn, + CodeInvalidSlice, + CodePlanTooExpensive, + CodeInvalidCursor, + CodeStaleCursor, + CodeDatasetGenerationChanged, + CodeUnsupportedExportFormat, + CodeClientCanceled, + CodeBackendUnavailable, + CodeInternalError, +} + +// UserError is the semantic error contract shared by GraphQL, preview, and +// export adapters. Details are intentionally a safe, copied view. +type UserError interface { + error + Code() string + FieldPath() []string + Details() map[string]any + Retryable() bool +} + +// Error is Loom's typed semantic error. The cause remains available to +// server-side logs and errors.Is/errors.As callers, but is never exposed by +// the transport mappers unless it is itself a safe UserError. +type Error struct { + code ErrorCode + message string + fieldPath []string + details map[string]any + retryable bool + cause error +} + +type errorOptions struct { + fieldPath []string + details map[string]any + retryable bool + cause error +} + +// ErrorOption configures a typed dataframe Error. +type ErrorOption func(*errorOptions) + +func WithFieldPath(path ...string) ErrorOption { + return func(opts *errorOptions) { opts.fieldPath = append([]string(nil), path...) } +} + +func WithDetails(details map[string]any) ErrorOption { + return func(opts *errorOptions) { opts.details = cloneSafeDetails(details) } +} + +func WithRetryable(retryable bool) ErrorOption { + return func(opts *errorOptions) { opts.retryable = retryable } +} + +func WithCause(cause error) ErrorOption { + return func(opts *errorOptions) { opts.cause = cause } +} + +func NewError(code ErrorCode, message string, options ...ErrorOption) *Error { + opts := errorOptions{} + for _, option := range options { + if option != nil { + option(&opts) + } + } + if message == "" { + message = defaultMessage(code) + } + return &Error{ + code: code, + message: message, + fieldPath: append([]string(nil), opts.fieldPath...), + details: cloneSafeDetails(opts.details), + retryable: opts.retryable, + cause: opts.cause, + } +} + +func Wrap(cause error, code ErrorCode, message string, options ...ErrorOption) *Error { + options = append(options, WithCause(cause)) + return NewError(code, message, options...) +} + +func (e *Error) Error() string { + if e == nil { + return "" + } + return e.message +} + +func (e *Error) Unwrap() error { + if e == nil { + return nil + } + return e.cause +} + +func (e *Error) Code() string { + if e == nil { + return string(CodeInternalError) + } + return string(e.code) +} + +func (e *Error) FieldPath() []string { + if e == nil { + return nil + } + return append([]string(nil), e.fieldPath...) +} + +func (e *Error) Details() map[string]any { + if e == nil { + return nil + } + return cloneSafeDetails(e.details) +} + +func (e *Error) Retryable() bool { + return e != nil && e.retryable +} + +// These sentinels let semantic owners wrap backend failures without making +// the GraphQL or HTTP layer inspect driver-specific errors. +var ( + ErrBackendUnavailable = errors.New("dataframe backend unavailable") + ErrClientCanceled = errors.New("dataframe client canceled") +) + +// AsUserError extracts a typed semantic error through arbitrary wrapping. +func AsUserError(err error) (UserError, bool) { + if err == nil { + return nil, false + } + var userErr UserError + if errors.As(err, &userErr) { + return userErr, true + } + return nil, false +} + +// Normalize converts only well-defined transport-neutral conditions. Unknown +// errors intentionally become INTERNAL_ERROR; no English error text is parsed. +func Normalize(err error) UserError { + if err == nil { + return nil + } + if userErr, ok := AsUserError(err); ok { + // Preserve our concrete type without adding an unnecessary wrapper. An + // adapter-owned implementation is copied through Error so its details + // receive the same redaction and defensive-copy rules. + if typed, ok := userErr.(*Error); ok { + return typed + } + code := ErrorCode(userErr.Code()) + return Wrap(err, code, defaultMessage(code), WithFieldPath(userErr.FieldPath()...), WithDetails(userErr.Details()), WithRetryable(userErr.Retryable())) + } + switch { + case errors.Is(err, context.Canceled), errors.Is(err, ErrClientCanceled): + return Wrap(err, CodeClientCanceled, defaultMessage(CodeClientCanceled)) + case errors.Is(err, context.DeadlineExceeded): + return Wrap(err, CodeBackendUnavailable, defaultMessage(CodeBackendUnavailable), WithRetryable(true)) + case errors.Is(err, ErrBackendUnavailable): + return Wrap(err, CodeBackendUnavailable, defaultMessage(CodeBackendUnavailable), WithRetryable(true)) + default: + return Wrap(err, CodeInternalError, defaultMessage(CodeInternalError)) + } +} + +func PublicMessage(err error) string { + if err == nil { + return "" + } + userErr := Normalize(err) + if userErr == nil { + return "internal server error" + } + return defaultMessage(ErrorCode(userErr.Code())) +} + +// IsUserCorrectable identifies failures for which the frontend should guide +// the user back to the request editor. Runtime Retryable on an Error remains +// the authoritative value for a specific occurrence. +func IsUserCorrectable(code ErrorCode) bool { + switch code { + case CodeProjectRequired, + CodeRootResourceTypeRequired, + CodeUnauthorizedProject, + CodeUnknownField, + CodeFieldNotPopulated, + CodeInvalidTraversal, + CodeUnsafeTraversalRoute, + CodeInvalidFilter, + CodeUnboundedPivot, + CodeInvalidPivotColumn, + CodeInvalidSlice, + CodePlanTooExpensive, + CodeInvalidCursor, + CodeStaleCursor, + CodeUnsupportedExportFormat: + return true + default: + return false + } +} + +func IsRetryableCode(code ErrorCode) bool { + return code == CodeBackendUnavailable +} + +func IsOperatorFailure(code ErrorCode) bool { + return code == CodeBackendUnavailable || code == CodeInternalError +} + +func defaultMessage(code ErrorCode) string { + switch code { + case CodeProjectRequired: + return "project is required" + case CodeRootResourceTypeRequired: + return "root resource type is required" + case CodeUnauthorizedProject: + return "the requested project is not available" + case CodeUnknownField: + return "the selected field is not recognized" + case CodeFieldNotPopulated: + return "the selected field is not populated in this dataset" + case CodeInvalidTraversal: + return "the requested traversal is invalid" + case CodeUnsafeTraversalRoute: + return "the requested traversal route is not supported" + case CodeInvalidFilter: + return "the requested filter is invalid" + case CodeUnboundedPivot: + return "the pivot must use a bounded set of columns" + case CodeInvalidPivotColumn: + return "the selected pivot column is invalid" + case CodeInvalidSlice: + return "the requested representative slice is invalid" + case CodePlanTooExpensive: + return "the dataframe request exceeds the preview cost limit" + case CodeInvalidCursor: + return "the preview cursor is invalid" + case CodeStaleCursor: + return "the preview cursor is no longer valid" + case CodeDatasetGenerationChanged: + return "the dataset changed while the request was being prepared" + case CodeUnsupportedExportFormat: + return "the requested export format is not supported" + case CodeClientCanceled: + return "the request was canceled" + case CodeBackendUnavailable: + return "the dataframe backend is temporarily unavailable" + default: + return "internal server error" + } +} + +func cloneSafeDetails(details map[string]any) map[string]any { + if len(details) == 0 { + return nil + } + result := make(map[string]any, len(details)) + for key, value := range details { + if sensitiveDetailKey(key) { + continue + } + if safe, ok := cloneSafeValue(value); ok { + result[key] = safe + } + } + if len(result) == 0 { + return nil + } + return result +} + +func sensitiveDetailKey(key string) bool { + key = strings.ToLower(strings.TrimSpace(key)) + for _, token := range []string{"aql", "bind", "credential", "secret", "token", "password", "collection", "filesystem", "stack"} { + if strings.Contains(key, token) { + return true + } + } + return key == "path" || key == "query" || key == "raw" || strings.Contains(key, "path") +} + +func cloneSafeValue(value any) (any, bool) { + if value == nil { + return nil, true + } + switch typed := value.(type) { + case string, bool, + int, int8, int16, int32, int64, + uint, uint8, uint16, uint32, uint64, + float32, float64: + return typed, true + case []string: + return append([]string(nil), typed...), true + case []any: + result := make([]any, 0, len(typed)) + for _, item := range typed { + safe, ok := cloneSafeValue(item) + if !ok { + return nil, false + } + result = append(result, safe) + } + return result, true + case map[string]any: + return cloneSafeDetails(typed), true + default: + // Accept only primitive aliases, not arbitrary structs such as Arango + // driver errors or query objects. + rv := reflect.ValueOf(value) + if rv.IsValid() && rv.Kind() == reflect.String { + return rv.String(), true + } + return nil, false + } +} + +// Ensure the concrete type continues to satisfy the public contract. +var _ UserError = (*Error)(nil) + +// Errorf is a small convenience for semantic owners that already have a +// formatted safe message. The message is still replaced by the stable public +// message at transport boundaries. +func Errorf(code ErrorCode, format string, args ...any) *Error { + return NewError(code, fmt.Sprintf(format, args...)) +} diff --git a/internal/dataframe/errors_test.go b/internal/dataframe/errors_test.go new file mode 100644 index 0000000..067a7f0 --- /dev/null +++ b/internal/dataframe/errors_test.go @@ -0,0 +1,134 @@ +package dataframe + +import ( + "context" + "errors" + "reflect" + "testing" +) + +func TestErrorCodesAreUniqueAndStable(t *testing.T) { + seen := make(map[ErrorCode]struct{}, len(AllErrorCodes)) + for _, code := range AllErrorCodes { + if code == "" { + t.Fatal("error registry contains an empty code") + } + if _, exists := seen[code]; exists { + t.Fatalf("duplicate error code %q", code) + } + seen[code] = struct{}{} + } + if len(seen) != 19 { + t.Fatalf("error registry length = %d, want 19", len(seen)) + } +} + +func TestErrorWrapPreservesCauseAndCopiesPublicFields(t *testing.T) { + cause := errors.New("driver details: collection=Patient bind=@secret") + details := map[string]any{ + "fieldRef": "Patient.id", + "collection": "Patient", + "aql": "FOR p IN Patient RETURN p", + "nested": map[string]any{"safe": true, "bind": "secret"}, + } + err := Wrap(cause, CodeUnknownField, "internal selector text", WithFieldPath("rootFields", "0", "fieldRef"), WithDetails(details)) + if !errors.Is(err, cause) { + t.Fatal("wrapped cause was not preserved") + } + if err.Code() != string(CodeUnknownField) { + t.Fatalf("code = %q", err.Code()) + } + if !reflect.DeepEqual(err.FieldPath(), []string{"rootFields", "0", "fieldRef"}) { + t.Fatalf("field path = %#v", err.FieldPath()) + } + public := err.Details() + if public["fieldRef"] != "Patient.id" { + t.Fatalf("safe detail missing: %#v", public) + } + if _, ok := public["collection"]; ok { + t.Fatalf("collection leaked: %#v", public) + } + if _, ok := public["aql"]; ok { + t.Fatalf("AQL leaked: %#v", public) + } + nested, ok := public["nested"].(map[string]any) + if !ok || nested["safe"] != true { + t.Fatalf("safe nested detail missing: %#v", public) + } + if _, ok := nested["bind"]; ok { + t.Fatalf("bind value leaked: %#v", public) + } + + path := err.FieldPath() + path[0] = "changed" + if err.FieldPath()[0] != "rootFields" { + t.Fatal("field path was not copied") + } + details["new"] = "not copied" + if _, ok := err.Details()["new"]; ok { + t.Fatal("details map was not copied") + } +} + +func TestNormalizeUsesTypedAndContextConditionsOnly(t *testing.T) { + typed := NewError(CodeInvalidFilter, "unsafe internal message") + if got := Normalize(typed); got.Code() != string(CodeInvalidFilter) { + t.Fatalf("typed code = %q", got.Code()) + } + if got := Normalize(context.Canceled); got.Code() != string(CodeClientCanceled) { + t.Fatalf("canceled code = %q", got.Code()) + } + if got := Normalize(context.DeadlineExceeded); got.Code() != string(CodeBackendUnavailable) || !got.Retryable() { + t.Fatalf("deadline mapping = code %q retryable=%v", got.Code(), got.Retryable()) + } + unknown := errors.New("unknown error mentioning invalid cursor") + got := Normalize(unknown) + if got.Code() != string(CodeInternalError) { + t.Fatalf("unknown code = %q", got.Code()) + } + if PublicMessage(unknown) != "internal server error" { + t.Fatalf("unknown message was exposed: %q", PublicMessage(unknown)) + } +} + +func TestPublicMessageDoesNotExposeTypedMessage(t *testing.T) { + err := NewError(CodeUnknownField, "field Patient.secret is not available") + if got := PublicMessage(err); got != "the selected field is not recognized" { + t.Fatalf("public message = %q", got) + } +} + +type unsafeUserError struct{} + +func (unsafeUserError) Error() string { return "private" } +func (unsafeUserError) Code() string { return string(CodeUnknownField) } +func (unsafeUserError) FieldPath() []string { return []string{"field"} } +func (unsafeUserError) Details() map[string]any { + return map[string]any{"aql": "private", "safe": true} +} +func (unsafeUserError) Retryable() bool { return false } + +func TestNormalizeRedactsAdapterOwnedUserErrors(t *testing.T) { + got := Normalize(unsafeUserError{}) + if got.Code() != string(CodeUnknownField) { + t.Fatalf("code = %q", got.Code()) + } + if _, leaked := got.Details()["aql"]; leaked { + t.Fatalf("unsafe adapter detail leaked: %#v", got.Details()) + } + if got.Details()["safe"] != true { + t.Fatalf("safe adapter detail missing: %#v", got.Details()) + } +} + +func TestErrorClassification(t *testing.T) { + if !IsUserCorrectable(CodeInvalidFilter) || IsUserCorrectable(CodeInternalError) { + t.Fatal("unexpected user-correctable classification") + } + if !IsRetryableCode(CodeBackendUnavailable) || IsRetryableCode(CodeClientCanceled) { + t.Fatal("unexpected retryable classification") + } + if !IsOperatorFailure(CodeInternalError) || IsOperatorFailure(CodeInvalidCursor) { + t.Fatal("unexpected operator classification") + } +} diff --git a/internal/dataframe/full_batch_tournament_test.go b/internal/dataframe/full_batch_tournament_test.go new file mode 100644 index 0000000..7819255 --- /dev/null +++ b/internal/dataframe/full_batch_tournament_test.go @@ -0,0 +1,265 @@ +package dataframe_test + +// This file is an isolated, test-only WP9 experiment. It hand-edits the +// production AQL emitted by BuilderFromInput; it intentionally does not add a +// compiler strategy or renderer branch. Promotion requires exact output +// parity and a whole-query runtime win on the complete GDC request. + +import ( + "context" + "encoding/json" + "fmt" + "os" + "path/filepath" + "runtime" + "strconv" + "strings" + "testing" + "time" + + dataframe "github.com/calypr/loom/internal/dataframe" + arangostore "github.com/calypr/loom/internal/store/arango" +) + +// TestFullBatchTournamentCandidateBuilds verifies that the candidate is +// generated from the real frontend input and remains parameterized. It does +// not require Arango and therefore protects the experiment when the live +// database is unavailable. +func TestFullBatchTournamentCandidateBuilds(t *testing.T) { + compiled := compileActualGDC(t, 1000) + candidate, err := batchRootChildSet1Query(compiled.Query) + if err != nil { + t.Fatal(err) + } + for _, fragment := range []string{ + "LET root_window = (", + "LET batch_child_set_1_grouped = (", + "FILTER edge._to IN SLICE(root_window[*]._id", + "COLLECT __batch_root_id = edge._to", + "FOR child_set_1_item IN (__batch_child_set_1_group ?", + "DOCUMENT(edge._from)", + } { + if !strings.Contains(candidate, fragment) { + t.Fatalf("batch candidate missing %q", fragment) + } + } + if strings.Contains(candidate, "FOR __batch_child_set_1 IN shared_root_subject_Patient_neighbors") { + t.Fatal("candidate still consumes child_set_1 from the correlated shared traversal") + } + if !strings.Contains(candidate, "@@child_set_1_edge_collection") || !strings.Contains(candidate, "@project") { + t.Fatal("candidate lost collection or scope binds") + } + if strings.Contains(candidate, "ARANGODB_PROTO") || strings.Contains(candidate, "Patient") == false { + t.Fatal("candidate unexpectedly lost the generic root shape") + } +} + +// TestFullBatchTournamentProfilesActualGDC is opt-in because it executes the +// complete 1,000-row request against the local Arango instance. The control +// and every candidate run alternate, consume all output, and add a harmless +// bind-backed predicate so Arango's result cache cannot satisfy the request. +func TestFullBatchTournamentProfilesActualGDC(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run WP9 against Arango") + } + compiled := compileActualGDC(t, 1000) + candidate, err := batchRootChildSet1Query(compiled.Query) + if err != nil { + t.Fatal(err) + } + url, database, _ := compilerArangoTarget() + client, err := arangostore.Open(context.Background(), url, database) + if err != nil { + t.Fatal(err) + } + defer client.Close(context.Background()) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) + defer cancel() + + batchSizes := []int{25, 100, 250, 500, 1000} + if raw := os.Getenv("LOOM_WP9_BATCH_SIZES"); raw != "" { + batchSizes = nil + for _, value := range strings.Split(raw, ",") { + size, parseErr := strconv.Atoi(strings.TrimSpace(value)) + if parseErr != nil || size <= 0 { + t.Fatalf("invalid LOOM_WP9_BATCH_SIZES value %q", value) + } + batchSizes = append(batchSizes, size) + } + } + runs := 5 + if raw := os.Getenv("LOOM_WP9_RUNS"); raw != "" { + parsed, parseErr := strconv.Atoi(raw) + if parseErr != nil || parsed <= 0 { + t.Fatalf("invalid LOOM_WP9_RUNS value %q", raw) + } + runs = parsed + } + results := make([]batchTournamentResult, 0, len(batchSizes)) + for _, batchSize := range batchSizes { + candidateSized := strings.ReplaceAll(candidate, "@__loom_batch_size", fmt.Sprintf("%d", batchSize)) + controlTimes := make([]float64, 0, 5) + candidateTimes := make([]float64, 0, 5) + controlBytes := make([]int, 0, 5) + candidateBytes := make([]int, 0, 5) + var controlHash, candidateHash string + for run := 0; run < runs; run++ { + controlQuery, controlBinds := cacheBust(compiled.Query, compiled.BindVars, 21000+batchSize*10+run) + candidateQuery, candidateBinds := cacheBust(candidateSized, compiled.BindVars, 22000+batchSize*10+run) + started := time.Now() + controlDuration, bytes, hash, err := executeOrdinary(ctx, client, controlQuery, controlBinds) + if err != nil { + t.Fatalf("batch size %d control run %d: %v", batchSize, run+1, err) + } + _ = started + controlTimes = append(controlTimes, controlDuration) + controlBytes = append(controlBytes, bytes) + controlHash = hash + candidateDuration, bytes, hash, err := executeOrdinary(ctx, client, candidateQuery, candidateBinds) + if err != nil { + t.Fatalf("batch size %d candidate run %d: %v", batchSize, run+1, err) + } + candidateTimes = append(candidateTimes, candidateDuration) + candidateBytes = append(candidateBytes, bytes) + candidateHash = hash + } + if controlHash != candidateHash { + t.Fatalf("batch size %d result parity mismatch control=%s candidate=%s", batchSize, controlHash, candidateHash) + } + controlProfileQuery, controlProfileBinds := cacheBust(compiled.Query, compiled.BindVars, 31000+batchSize) + candidateProfileQuery, candidateProfileBinds := cacheBust(candidateSized, compiled.BindVars, 32000+batchSize) + controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{ + Query: controlProfileQuery, BindVars: controlProfileBinds, BatchSize: 10000, Count: true, + Options: arangostore.ProfileOptions{Profile: 2}, + }) + if err != nil { + t.Fatalf("batch size %d control PROFILE: %v", batchSize, err) + } + candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{ + Query: candidateProfileQuery, BindVars: candidateProfileBinds, BatchSize: 10000, Count: true, + Options: arangostore.ProfileOptions{Profile: 2}, + }) + if err != nil { + t.Fatalf("batch size %d candidate PROFILE: %v", batchSize, err) + } + if hashRawRows(controlProfile.Result) != hashRawRows(candidateProfile.Result) { + t.Fatalf("batch size %d PROFILE result parity mismatch", batchSize) + } + controlSummary := arangostore.SummarizeProfile(controlProfile) + candidateSummary := arangostore.SummarizeProfile(candidateProfile) + results = append(results, batchTournamentResult{ + BatchSize: batchSize, ControlSeconds: controlTimes, CandidateSeconds: candidateTimes, + ControlBytes: controlBytes, CandidateBytes: candidateBytes, ControlHash: controlHash, + CandidateHash: candidateHash, ControlProfile: controlSummary, CandidateProfile: candidateSummary, + }) + t.Logf("WP9 batch size=%d control_median=%.6f candidate_median=%.6f control_profile=%+v candidate_profile=%+v bytes=%v/%v", batchSize, median(controlTimes), median(candidateTimes), controlSummary, candidateSummary, controlBytes, candidateBytes) + } + writeBatchTournamentEvidence(t, compiled, candidate, results) +} + +type batchTournamentResult struct { + BatchSize int `json:"batch_size"` + ControlSeconds []float64 `json:"control_seconds"` + CandidateSeconds []float64 `json:"candidate_seconds"` + ControlBytes []int `json:"control_bytes"` + CandidateBytes []int `json:"candidate_bytes"` + ControlHash string `json:"control_result_sha256"` + CandidateHash string `json:"candidate_result_sha256"` + ControlProfile arangostore.ProfileSummary `json:"control_profile"` + CandidateProfile arangostore.ProfileSummary `json:"candidate_profile"` +} + +// batchRootChildSet1Query converts only the Condition relationship to a +// batched endpoint lookup. The existing shared root traversal is still used +// by Specimen and Observation, but Condition nodes are excluded from it so the +// candidate does not pay for the same relationship twice. +func batchRootChildSet1Query(query string) (string, error) { + rootStart := strings.Index(query, "FOR root IN @@root_collection") + sharedStart := strings.Index(query, " LET shared_root_subject_Patient_neighbors =") + child1Start := strings.Index(query, " LET child_set_1 = UNIQUE((") + child2Start := strings.Index(query, " LET child_set_2 = UNIQUE((") + if rootStart < 0 || sharedStart < 0 || child1Start < 0 || child2Start < 0 || !(rootStart < sharedStart && sharedStart < child1Start && child1Start < child2Start) { + return "", fmt.Errorf("production AQL markers for root/child_set_1 not found") + } + rootPrefix := strings.TrimSpace(query[rootStart:sharedStart]) + rootWindow := "LET root_window = (\n" + batchIndent(rootPrefix, 2) + "\n RETURN root\n)\n" + + shared := query[sharedStart:child1Start] + nodeFilter := " FILTER POSITION(@shared_root_subject_Patient_neighbors_target_types, child_set_1_node.resourceType)\n" + if !strings.Contains(shared, nodeFilter) { + return "", fmt.Errorf("shared traversal node type filter not found") + } + shared = strings.Replace(shared, nodeFilter, nodeFilter+" FILTER child_set_1_node.resourceType != @child_set_1_target_type\n", 1) + + child1 := query[child1Start:child2Start] + oldConsumer := "FOR child_set_1_item IN shared_root_subject_Patient_neighbors" + newConsumer := "LET __batch_child_set_1_group = FIRST((\n FOR __batch_group IN batch_child_set_1_grouped\n FILTER __batch_group.root_id == root._id\n RETURN __batch_group\n ))\n LET child_set_1 = UNIQUE((\n FOR child_set_1_item IN (__batch_child_set_1_group ? __batch_child_set_1_group.nodes : [])" + if !strings.Contains(child1, oldConsumer) { + return "", fmt.Errorf("child_set_1 shared consumer not found") + } + child1 = strings.Replace(child1, " LET child_set_1 = UNIQUE((\n FOR "+oldConsumer[len("FOR "):], newConsumer, 1) + // The replacement above intentionally retains the original projection and + // closes; it changes only the input collection and inserts the left join. + if strings.Contains(child1, oldConsumer) { + return "", fmt.Errorf("child_set_1 consumer replacement incomplete") + } + + batch := `LET batch_child_set_1_grouped = ( + FOR __batch_offset IN RANGE(0, LENGTH(root_window), @__loom_batch_size) + FOR edge IN @@child_set_1_edge_collection + FILTER edge._to IN SLICE(root_window[*]._id, __batch_offset, @__loom_batch_size) + FILTER edge.label == @child_set_1_label + FILTER edge.project == @project + FILTER edge.dataset_generation == @dataset_generation + FILTER @auth_resource_paths_unrestricted == true OR edge.auth_resource_path IN @auth_resource_paths + LET node = DOCUMENT(edge._from) + FILTER node != null + FILTER node.resourceType == @child_set_1_target_type + FILTER node.project == @project + FILTER node.dataset_generation == @dataset_generation + FILTER @auth_resource_paths_unrestricted == true OR node.auth_resource_path IN @auth_resource_paths + COLLECT __batch_root_id = edge._to INTO __batch_rows + RETURN {root_id: __batch_root_id, nodes: __batch_rows[*].node} +) +FOR root IN root_window +` + return rootWindow + batch + shared + child1 + query[child2Start:], nil +} + +func batchIndent(value string, spaces int) string { + prefix := strings.Repeat(" ", spaces) + lines := strings.Split(strings.TrimSpace(value), "\n") + for i := range lines { + lines[i] = prefix + lines[i] + } + return strings.Join(lines, "\n") +} + +func writeBatchTournamentEvidence(t *testing.T, compiled dataframe.CompiledQuery, candidate string, results []batchTournamentResult) { + _, source, _, _ := runtime.Caller(0) + directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "wp9") + if err := os.MkdirAll(directory, 0o755); err != nil { + t.Fatalf("create WP9 evidence directory: %v", err) + } + if err := os.WriteFile(filepath.Join(directory, "control.aql"), []byte(compiled.Query+"\n"), 0o644); err != nil { + t.Fatalf("write WP9 control AQL: %v", err) + } + if err := os.WriteFile(filepath.Join(directory, "candidate.aql"), []byte(candidate+"\n"), 0o644); err != nil { + t.Fatalf("write WP9 candidate AQL: %v", err) + } + payload := map[string]any{ + "input": "examples/meta_gdc_case_matrix.variables.json", + "limit": 1000, + "control_aql_sha256": sha256Hex(compiled.Query), + "candidate_aql_sha256": sha256Hex(candidate), + "results": results, + "decision": "pending-live-evidence", + } + data, err := json.MarshalIndent(payload, "", " ") + if err != nil { + t.Fatalf("encode WP9 evidence: %v", err) + } + if err := os.WriteFile(filepath.Join(directory, "evidence.json"), append(data, '\n'), 0o644); err != nil { + t.Fatalf("write WP9 evidence: %v", err) + } +} diff --git a/internal/dataframe/full_identity_tournament_test.go b/internal/dataframe/full_identity_tournament_test.go new file mode 100644 index 0000000..5d7aebb --- /dev/null +++ b/internal/dataframe/full_identity_tournament_test.go @@ -0,0 +1,263 @@ +package dataframe_test + +// WP3 Round 4 is an experiment-only, full-query identity-deduplication +// tournament. It starts with the AQL produced by compileActualGDC (the real +// graphqlapi/dataframe.BuilderFromInput path) and edits only the rendered +// child-set expressions. No production compiler or renderer code is changed. + +import ( + "context" + "encoding/json" + "fmt" + "os" + "path/filepath" + "regexp" + "runtime" + "strings" + "testing" + "time" + + dataframe "github.com/calypr/loom/internal/dataframe" + arangostore "github.com/calypr/loom/internal/store/arango" +) + +type identityDedupReport struct { + Input string `json:"input"` + Limit int `json:"limit"` + ChildSets int `json:"child_sets"` + TransformedSets int `json:"transformed_sets"` + ControlObjectUnique int `json:"control_object_unique"` + CandidateObjectUnique int `json:"candidate_object_unique"` + CandidateIdentityCollects int `json:"candidate_identity_collects"` + ControlAQLSHA256 string `json:"control_aql_sha256"` + CandidateAQLSHA256 string `json:"candidate_aql_sha256"` + ControlResultSHA256 string `json:"control_result_sha256,omitempty"` + CandidateResultSHA256 string `json:"candidate_result_sha256,omitempty"` + ControlRows int `json:"control_rows,omitempty"` + CandidateRows int `json:"candidate_rows,omitempty"` + ControlBytes []int `json:"control_bytes,omitempty"` + CandidateBytes []int `json:"candidate_bytes,omitempty"` + ControlSeconds []float64 `json:"control_seconds,omitempty"` + CandidateSeconds []float64 `json:"candidate_seconds,omitempty"` + ControlProfile any `json:"control_profile,omitempty"` + CandidateProfile any `json:"candidate_profile,omitempty"` + Decision string `json:"decision"` + Blocker string `json:"blocker,omitempty"` +} + +// TestIdentityDedupCandidateBuildsActualGDC proves that the candidate is +// generated from the actual frontend request and keeps all user values bound. +func TestIdentityDedupCandidateBuildsActualGDC(t *testing.T) { + compiled := compileActualGDC(t, 1000) + candidate, report, err := buildIdentityDedupCandidate(compiled.Query) + if err != nil { + t.Fatal(err) + } + if report.ChildSets == 0 || report.TransformedSets == 0 { + t.Fatalf("no child sets transformed: %+v", report) + } + // Shared child sets may remain on the conservative object-shaping path; + // only independently materialized sets are eligible for identity-first + // grouping in this experiment. + if report.TransformedSets > report.ChildSets { + t.Fatalf("candidate transformed more sets than exist: %+v", report) + } + if report.CandidateObjectUnique >= report.ControlObjectUnique { + t.Fatalf("candidate did not remove child-set object UNIQUE wrappers: %+v", report) + } + if report.CandidateIdentityCollects != report.TransformedSets { + t.Fatalf("candidate identity collect count = %d, want eligible transformed set count %d", report.CandidateIdentityCollects, report.TransformedSets) + } + if !strings.Contains(candidate, "COLLECT __loom_identity_key_") { + t.Fatalf("candidate has no identity grouping:\n%s", candidate) + } + if strings.Contains(candidate, "LET child_set_1 = UNIQUE((") { + t.Fatal("candidate retained object-level child_set_1 UNIQUE") + } + if !strings.Contains(candidate, "@@child_set_1_edge_collection") || !strings.Contains(candidate, "@dataset_generation") { + t.Fatal("candidate lost route or scope binds") + } + t.Logf("WP3 identity candidate report: %+v", report) +} + +// TestIdentityDedupProfilesActualGDC is opt-in because it executes the full +// 1,000-row request against the local Arango instance. It alternates control +// and candidate with a bind-backed harmless predicate, consumes every row, +// captures PROFILE/Explain-derived node statistics, and always writes the +// decision artifact when live execution is available. +func TestIdentityDedupProfilesActualGDC(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run WP3 identity tournament") + } + compiled := compileActualGDC(t, 1000) + candidate, report, err := buildIdentityDedupCandidate(compiled.Query) + if err != nil { + t.Fatal(err) + } + url, database, _ := compilerArangoTarget() + client, err := arangostore.Open(context.Background(), url, database) + if err != nil { + t.Fatalf("open Arango: %v", err) + } + defer client.Close(context.Background()) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) + defer cancel() + + controlSeconds := make([]float64, 0, 5) + candidateSeconds := make([]float64, 0, 5) + controlBytes := make([]int, 0, 5) + candidateBytes := make([]int, 0, 5) + var controlHash, candidateHash string + var controlRows, candidateRows int + for run := 0; run < 5; run++ { + controlQuery, controlBinds := cacheBust(compiled.Query, compiled.BindVars, 41000+run) + candidateQuery, candidateBinds := cacheBust(candidate, compiled.BindVars, 42000+run) + seconds, bytes, hash, err := executeOrdinary(ctx, client, controlQuery, controlBinds) + if err != nil { + t.Fatalf("control run %d: %v", run+1, err) + } + controlSeconds = append(controlSeconds, seconds) + controlBytes = append(controlBytes, bytes) + controlHash = hash + if run == 0 { + controlRows = 1000 + } + seconds, bytes, hash, err = executeOrdinary(ctx, client, candidateQuery, candidateBinds) + if err != nil { + t.Fatalf("candidate run %d: %v", run+1, err) + } + candidateSeconds = append(candidateSeconds, seconds) + candidateBytes = append(candidateBytes, bytes) + candidateHash = hash + if run == 0 { + candidateRows = 1000 + } + } + report.ControlResultSHA256 = controlHash + report.CandidateResultSHA256 = candidateHash + report.ControlRows = controlRows + report.CandidateRows = candidateRows + report.ControlBytes = controlBytes + report.CandidateBytes = candidateBytes + report.ControlSeconds = controlSeconds + report.CandidateSeconds = candidateSeconds + + controlProfileQuery, controlProfileBinds := cacheBust(compiled.Query, compiled.BindVars, 43001) + candidateProfileQuery, candidateProfileBinds := cacheBust(candidate, compiled.BindVars, 43002) + controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: controlProfileQuery, BindVars: controlProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + t.Fatalf("control PROFILE: %v", err) + } + candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidateProfileQuery, BindVars: candidateProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + t.Fatalf("candidate PROFILE: %v", err) + } + controlSummary := arangostore.SummarizeProfile(controlProfile) + candidateSummary := arangostore.SummarizeProfile(candidateProfile) + report.ControlProfile = controlSummary + report.CandidateProfile = candidateSummary + report.ControlAQLSHA256 = sha256Hex(compiled.Query) + report.CandidateAQLSHA256 = sha256Hex(candidate) + if controlHash != candidateHash || hashRawRows(controlProfile.Result) != hashRawRows(candidateProfile.Result) { + report.Decision = "reject-parity" + writeIdentityEvidence(t, compiled, candidate, report) + t.Fatalf("identity candidate result parity mismatch control=%s candidate=%s", controlHash, candidateHash) + } + controlMedian := median(controlSeconds) + candidateMedian := median(candidateSeconds) + if candidateMedian < controlMedian*0.90 { + report.Decision = "pass-10-percent-gate" + } else { + report.Decision = "reject-under-10-percent-gate" + } + writeIdentityEvidence(t, compiled, candidate, report) + t.Logf("WP3 identity tournament control_median=%.6fs candidate_median=%.6fs control_profile=%+v candidate_profile=%+v report=%+v", controlMedian, candidateMedian, controlSummary, candidateSummary, report) +} + +// buildIdentityDedupCandidate inserts identity grouping before the existing +// child projection. It intentionally retains the original scope filters and +// sorts, then sorts the deduplicated node stream again because COLLECT does +// not provide a documented order guarantee. The outer object projection is +// unchanged except that it reads the grouped node variable. +func buildIdentityDedupCandidate(control string) (string, identityDedupReport, error) { + report := identityDedupReport{ + Input: "examples/meta_gdc_case_matrix.variables.json", + Limit: 1000, + ControlObjectUnique: strings.Count(control, "UNIQUE(("), + } + startRE := regexp.MustCompile(`(?m)^ LET (child_set_[0-9]+) = UNIQUE\(\(\n`) + matches := startRE.FindAllStringSubmatchIndex(control, -1) + if len(matches) == 0 { + return "", report, fmt.Errorf("no typed child-set materializations in actual production AQL") + } + report.ChildSets = len(matches) + candidate := control + for index := len(matches) - 1; index >= 0; index-- { + match := matches[index] + name := control[match[2]:match[3]] + start := match[0] + bodyStart := match[1] + closeRel := strings.Index(control[bodyStart:], "\n ))") + if closeRel < 0 { + return "", report, fmt.Errorf("child set %s has no closing wrapper", name) + } + closeStart := bodyStart + closeRel + closeEnd := closeStart + len("\n ))") + block := control[start:closeEnd] + loopRE := regexp.MustCompile(`(?m)^ FOR ([A-Za-z0-9_]+) IN `) + loop := loopRE.FindStringSubmatch(block) + if len(loop) != 2 { + return "", report, fmt.Errorf("child set %s has no source loop", name) + } + loopVar := loop[1] + returnAt := strings.Index(block, "\n RETURN ") + if returnAt < 0 { + return "", report, fmt.Errorf("child set %s has no projection return", name) + } + identityKey := fmt.Sprintf("__loom_identity_key_%d", index) + identityRows := fmt.Sprintf("__loom_identity_rows_%d", index) + identityItem := fmt.Sprintf("__loom_identity_item_%d", index) + insert := fmt.Sprintf("\n COLLECT %s = %s._id INTO %s\n LET %s = FIRST(%s).%s\n SORT %s._key", identityKey, loopVar, identityRows, identityItem, identityRows, loopVar, identityItem) + block = block[:returnAt] + insert + block[returnAt:] + projectionStart := strings.Index(block, "\n RETURN ") + len("\n RETURN ") + projectionEnd := strings.LastIndex(block, "\n ))") + if projectionEnd < 0 { + return "", report, fmt.Errorf("child set %s projection boundary not found", name) + } + projection := strings.ReplaceAll(block[projectionStart:projectionEnd], loopVar+".", identityItem+".") + block = block[:projectionStart] + projection + block[projectionEnd:] + block = strings.Replace(block, " = UNIQUE((\n", " = (\n", 1) + block = strings.Replace(block, "\n ))", "\n )", 1) + candidate = candidate[:start] + block + candidate[closeEnd:] + report.TransformedSets++ + } + report.CandidateObjectUnique = strings.Count(candidate, "UNIQUE((") + report.CandidateIdentityCollects = strings.Count(candidate, "COLLECT __loom_identity_key_") + // Count the materialized identity groups that survived the textual rewrite; + // shared/nested blocks may be conservatively left unchanged. + report.TransformedSets = report.CandidateIdentityCollects + report.ControlAQLSHA256 = sha256Hex(control) + report.CandidateAQLSHA256 = sha256Hex(candidate) + return candidate, report, nil +} + +func writeIdentityEvidence(t *testing.T, compiled dataframe.CompiledQuery, candidate string, report identityDedupReport) { + _, source, _, _ := runtime.Caller(0) + directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "wp3") + if err := os.MkdirAll(directory, 0o755); err != nil { + t.Fatalf("create WP3 evidence directory: %v", err) + } + if err := os.WriteFile(filepath.Join(directory, "control.aql"), []byte(compiled.Query+"\n"), 0o644); err != nil { + t.Fatalf("write WP3 control AQL: %v", err) + } + if err := os.WriteFile(filepath.Join(directory, "candidate.aql"), []byte(candidate+"\n"), 0o644); err != nil { + t.Fatalf("write WP3 candidate AQL: %v", err) + } + data, err := json.MarshalIndent(report, "", " ") + if err != nil { + t.Fatalf("encode WP3 evidence: %v", err) + } + if err := os.WriteFile(filepath.Join(directory, "evidence.json"), append(data, '\n'), 0o644); err != nil { + t.Fatalf("write WP3 evidence: %v", err) + } +} diff --git a/internal/dataframe/generic_physical_plan.go b/internal/dataframe/generic_physical_plan.go index c92e483..0c6887b 100644 --- a/internal/dataframe/generic_physical_plan.go +++ b/internal/dataframe/generic_physical_plan.go @@ -11,6 +11,13 @@ import ( // BuildGenericPhysicalPlan lowers generic navigation plus root and optional // child selections into the typed physical IR. func BuildGenericPhysicalPlan(semantic SemanticPlan) (PhysicalPlan, error) { + return BuildGenericPhysicalPlanWithPolicy(semantic, DefaultPhysicalOptimizationPolicy()) +} + +// BuildGenericPhysicalPlanWithPolicy threads an explicit optimizer policy +// through physical construction so prepared-selector ablations happen before +// references to prepared variables are attached to projections. +func BuildGenericPhysicalPlanWithPolicy(semantic SemanticPlan, policy PhysicalOptimizationPolicy) (PhysicalPlan, error) { if strings.TrimSpace(semantic.Project) == "" { return PhysicalPlan{}, fmt.Errorf("semantic plan project is required") } @@ -73,7 +80,7 @@ func BuildGenericPhysicalPlan(semantic SemanticPlan) (PhysicalPlan, error) { if projectionPrefix != "" { childProjectionPrefix = projectionPrefix + "__" + child.Alias } - set, projections, err := buildOptionalChildPhysicalSet(&physical, childSetIndex, parent, parentVariable, child, childProjectionPrefix) + set, projections, err := buildOptionalChildPhysicalSet(&physical, childSetIndex, parent, parentVariable, child, childProjectionPrefix, policy) if err != nil { return err } @@ -104,10 +111,11 @@ func BuildGenericPhysicalPlan(semantic SemanticPlan) (PhysicalPlan, error) { physical.BindVars[labelBind] = child.EdgeLabel physical.BindVars[typeBind] = child.ResourceType physical.BindVars[edgeCollectionBind] = "fhir_edge" + strategy, endpointField, endpointJoinField, endpointIndexFields := physicalTraversalStrategyForRoute(policy, parentVariable, route) physical.Operations = append(physical.Operations, PhysicalOperation{Kind: PhysicalTraversalOp, Source: PhysicalSource{SemanticNode: child.Alias, ResourceType: child.ResourceType, Relationship: child.EdgeLabel}, Traversal: &PhysicalTraversal{SourceVariable: parentVariable, TargetVariable: nodeVariable, EdgeVariable: edgeVariable, Direction: route.Direction, - EdgeCollectionBindKey: edgeCollectionBind, EdgeLabelBindKey: labelBind, TargetTypeBindKey: typeBind, EdgeTargetTypeField: route.targetEdgeTypeField()}}) + EdgeCollectionBindKey: edgeCollectionBind, EdgeLabelBindKey: labelBind, TargetTypeBindKey: typeBind, EdgeTargetTypeField: route.targetEdgeTypeField(), Strategy: strategy, EndpointField: endpointField, EndpointJoinField: endpointJoinField, EndpointIndexFields: endpointIndexFields}}) physical.Operations = appendProjectScope(physical.Operations, []string{edgeVariable, nodeVariable}, child.EdgeLabel, child) physical.Operations = appendDatasetGenerationScope(physical.Operations, []string{edgeVariable, nodeVariable}, child.EdgeLabel, child) physical.Operations = appendAuthScope(physical.Operations, []PhysicalValue{{Variable: edgeVariable, Path: []string{"auth_resource_path"}}, {Variable: nodeVariable, Path: []string{"auth_resource_path"}}}, fmt.Sprintf("traversal_%d_scope_allowed", traversalIndex), child) @@ -124,7 +132,7 @@ func BuildGenericPhysicalPlan(semantic SemanticPlan) (PhysicalPlan, error) { if projectionPrefix != "" { childProjectionPrefix = projectionPrefix + "__" + child.Alias } - set, projections, err := buildOptionalChildPhysicalSet(&physical, childSetIndex, parent, parentVariable, child, childProjectionPrefix) + set, projections, err := buildOptionalChildPhysicalSet(&physical, childSetIndex, parent, parentVariable, child, childProjectionPrefix, policy) if err != nil { return err } @@ -253,7 +261,7 @@ func rootPhysicalProjections(physical *PhysicalPlan, root SemanticNode) ([]Physi } expression := PhysicalExpression{ Kind: PhysicalExtractExpression, Cardinality: cardinality, NullBehavior: PhysicalPreserveNull, - Extract: &PhysicalExtract{Source: PhysicalValue{Variable: "root", Path: []string{"payload"}}, ResourceType: root.ResourceType, Selector: field.Selector, Fallbacks: append([]Selector(nil), field.Fallbacks...), Distinct: distinct}, + Extract: &PhysicalExtract{Source: PhysicalValue{Variable: "root", Path: []string{"payload"}}, ResourceType: root.ResourceType, Selector: field.Selector, Fallbacks: append([]Selector(nil), field.Fallbacks...), Distinct: distinct, ExecutionMode: selectorExecutionMode(root.ResourceType, field.Selector, field.Fallbacks...)}, } if cardinality == PhysicalArrayCardinality { expression.NullBehavior = PhysicalEmptyOnNull @@ -318,7 +326,7 @@ func physicalAggregateExpression(physical *PhysicalPlan, resourceType string, so valueSource = PhysicalValue{Variable: source.Variable, Path: []string{"payload"}} } value := PhysicalExpression{Kind: PhysicalExtractExpression, Cardinality: PhysicalArrayCardinality, NullBehavior: PhysicalEmptyOnNull, - Extract: &PhysicalExtract{Source: valueSource, ResourceType: resourceType, Selector: *aggregate.Selector}} + Extract: &PhysicalExtract{Source: valueSource, ResourceType: resourceType, Selector: *aggregate.Selector, ExecutionMode: selectorExecutionMode(resourceType, *aggregate.Selector)}} aggregatePhysical.Value = &value } if aggregate.Predicate != nil { @@ -327,7 +335,7 @@ func physicalAggregateExpression(physical *PhysicalPlan, resourceType string, so leftSource = PhysicalValue{Variable: source.Variable, Path: []string{"payload"}} } left := PhysicalExpression{Kind: PhysicalExtractExpression, Cardinality: PhysicalArrayCardinality, NullBehavior: PhysicalEmptyOnNull, - Extract: &PhysicalExtract{Source: leftSource, ResourceType: resourceType, Selector: *aggregate.Predicate}} + Extract: &PhysicalExtract{Source: leftSource, ResourceType: resourceType, Selector: *aggregate.Predicate, ExecutionMode: selectorExecutionMode(resourceType, *aggregate.Predicate)}} comparison := &PhysicalPredicate{Operator: "EXISTS", LeftExpression: &left} if aggregate.PredicateEquals != "" { comparison.Operator = "EQUALS" @@ -369,7 +377,7 @@ func physicalSliceExpression(physical *PhysicalPlan, resourceType string, source } if slice.Predicate != nil { left := PhysicalExpression{Kind: PhysicalExtractExpression, Cardinality: PhysicalArrayCardinality, NullBehavior: PhysicalEmptyOnNull, - Extract: &PhysicalExtract{Source: leftSource, ResourceType: resourceType, Selector: *slice.Predicate}} + Extract: &PhysicalExtract{Source: leftSource, ResourceType: resourceType, Selector: *slice.Predicate, ExecutionMode: selectorExecutionMode(resourceType, *slice.Predicate)}} comparison := &PhysicalPredicate{Operator: "EXISTS", LeftExpression: &left} if slice.PredicateEquals != "" { key := "slice_" + sanitizeColumnName(source.Variable) + "_" + sanitizeColumnName(slice.Name) + "_predicate_equals" @@ -388,7 +396,7 @@ func physicalSliceExpression(physical *PhysicalPlan, resourceType string, source physicalSlice.Projections = append(physicalSlice.Projections, PhysicalExpressionProjection{ Name: selection.Name, Expression: PhysicalExpression{Kind: PhysicalExtractExpression, Cardinality: PhysicalScalarCardinality, NullBehavior: PhysicalPreserveNull, - Extract: &PhysicalExtract{Source: leftSource, ResourceType: resourceType, Selector: selection.Selector, Fallbacks: append([]Selector(nil), selection.Fallbacks...)}}, + Extract: &PhysicalExtract{Source: leftSource, ResourceType: resourceType, Selector: selection.Selector, Fallbacks: append([]Selector(nil), selection.Fallbacks...), ExecutionMode: selectorExecutionMode(resourceType, selection.Selector, selection.Fallbacks...)}}, }) } return PhysicalExpression{Kind: PhysicalSliceExpression, Cardinality: PhysicalArrayCardinality, NullBehavior: PhysicalEmptyOnNull, Slice: &physicalSlice}, nil @@ -406,7 +414,7 @@ func appendRootPhysicalFilters(physical *PhysicalPlan, root SemanticNode) error predicate := PhysicalPredicate{ Operator: string(filter.Operator), Quantifier: filter.Quantifier, ValueKind: filter.FieldKind, LeftExpression: &PhysicalExpression{Kind: PhysicalExtractExpression, Cardinality: PhysicalArrayCardinality, NullBehavior: PhysicalEmptyOnNull, - Extract: &PhysicalExtract{Source: PhysicalValue{Variable: "root", Path: []string{"payload"}}, ResourceType: root.ResourceType, Selector: selector}}, + Extract: &PhysicalExtract{Source: PhysicalValue{Variable: "root", Path: []string{"payload"}}, ResourceType: root.ResourceType, Selector: selector, ExecutionMode: selectorExecutionMode(root.ResourceType, selector)}}, } if filter.Operator != FilterExists && filter.Operator != FilterMissing { key := fmt.Sprintf("root_filter_%d_value", index+1) @@ -440,7 +448,7 @@ func appendRootPhysicalFilters(physical *PhysicalPlan, root SemanticNode) error // The set retains resource documents (rather than pre-shaped maps), allowing // the renderer to apply each child selector against the document payload at // the outer return while preserving root row grain. -func buildOptionalChildPhysicalSet(physical *PhysicalPlan, setIndex int, parent SemanticNode, parentVariable string, child SemanticNode, projectionPrefix string) (PhysicalSet, []PhysicalProjection, error) { +func buildOptionalChildPhysicalSet(physical *PhysicalPlan, setIndex int, parent SemanticNode, parentVariable string, child SemanticNode, projectionPrefix string, policy PhysicalOptimizationPolicy) (PhysicalSet, []PhysicalProjection, error) { route, err := resolveStorageRoute(parent.ResourceType, child.EdgeLabel, child.ResourceType) if err != nil { return PhysicalSet{}, nil, err @@ -454,10 +462,11 @@ func buildOptionalChildPhysicalSet(physical *PhysicalPlan, setIndex int, parent physical.BindVars[edgeCollectionBind] = "fhir_edge" targetVariable := fmt.Sprintf("%s_node", prefix) edgeVariable := fmt.Sprintf("%s_edge", prefix) + strategy, endpointField, endpointJoinField, endpointIndexFields := physicalTraversalStrategyForRoute(policy, parentVariable, route) source := PhysicalSource{SemanticNode: child.Alias, ResourceType: child.ResourceType, Relationship: child.EdgeLabel} subplan := PhysicalSubplan{Captures: []string{parentVariable}, Operations: []PhysicalOperation{{ Kind: PhysicalTraversalOp, Source: source, - Traversal: &PhysicalTraversal{SourceVariable: parentVariable, TargetVariable: targetVariable, EdgeVariable: edgeVariable, Direction: route.Direction, EdgeCollectionBindKey: edgeCollectionBind, EdgeLabelBindKey: labelBind, TargetTypeBindKey: typeBind, EdgeTargetTypeField: route.targetEdgeTypeField()}, + Traversal: &PhysicalTraversal{SourceVariable: parentVariable, TargetVariable: targetVariable, EdgeVariable: edgeVariable, Direction: route.Direction, EdgeCollectionBindKey: edgeCollectionBind, EdgeLabelBindKey: labelBind, TargetTypeBindKey: typeBind, EdgeTargetTypeField: route.targetEdgeTypeField(), Strategy: strategy, EndpointField: endpointField, EndpointJoinField: endpointJoinField, EndpointIndexFields: endpointIndexFields}, }}} subplan.Operations = appendProjectScope(subplan.Operations, []string{edgeVariable, targetVariable}, child.EdgeLabel, child) subplan.Operations = appendDatasetGenerationScope(subplan.Operations, []string{edgeVariable, targetVariable}, child.EdgeLabel, child) @@ -470,7 +479,7 @@ func buildOptionalChildPhysicalSet(physical *PhysicalPlan, setIndex int, parent if err != nil { return PhysicalSet{}, nil, fmt.Errorf("child filter %q selector: %w", filter.FieldRef, err) } - predicate := PhysicalPredicate{Operator: string(filter.Operator), Quantifier: filter.Quantifier, ValueKind: filter.FieldKind, LeftExpression: &PhysicalExpression{Kind: PhysicalExtractExpression, Cardinality: PhysicalArrayCardinality, NullBehavior: PhysicalEmptyOnNull, Extract: &PhysicalExtract{Source: PhysicalValue{Variable: targetVariable, Path: []string{"payload"}}, ResourceType: child.ResourceType, Selector: selector}}} + predicate := PhysicalPredicate{Operator: string(filter.Operator), Quantifier: filter.Quantifier, ValueKind: filter.FieldKind, LeftExpression: &PhysicalExpression{Kind: PhysicalExtractExpression, Cardinality: PhysicalArrayCardinality, NullBehavior: PhysicalEmptyOnNull, Extract: &PhysicalExtract{Source: PhysicalValue{Variable: targetVariable, Path: []string{"payload"}}, ResourceType: child.ResourceType, Selector: selector, ExecutionMode: selectorExecutionMode(child.ResourceType, selector)}}} if filter.Operator != FilterExists && filter.Operator != FilterMissing { key := fmt.Sprintf("%s_filter_%d_value", prefix, index+1) if filter.Operator == FilterIn { @@ -498,14 +507,18 @@ func buildOptionalChildPhysicalSet(physical *PhysicalPlan, setIndex int, parent subplan.Operations = append(subplan.Operations, PhysicalOperation{Kind: PhysicalFilterOp, Source: PhysicalSource{SemanticNode: child.Alias, ResourceType: child.ResourceType, SemanticField: filter.FieldRef}, Filter: &PhysicalFilter{Expression: &PhysicalPredicateExpression{Kind: PhysicalComparisonPredicate, Comparison: &predicate}}}) } subplan.Return = PhysicalExpression{Kind: PhysicalValueExpression, Cardinality: PhysicalObjectCardinality, NullBehavior: PhysicalPreserveNull, Value: &PhysicalValue{Variable: targetVariable}} - set := PhysicalSet{Variable: prefix, Subplan: subplan, Unique: true, SortByKey: true} + var output *PhysicalSetOutput + if policy.RuleEnabled(PhysicalOptimizationRuleCompactProjection) { + output = compactPhysicalSetOutput(child) + } + set := PhysicalSet{Variable: prefix, Subplan: subplan, Unique: true, SortByKey: true, Output: output} projections := make([]PhysicalProjection, 0, len(child.Fields)) for index, field := range child.Fields { selection, err := ResolveSemanticField(child.ResourceType, child.Alias, index, field) if err != nil { return PhysicalSet{}, nil, err } - projections = append(projections, PhysicalProjection{Name: projectionPrefix + "__" + field.Name, Expression: &PhysicalExpression{Kind: PhysicalExtractExpression, Cardinality: PhysicalArrayCardinality, NullBehavior: PhysicalEmptyOnNull, Extract: &PhysicalExtract{Source: PhysicalValue{Variable: set.Variable}, ResourceType: child.ResourceType, Selector: selection.Selector, Fallbacks: append([]Selector(nil), selection.Fallbacks...), Distinct: selection.Projection == ProjectionDistinctArray}}}) + projections = append(projections, PhysicalProjection{Name: projectionPrefix + "__" + field.Name, Expression: &PhysicalExpression{Kind: PhysicalExtractExpression, Cardinality: PhysicalArrayCardinality, NullBehavior: PhysicalEmptyOnNull, Extract: &PhysicalExtract{Source: PhysicalValue{Variable: set.Variable}, ResourceType: child.ResourceType, Selector: selection.Selector, Fallbacks: append([]Selector(nil), selection.Fallbacks...), Distinct: selection.Projection == ProjectionDistinctArray, ExecutionMode: selectorExecutionMode(child.ResourceType, selection.Selector, selection.Fallbacks...)}}}) } for _, aggregate := range child.Aggregates { expression, err := physicalAggregateExpression(physical, child.ResourceType, PhysicalValue{Variable: set.Variable}, aggregate, true) @@ -528,15 +541,71 @@ func buildOptionalChildPhysicalSet(physical *PhysicalPlan, setIndex int, parent } projections = append(projections, PhysicalProjection{Name: projectionPrefix + "__" + slice.Name, Expression: &expression}) } - prepareRichChildSet(&set, child.ResourceType, projections) + // A traversal-time projection is the production form of selector reuse. It + // computes selector arrays in the original child subquery and removes the + // payload before materialization. The older prepared-set pass is retained + // only for explicit experiments and is never layered on top of this shape. + if policy.RuleEnabled(PhysicalOptimizationRuleCompactProjection) { + projectPhysicalChildSet(&set, child.ResourceType, projections) + } + if set.Projection == nil { + prepareRichChildSet(&set, child.ResourceType, projections, policy) + } return set, projections, nil } +func physicalTraversalStrategyForRoute(policy PhysicalOptimizationPolicy, parentVariable string, route storageRoute) (PhysicalTraversalStrategy, string, string, []string) { + // Endpoint equality is eligible for every validated depth-one route, + // including a root sibling group. When sibling sets are shared, the + // optimizer preserves this typed endpoint contract on the broad set and + // replaces the target-type predicate with a bind-backed list. If route + // metadata cannot provide the complete endpoint/index contract, native + // traversal remains the safe fallback. + if !policy.RuleEnabled(PhysicalOptimizationRuleEndpointTraversal) { + return PhysicalTraversalNative, "", "", nil + } + if parentField, joinField, fields, ok := route.endpointLookupFields(); ok && len(fields) > 0 { + return PhysicalTraversalEndpointLookup, parentField, joinField, append([]string(nil), fields...) + } + return PhysicalTraversalNative, "", "", nil +} + +// compactPhysicalSetOutput retains graph identity and only the payload needed +// by downstream selectors/rich consumers. Scope predicates run before this +// projection, so project, generation, and authorization metadata do not need +// to remain in the post-window set. Nested traversal still receives _id, and +// UNIQUE/SORT retain both identity keys to preserve duplicate and ordering +// semantics. +func compactPhysicalSetOutput(node SemanticNode) *PhysicalSetOutput { + fields := []PhysicalSetOutputField{ + PhysicalSetGraphIDField, + PhysicalSetKeyField, + PhysicalSetIDField, + PhysicalSetResourceTypeField, + } + needsPayload := len(node.Fields) > 0 || len(node.Pivots) > 0 || len(node.Slices) > 0 + if !needsPayload { + for _, aggregate := range node.Aggregates { + if aggregate.Selector != nil || aggregate.Predicate != nil { + needsPayload = true + break + } + } + } + if needsPayload { + fields = append(fields, PhysicalSetPayloadField) + } + return &PhysicalSetOutput{Fields: fields} +} + // prepareRichChildSet adds a generic selector cache when at least two rich // consumers read the same child relationship set. The cache is deliberately // selector-based (not FHIR-resource-specific): any generated resource type // with repeated aggregate, pivot, or slice selectors can use it. -func prepareRichChildSet(set *PhysicalSet, resourceType string, projections []PhysicalProjection) { +func prepareRichChildSet(set *PhysicalSet, resourceType string, projections []PhysicalProjection, policy PhysicalOptimizationPolicy) { + if !policy.RuleEnabled(PhysicalOptimizationRulePreparedSelectors) { + return + } counts := map[string]int{} selectors := map[string]Selector{} add := func(selector Selector) { @@ -674,6 +743,126 @@ func prepareRichChildSet(set *PhysicalSet, resourceType string, projections []Ph } } +// projectPhysicalChildSet attaches selector values to the original set item +// rather than creating a second prepared array. A fallback selector is an +// ordered multi-source contract that cannot be represented by one projected +// field, so the entire set conservatively retains its existing payload output. +func projectPhysicalChildSet(set *PhysicalSet, resourceType string, projections []PhysicalProjection) { + if set == nil || len(projections) == 0 { + return + } + selectors := map[string]Selector{} + fallback := false + var collect func(*PhysicalExpression) + collect = func(expression *PhysicalExpression) { + if expression == nil { + return + } + switch expression.Kind { + case PhysicalExtractExpression: + if expression.Extract == nil || expression.Extract.Source.Variable != set.Variable { + return + } + if len(expression.Extract.Fallbacks) != 0 { + fallback = true + return + } + selectors[physicalSelectorIdentity(expression.Extract.Selector)] = expression.Extract.Selector + case PhysicalAggregateExpression: + if expression.Aggregate != nil { + collect(expression.Aggregate.Value) + if expression.Aggregate.Predicate != nil && expression.Aggregate.Predicate.Comparison != nil { + collect(expression.Aggregate.Predicate.Comparison.LeftExpression) + } + } + case PhysicalPivotExpression: + if expression.Pivot != nil && expression.Pivot.Source.Variable == set.Variable { + selectors[physicalSelectorIdentity(expression.Pivot.KeySelector)] = expression.Pivot.KeySelector + selectors[physicalSelectorIdentity(expression.Pivot.ValueSelector)] = expression.Pivot.ValueSelector + } + case PhysicalSliceExpression: + if expression.Slice != nil { + if expression.Slice.Predicate != nil && expression.Slice.Predicate.Comparison != nil { + collect(expression.Slice.Predicate.Comparison.LeftExpression) + } + for index := range expression.Slice.Projections { + collect(&expression.Slice.Projections[index].Expression) + } + } + case PhysicalObjectExpression: + if expression.Object != nil { + for index := range expression.Object.Fields { + collect(&expression.Object.Fields[index].Expression) + } + } + } + } + for index := range projections { + collect(projections[index].Expression) + } + if fallback || len(selectors) == 0 { + return + } + keys := make([]string, 0, len(selectors)) + for key := range selectors { + keys = append(keys, key) + } + sort.Strings(keys) + fields := make([]PhysicalSetProjectionField, 0, len(keys)) + fieldBySelector := make(map[string]string, len(keys)) + for index, key := range keys { + name := fmt.Sprintf("__loom_projection_%d", index) + fields = append(fields, PhysicalSetProjectionField{Name: name, ResourceType: resourceType, Selector: selectors[key], ExecutionMode: selectorExecutionMode(resourceType, selectors[key])}) + fieldBySelector[key] = name + } + var rewrite func(*PhysicalExpression) + rewrite = func(expression *PhysicalExpression) { + if expression == nil { + return + } + switch expression.Kind { + case PhysicalExtractExpression: + if expression.Extract != nil && expression.Extract.Source.Variable == set.Variable && len(expression.Extract.Fallbacks) == 0 { + if field := fieldBySelector[physicalSelectorIdentity(expression.Extract.Selector)]; field != "" { + expression.Extract.Prepared = &PhysicalPreparedReference{SetVariable: set.Variable, Field: field} + } + } + case PhysicalAggregateExpression: + if expression.Aggregate != nil { + rewrite(expression.Aggregate.Value) + if expression.Aggregate.Predicate != nil && expression.Aggregate.Predicate.Comparison != nil { + rewrite(expression.Aggregate.Predicate.Comparison.LeftExpression) + } + } + case PhysicalPivotExpression: + if expression.Pivot != nil && expression.Pivot.Source.Variable == set.Variable { + expression.Pivot.PreparedKey = &PhysicalPreparedReference{SetVariable: set.Variable, Field: fieldBySelector[physicalSelectorIdentity(expression.Pivot.KeySelector)]} + expression.Pivot.PreparedValue = &PhysicalPreparedReference{SetVariable: set.Variable, Field: fieldBySelector[physicalSelectorIdentity(expression.Pivot.ValueSelector)]} + } + case PhysicalSliceExpression: + if expression.Slice != nil { + if expression.Slice.Predicate != nil && expression.Slice.Predicate.Comparison != nil { + rewrite(expression.Slice.Predicate.Comparison.LeftExpression) + } + for index := range expression.Slice.Projections { + rewrite(&expression.Slice.Projections[index].Expression) + } + } + case PhysicalObjectExpression: + if expression.Object != nil { + for index := range expression.Object.Fields { + rewrite(&expression.Object.Fields[index].Expression) + } + } + } + } + for index := range projections { + rewrite(projections[index].Expression) + } + set.Projection = &PhysicalSetProjection{Fields: fields} + set.Output = nil +} + func physicalSelectorIdentity(selector Selector) string { var b strings.Builder for _, step := range selector.Steps { diff --git a/internal/dataframe/generic_physical_plan_test.go b/internal/dataframe/generic_physical_plan_test.go index 35603b7..dfde90a 100644 --- a/internal/dataframe/generic_physical_plan_test.go +++ b/internal/dataframe/generic_physical_plan_test.go @@ -95,7 +95,7 @@ func TestBuildAndRenderGenericPhysicalPlanOptionalChildFieldsAndFilters(t *testi if err != nil { t.Fatal(err) } - if !strings.Contains(rendered.Query, "LET child_set_1 = UNIQUE") || !strings.Contains(rendered.Query, "@child_set_1_filter_1_value") || !strings.Contains(rendered.Query, "FOR __item IN child_set_1") { + if !strings.Contains(rendered.Query, "LET child_set_1 = UNIQUE") || !strings.Contains(rendered.Query, "@child_set_1_filter_1_value") || !strings.Contains(rendered.Query, "__loom_projection_0") { t.Fatalf("optional child fields/filter were not rendered:\n%s", rendered.Query) } if rendered.BindVars["child_set_1_filter_1_value"] != wantID { @@ -130,13 +130,16 @@ func TestBuildAndRenderGenericPhysicalPlanNestedOptionalFieldsAndAggregates(t *t t.Fatal(err) } for _, want := range []string{ - "LET child_set_1 = UNIQUE((", "FOR child_set_2_node, child_set_2_edge IN 1..1 INBOUND __loom_physical_parent_set_2 @@child_set_2_edge_collection", - "@child_set_2_filter_1_value", "LENGTH(child_set_2)", "FOR __item IN child_set_2", + "LET child_set_1 = UNIQUE((", + "@child_set_2_filter_1_value", "LENGTH(child_set_2)", "FOR __loom_prepared_value IN child_set_2", } { if !strings.Contains(rendered.Query, want) { t.Fatalf("nested physical query missing %q:\n%s", want, rendered.Query) } } + if !strings.Contains(rendered.Query, "FOR child_set_2_node, child_set_2_edge IN 1..1 INBOUND __loom_physical_parent_set_2 @@child_set_2_edge_collection") && !strings.Contains(rendered.Query, "FOR child_set_2_edge IN @@child_set_2_edge_collection") { + t.Fatalf("nested physical query lost both native and endpoint traversal forms:\n%s", rendered.Query) + } foundNestedName := false for key, value := range rendered.BindVars { if strings.HasPrefix(key, "__loom_physical_projection_") && value == "specimen__file__id" { @@ -250,7 +253,8 @@ func TestBuildAndRenderGenericPhysicalPlanAggregatePredicates(t *testing.T) { func TestBuildGenericPhysicalPlanPreparesSelectorsAcrossRichConsumers(t *testing.T) { status := Selector{Steps: []SelectorStep{{Field: "id"}}} - plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + policy := DefaultPhysicalOptimizationPolicy().WithRule(PhysicalOptimizationRuleCompactProjection, false).WithRule(PhysicalOptimizationRulePreparedSelectors, true) + plan, err := BuildGenericPhysicalPlanWithPolicy(SemanticPlan{ Version: 1, Project: "p", Root: SemanticNode{ Alias: "root", ResourceType: "Patient", Children: []SemanticNode{{ @@ -260,7 +264,7 @@ func TestBuildGenericPhysicalPlanPreparesSelectorsAcrossRichConsumers(t *testing Slices: []SemanticSlice{{Name: "representative", Limit: 1, Fields: []SemanticField{{Name: "status", Selector: status}}}}, }}, }, - }) + }, policy) if err != nil { t.Fatal(err) } @@ -335,7 +339,8 @@ func TestBuildGenericPhysicalPlanPreparesSelectorsAcrossRichConsumers(t *testing func TestPreparedSelectorsPreserveFallbackExtraction(t *testing.T) { primary := Selector{Steps: []SelectorStep{{Field: "id"}}} fallback := Selector{Steps: []SelectorStep{{Field: "code"}}} - plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + policy := DefaultPhysicalOptimizationPolicy().WithRule(PhysicalOptimizationRulePreparedSelectors, true) + plan, err := BuildGenericPhysicalPlanWithPolicy(SemanticPlan{ Version: 1, Project: "p", Root: SemanticNode{ Alias: "root", ResourceType: "Patient", Children: []SemanticNode{{ @@ -344,7 +349,7 @@ func TestPreparedSelectorsPreserveFallbackExtraction(t *testing.T) { Aggregates: []SemanticAggregate{{Name: "status_count", Operation: "COUNT_DISTINCT", Selector: &primary}}, }}, }, - }) + }, policy) if err != nil { t.Fatal(err) } diff --git a/internal/dataframe/identity_order_experiment_test.go b/internal/dataframe/identity_order_experiment_test.go new file mode 100644 index 0000000..c3ec5d0 --- /dev/null +++ b/internal/dataframe/identity_order_experiment_test.go @@ -0,0 +1,308 @@ +package dataframe + +import ( + "crypto/sha256" + "encoding/hex" + "fmt" + "os" + "path/filepath" + "regexp" + "runtime" + "strings" + "testing" +) + +// WP6 is intentionally an experiment-only proof packet. These helpers model +// physical properties without changing the production IR. Unknown is always +// the safe answer; a coordinator may promote a rule only after the same proof +// is represented by typed production properties and its live profile passes. +type wp6Properties struct { + identityUnique bool + order []string + retained map[string]bool +} + +func wp6UnknownProperties() wp6Properties { + return wp6Properties{retained: map[string]bool{}} +} + +func wp6TransferProperties(in wp6Properties, operation string, keys ...string) wp6Properties { + out := wp6UnknownProperties() + switch operation { + case "filter": + // Filtering removes rows but does not reorder or duplicate them. + out.identityUnique = in.identityUnique + out.order = append([]string(nil), in.order...) + out.retained = cloneWP6Set(in.retained) + case "projection": + // Identity and order survive only when their proof keys remain in the + // projected item. A payload-only projection cannot inherit either. + out.identityUnique = in.identityUnique && in.retained["_id"] && in.retained["_key"] && containsWP6(keys, "_id") && containsWP6(keys, "_key") + for _, key := range in.order { + if !containsWP6(keys, key) { + out.order = nil + break + } + out.order = append(out.order, key) + } + for _, key := range keys { + out.retained[key] = true + } + case "identity_dedup": + // Arango UNIQUE does not provide a compiler contract that its output + // order is stable. Dedup proves identity uniqueness, but invalidates + // order until a physical SORT establishes it again. + out.identityUnique = true + out.retained = cloneWP6Set(in.retained) + case "sort": + out.identityUnique = in.identityUnique + out.order = append([]string(nil), keys...) + out.retained = cloneWP6Set(in.retained) + case "traversal": + // A traversal may repeat a node through duplicate edges; a union/group + // can reorder or multiply rows. No property transfers implicitly. + out = wp6UnknownProperties() + // The target document still exposes whatever graph identity fields the + // source contract explicitly retained; uniqueness/order remain unknown. + out.retained = cloneWP6Set(in.retained) + case "union", "group": + out = wp6UnknownProperties() + default: + panic("unknown WP6 property operation: " + operation) + } + return out +} + +func cloneWP6Set(in map[string]bool) map[string]bool { + out := map[string]bool{} + for key, value := range in { + out[key] = value + } + return out +} + +func containsWP6(values []string, want string) bool { + for _, value := range values { + if value == want { + return true + } + } + return false +} + +func TestWP6RenderedBaselineInventory(t *testing.T) { + aql := wp6ReadRepoFile(t, "docs/benchmarks/round3/wp0/baseline.aql") + exactUnique := regexp.MustCompile(`(?m)\bUNIQUE\(`).FindAllStringIndex(aql, -1) + if got := len(exactUnique); got != 8 { + t.Fatalf("baseline UNIQUE inventory = %d, want 8; SORTED_UNIQUE must not be counted", got) + } + sorts := regexp.MustCompile(`(?m)^\s+SORT `).FindAllStringIndex(aql, -1) + if got := len(sorts); got != 11 { + t.Fatalf("baseline SORT inventory = %d, want 11", got) + } + if got := strings.Count(aql, " INBOUND "); got != 4 { + t.Fatalf("baseline inbound traversal inventory = %d, want 4", got) + } + if got := len(regexp.MustCompile(`(?m)^\s+LET child_set_[0-9]+ = UNIQUE`).FindAllStringIndex(aql, -1)); got != 6 { + t.Fatalf("payload child-set materializations = %d, want 6", got) + } + if got := len(regexp.MustCompile(`FOR __item IN child_set_[0-9]+`).FindAllStringIndex(aql, -1)); got != 7 { + t.Fatalf("post-materialization aggregate child-set loops = %d, want 7", got) + } + if got := strings.Count(aql, "payload: "); got != 6 { + t.Fatalf("payload-retaining child sets = %d, want 6", got) + } + if got := len(regexp.MustCompile(`SORT [^\n]+\._key ASC, [^\n]+\._key ASC`).FindAllStringIndex(aql, -1)); got != 3 { + t.Fatalf("duplicate slice sort keys = %d, want 3", got) + } +} + +func TestWP6IdentityDedupRequiresScopeBeforeDedup(t *testing.T) { + type row struct { + id string + project string + generation string + auth string + } + rows := []row{ + {id: "n1", project: "p", generation: "g2", auth: "denied"}, + {id: "n1", project: "p", generation: "g1", auth: "allowed"}, + {id: "n2", project: "p", generation: "g1", auth: "allowed"}, + } + // Scope is evaluated on edge and node before identity dedup. Deduping + // first would let an inaccessible duplicate hide the accessible row. + scoped := make([]row, 0, len(rows)) + for _, candidate := range rows { + if candidate.project == "p" && candidate.generation == "g1" && candidate.auth == "allowed" { + scoped = append(scoped, candidate) + } + } + got := wp6DedupRowsByKey(scoped, func(candidate row) string { return candidate.id }) + if len(got) != 2 || got[0].id != "n1" || got[1].id != "n2" { + t.Fatalf("scope-before-dedup rows = %#v, want n1,n2", got) + } + // This intentionally demonstrates why a property rule may not move scope + // after dedup, even when the identity key is stable. + preScope := wp6DedupRowsByKey(rows, func(candidate row) string { return candidate.id }) + if len(preScope) != 2 || preScope[0].generation != "g2" { + t.Fatalf("fixture did not retain inaccessible first duplicate for unsafe order proof: %#v", preScope) + } +} + +func TestWP6DuplicateEdgesUseNodeIdentityNotObjectEquality(t *testing.T) { + type row struct { + id string + key string + payload string + } + rows := []row{ + {id: "Patient/n1", key: "n1", payload: "same"}, + {id: "Patient/n1", key: "n1", payload: "same"}, // duplicate edge + {id: "Patient/n2", key: "n2", payload: "different"}, + } + got := wp6DedupRowsByKey(rows, func(candidate row) string { return candidate.id }) + if len(got) != 2 || got[0].id != "Patient/n1" || got[1].id != "Patient/n2" { + t.Fatalf("identity dedup = %#v, want one row per node", got) + } + // A candidate that dedups only after projecting arbitrary payload fields + // is not equivalent to node identity. Keep this assertion explicit so a + // future property implementation cannot silently use object equality. + if got[0].id == "" || got[0].key == "" { + t.Fatal("identity proof lost stable node keys") + } +} + +func TestWP6PropertyTransferRejectsUndocumentedTraversalOrder(t *testing.T) { + initial := wp6UnknownProperties() + initial.retained["_id"] = true + initial.retained["_key"] = true + traversed := wp6TransferProperties(initial, "traversal") + if traversed.identityUnique || len(traversed.order) != 0 { + t.Fatalf("traversal unexpectedly inherited identity/order: %#v", traversed) + } + filtered := wp6TransferProperties(traversed, "filter") + if filtered.identityUnique || len(filtered.order) != 0 { + t.Fatalf("filter manufactured identity/order proof: %#v", filtered) + } + deduped := wp6TransferProperties(filtered, "identity_dedup") + if !deduped.identityUnique || len(deduped.order) != 0 { + t.Fatalf("identity dedup properties = %#v, want unique and unknown order", deduped) + } + sorted := wp6TransferProperties(deduped, "sort", "_key") + if !sorted.identityUnique || fmt.Sprint(sorted.order) != "[_key]" { + t.Fatalf("explicit sort properties = %#v, want unique and [_key] order", sorted) + } + projected := wp6TransferProperties(sorted, "projection", "_id", "_key") + if !projected.identityUnique || fmt.Sprint(projected.order) != "[_key]" { + t.Fatalf("identity projection properties = %#v, want proof retained", projected) + } + withoutKey := wp6TransferProperties(sorted, "projection", "_id") + if withoutKey.identityUnique || len(withoutKey.order) != 0 { + t.Fatalf("projection without _key retained unsafe properties: %#v", withoutKey) + } + union := wp6TransferProperties(sorted, "union") + if union.identityUnique || len(union.order) != 0 { + t.Fatalf("union retained unsafe properties: %#v", union) + } +} + +func TestWP6SliceTieBreakRequiresExactOrderProperty(t *testing.T) { + // A representative slice sorted by a non-unique selector requires an + // explicit stable identity tie-break. Traversal order is not a substitute. + sortedByDate := wp6TransferProperties(wp6Properties{identityUnique: true, retained: map[string]bool{"_id": true, "_key": true}}, "sort", "date", "_key") + if fmt.Sprint(sortedByDate.order) != "[date _key]" { + t.Fatalf("date slice order = %#v", sortedByDate.order) + } + if !wp6HasExactOrder(sortedByDate, []string{"date", "_key"}) { + t.Fatal("date slice lost explicit identity tie-break") + } + unknown := wp6UnknownProperties() + if wp6HasExactOrder(unknown, []string{"date", "_key"}) { + t.Fatal("unknown traversal order incorrectly satisfied slice order") + } + // `_key` is itself a unique identity key. Once a production property + // proves the source is identity-unique and sorted by _key, the renderer may + // normalize the current duplicate `_key, _key` tie-break text. This is a + // correctness cleanup; it is not counted as a meaningful execution win. + keySorted := wp6TransferProperties(wp6Properties{identityUnique: true, retained: map[string]bool{"_id": true, "_key": true}}, "sort", "_key") + if !wp6HasExactOrder(keySorted, []string{"_key"}) { + t.Fatal("unique _key order was not recognized") + } +} + +func wp6HasExactOrder(properties wp6Properties, required []string) bool { + if len(properties.order) != len(required) { + return false + } + for index := range required { + if properties.order[index] != required[index] { + return false + } + } + return true +} + +func wp6DedupRowsByKey[T any](rows []T, key func(T) string) []T { + seen := map[string]bool{} + out := make([]T, 0, len(rows)) + for _, row := range rows { + id := key(row) + if id == "" { + panic("identity proof requires non-empty _id") + } + if seen[id] { + continue + } + seen[id] = true + out = append(out, row) + } + return out +} + +func wp6ReadRepoFile(t *testing.T, relative string) string { + t.Helper() + _, filename, _, ok := runtime.Caller(0) + if !ok { + t.Fatal("runtime.Caller failed") + } + repo := filepath.Clean(filepath.Join(filepath.Dir(filename), "..", "..")) + contents, err := os.ReadFile(filepath.Join(repo, relative)) + if err != nil { + t.Fatalf("read %s: %v", relative, err) + } + return string(contents) +} + +func TestWP6BaselineHashEvidence(t *testing.T) { + aql := wp6ReadRepoFile(t, "docs/benchmarks/round3/wp0/baseline.aql") + if got := sha256.Sum256([]byte(aql)); hex.EncodeToString(got[:]) != "aea66e4cf03bfbe460df2d07d3bfd7c874f8176756fe99348288addd3c589642" { + t.Fatalf("raw baseline AQL hash changed: %x", got) + } + // The profile command hashes canonical AQL (normalized before hashing), so + // retain the checked-in canonical hash separately from the raw-file hash. + metadata := wp6ReadRepoFile(t, "docs/benchmarks/round3/wp0/baseline.json") + if !strings.Contains(metadata, `"aql_sha256": "c0b39eb0ec0f29a09b1661c78fc377159881aae81214e505a5427495c8a7e07c"`) { + t.Fatal("baseline metadata lost canonical AQL hash") + } + if !strings.Contains(metadata, `"result_sha256": "17faea7ac3ee7f308b37223f376530a0660f8068d5e015cc573cf99ccb4045ca"`) { + t.Fatal("baseline metadata lost canonical result hash") + } +} + +func TestWP6SortInventoryIsDeterministic(t *testing.T) { + aql := wp6ReadRepoFile(t, "docs/benchmarks/round3/wp0/baseline.aql") + var sortLines []string + for _, line := range strings.Split(aql, "\n") { + if strings.Contains(line, "SORT ") { + sortLines = append(sortLines, strings.TrimSpace(line)) + } + } + if len(sortLines) != 11 { + t.Fatalf("sort inventory = %d, want 11", len(sortLines)) + } + for index, line := range sortLines { + if strings.TrimSpace(line) == "" { + t.Fatalf("sort inventory line %d is empty", index) + } + } +} diff --git a/internal/dataframe/materialization_tournament_test.go b/internal/dataframe/materialization_tournament_test.go new file mode 100644 index 0000000..aa90f91 --- /dev/null +++ b/internal/dataframe/materialization_tournament_test.go @@ -0,0 +1,201 @@ +package dataframe_test + +// Tournament C is an isolated AQL experiment. It freezes the current +// endpoint-first plus typed-selector query produced by the real compiler and +// replaces only the three nested DOCUMENT(edge._from) lookups. No production +// IR, renderer, storage route, or index is changed by this file. + +import ( + "context" + "encoding/json" + "fmt" + "os" + "path/filepath" + "runtime" + "strings" + "testing" + "time" + + dataframe "github.com/calypr/loom/internal/dataframe" + arangostore "github.com/calypr/loom/internal/store/arango" +) + +func TestMaterializationTournamentCandidateBuilds(t *testing.T) { + compiled := compileActualGDC(t, 1000) + candidate, binds, err := compactMaterializationCandidate(compiled.Query, compiled.BindVars) + if err != nil { + t.Fatal(err) + } + if strings.Count(compiled.Query, "DOCUMENT(child_set_3_edge._from)") != 1 || + strings.Count(compiled.Query, "DOCUMENT(child_set_4_edge._from)") != 1 || + strings.Count(compiled.Query, "DOCUMENT(child_set_5_edge._from)") != 1 { + t.Fatalf("current compiled request is not the expected endpoint-first baseline; document lookups=%d/%d/%d", strings.Count(compiled.Query, "DOCUMENT(child_set_3_edge._from)"), strings.Count(compiled.Query, "DOCUMENT(child_set_4_edge._from)"), strings.Count(compiled.Query, "DOCUMENT(child_set_5_edge._from)")) + } + for _, set := range []string{"3", "4", "5"} { + for _, fragment := range []string{ + "FOR child_set_" + set + "_doc IN @@child_set_" + set + "_node_collection", + "PARSE_IDENTIFIER(child_set_" + set + "_edge._from).key", + "KEEP(child_set_" + set + "_doc", + } { + if !strings.Contains(candidate, fragment) { + t.Fatalf("candidate missing compact materialization fragment %q", fragment) + } + } + if _, ok := binds["@child_set_"+set+"_node_collection"]; !ok { + t.Fatalf("candidate missing node collection bind for child_set_%s", set) + } + } + if strings.Contains(candidate, "DOCUMENT(child_set_3_edge._from)") || strings.Contains(candidate, "DOCUMENT(child_set_4_edge._from)") || strings.Contains(candidate, "DOCUMENT(child_set_5_edge._from)") { + t.Fatal("candidate retained a DOCUMENT endpoint lookup") + } +} + +func TestMaterializationTournamentProfilesActualGDC(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run materialization tournament against Arango") + } + compiled := compileActualGDC(t, 1000) + candidate, candidateBinds, err := compactMaterializationCandidate(compiled.Query, compiled.BindVars) + if err != nil { + t.Fatal(err) + } + url, database, _ := compilerArangoTarget() + client, err := arangostore.Open(context.Background(), url, database) + if err != nil { + t.Fatal(err) + } + defer client.Close(context.Background()) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) + defer cancel() + + controlTimes := make([]float64, 0, 5) + candidateTimes := make([]float64, 0, 5) + controlBytes := make([]int, 0, 5) + candidateBytes := make([]int, 0, 5) + var controlHash, candidateHash string + for run := 0; run < 5; run++ { + controlQuery, controlBinds := cacheBust(compiled.Query, compiled.BindVars, 41000+run) + candidateQuery, binds := cacheBust(candidate, candidateBinds, 42000+run) + controlDuration, bytes, hash, err := executeOrdinary(ctx, client, controlQuery, controlBinds) + if err != nil { + t.Fatalf("control run %d: %v", run+1, err) + } + candidateDuration, candidateSize, candidateResultHash, err := executeOrdinary(ctx, client, candidateQuery, binds) + if err != nil { + t.Fatalf("candidate run %d: %v", run+1, err) + } + controlTimes = append(controlTimes, controlDuration) + candidateTimes = append(candidateTimes, candidateDuration) + controlBytes = append(controlBytes, bytes) + candidateBytes = append(candidateBytes, candidateSize) + controlHash, candidateHash = hash, candidateResultHash + } + if controlHash != candidateHash { + t.Fatalf("result parity mismatch control=%s candidate=%s", controlHash, candidateHash) + } + + controlProfileQuery, controlProfileBinds := cacheBust(compiled.Query, compiled.BindVars, 41999) + candidateProfileQuery, candidateProfileBinds := cacheBust(candidate, candidateBinds, 42999) + controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{ + Query: controlProfileQuery, BindVars: controlProfileBinds, BatchSize: 10000, Count: true, + Options: arangostore.ProfileOptions{Profile: 2}, + }) + if err != nil { + t.Fatalf("control PROFILE: %v", err) + } + candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{ + Query: candidateProfileQuery, BindVars: candidateProfileBinds, BatchSize: 10000, Count: true, + Options: arangostore.ProfileOptions{Profile: 2}, + }) + if err != nil { + t.Fatalf("candidate PROFILE: %v", err) + } + if hashRawRows(controlProfile.Result) != hashRawRows(candidateProfile.Result) { + t.Fatalf("PROFILE result parity mismatch control=%s candidate=%s", hashRawRows(controlProfile.Result), hashRawRows(candidateProfile.Result)) + } + controlExplain, err := client.Explain(ctx, arangostore.ExplainRequest{Query: controlProfileQuery, BindVars: controlProfileBinds}) + if err != nil { + t.Fatalf("control EXPLAIN: %v", err) + } + candidateExplain, err := client.Explain(ctx, arangostore.ExplainRequest{Query: candidateProfileQuery, BindVars: candidateProfileBinds}) + if err != nil { + t.Fatalf("candidate EXPLAIN: %v", err) + } + controlSummary := arangostore.SummarizeProfile(controlProfile) + candidateSummary := arangostore.SummarizeProfile(candidateProfile) + t.Logf("materialization tournament control median=%.6f candidate median=%.6f control profile=%+v candidate profile=%+v bytes=%v/%v", median(controlTimes), median(candidateTimes), controlSummary, candidateSummary, controlBytes, candidateBytes) + writeMaterializationEvidence(t, compiled, candidate, controlTimes, candidateTimes, controlBytes, candidateBytes, controlHash, candidateHash, controlProfile, candidateProfile, controlExplain, candidateExplain) + if median(candidateTimes) >= median(controlTimes)*0.95 { + t.Logf("candidate rejected: median does not clear 5%% whole-query gate control=%.6f candidate=%.6f", median(controlTimes), median(candidateTimes)) + } +} + +// compactMaterializationCandidate replaces DOCUMENT endpoint retrieval with a +// type-directed primary-key lookup. KEEP retains only fields used by the +// current child projections and scope checks. The node collection binds are +// derived from the compiled target-type binds; no FHIR route is hard-coded in +// production code. +func compactMaterializationCandidate(query string, sourceBinds map[string]any) (string, map[string]any, error) { + candidate := query + binds := make(map[string]any, len(sourceBinds)+3) + for key, value := range sourceBinds { + binds[key] = value + } + for _, set := range []string{"3", "4", "5"} { + setPrefix := "child_set_" + set + old := fmt.Sprintf("LET %s_node = DOCUMENT(%s_edge._from)", setPrefix, setPrefix) + new := fmt.Sprintf("FOR %s_doc IN @@%s_node_collection\n FILTER %s_doc._key == PARSE_IDENTIFIER(%s_edge._from).key\n FILTER %s_doc._id == %s_edge._from\n LET %s_node = KEEP(%s_doc, \"_id\", \"_key\", \"id\", \"resourceType\", \"project\", \"dataset_generation\", \"auth_resource_path\", \"payload\")", setPrefix, setPrefix, setPrefix, setPrefix, setPrefix, setPrefix, setPrefix, setPrefix) + if strings.Count(candidate, old) != 1 { + return "", nil, fmt.Errorf("expected one %s in endpoint baseline, found %d", old, strings.Count(candidate, old)) + } + candidate = strings.Replace(candidate, old, new, 1) + target, ok := binds[setPrefix+"_target_type"].(string) + if !ok || target == "" { + return "", nil, fmt.Errorf("missing compiled target type bind %s_target_type", setPrefix) + } + binds["@"+setPrefix+"_node_collection"] = target + } + return candidate, binds, nil +} + +func writeMaterializationEvidence(t *testing.T, compiled dataframe.CompiledQuery, candidate string, controlTimes, candidateTimes []float64, controlBytes, candidateBytes []int, controlHash, candidateHash string, controlProfile, candidateProfile arangostore.ProfileResult, controlExplain, candidateExplain arangostore.ExplainResult) { + _, source, _, _ := runtime.Caller(0) + directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "tournament_materialization") + if err := os.MkdirAll(directory, 0o755); err != nil { + t.Fatalf("create materialization evidence directory: %v", err) + } + writeJSON := func(name string, value any) { + data, err := json.MarshalIndent(value, "", " ") + if err != nil { + t.Fatalf("encode %s: %v", name, err) + } + if err := os.WriteFile(filepath.Join(directory, name), append(data, '\n'), 0o644); err != nil { + t.Fatalf("write %s: %v", name, err) + } + } + if err := os.WriteFile(filepath.Join(directory, "control.aql"), []byte(compiled.Query+"\n"), 0o644); err != nil { + t.Fatalf("write control AQL: %v", err) + } + if err := os.WriteFile(filepath.Join(directory, "candidate.aql"), []byte(candidate+"\n"), 0o644); err != nil { + t.Fatalf("write candidate AQL: %v", err) + } + writeJSON("control.profile.json", controlProfile) + writeJSON("candidate.profile.json", candidateProfile) + writeJSON("evidence.json", map[string]any{ + "fixture": "examples/meta_gdc_case_matrix.variables.json", + "limit": 1000, + "control_aql_sha256": sha256Hex(compiled.Query), + "candidate_aql_sha256": sha256Hex(candidate), + "control_result_sha256": controlHash, + "candidate_result_sha256": candidateHash, + "control_seconds": controlTimes, + "candidate_seconds": candidateTimes, + "control_bytes": controlBytes, + "candidate_bytes": candidateBytes, + "control_profile": arangostore.SummarizeProfile(controlProfile), + "candidate_profile": arangostore.SummarizeProfile(candidateProfile), + "control_explain": arangostore.AssessExplainResult(controlExplain), + "candidate_explain": arangostore.AssessExplainResult(candidateExplain), + "decision": "pending-threshold-review", + }) +} diff --git a/internal/dataframe/physical_cost.go b/internal/dataframe/physical_cost.go index b1e58fb..58e01ce 100644 --- a/internal/dataframe/physical_cost.go +++ b/internal/dataframe/physical_cost.go @@ -12,13 +12,77 @@ import ( // deciding whether a rewrite is worthwhile on a particular dataset. type PhysicalOptimizationPolicy struct { // Enabled is false when the policy is disabled explicitly. Disabling the - // policy never disables validation or changes the physical plan supplied by - // the caller; it only prevents optional traversal-sharing rewrites. Rich - // selector preparation has its own structural gate during lowering. + // policy never disables validation or changes semantic meaning; it prevents + // all optional optimizer families while preserving the unoptimized physical + // execution plan. Enabled bool // MinimumSavings is the minimum estimated operation-work reduction required // before an optional rewrite is applied. The default is one operation. MinimumSavings int + // RuleOverrides contains explicit per-rule ablation decisions. A nil entry + // preserves the production default: traversal sharing and compact set + // projection are enabled after their live parity/profile gates. The older + // second-pass prepared selector experiment and later optimization families + // remain disabled until their own payload/cost gate has passed. + RuleOverrides map[PhysicalOptimizationRule]bool +} + +// PhysicalOptimizationRule names an independently ablatable optimizer family. +// These names are compiler-owned and are intentionally independent of FHIR +// resource names or rendered AQL fragments. +type PhysicalOptimizationRule string + +const ( + PhysicalOptimizationRuleTraversalSharing PhysicalOptimizationRule = "traversal_sharing" + PhysicalOptimizationRulePreparedSelectors PhysicalOptimizationRule = "prepared_selectors" + PhysicalOptimizationRuleNestedSharing PhysicalOptimizationRule = "nested_traversal_sharing" + PhysicalOptimizationRuleRichConsumerFusion PhysicalOptimizationRule = "rich_consumer_fusion" + PhysicalOptimizationRuleCompactProjection PhysicalOptimizationRule = "compact_set_projection" + PhysicalOptimizationRuleEndpointTraversal PhysicalOptimizationRule = "endpoint_traversal" +) + +var allPhysicalOptimizationRules = []PhysicalOptimizationRule{ + PhysicalOptimizationRuleTraversalSharing, + PhysicalOptimizationRulePreparedSelectors, + PhysicalOptimizationRuleNestedSharing, + PhysicalOptimizationRuleRichConsumerFusion, + PhysicalOptimizationRuleCompactProjection, + PhysicalOptimizationRuleEndpointTraversal, +} + +// RuleEnabled resolves one rule without mutating the caller's policy. A +// global disable always wins; an explicit override wins over the defaults. +func (policy PhysicalOptimizationPolicy) RuleEnabled(rule PhysicalOptimizationRule) bool { + if !policy.Enabled { + return false + } + if policy.RuleOverrides != nil { + if enabled, ok := policy.RuleOverrides[rule]; ok { + return enabled + } + } + switch rule { + case PhysicalOptimizationRuleTraversalSharing, PhysicalOptimizationRuleCompactProjection, PhysicalOptimizationRuleEndpointTraversal: + return true + default: + return false + } +} + +// WithRule returns a copy with one named rule explicitly enabled or disabled. +// It is used by benchmark and parity harnesses to change exactly one rule. +func (policy PhysicalOptimizationPolicy) WithRule(rule PhysicalOptimizationRule, enabled bool) PhysicalOptimizationPolicy { + if policy.RuleOverrides == nil { + policy.RuleOverrides = make(map[PhysicalOptimizationRule]bool) + } else { + copy := make(map[PhysicalOptimizationRule]bool, len(policy.RuleOverrides)+1) + for key, value := range policy.RuleOverrides { + copy[key] = value + } + policy.RuleOverrides = copy + } + policy.RuleOverrides[rule] = enabled + return policy } // PhysicalOptimizationDecision explains one candidate rewrite. The values are @@ -42,17 +106,30 @@ type PhysicalOptimizationReport struct { Policy string Enabled bool MinimumSavings int + RuleStates []PhysicalOptimizationRuleState Decisions []PhysicalOptimizationDecision } +// PhysicalOptimizationRuleState reports the resolved state of every known +// optimizer family, including families that had no candidate in this plan. +// Decisions remain reserved for candidate-specific estimates and rewrites. +type PhysicalOptimizationRuleState struct { + Rule PhysicalOptimizationRule + Enabled bool + Reason string +} + const physicalOptimizationPolicyName = "conservative-structural-v1" // DefaultPhysicalOptimizationPolicy returns the production policy. The // LOOM_PHYSICAL_COST_POLICY environment variable is intentionally a local // developer switch, not a user-controlled query input. Set it to "off" (or // "0"/"false") to compare the unshared physical shape; all validation and -// result semantics remain unchanged. Rich selector preparation is governed by -// its independent repeated-consumer proof. +// result semantics remain unchanged. Compact set projection includes +// traversal-time selector projection for fallback-free rich consumers; set +// LOOM_PHYSICAL_RULE_COMPACT_PROJECTION=off to compare full-node output. The +// older second-pass prepared selector experiment remains opt-in via +// LOOM_PHYSICAL_RULE_PREPARED_SELECTORS=on. func DefaultPhysicalOptimizationPolicy() PhysicalOptimizationPolicy { policy := PhysicalOptimizationPolicy{Enabled: true, MinimumSavings: 1} switch strings.ToLower(strings.TrimSpace(os.Getenv("LOOM_PHYSICAL_COST_POLICY"))) { @@ -64,6 +141,24 @@ func DefaultPhysicalOptimizationPolicy() PhysicalOptimizationPolicy { policy.MinimumSavings = value } } + for _, setting := range []struct { + name string + rule PhysicalOptimizationRule + }{ + {name: "LOOM_PHYSICAL_RULE_TRAVERSAL_SHARING", rule: PhysicalOptimizationRuleTraversalSharing}, + {name: "LOOM_PHYSICAL_RULE_PREPARED_SELECTORS", rule: PhysicalOptimizationRulePreparedSelectors}, + {name: "LOOM_PHYSICAL_RULE_NESTED_SHARING", rule: PhysicalOptimizationRuleNestedSharing}, + {name: "LOOM_PHYSICAL_RULE_RICH_FUSION", rule: PhysicalOptimizationRuleRichConsumerFusion}, + {name: "LOOM_PHYSICAL_RULE_COMPACT_PROJECTION", rule: PhysicalOptimizationRuleCompactProjection}, + {name: "LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL", rule: PhysicalOptimizationRuleEndpointTraversal}, + } { + switch strings.ToLower(strings.TrimSpace(os.Getenv(setting.name))) { + case "on", "1", "true", "enabled": + policy = policy.WithRule(setting.rule, true) + case "off", "0", "false", "disabled": + policy = policy.WithRule(setting.rule, false) + } + } return policy } @@ -71,11 +166,29 @@ func newPhysicalOptimizationReport(policy PhysicalOptimizationPolicy) PhysicalOp if policy.MinimumSavings < 0 { policy.MinimumSavings = 0 } - return PhysicalOptimizationReport{ + report := PhysicalOptimizationReport{ Policy: physicalOptimizationPolicyName, Enabled: policy.Enabled, MinimumSavings: policy.MinimumSavings, } + for _, rule := range allPhysicalOptimizationRules { + enabled := policy.RuleEnabled(rule) + reason := "disabled until implemented and profile-gated" + if enabled { + reason = "enabled; candidate-specific decisions are reported separately" + } + if !policy.Enabled { + reason = "global optimization policy disabled" + } else if override, ok := policy.RuleOverrides[rule]; ok { + if override { + reason = "enabled by explicit policy override" + } else { + reason = "disabled by explicit policy override" + } + } + report.RuleStates = append(report.RuleStates, PhysicalOptimizationRuleState{Rule: rule, Enabled: enabled, Reason: reason}) + } + return report } func (report *PhysicalOptimizationReport) addDecision(decision PhysicalOptimizationDecision) { @@ -124,6 +237,7 @@ func estimatePreparedSelectorWork(selectorUseCount int) (baseline, optimized, sa func clonePhysicalOptimizationReport(report PhysicalOptimizationReport) PhysicalOptimizationReport { copy := report + copy.RuleStates = append([]PhysicalOptimizationRuleState(nil), report.RuleStates...) copy.Decisions = append([]PhysicalOptimizationDecision(nil), report.Decisions...) return copy } diff --git a/internal/dataframe/physical_diagnostics.go b/internal/dataframe/physical_diagnostics.go index 1e2df5f..1dd7d4c 100644 --- a/internal/dataframe/physical_diagnostics.go +++ b/internal/dataframe/physical_diagnostics.go @@ -1,12 +1,18 @@ package dataframe -import "sort" +import ( + "encoding/json" + "sort" +) // CompilerPlanDiagnostics describes work the physical renderer will ask AQL to // perform. It deliberately reports compiler facts, not estimated database // cost: use it alongside Arango PROFILE to decide which rewrite is worthwhile. type CompilerPlanDiagnostics struct { TraversalSets int + EndpointTraversalCount int + NativeTraversalCount int + TraversalStrategies []PhysicalTraversalDecision SharedTraversalCount int RequiredMatchReuseCount int ScopedSharingCandidateGroups int @@ -14,12 +20,31 @@ type CompilerPlanDiagnostics struct { PotentialSharingOpportunityGroups int PotentialSharingOpportunitySets int RichSourceReuse []RichSourceReuse + RichConsumerGroups []RichConsumerGroup // OptimizationPolicy is the explainable decision record for optional // physical rewrites. It reports both enabled rewrites and conservative // rejections so rendered AQL is never the only evidence of a decision. OptimizationPolicy PhysicalOptimizationReport } +// PhysicalTraversalDecision exposes the route strategy selected by the typed +// physical compiler. It is deliberately metadata-only: no user values or raw +// AQL are included. Native decisions explain whether endpoint lowering was +// disabled by policy or rejected because its validated storage contract was +// unavailable. +type PhysicalTraversalDecision struct { + SourceVariable string + TargetVariable string + Direction PhysicalTraversalDirection + Strategy PhysicalTraversalStrategy + EndpointField string + EndpointJoinField string + EndpointIndexFields []string + Relationship string + TargetResourceType string + Reason string +} + // RichSourceReuse identifies a materialized relationship set that is scanned // repeatedly by rich projections. A high count does not mean the traversal is // repeated; it means aggregate/pivot/slice operations each loop over the same @@ -31,6 +56,20 @@ type RichSourceReuse struct { SliceConsumers int } +// RichConsumerGroup is a renderer-independent compatibility classification +// for rich expressions over one materialized set. A group is eligible only +// when its complete semantic expression signature is identical; source reuse +// alone is not enough to fuse predicates, ordering, pivot reduction, or slice +// limits safely. +type RichConsumerGroup struct { + SourceSet string + Kind PhysicalExpressionKind + Signature string + Consumers int + Eligible bool + Reason string +} + func (r RichSourceReuse) TotalConsumers() int { return r.AggregateConsumers + r.PivotConsumers + r.SliceConsumers } @@ -41,9 +80,46 @@ func physicalPlanDiagnostics(plan PhysicalPlan) CompilerPlanDiagnostics { RequiredMatchReuseCount: plan.RequiredMatchReuseCount, OptimizationPolicy: clonePhysicalOptimizationReport(plan.OptimizationPolicy), } + endpointPolicyEnabled := false + for _, state := range plan.OptimizationPolicy.RuleStates { + if state.Rule == PhysicalOptimizationRuleEndpointTraversal { + endpointPolicyEnabled = state.Enabled + break + } + } groups := map[string][]int{} potentialGroups := map[string][]int{} for i, operation := range plan.Operations { + if operation.Kind == PhysicalTraversalOp && operation.Traversal != nil { + traversal := operation.Traversal + strategy := traversal.Strategy + if strategy == "" { + strategy = PhysicalTraversalNative + } + decision := PhysicalTraversalDecision{ + SourceVariable: traversal.SourceVariable, + TargetVariable: traversal.TargetVariable, + Direction: traversal.Direction, + Strategy: strategy, + EndpointField: traversal.EndpointField, + EndpointJoinField: traversal.EndpointJoinField, + EndpointIndexFields: append([]string(nil), traversal.EndpointIndexFields...), + Relationship: operation.Source.Relationship, + TargetResourceType: operation.Source.ResourceType, + } + if strategy == PhysicalTraversalEndpointLookup { + decision.Reason = "endpoint lookup enabled by validated storage-route and index contract" + diagnostics.EndpointTraversalCount++ + } else { + diagnostics.NativeTraversalCount++ + if !endpointPolicyEnabled { + decision.Reason = "endpoint lookup disabled by optimization policy" + } else { + decision.Reason = "endpoint contract unavailable; native traversal fallback" + } + } + diagnostics.TraversalStrategies = append(diagnostics.TraversalStrategies, decision) + } if operation.Kind != PhysicalSetOp || operation.Set == nil { continue } @@ -89,9 +165,75 @@ func physicalPlanDiagnostics(plan PhysicalPlan) CompilerPlanDiagnostics { sort.Slice(diagnostics.RichSourceReuse, func(i, j int) bool { return diagnostics.RichSourceReuse[i].SourceSet < diagnostics.RichSourceReuse[j].SourceSet }) + consumerGroups := map[string]*RichConsumerGroup{} + for _, operation := range plan.Operations { + if operation.Kind != PhysicalReturnOp || operation.Return == nil { + continue + } + for _, projection := range operation.Return.Projections { + collectRichConsumerGroups(projection.Expression, consumerGroups) + } + } + groupKeys := make([]string, 0, len(consumerGroups)) + for key := range consumerGroups { + groupKeys = append(groupKeys, key) + } + sort.Strings(groupKeys) + for _, key := range groupKeys { + group := *consumerGroups[key] + if group.Consumers > 1 { + group.Eligible = true + group.Reason = "identical source, operation, and semantic expression" + } else { + group.Reason = "single consumer" + } + diagnostics.RichConsumerGroups = append(diagnostics.RichConsumerGroups, group) + } return diagnostics } +func collectRichConsumerGroups(expression *PhysicalExpression, groups map[string]*RichConsumerGroup) { + if expression == nil { + return + } + var source string + switch expression.Kind { + case PhysicalAggregateExpression: + if expression.Aggregate != nil { + source = expression.Aggregate.Source.Variable + } + case PhysicalPivotExpression: + if expression.Pivot != nil { + source = expression.Pivot.Source.Variable + } + case PhysicalSliceExpression: + if expression.Slice != nil { + source = expression.Slice.Source.Variable + } + case PhysicalObjectExpression: + if expression.Object != nil { + for index := range expression.Object.Fields { + collectRichConsumerGroups(&expression.Object.Fields[index].Expression, groups) + } + } + return + } + if source == "" { + return + } + payload, err := json.Marshal(expression) + if err != nil { + return + } + signature := string(payload) + key := source + "\x00" + string(expression.Kind) + "\x00" + signature + if group := groups[key]; group != nil { + group.Consumers++ + return + } + groups[key] = &RichConsumerGroup{SourceSet: source, Kind: expression.Kind, Signature: signature, Consumers: 1} +} + // physicalTraversalOpportunityKey intentionally ignores scoped filters and // semantic provenance. It identifies broader neighbor traversals that could // serve multiple typed children once the scope-safe rewrite exists. diff --git a/internal/dataframe/physical_diagnostics_test.go b/internal/dataframe/physical_diagnostics_test.go new file mode 100644 index 0000000..f6a160d --- /dev/null +++ b/internal/dataframe/physical_diagnostics_test.go @@ -0,0 +1,49 @@ +package dataframe + +import "testing" + +func TestRichConsumerDiagnosticsClassifiesOnlyIdenticalExpressions(t *testing.T) { + selector := Selector{Steps: []SelectorStep{{Field: "id"}}} + plan, err := BuildGenericPhysicalPlan(SemanticPlan{ + Version: 1, + Project: "p", + Root: SemanticNode{ + Alias: "root", ResourceType: "Patient", + Children: []SemanticNode{{ + Alias: "condition", ResourceType: "Condition", EdgeLabel: "subject_Patient", + Aggregates: []SemanticAggregate{ + {Name: "count_a", Operation: "COUNT"}, + {Name: "count_b", Operation: "COUNT"}, + {Name: "distinct_ids", Operation: "DISTINCT_VALUES", Selector: &selector}, + }, + }}, + }, + }) + if err != nil { + t.Fatal(err) + } + diagnostics := physicalPlanDiagnostics(plan) + var identicalCounts, singletonGroups int + for _, group := range diagnostics.RichConsumerGroups { + if group.SourceSet != "child_set_1" || group.Kind != PhysicalAggregateExpression { + continue + } + if group.Eligible && group.Consumers == 2 { + identicalCounts++ + } + if !group.Eligible && group.Consumers == 1 { + singletonGroups++ + } + } + if identicalCounts != 1 { + t.Fatalf("identical aggregate group count = %d, diagnostics=%#v", identicalCounts, diagnostics.RichConsumerGroups) + } + if singletonGroups != 1 { + t.Fatalf("non-identical aggregate singleton count = %d, diagnostics=%#v", singletonGroups, diagnostics.RichConsumerGroups) + } + for _, state := range diagnostics.OptimizationPolicy.RuleStates { + if state.Rule == PhysicalOptimizationRuleRichConsumerFusion && state.Enabled { + t.Fatalf("rich-consumer fusion unexpectedly enabled: %#v", state) + } + } +} diff --git a/internal/dataframe/physical_helpers.go b/internal/dataframe/physical_helpers.go index 7eccc2b..8c40221 100644 --- a/internal/dataframe/physical_helpers.go +++ b/internal/dataframe/physical_helpers.go @@ -59,6 +59,21 @@ func clonePhysicalOperation(operation PhysicalOperation) PhysicalOperation { if operation.Set != nil { setCopy := *operation.Set setCopy.Subplan = clonePhysicalSubplan(operation.Set.Subplan) + if operation.Set.Output != nil { + outputCopy := *operation.Set.Output + outputCopy.Fields = append([]PhysicalSetOutputField(nil), operation.Set.Output.Fields...) + setCopy.Output = &outputCopy + } + if operation.Set.Projection != nil { + projectionCopy := *operation.Set.Projection + projectionCopy.Fields = append([]PhysicalSetProjectionField(nil), operation.Set.Projection.Fields...) + setCopy.Projection = &projectionCopy + } + if operation.Set.Prepared != nil { + preparedCopy := *operation.Set.Prepared + preparedCopy.Fields = append([]PhysicalPreparedField(nil), operation.Set.Prepared.Fields...) + setCopy.Prepared = &preparedCopy + } copy.Set = &setCopy } if operation.DerivedLet != nil { @@ -132,12 +147,24 @@ func clonePhysicalExpression(expression PhysicalExpression) PhysicalExpression { extract := *expression.Extract extract.Source = clonePhysicalValue(extract.Source) extract.Fallbacks = append([]Selector(nil), extract.Fallbacks...) + if extract.Prepared != nil { + prepared := *extract.Prepared + extract.Prepared = &prepared + } copy.Extract = &extract } if expression.Pivot != nil { pivot := *expression.Pivot pivot.Source = clonePhysicalValue(expression.Pivot.Source) pivot.ColumnsBindKey = expression.Pivot.ColumnsBindKey + if pivot.PreparedKey != nil { + prepared := *pivot.PreparedKey + pivot.PreparedKey = &prepared + } + if pivot.PreparedValue != nil { + prepared := *pivot.PreparedValue + pivot.PreparedValue = &prepared + } copy.Pivot = &pivot } if expression.Aggregate != nil { @@ -156,8 +183,28 @@ func clonePhysicalExpression(expression PhysicalExpression) PhysicalExpression { sort := clonePhysicalExpression(*slice.Sort) slice.Sort = &sort } + if slice.Predicate != nil { + predicate := clonePhysicalPredicateExpression(*slice.Predicate) + slice.Predicate = &predicate + } + slice.Projections = make([]PhysicalExpressionProjection, len(expression.Slice.Projections)) + for index, projection := range expression.Slice.Projections { + projectionCopy := projection + projectionCopy.Expression = clonePhysicalExpression(projection.Expression) + slice.Projections[index] = projectionCopy + } copy.Slice = &slice } + if expression.Object != nil { + object := *expression.Object + object.Fields = make([]PhysicalExpressionProjection, len(expression.Object.Fields)) + for index, field := range expression.Object.Fields { + fieldCopy := field + fieldCopy.Expression = clonePhysicalExpression(field.Expression) + object.Fields[index] = fieldCopy + } + copy.Object = &object + } return copy } diff --git a/internal/dataframe/physical_lowering.go b/internal/dataframe/physical_lowering.go index 2eaa745..07d8c68 100644 --- a/internal/dataframe/physical_lowering.go +++ b/internal/dataframe/physical_lowering.go @@ -7,11 +7,19 @@ import "fmt" // It deliberately accepts SemanticPlan rather than the public request // builder, keeping storage and AQL details out of semantic validation. func BuildPhysicalPlan(semantic SemanticPlan) (PhysicalPlan, error) { + return BuildPhysicalPlanWithPolicy(semantic, DefaultPhysicalOptimizationPolicy()) +} + +// BuildPhysicalPlanWithPolicy is the policy-aware semantic-to-physical +// boundary used by ablation and parity harnesses. Production callers should +// use BuildPhysicalPlan unless they are deliberately comparing one optimizer +// rule. +func BuildPhysicalPlanWithPolicy(semantic SemanticPlan, policy PhysicalOptimizationPolicy) (PhysicalPlan, error) { if err := ValidateSemanticGraph(semantic); err != nil { return PhysicalPlan{}, fmt.Errorf("validate semantic plan: %w", err) } if reason := genericPhysicalPlanUnavailableReason(semantic.Root); reason != "" { return PhysicalPlan{}, fmt.Errorf("physical lowering does not yet support %s", reason) } - return BuildGenericPhysicalPlan(semantic) + return BuildGenericPhysicalPlanWithPolicy(semantic, policy) } diff --git a/internal/dataframe/physical_optimize.go b/internal/dataframe/physical_optimize.go index 8fd64dd..d5a17aa 100644 --- a/internal/dataframe/physical_optimize.go +++ b/internal/dataframe/physical_optimize.go @@ -68,8 +68,12 @@ func OptimizePhysicalPlanWithPolicy(plan PhysicalPlan, policy PhysicalOptimizati decision.EstimatedBaselineWork = baseline decision.EstimatedOptimizedWork = optimized decision.EstimatedSavings = savings - if !policy.Enabled { - decision.Reason = "cost policy disabled" + if !policy.RuleEnabled(PhysicalOptimizationRuleTraversalSharing) { + if !policy.Enabled { + decision.Reason = "cost policy disabled" + } else { + decision.Reason = "traversal sharing rule disabled" + } out.OptimizationPolicy.addDecision(decision) continue } @@ -78,7 +82,7 @@ func OptimizePhysicalPlanWithPolicy(plan PhysicalPlan, policy PhysicalOptimizati out.OptimizationPolicy.addDecision(decision) continue } - if err := sharePhysicalSetGroup(&out, indices, types, decompositions); err != nil { + if err := sharePhysicalSetGroup(&out, indices, types, decompositions, policy); err != nil { decision.Reason = "rewrite rejected: " + err.Error() out.OptimizationPolicy.addDecision(decision) continue @@ -93,7 +97,7 @@ func OptimizePhysicalPlanWithPolicy(plan PhysicalPlan, policy PhysicalOptimizati return out, nil } -func sharePhysicalSetGroup(plan *PhysicalPlan, indices []int, types map[string]bool, decompositions map[int]PhysicalTraversalPrefixDecomposition) error { +func sharePhysicalSetGroup(plan *PhysicalPlan, indices []int, types map[string]bool, decompositions map[int]PhysicalTraversalPrefixDecomposition, policy PhysicalOptimizationPolicy) error { first := indices[0] // The broad set changes its target bind from one type to a type list. Deep // clone before that change: its first consumer must retain the original @@ -127,14 +131,32 @@ func sharePhysicalSetGroup(plan *PhysicalPlan, indices []int, types map[string]b } plan.BindVars[typesKey] = targetTypes t.TargetTypeBindKey = typesKey + if policy.RuleEnabled(PhysicalOptimizationRuleEndpointTraversal) { + route := storageRoute{Direction: t.Direction} + if endpoint, join, fields, ok := route.endpointLookupFields(); ok { + t.Strategy = PhysicalTraversalEndpointLookup + t.EndpointField, t.EndpointJoinField = endpoint, join + t.EndpointIndexFields = append([]string(nil), fields...) + } + } base.Subplan.Operations[0].Traversal = &t base.Subplan.Operations = clonePhysicalOperations(original.Subplan.Operations[:7]) base.Variable = baseName base.SourceSetVariable, base.ItemVariable = "", "" + // The broad source must remain a full node because sibling consumers may + // require different compact fields. Each typed subset retains its own + // proven output contract below; unioning those contracts into the broad + // traversal would make sharing resource/cardinality dependent. + base.Output = nil // Prepared values belong to typed consumer sets. The broad shared neighbor // set must contain raw nodes only; consumers prepare their own projections // after resource-type filtering. base.Prepared = nil + // Traversal-time selector projections are also consumer-specific. Keeping + // the first sibling's projection on the broad heterogeneous set evaluates + // selectors against the wrong resource payload and leaves typed subsets + // with empty values. + base.Projection = nil base.Subplan.Return = PhysicalExpression{Kind: PhysicalValueExpression, Cardinality: PhysicalObjectCardinality, NullBehavior: PhysicalPreserveNull, Value: &PhysicalValue{Variable: t.TargetVariable}} // Rebuild operation stream, inserting the broad traversal immediately before // the first consumer and replacing each consumer with a typed subset. @@ -167,6 +189,14 @@ func sharePhysicalSetGroup(plan *PhysicalPlan, indices []int, types map[string]b } set.SourceSetVariable, set.ItemVariable, set.Subplan = baseName, item, sub set.Unique, set.SortByKey = true, true + if set.Prepared != nil { + // The typed consumer now reads the shared subset rather than the + // original traversal set. Rebind the prepared projection's source + // to the consumer set so rendering defines it in the same scope. + prepared := *set.Prepared + prepared.SourceSetVariable = set.Variable + set.Prepared = &prepared + } newOps = append(newOps, PhysicalOperation{Kind: PhysicalSetOp, Source: op.Source, Set: &set}) } plan.Operations = newOps diff --git a/internal/dataframe/physical_optimize_test.go b/internal/dataframe/physical_optimize_test.go index 290be09..cae2508 100644 --- a/internal/dataframe/physical_optimize_test.go +++ b/internal/dataframe/physical_optimize_test.go @@ -39,6 +39,36 @@ func TestOptimizePhysicalPlanSharesEquivalentTypedPrefixes(t *testing.T) { } } +func TestOptimizePhysicalPlanKeepsConsumerProjectionOffBroadSharedSet(t *testing.T) { + plan := physicalScopedSiblingPlan(t) + for _, set := range physicalSets(plan) { + resourceType := valueString(plan.BindVars[set.Subplan.Operations[0].Traversal.TargetTypeBindKey]) + set.Projection = &PhysicalSetProjection{Fields: []PhysicalSetProjectionField{{Name: "__loom_projection_0", ResourceType: resourceType, Selector: mustPhysicalSelector(t, "id")}}} + set.Output = nil + } + optimized, err := OptimizePhysicalPlan(plan) + if err != nil { + t.Fatal(err) + } + var broad, subsets int + for _, set := range physicalSets(optimized) { + if set.SourceSetVariable == "" { + broad++ + if set.Projection != nil { + t.Fatalf("heterogeneous shared set retained consumer projection: %#v", set.Projection) + } + } else { + subsets++ + if set.Projection == nil { + t.Fatalf("typed subset lost consumer projection: %#v", set) + } + } + } + if broad != 1 || subsets != 2 { + t.Fatalf("shared projection sets = broad %d subsets %d, want 1/2", broad, subsets) + } +} + func TestOptimizePhysicalPlanReportsStructuralCostDecision(t *testing.T) { optimized, err := OptimizePhysicalPlanWithPolicy(physicalScopedSiblingPlan(t), PhysicalOptimizationPolicy{Enabled: true, MinimumSavings: 1}) if err != nil { @@ -113,10 +143,126 @@ func TestDefaultPhysicalOptimizationPolicyDeveloperSwitch(t *testing.T) { } t.Setenv("LOOM_PHYSICAL_COST_POLICY", "on") t.Setenv("LOOM_PHYSICAL_COST_MIN_SAVINGS", "17") + t.Setenv("LOOM_PHYSICAL_RULE_TRAVERSAL_SHARING", "off") + t.Setenv("LOOM_PHYSICAL_RULE_PREPARED_SELECTORS", "on") policy = DefaultPhysicalOptimizationPolicy() if !policy.Enabled || policy.MinimumSavings != 17 { t.Fatalf("configured environment policy = %#v", policy) } + if policy.RuleEnabled(PhysicalOptimizationRuleTraversalSharing) || !policy.RuleEnabled(PhysicalOptimizationRulePreparedSelectors) { + t.Fatalf("configured independent rule policy = %#v", policy.RuleOverrides) + } +} + +func TestPhysicalOptimizationPolicyResolvesIndependentRules(t *testing.T) { + policy := DefaultPhysicalOptimizationPolicy() + if !policy.RuleEnabled(PhysicalOptimizationRuleTraversalSharing) || !policy.RuleEnabled(PhysicalOptimizationRuleCompactProjection) || policy.RuleEnabled(PhysicalOptimizationRulePreparedSelectors) { + t.Fatalf("default active rules = %#v", policy) + } + for _, rule := range []PhysicalOptimizationRule{ + PhysicalOptimizationRuleNestedSharing, + PhysicalOptimizationRuleRichConsumerFusion, + } { + if policy.RuleEnabled(rule) { + t.Fatalf("unimplemented rule %q was enabled by default", rule) + } + } + policy = policy.WithRule(PhysicalOptimizationRuleTraversalSharing, false).WithRule(PhysicalOptimizationRulePreparedSelectors, false) + if policy.RuleEnabled(PhysicalOptimizationRuleTraversalSharing) || policy.RuleEnabled(PhysicalOptimizationRulePreparedSelectors) { + t.Fatalf("explicit rule overrides were ignored: %#v", policy.RuleOverrides) + } +} + +func TestOptimizePhysicalPlanReportsExplicitRuleDisable(t *testing.T) { + policy := DefaultPhysicalOptimizationPolicy().WithRule(PhysicalOptimizationRuleTraversalSharing, false) + optimized, err := OptimizePhysicalPlanWithPolicy(physicalScopedSiblingPlan(t), policy) + if err != nil { + t.Fatal(err) + } + if optimized.SharedTraversalCount != 0 { + t.Fatalf("explicitly disabled sharing changed plan: %d", optimized.SharedTraversalCount) + } + if len(optimized.OptimizationPolicy.Decisions) != 1 || optimized.OptimizationPolicy.Decisions[0].Reason != "traversal sharing rule disabled" { + t.Fatalf("explicit sharing decision = %#v", optimized.OptimizationPolicy.Decisions) + } + for _, state := range optimized.OptimizationPolicy.RuleStates { + if state.Rule == PhysicalOptimizationRuleTraversalSharing && state.Enabled { + t.Fatalf("sharing rule state remained enabled: %#v", state) + } + } +} + +func TestBuildGenericPhysicalPlanPolicyDisablesPreparedSelectors(t *testing.T) { + status := Selector{Steps: []SelectorStep{{Field: "id"}}} + semantic := SemanticPlan{ + Version: 1, Project: "p", Root: SemanticNode{ + Alias: "root", ResourceType: "Patient", + Children: []SemanticNode{{ + Alias: "condition", ResourceType: "Condition", EdgeLabel: "subject_Patient", + Aggregates: []SemanticAggregate{{Name: "status_count", Operation: "COUNT_DISTINCT", Selector: &status}}, + Slices: []SemanticSlice{{Name: "representative", Limit: 1, Fields: []SemanticField{{Name: "status", Selector: status}}}}, + }}, + }, + } + policy := DefaultPhysicalOptimizationPolicy().WithRule(PhysicalOptimizationRuleCompactProjection, false).WithRule(PhysicalOptimizationRulePreparedSelectors, false) + plan, err := BuildGenericPhysicalPlanWithPolicy(semantic, policy) + if err != nil { + t.Fatal(err) + } + for _, operation := range plan.Operations { + if operation.Kind == PhysicalSetOp && operation.Set != nil && operation.Set.Prepared != nil { + t.Fatalf("prepared selector set survived explicit disable: %#v", operation.Set.Prepared) + } + } + rendered, err := RenderPhysicalPlan(plan) + if err != nil { + t.Fatal(err) + } + if strings.Contains(rendered.Query, "_prepared") { + t.Fatalf("prepared selector variable survived explicit disable:\n%s", rendered.Query) + } +} + +func TestBuildGenericPhysicalPlanCompactOutputPolicy(t *testing.T) { + semantic := SemanticPlan{ + Version: 1, Project: "p", Root: SemanticNode{ + Alias: "root", ResourceType: "Patient", + Children: []SemanticNode{{Alias: "condition", ResourceType: "Condition", EdgeLabel: "subject_Patient", Aggregates: []SemanticAggregate{{Name: "count", Operation: "COUNT"}}}}, + }, + } + fullPolicy := DefaultPhysicalOptimizationPolicy().WithRule(PhysicalOptimizationRuleCompactProjection, false) + full, err := BuildGenericPhysicalPlanWithPolicy(semantic, fullPolicy) + if err != nil { + t.Fatal(err) + } + compactPolicy := DefaultPhysicalOptimizationPolicy() + compact, err := BuildGenericPhysicalPlanWithPolicy(semantic, compactPolicy) + if err != nil { + t.Fatal(err) + } + var fullSet, compactSet *PhysicalSet + for _, operation := range full.Operations { + if operation.Kind == PhysicalSetOp { + fullSet = operation.Set + } + } + for _, operation := range compact.Operations { + if operation.Kind == PhysicalSetOp { + compactSet = operation.Set + } + } + if fullSet == nil || fullSet.Output != nil { + t.Fatalf("default policy unexpectedly retained compact output: %#v", fullSet) + } + if compactSet == nil || compactSet.Output == nil { + t.Fatalf("compact policy did not define output: %#v", compactSet) + } + if err := compact.Validate(); err != nil { + t.Fatalf("compact plan validation failed: %v", err) + } + if len(compactSet.Output.Fields) != 4 || compactSet.Output.Fields[0] != PhysicalSetGraphIDField || compactSet.Output.Fields[1] != PhysicalSetKeyField { + t.Fatalf("compact output fields = %#v, want graph identity plus metadata", compactSet.Output.Fields) + } } func TestOptimizePhysicalPlanRendersOneScopedTraversalForSiblingSets(t *testing.T) { @@ -129,8 +275,10 @@ func TestOptimizePhysicalPlanRendersOneScopedTraversalForSiblingSets(t *testing. if err != nil { t.Fatal(err) } - if got := strings.Count(rendered.Query, "INBOUND root @@child_set_"); got != 1 { - t.Fatalf("rendered sibling group used %d root traversals, want 1:\n%s", got, rendered.Query) + nativeRoot := strings.Count(rendered.Query, "INBOUND root @@child_set_") + endpointRoot := strings.Count(rendered.Query, "FOR child_set_1_edge IN @@child_set_1_edge_collection") + if got := nativeRoot + endpointRoot; got != 1 { + t.Fatalf("rendered sibling group used %d root edge operations, want 1 (native=%d endpoint=%d):\n%s", got, nativeRoot, endpointRoot, rendered.Query) } if got := strings.Count(rendered.Query, "child_set_1_edge.auth_resource_path IN @auth_resource_paths"); got != 1 { t.Fatalf("shared traversal did not retain its edge auth scope exactly once:\n%s", rendered.Query) diff --git a/internal/dataframe/physical_plan.go b/internal/dataframe/physical_plan.go index f47958b..432bf28 100644 --- a/internal/dataframe/physical_plan.go +++ b/internal/dataframe/physical_plan.go @@ -88,6 +88,17 @@ const ( PhysicalAny PhysicalTraversalDirection = "ANY" ) +// PhysicalTraversalStrategy selects the execution shape for a validated +// depth-one relationship. Native graph traversal is the conservative +// fallback. EndpointLookup is only legal when storage-route metadata proves +// the endpoint/discriminator fields and their compound index contract. +type PhysicalTraversalStrategy string + +const ( + PhysicalTraversalNative PhysicalTraversalStrategy = "NATIVE" + PhysicalTraversalEndpointLookup PhysicalTraversalStrategy = "ENDPOINT_LOOKUP" +) + type PhysicalTraversal struct { SourceVariable string TargetVariable string @@ -101,6 +112,13 @@ type PhysicalTraversal struct { // from_type; for a proven forward OUTBOUND route it is to_type. The node // resourceType check remains independently mandatory. EdgeTargetTypeField string + // Strategy is deliberately typed rather than an AQL fragment. Endpoint + // fields are supplied by resolveStorageRoute and validated against the + // direction before the renderer can use them. + Strategy PhysicalTraversalStrategy + EndpointField string + EndpointJoinField string + EndpointIndexFields []string } // PhysicalValue is either a variable/path reference or a bind variable. A @@ -141,6 +159,17 @@ const ( PhysicalObjectExpression PhysicalExpressionKind = "OBJECT" ) +// PhysicalSelectorExecutionMode records a schema-proven selector lowering. +// Generic is the safe fallback for predicates, fallbacks, choice paths, and +// unknown cardinality. +type PhysicalSelectorExecutionMode string + +const ( + PhysicalSelectorGeneric PhysicalSelectorExecutionMode = "GENERIC" + PhysicalSelectorDirectScalar PhysicalSelectorExecutionMode = "DIRECT_SCALAR" + PhysicalSelectorConditionalArray PhysicalSelectorExecutionMode = "CONDITIONAL_ARRAY" +) + // PhysicalExpression is a closed, renderer-independent value tree. It carries // no AQL source text: selector paths have already been parsed and all literals // are represented by bind values. @@ -166,7 +195,8 @@ type PhysicalExtract struct { Fallbacks []Selector // Distinct preserves the explicit DISTINCT projection mode after semantic // lowering. It is meaningful only for an array-valued expression. - Distinct bool + Distinct bool + ExecutionMode PhysicalSelectorExecutionMode // Prepared points at a selector value projected by a prepared child set. // Source remains the owning set for scope validation and diagnostics. Prepared *PhysicalPreparedReference @@ -249,6 +279,14 @@ type PhysicalSet struct { Variable string Subplan PhysicalSubplan Unique bool + // Output describes a compact, identity-safe projection of each set item. + // A nil output preserves the full stored document for shared traversal or + // other consumers that have not proved a smaller contract. + Output *PhysicalSetOutput + // Projection describes selector values computed in the original child-set + // subquery. It replaces the payload-bearing second prepared array when all + // downstream consumers have a projection-safe selector contract. + Projection *PhysicalSetProjection // SourceSetVariable is set for a typed subset over an already materialized // shared traversal. Such a set does not begin with TRAVERSAL; ItemVariable // is bound by the renderer while iterating SourceSetVariable. @@ -260,6 +298,39 @@ type PhysicalSet struct { Prepared *PhysicalPreparedSet } +// PhysicalSetProjection is a single-materialization selector projection. The +// fields are arrays because selector evaluation preserves repeated FHIR +// values; scalar consumers apply their normal FIRST/FLATTEN semantics when +// reading the projected field. +type PhysicalSetProjection struct { + Fields []PhysicalSetProjectionField +} + +type PhysicalSetProjectionField struct { + Name string + ResourceType string + Selector Selector + ExecutionMode PhysicalSelectorExecutionMode +} + +// PhysicalSetOutputField names the only stored properties that may survive a +// compact set projection. The graph identity fields preserve nested traversal +// and duplicate-edge semantics; payload is retained only when a downstream +// selector or rich consumer needs it. +type PhysicalSetOutputField string + +const ( + PhysicalSetGraphIDField PhysicalSetOutputField = "_id" + PhysicalSetKeyField PhysicalSetOutputField = "_key" + PhysicalSetIDField PhysicalSetOutputField = "id" + PhysicalSetResourceTypeField PhysicalSetOutputField = "resourceType" + PhysicalSetPayloadField PhysicalSetOutputField = "payload" +) + +type PhysicalSetOutput struct { + Fields []PhysicalSetOutputField +} + type PhysicalSubplan struct { Captures []string Operations []PhysicalOperation @@ -390,6 +461,9 @@ func (p PhysicalPlan) Validate() error { if traversal.EdgeTargetTypeField != "" && !physicalPathPartPattern.MatchString(traversal.EdgeTargetTypeField) { return fmt.Errorf("operation %d: unsafe traversal edge type field %q", i, traversal.EdgeTargetTypeField) } + if err := validatePhysicalTraversalStrategy(*traversal); err != nil { + return fmt.Errorf("operation %d: %w", i, err) + } for _, key := range []string{traversal.EdgeCollectionBindKey, traversal.EdgeLabelBindKey, traversal.TargetTypeBindKey} { if key != "" { if err := requireBind(p.BindVars, key); err != nil { @@ -471,7 +545,70 @@ func (p PhysicalPlan) Validate() error { return nil } +func validatePhysicalTraversalStrategy(traversal PhysicalTraversal) error { + strategy := traversal.Strategy + if strategy == "" || strategy == PhysicalTraversalNative { + return nil + } + if strategy != PhysicalTraversalEndpointLookup { + return fmt.Errorf("unsupported traversal strategy %q", strategy) + } + if traversal.Direction != PhysicalInbound && traversal.Direction != PhysicalOutbound { + return fmt.Errorf("endpoint lookup requires INBOUND or OUTBOUND direction") + } + if !physicalPathPartPattern.MatchString(traversal.EndpointField) || !physicalPathPartPattern.MatchString(traversal.EndpointJoinField) { + return fmt.Errorf("endpoint lookup requires safe endpoint and join fields") + } + if len(traversal.EndpointIndexFields) == 0 { + return fmt.Errorf("endpoint lookup requires declared compound index fields") + } + for _, field := range traversal.EndpointIndexFields { + if !physicalPathPartPattern.MatchString(field) { + return fmt.Errorf("endpoint lookup has unsafe index field %q", field) + } + } + return nil +} + func validatePhysicalSet(set PhysicalSet, parent map[string]bool, bindVars map[string]any) error { + if set.Projection != nil { + if len(set.Projection.Fields) == 0 { + return fmt.Errorf("set %q projection requires at least one field", set.Variable) + } + seenProjectionFields := map[string]bool{} + for _, field := range set.Projection.Fields { + if !physicalVariablePattern.MatchString(field.Name) || seenProjectionFields[field.Name] { + return fmt.Errorf("set %q projection field %q is unsafe or duplicated", set.Variable, field.Name) + } + seenProjectionFields[field.Name] = true + if strings.TrimSpace(field.ResourceType) == "" || !fhirschema.HasResource(field.ResourceType) { + return fmt.Errorf("set %q projection field %q has invalid resource type %q", set.Variable, field.Name, field.ResourceType) + } + if err := validatePhysicalSelector(field.ResourceType, field.Selector); err != nil { + return fmt.Errorf("set %q projection field %q selector: %w", set.Variable, field.Name, err) + } + } + } + if set.Output != nil { + if len(set.Output.Fields) == 0 { + return fmt.Errorf("set %q compact output requires at least one retained field", set.Variable) + } + seenOutputFields := map[PhysicalSetOutputField]bool{} + for _, field := range set.Output.Fields { + switch field { + case PhysicalSetGraphIDField, PhysicalSetKeyField, PhysicalSetIDField, PhysicalSetResourceTypeField, PhysicalSetPayloadField: + default: + return fmt.Errorf("set %q compact output field %q is unsupported", set.Variable, field) + } + if seenOutputFields[field] { + return fmt.Errorf("set %q compact output field %q is duplicated", set.Variable, field) + } + seenOutputFields[field] = true + } + if !seenOutputFields[PhysicalSetGraphIDField] || !seenOutputFields[PhysicalSetKeyField] { + return fmt.Errorf("set %q compact output must retain _id and _key", set.Variable) + } + } if set.Prepared != nil { prepared := set.Prepared if !physicalVariablePattern.MatchString(prepared.Variable) || !physicalVariablePattern.MatchString(prepared.SourceSetVariable) { @@ -888,6 +1025,15 @@ func validatePhysicalExtract(extract PhysicalExtract, defined map[string]bool, b if err := validatePhysicalSelector(extract.ResourceType, extract.Selector); err != nil { return fmt.Errorf("extract selector: %w", err) } + if extract.ExecutionMode != "" && extract.ExecutionMode != PhysicalSelectorGeneric && extract.ExecutionMode != PhysicalSelectorDirectScalar && extract.ExecutionMode != PhysicalSelectorConditionalArray { + return fmt.Errorf("unknown selector execution mode %q", extract.ExecutionMode) + } + if extract.ExecutionMode == PhysicalSelectorDirectScalar && (len(extract.Fallbacks) != 0 || extract.Selector.Filter != nil || !selectorHasNoArrays(extract.Selector)) { + return fmt.Errorf("direct scalar selector mode requires one fallback-free non-repeated selector") + } + if extract.ExecutionMode == PhysicalSelectorConditionalArray && (len(extract.Fallbacks) != 0 || extract.Selector.Filter != nil || !selectorHasIteratedArray(extract.Selector)) { + return fmt.Errorf("conditional array selector mode requires one fallback-free repeated selector") + } for index, fallback := range extract.Fallbacks { if err := validatePhysicalSelector(extract.ResourceType, fallback); err != nil { return fmt.Errorf("extract fallback %d: %w", index, err) @@ -1101,6 +1247,9 @@ func validatePhysicalSubplan(subplan PhysicalSubplan, parent map[string]bool, bi if traversal.EdgeTargetTypeField != "" && !physicalPathPartPattern.MatchString(traversal.EdgeTargetTypeField) { return fmt.Errorf("subplan operation %d: unsafe traversal edge type field %q", index, traversal.EdgeTargetTypeField) } + if err := validatePhysicalTraversalStrategy(*traversal); err != nil { + return fmt.Errorf("subplan operation %d: %w", index, err) + } if err := requireCollectionBind(bindVars, traversal.EdgeCollectionBindKey); err != nil { return fmt.Errorf("subplan operation %d: %w", index, err) } diff --git a/internal/dataframe/physical_render.go b/internal/dataframe/physical_render.go index e4460f8..6c9e22d 100644 --- a/internal/dataframe/physical_render.go +++ b/internal/dataframe/physical_render.go @@ -94,12 +94,28 @@ func RenderPhysicalPlan(plan PhysicalPlan) (RenderedPhysicalPlan, error) { return RenderedPhysicalPlan{}, fmt.Errorf("render RETURN: %w", err) } lines = append(lines, "RETURN "+returnExpression) + query := strings.Join(lines, "\n") + "\n" return RenderedPhysicalPlan{ - Query: strings.Join(lines, "\n") + "\n", - BindVars: renderer.bindVars, + Query: query, + BindVars: pruneUnusedRuntimeBindVars(renderer.bindVars, query), }, nil } +// pruneUnusedRuntimeBindVars is required after physical rewrites. Traversal +// sharing can remove a typed edge predicate while retaining its original +// logical bind in the cloned plan. Arango rejects undeclared bind variables, +// so only values referenced by the final rendered AQL may cross the execution +// boundary. +func pruneUnusedRuntimeBindVars(bindVars map[string]any, query string) map[string]any { + pruned := make(map[string]any, len(bindVars)) + for key, value := range bindVars { + if strings.Contains(query, "@"+key) { + pruned[key] = value + } + } + return pruned +} + func (r *physicalPlanRenderer) renderRootWindowOperation(operation PhysicalOperation, indent string) ([]string, error) { switch operation.Kind { case PhysicalSortOp: @@ -261,6 +277,32 @@ func validateGenericNavigationTraversal(plan PhysicalPlan, traversal PhysicalTra if !ok || collection != "fhir_edge" { return fmt.Errorf("generic navigation traversal must use fhir_edge through its collection bind") } + strategy := traversal.Strategy + if strategy == "" { + strategy = PhysicalTraversalNative + } + if strategy != PhysicalTraversalNative && strategy != PhysicalTraversalEndpointLookup { + return fmt.Errorf("unsupported generic navigation traversal strategy %q", strategy) + } + if strategy == PhysicalTraversalEndpointLookup { + wantEndpoint, wantJoin := "_to", "_from" + wantIndexType := "from_type" + if traversal.Direction == PhysicalOutbound { + wantEndpoint, wantJoin, wantIndexType = "_from", "_to", "to_type" + } + if traversal.EndpointField != wantEndpoint || traversal.EndpointJoinField != wantJoin { + return fmt.Errorf("endpoint lookup %s requires %s -> %s, got %s -> %s", traversal.Direction, wantEndpoint, wantJoin, traversal.EndpointField, traversal.EndpointJoinField) + } + wantIndex := []string{wantEndpoint, "project", "dataset_generation", "label", wantIndexType} + if len(traversal.EndpointIndexFields) != len(wantIndex) { + return fmt.Errorf("endpoint lookup requires compound index fields %#v", wantIndex) + } + for index := range wantIndex { + if traversal.EndpointIndexFields[index] != wantIndex[index] { + return fmt.Errorf("endpoint lookup index field %d = %q, want %q", index, traversal.EndpointIndexFields[index], wantIndex[index]) + } + } + } return nil } @@ -387,12 +429,28 @@ func (r *physicalPlanRenderer) renderTraversalSet(block physicalNavigationTraver lines = append(lines, fmt.Sprintf(" FOR %s IN %s", parentVariable, parentSet)) traversalIndent = " " } - lines = append(lines, - fmt.Sprintf("%sFOR %s, %s IN 1..1 %s %s @@%s", traversalIndent, traversal.TargetVariable, traversal.EdgeVariable, traversal.Direction, parentVariable, traversal.EdgeCollectionBindKey), - fmt.Sprintf("%s FILTER %s.label == @%s", traversalIndent, traversal.EdgeVariable, traversal.EdgeLabelBindKey), - fmt.Sprintf("%s FILTER %s.%s == @%s", traversalIndent, traversal.EdgeVariable, traversal.EdgeTargetTypeField, traversal.TargetTypeBindKey), - fmt.Sprintf("%s FILTER %s.resourceType == @%s", traversalIndent, traversal.TargetVariable, traversal.TargetTypeBindKey), - ) + strategy := traversal.Strategy + if strategy == "" { + strategy = PhysicalTraversalNative + } + if strategy == PhysicalTraversalEndpointLookup { + lines = append(lines, + fmt.Sprintf("%sFOR %s IN @@%s", traversalIndent, traversal.EdgeVariable, traversal.EdgeCollectionBindKey), + fmt.Sprintf("%s FILTER %s.%s == %s._id", traversalIndent, traversal.EdgeVariable, traversal.EndpointField, parentVariable), + fmt.Sprintf("%s FILTER %s.label == @%s", traversalIndent, traversal.EdgeVariable, traversal.EdgeLabelBindKey), + fmt.Sprintf("%s FILTER %s.%s == @%s", traversalIndent, traversal.EdgeVariable, traversal.EdgeTargetTypeField, traversal.TargetTypeBindKey), + fmt.Sprintf("%s LET %s = DOCUMENT(%s.%s)", traversalIndent, traversal.TargetVariable, traversal.EdgeVariable, traversal.EndpointJoinField), + fmt.Sprintf("%s FILTER %s != null", traversalIndent, traversal.TargetVariable), + fmt.Sprintf("%s FILTER %s.resourceType == @%s", traversalIndent, traversal.TargetVariable, traversal.TargetTypeBindKey), + ) + } else { + lines = append(lines, + fmt.Sprintf("%sFOR %s, %s IN 1..1 %s %s @@%s", traversalIndent, traversal.TargetVariable, traversal.EdgeVariable, traversal.Direction, parentVariable, traversal.EdgeCollectionBindKey), + fmt.Sprintf("%s FILTER %s.label == @%s", traversalIndent, traversal.EdgeVariable, traversal.EdgeLabelBindKey), + fmt.Sprintf("%s FILTER %s.%s == @%s", traversalIndent, traversal.EdgeVariable, traversal.EdgeTargetTypeField, traversal.TargetTypeBindKey), + fmt.Sprintf("%s FILTER %s.resourceType == @%s", traversalIndent, traversal.TargetVariable, traversal.TargetTypeBindKey), + ) + } for scopeIndex, operation := range block.scope { line, err := r.renderScopeOperation(operation, traversalIndent+" ") if err != nil { @@ -425,9 +483,42 @@ func (r *physicalPlanRenderer) renderSet(set PhysicalSet, index int) ([]string, lines = append(lines, fmt.Sprintf(" FOR %s IN %s", parentVariable, parentSet)) indent = " " } - lines = append(lines, fmt.Sprintf("%sFOR %s, %s IN 1..1 %s %s @@%s", indent, t.TargetVariable, t.EdgeVariable, t.Direction, parentVariable, t.EdgeCollectionBindKey), fmt.Sprintf("%s FILTER %s.label == @%s", indent, t.EdgeVariable, t.EdgeLabelBindKey)) - if t.EdgeTargetTypeField != "" { - lines = append(lines, r.renderTraversalTypeFilters(t, indent)...) + strategy := t.Strategy + if strategy == "" { + strategy = PhysicalTraversalNative + } + if strategy == PhysicalTraversalEndpointLookup { + // The endpoint equality is the first edge predicate so Arango can use + // the route's compound endpoint index. The node is materialized only + // after edge scope/type predicates have narrowed the candidate set. + lines = append(lines, + fmt.Sprintf("%sFOR %s IN @@%s", indent, t.EdgeVariable, t.EdgeCollectionBindKey), + fmt.Sprintf("%s FILTER %s.%s == %s._id", indent, t.EdgeVariable, t.EndpointField, parentVariable), + fmt.Sprintf("%s FILTER %s.label == @%s", indent, t.EdgeVariable, t.EdgeLabelBindKey), + ) + if t.TargetTypeBindKey != "" && t.EdgeTargetTypeField != "" { + if _, ok := r.bindVars[t.TargetTypeBindKey].([]string); ok { + lines = append(lines, fmt.Sprintf("%s FILTER POSITION(@%s, %s.%s)", indent, t.TargetTypeBindKey, t.EdgeVariable, t.EdgeTargetTypeField)) + } else { + lines = append(lines, fmt.Sprintf("%s FILTER %s.%s == @%s", indent, t.EdgeVariable, t.EdgeTargetTypeField, t.TargetTypeBindKey)) + } + } + lines = append(lines, + fmt.Sprintf("%s LET %s = DOCUMENT(%s.%s)", indent, t.TargetVariable, t.EdgeVariable, t.EndpointJoinField), + fmt.Sprintf("%s FILTER %s != null", indent, t.TargetVariable), + ) + if t.TargetTypeBindKey != "" { + if _, ok := r.bindVars[t.TargetTypeBindKey].([]string); ok { + lines = append(lines, fmt.Sprintf("%s FILTER POSITION(@%s, %s.resourceType)", indent, t.TargetTypeBindKey, t.TargetVariable)) + } else { + lines = append(lines, fmt.Sprintf("%s FILTER %s.resourceType == @%s", indent, t.TargetVariable, t.TargetTypeBindKey)) + } + } + } else { + lines = append(lines, fmt.Sprintf("%sFOR %s, %s IN 1..1 %s %s @@%s", indent, t.TargetVariable, t.EdgeVariable, t.Direction, parentVariable, t.EdgeCollectionBindKey), fmt.Sprintf("%s FILTER %s.label == @%s", indent, t.EdgeVariable, t.EdgeLabelBindKey)) + if t.EdgeTargetTypeField != "" { + lines = append(lines, r.renderTraversalTypeFilters(t, indent)...) + } } for opIndex, operation := range set.Subplan.Operations[1:] { rendered, err := r.renderScopeOperation(operation, indent+" ") @@ -440,6 +531,14 @@ func (r *physicalPlanRenderer) renderSet(set PhysicalSet, index int) ([]string, if err != nil { return nil, err } + if set.Projection != nil { + value, err = r.renderPhysicalSetProjection(t.TargetVariable, *set.Projection) + } else { + value, err = renderPhysicalSetOutput(value, set.Output) + } + if err != nil { + return nil, err + } if set.SortByKey { lines = append(lines, indent+" SORT "+t.TargetVariable+"._key") } @@ -461,13 +560,61 @@ func (r *physicalPlanRenderer) renderSet(set PhysicalSet, index int) ([]string, return lines, nil } +func renderPhysicalSetOutput(value string, output *PhysicalSetOutput) (string, error) { + if output == nil { + return value, nil + } + fields := make([]string, 0, len(output.Fields)) + for _, field := range output.Fields { + name := string(field) + switch field { + case PhysicalSetGraphIDField, PhysicalSetKeyField, PhysicalSetIDField, PhysicalSetResourceTypeField, PhysicalSetPayloadField: + fields = append(fields, fmt.Sprintf("%s: %s.%s", name, value, name)) + default: + return "", fmt.Errorf("unsupported compact set output field %q", field) + } + } + return "{ " + strings.Join(fields, ", ") + " }", nil +} + +func (r *physicalPlanRenderer) renderPhysicalSetProjection(item string, projection PhysicalSetProjection) (string, error) { + if len(projection.Fields) == 0 { + return "", fmt.Errorf("set projection requires at least one field") + } + fields := []string{ + "_id: " + item + "._id", + "_key: " + item + "._key", + "id: " + item + ".id", + "resourceType: " + item + ".resourceType", + } + for _, field := range projection.Fields { + values, err := r.renderSelectorByMode(item+".payload", field.Selector, field.ExecutionMode) + if err != nil { + return "", fmt.Errorf("projected field %q: %w", field.Name, err) + } + fields = append(fields, field.Name+": "+values) + } + return "{ " + strings.Join(fields, ", ") + " }", nil +} + func (r *physicalPlanRenderer) renderPreparedSet(prepared PhysicalPreparedSet) ([]string, error) { if r.setVariables[prepared.SourceSetVariable] == "" { return nil, fmt.Errorf("prepared source set %q has not been rendered", prepared.SourceSetVariable) } item := r.newInternalVariable("prepared_item") lines := []string{fmt.Sprintf(" LET %s = (", prepared.Variable), fmt.Sprintf(" FOR %s IN %s", item, prepared.SourceSetVariable)} - fields := []string{fmt.Sprintf("_key: %s._key", item), fmt.Sprintf("__loom_prepared_node: %s", item)} + // Rich consumers may combine a prepared selector with a direct payload + // fallback (slice identity, an unprepared pivot value, or a nested object + // field). Preserve the node-facing fields those consumers already read while + // adding prepared projections; the optimizer can remove this retention only + // after a separate compact-set contract proves it safe. + fields := []string{ + fmt.Sprintf("_key: %s._key", item), + fmt.Sprintf("id: %s.id", item), + fmt.Sprintf("resourceType: %s.resourceType", item), + fmt.Sprintf("payload: %s.payload", item), + fmt.Sprintf("__loom_prepared_node: %s", item), + } for _, field := range prepared.Fields { values, err := r.renderSelectorArrayFromSource(item+".payload", field.Selector, false) if err != nil { @@ -485,8 +632,8 @@ func (r *physicalPlanRenderer) renderTraversalTypeFilters(t *PhysicalTraversal, } if _, ok := r.bindVars[t.TargetTypeBindKey].([]string); ok { return []string{ - fmt.Sprintf("%s FILTER POSITION(@%s, %s.%s, true)", indent, t.TargetTypeBindKey, t.EdgeVariable, t.EdgeTargetTypeField), - fmt.Sprintf("%s FILTER POSITION(@%s, %s.resourceType, true)", indent, t.TargetTypeBindKey, t.TargetVariable), + fmt.Sprintf("%s FILTER POSITION(@%s, %s.%s)", indent, t.TargetTypeBindKey, t.EdgeVariable, t.EdgeTargetTypeField), + fmt.Sprintf("%s FILTER POSITION(@%s, %s.resourceType)", indent, t.TargetTypeBindKey, t.TargetVariable), } } return []string{fmt.Sprintf("%s FILTER %s.%s == @%s", indent, t.EdgeVariable, t.EdgeTargetTypeField, t.TargetTypeBindKey), fmt.Sprintf("%s FILTER %s.resourceType == @%s", indent, t.TargetVariable, t.TargetTypeBindKey)} @@ -508,6 +655,14 @@ func (r *physicalPlanRenderer) renderSharedSubset(set PhysicalSet) ([]string, er if err != nil { return nil, err } + if set.Projection != nil { + value, err = r.renderPhysicalSetProjection(set.ItemVariable, *set.Projection) + } else { + value, err = renderPhysicalSetOutput(value, set.Output) + } + if err != nil { + return nil, err + } if set.SortByKey { lines = append(lines, " SORT "+set.ItemVariable+"._key") } @@ -517,6 +672,14 @@ func (r *physicalPlanRenderer) renderSharedSubset(set PhysicalSet) ([]string, er lines[len(lines)-1] = " ))" } r.setVariables[set.Variable] = set.Variable + if set.Prepared != nil { + prepared, err := r.renderPreparedSet(*set.Prepared) + if err != nil { + return nil, err + } + lines = append(lines, prepared...) + r.setVariables[set.Prepared.Variable] = set.Prepared.Variable + } return lines, nil } @@ -601,7 +764,7 @@ func (r *physicalPlanRenderer) renderSelectorPredicate(predicate PhysicalPredica case "NOT_EQUALS": match = valueVar + " != " + right case "IN": - match = "POSITION(" + right + ", " + valueVar + ", true)" + match = "POSITION(" + right + ", " + valueVar + ")" case "CONTAINS_TEXT": match = "CONTAINS(TO_STRING(" + valueVar + "), " + right + ")" case "GT", "GTE", "LT", "LTE": @@ -924,7 +1087,7 @@ func (r *physicalPlanRenderer) renderPivot(expression PhysicalExpression) (strin LET __pivot_values = %s FILTER LENGTH(__pivot_values) > 0 FOR __pivot_key IN __pivot_keys - FILTER POSITION(@%s, __pivot_key, true) + FILTER POSITION(@%s, __pivot_key) RETURN { key: __pivot_key, values: __pivot_values } ) COLLECT __pivot_key = __pair.key INTO __pivot_group @@ -1088,6 +1251,26 @@ func (r *physicalPlanRenderer) renderExtract(expression PhysicalExpression) (str if err != nil { return "", err } + if len(extract.Fallbacks) == 0 && extract.Selector.Filter == nil { + switch extract.ExecutionMode { + case PhysicalSelectorDirectScalar: + if expression.Cardinality != PhysicalArrayCardinality { + return compileDirectExpr(source, extract.Selector.Steps), nil + } + case PhysicalSelectorConditionalArray: + values, err := r.renderConditionalSelectorArray(source, extract.Selector) + if err != nil { + return "", err + } + if expression.Cardinality == PhysicalArrayCardinality { + if extract.Distinct { + return "SORTED_UNIQUE(" + values + ")", nil + } + return values, nil + } + return "FIRST(" + values + ")", nil + } + } arrays := make([]string, 0, 1+len(extract.Fallbacks)) setSource := extract.Source.Variable != "" && r.setVariables[extract.Source.Variable] != "" for _, selector := range append([]Selector{extract.Selector}, extract.Fallbacks...) { @@ -1113,6 +1296,39 @@ func (r *physicalPlanRenderer) renderExtract(expression PhysicalExpression) (str return "FIRST(" + values + ")", nil } +func (r *physicalPlanRenderer) renderSelectorByMode(source string, selector Selector, mode PhysicalSelectorExecutionMode) (string, error) { + if mode == PhysicalSelectorDirectScalar && selectorHasNoArrays(selector) && selector.Filter == nil { + return "(FOR __loom_value IN [" + compileDirectExpr(source, selector.Steps) + "] FILTER __loom_value != null RETURN __loom_value)", nil + } + if mode == PhysicalSelectorConditionalArray && selectorHasIteratedArray(selector) && selector.Filter == nil { + return r.renderConditionalSelectorArray(source, selector) + } + return r.renderSelectorArrayFromSource(source, selector, false) +} + +func (r *physicalPlanRenderer) renderConditionalSelectorArray(source string, selector Selector) (string, error) { + if len(selector.Steps) == 0 { + return "", fmt.Errorf("selector is required") + } + prefix, last := selector.Steps[:len(selector.Steps)-1], selector.Steps[len(selector.Steps)-1] + lines := make([]string, 0, len(prefix)+3) + current := source + for index, step := range prefix { + next := fmt.Sprintf("__loom_selector_%d", index) + switch { + case step.Iterate: + lines = append(lines, fmt.Sprintf("FOR %s IN (%s.%s ? %s.%s : [])", next, current, step.Field, current, step.Field)) + case step.Index != nil: + lines = append(lines, fmt.Sprintf("LET %s = ((%s.%s ? %s.%s : [])[%d])", next, current, step.Field, current, step.Field, *step.Index), "FILTER "+next+" != null") + default: + lines = append(lines, fmt.Sprintf("LET %s = %s.%s", next, current, step.Field), "FILTER "+next+" != null") + } + current = next + } + lines = append(lines, "LET __value = "+extractFinalExpr(current, last), "FILTER __value != null", "RETURN __value") + return "(\n " + strings.Join(lines, "\n ") + "\n )", nil +} + func (r *physicalPlanRenderer) renderSelectorArrayFromSource(source string, selector Selector, setSource bool) (string, error) { if len(selector.Steps) == 0 { return "", fmt.Errorf("selector is required") diff --git a/internal/dataframe/physical_render_test.go b/internal/dataframe/physical_render_test.go index cb71701..ca5aa68 100644 --- a/internal/dataframe/physical_render_test.go +++ b/internal/dataframe/physical_render_test.go @@ -98,8 +98,13 @@ func TestRenderPhysicalPlanTraversalSetsPreserveRootRowGrain(t *testing.T) { setTwo := strings.Index(rendered.Query, "\n LET __loom_physical_set_2 = (") parentLoop := strings.Index(rendered.Query, "\n FOR __loom_physical_parent_2 IN __loom_physical_set_1") secondTraversal := strings.Index(rendered.Query, "\n FOR node_2, edge_2 IN 1..1 INBOUND __loom_physical_parent_2 @@traversal_2_edge_collection") + secondEndpoint := strings.Index(rendered.Query, "\n FOR edge_2 IN @@traversal_2_edge_collection") outerReturn := strings.LastIndex(rendered.Query, "\nRETURN { [@__loom_physical_projection_0_name]: root._key }") - if setOne < 0 || firstTraversal < setOne || setTwo < firstTraversal || parentLoop < setTwo || secondTraversal < parentLoop || outerReturn < secondTraversal { + secondTraversalEnd := secondTraversal + if secondTraversalEnd < 0 { + secondTraversalEnd = secondEndpoint + } + if setOne < 0 || firstTraversal < setOne || setTwo < firstTraversal || parentLoop < setTwo || secondTraversalEnd < parentLoop || outerReturn < secondTraversalEnd { t.Fatalf("nested traversal sets did not preserve outer root shape:\n%s", rendered.Query) } if strings.Contains(rendered.Query, "\nFOR node_1") || strings.Contains(rendered.Query, "\nFOR node_2") { @@ -145,6 +150,17 @@ func TestRenderPhysicalPlanIsDeterministicAndCopiesBindVars(t *testing.T) { } } +func TestPruneUnusedRuntimeBindVars(t *testing.T) { + bindVars := map[string]any{"used": 1, "unused": 2} + got := pruneUnusedRuntimeBindVars(bindVars, "FOR doc IN c FILTER @used == 1 RETURN doc") + if _, ok := got["used"]; !ok { + t.Fatalf("used bind was pruned: %#v", got) + } + if _, ok := got["unused"]; ok { + t.Fatalf("unused bind was retained: %#v", got) + } +} + func TestRenderPhysicalPlanNestedObjectExpression(t *testing.T) { plan, err := BuildGenericPhysicalPlan(SemanticPlan{ Version: 1, Project: "project-1", AuthResourcePaths: []string{"/programs/p1"}, diff --git a/internal/dataframe/root_endpoint_experiment_test.go b/internal/dataframe/root_endpoint_experiment_test.go new file mode 100644 index 0000000..7017763 --- /dev/null +++ b/internal/dataframe/root_endpoint_experiment_test.go @@ -0,0 +1,274 @@ +package dataframe_test + +// Opt-in, read-only tournament for the broad root sibling hop. The incumbent +// is the current endpoint+typed-selector AQL artifact; this test rewrites only +// its root depth-one traversal and never edits compiler or index definitions. + +import ( + "context" + "encoding/json" + "fmt" + "os" + "path/filepath" + "regexp" + "runtime" + "strings" + "testing" + "time" + + arangostore "github.com/calypr/loom/internal/store/arango" +) + +const incumbentSelectorAQLSHA = "ad8542e8f158d6443b047c63f5cbffd54264c6d2c63fa5bfbbfe87d84e0fa79d" + +type rootEndpointRun struct { + Name string `json:"name"` + QuerySHA256 string `json:"query_sha256"` + ResultSHA256 string `json:"result_sha256"` + Rows int `json:"rows"` + Bytes []int `json:"bytes"` + WarmSeconds []float64 `json:"warm_seconds"` + MedianSeconds float64 `json:"median_seconds"` + MinSeconds float64 `json:"min_seconds"` + Explain arangostore.ExplainAssessment `json:"explain"` + Profile rootEndpointProfile `json:"profile"` + RawProfile arangostore.ProfileResult `json:"-"` +} + +type rootEndpointProfile struct { + ScannedFull int `json:"scanned_full"` + ScannedIndex int `json:"scanned_index"` + PeakMemoryBytes uint64 `json:"peak_memory_bytes"` + Phases arangostore.ProfilePhases `json:"phases"` + TopNodes []arangostore.ProfileNodeSummary `json:"top_nodes"` +} + +func TestRootEndpointCandidateRendersFromFrozenIncumbent(t *testing.T) { + incumbent, binds := loadFrozenIncumbent(t) + candidate, rewrite, err := rewriteRootEndpoint(incumbent) + if err != nil { + t.Fatal(err) + } + if rewrite.Direction != "INBOUND" || rewrite.Endpoint != "_to" || rewrite.TargetEndpoint != "_from" { + t.Fatalf("unexpected root rewrite metadata: %#v", rewrite) + } + if !strings.Contains(candidate, "FILTER "+rewrite.Edge+"._to == root._id") || !strings.Contains(candidate, "DOCUMENT("+rewrite.Edge+"._from)") { + t.Fatalf("candidate omitted endpoint equality/document lookup:\n%s", candidate[:minRootLen(len(candidate), 5000)]) + } + if strings.Contains(candidate, "IN 1..1 INBOUND root @@") { + t.Fatalf("candidate retained native root traversal") + } + if _, ok := binds["@root_collection"]; !ok { + t.Fatalf("frozen incumbent bind variables lost root collection bind") + } +} + +func TestRootEndpointProfilesAgainstFrozenIncumbent(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run root endpoint tournament against Arango") + } + incumbent, binds := loadFrozenIncumbent(t) + candidate, rewrite, err := rewriteRootEndpoint(incumbent) + if err != nil { + t.Fatal(err) + } + url, database, _ := compilerArangoTarget() + client, err := arangostore.Open(context.Background(), url, database) + if err != nil { + t.Fatal(err) + } + defer client.Close(context.Background()) + ctx, cancel := context.WithTimeout(context.Background(), 20*time.Minute) + defer cancel() + control, candidateRun, err := runRootEndpointAlternating(ctx, client, incumbent, candidate, binds) + if err != nil { + t.Fatal(err) + } + if control.ResultSHA256 != candidateRun.ResultSHA256 { + t.Fatalf("result parity mismatch control=%s candidate=%s", control.ResultSHA256, candidateRun.ResultSHA256) + } + if candidateRun.MedianSeconds >= control.MedianSeconds { + t.Logf("root endpoint candidate rejected for regression: control=%.6fs candidate=%.6fs", control.MedianSeconds, candidateRun.MedianSeconds) + } else { + t.Logf("root endpoint candidate improvement=%.2f%% control=%.6fs candidate=%.6fs direction=%s endpoint=%s target_endpoint=%s", 100*(control.MedianSeconds-candidateRun.MedianSeconds)/control.MedianSeconds, control.MedianSeconds, candidateRun.MedianSeconds, rewrite.Direction, rewrite.Endpoint, rewrite.TargetEndpoint) + } + writeRootEndpointArtifacts(t, incumbent, candidate, binds, rewrite, control, candidateRun) +} + +type rootEndpointRewrite struct { + Node string `json:"node"` + Edge string `json:"edge"` + Direction string `json:"direction"` + Endpoint string `json:"endpoint"` + TargetEndpoint string `json:"target_endpoint"` + Collection string `json:"collection"` +} + +var rootTraversalHeaderRE = regexp.MustCompile(`(?m)^(\s*)FOR ([A-Za-z_][A-Za-z0-9_]*_node), ([A-Za-z_][A-Za-z0-9_]*_edge) IN 1\.\.1 (INBOUND|OUTBOUND) root (@@[A-Za-z_][A-Za-z0-9_]*_edge_collection)\n`) + +func rewriteRootEndpoint(query string) (string, rootEndpointRewrite, error) { + matches := rootTraversalHeaderRE.FindAllStringSubmatchIndex(query, -1) + if len(matches) != 1 { + return query, rootEndpointRewrite{}, fmt.Errorf("expected one root depth-one traversal, found %d", len(matches)) + } + m := matches[0] + indent := query[m[2]:m[3]] + node := query[m[4]:m[5]] + edge := query[m[6]:m[7]] + direction := query[m[8]:m[9]] + collection := query[m[10]:m[11]] + endpoint, target := "_to", "_from" + if direction == "OUTBOUND" { + endpoint, target = "_from", "_to" + } + replacement := indent + "FOR " + edge + " IN " + collection + "\n" + + indent + " FILTER " + edge + "." + endpoint + " == root._id\n" + + indent + " LET " + node + " = DOCUMENT(" + edge + "." + target + ")\n" + return query[:m[0]] + replacement + query[m[1]:], rootEndpointRewrite{Node: node, Edge: edge, Direction: direction, Endpoint: endpoint, TargetEndpoint: target, Collection: collection}, nil +} + +func loadFrozenIncumbent(t *testing.T) (string, map[string]any) { + _, source, _, _ := runtime.Caller(0) + root := filepath.Join(filepath.Dir(source), "..", "..") + queryPath := filepath.Join(root, "docs", "benchmarks", "round4", "wp2_selector_combo", "candidate.aql") + reportPath := filepath.Join(root, "docs", "benchmarks", "round4", "wp2", "integrated.json") + queryBytes, err := os.ReadFile(queryPath) + if err != nil { + t.Fatalf("read incumbent selector AQL: %v", err) + } + query := strings.TrimSuffix(strings.TrimSuffix(string(queryBytes), "\n"), "\r") + if sha256Hex(query) != incumbentSelectorAQLSHA { + t.Fatalf("incumbent selector AQL hash changed: got %s want %s", sha256Hex(query), incumbentSelectorAQLSHA) + } + reportBytes, err := os.ReadFile(reportPath) + if err != nil { + t.Fatalf("read incumbent bind report: %v", err) + } + var report struct { + BindVars map[string]any `json:"bind_vars"` + } + if err := json.Unmarshal(reportBytes, &report); err != nil { + t.Fatalf("decode incumbent bind report: %v", err) + } + return query, report.BindVars +} + +func runRootEndpointAlternating(ctx context.Context, client *arangostore.Client, incumbent, candidate string, baseBinds map[string]any) (rootEndpointRun, rootEndpointRun, error) { + control := rootEndpointRun{Name: "incumbent_endpoint_selector", QuerySHA256: sha256Hex(incumbent)} + candidateRun := rootEndpointRun{Name: "root_endpoint_endpoint_selector", QuerySHA256: sha256Hex(candidate)} + for i := 0; i < 5; i++ { + controlQuery, controlBinds := cacheBust(incumbent, baseBinds, 12000+i) + candidateQuery, candidateBinds := cacheBust(candidate, baseBinds, 13000+i) + controlSeconds, controlBytes, controlHash, err := executeOrdinary(ctx, client, controlQuery, controlBinds) + if err != nil { + return control, candidateRun, fmt.Errorf("control run %d: %w", i+1, err) + } + candidateSeconds, candidateBytes, candidateHash, err := executeOrdinary(ctx, client, candidateQuery, candidateBinds) + if err != nil { + return control, candidateRun, fmt.Errorf("candidate run %d: %w", i+1, err) + } + control.WarmSeconds = append(control.WarmSeconds, controlSeconds) + control.Bytes = append(control.Bytes, controlBytes) + control.ResultSHA256 = controlHash + control.Rows = 1000 + candidateRun.WarmSeconds = append(candidateRun.WarmSeconds, candidateSeconds) + candidateRun.Bytes = append(candidateRun.Bytes, candidateBytes) + candidateRun.ResultSHA256 = candidateHash + candidateRun.Rows = 1000 + } + control.MedianSeconds, control.MinSeconds = median(control.WarmSeconds), minFloatRoot(control.WarmSeconds) + candidateRun.MedianSeconds, candidateRun.MinSeconds = median(candidateRun.WarmSeconds), minFloatRoot(candidateRun.WarmSeconds) + controlProfileQuery, controlProfileBinds := cacheBust(incumbent, baseBinds, 14001) + candidateProfileQuery, candidateProfileBinds := cacheBust(candidate, baseBinds, 14002) + controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: controlProfileQuery, BindVars: controlProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + return control, candidateRun, fmt.Errorf("control PROFILE: %w", err) + } + candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidateProfileQuery, BindVars: candidateProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + return control, candidateRun, fmt.Errorf("candidate PROFILE: %w", err) + } + control.Explain, err = explainRoot(ctx, client, incumbent, baseBinds) + if err != nil { + return control, candidateRun, err + } + candidateRun.Explain, err = explainRoot(ctx, client, candidate, baseBinds) + if err != nil { + return control, candidateRun, err + } + control.RawProfile, candidateRun.RawProfile = controlProfile, candidateProfile + control.Profile, candidateRun.Profile = summarizeRootProfile(controlProfile), summarizeRootProfile(candidateProfile) + return control, candidateRun, nil +} + +func explainRoot(ctx context.Context, client *arangostore.Client, query string, binds map[string]any) (arangostore.ExplainAssessment, error) { + explain, err := client.Explain(ctx, arangostore.ExplainRequest{Query: query, BindVars: binds}) + if err != nil { + return arangostore.ExplainAssessment{}, err + } + assessment := arangostore.AssessExplainResult(explain) + if len(assessment.FullCollectionScans) != 0 { + return assessment, fmt.Errorf("root endpoint candidate has full scans: %#v", assessment.FullCollectionScans) + } + return assessment, nil +} + +func summarizeRootProfile(profile arangostore.ProfileResult) rootEndpointProfile { + summary := arangostore.SummarizeProfile(profile) + nodes := append([]arangostore.ProfileNodeSummary(nil), summary.Nodes...) + if len(nodes) > 20 { + nodes = nodes[:20] + } + return rootEndpointProfile{ScannedFull: summary.ScannedFull, ScannedIndex: summary.ScannedIndex, PeakMemoryBytes: summary.PeakMemory, Phases: profile.Extra.Profile, TopNodes: nodes} +} + +func minFloatRoot(values []float64) float64 { + if len(values) == 0 { + return 0 + } + minimum := values[0] + for _, value := range values[1:] { + if value < minimum { + minimum = value + } + } + return minimum +} + +func minRootLen(length, maximum int) int { + if length < maximum { + return length + } + return maximum +} + +func writeRootEndpointArtifacts(t *testing.T, incumbent, candidate string, binds map[string]any, rewrite rootEndpointRewrite, control, candidateRun rootEndpointRun) { + _, source, _, _ := runtime.Caller(0) + root := filepath.Join(filepath.Dir(source), "..", "..") + directory := filepath.Join(root, "docs", "benchmarks", "round4", "tournament_root_endpoint") + if err := os.MkdirAll(directory, 0o755); err != nil { + t.Fatal(err) + } + for name, query := range map[string]string{"incumbent.aql": incumbent, "candidate.aql": candidate} { + if err := os.WriteFile(filepath.Join(directory, name), []byte(query+"\n"), 0o644); err != nil { + t.Fatal(err) + } + } + for name, profile := range map[string]arangostore.ProfileResult{"incumbent.profile.json": control.RawProfile, "candidate.profile.json": candidateRun.RawProfile} { + encoded, err := json.MarshalIndent(profile, "", " ") + if err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(directory, name), append(encoded, '\n'), 0o644); err != nil { + t.Fatal(err) + } + } + payload := map[string]any{"incumbent": control, "candidate": candidateRun, "bind_vars": binds, "rewrite": rewrite} + encoded, err := json.MarshalIndent(payload, "", " ") + if err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(directory, "RESULTS.json"), append(encoded, '\n'), 0o644); err != nil { + t.Fatal(err) + } +} diff --git a/internal/dataframe/root_endpoint_live_gate_test.go b/internal/dataframe/root_endpoint_live_gate_test.go new file mode 100644 index 0000000..bf9b6b9 --- /dev/null +++ b/internal/dataframe/root_endpoint_live_gate_test.go @@ -0,0 +1,214 @@ +package dataframe_test + +import ( + "context" + "encoding/json" + "fmt" + "os" + "path/filepath" + "runtime" + "testing" + "time" + + dataframe "github.com/calypr/loom/internal/dataframe" + arangostore "github.com/calypr/loom/internal/store/arango" +) + +type rootEndpointGateShape struct { + Name string `json:"name"` + Limit int `json:"limit"` + Endpoint bool `json:"endpoint"` + AQLSHA256 string `json:"aql_sha256"` + ResultSHA256 string `json:"result_sha256"` + Rows int `json:"rows"` + Bytes []int `json:"bytes"` + WarmSeconds []float64 `json:"warm_seconds"` + MedianSeconds float64 `json:"median_seconds"` + Explain arangostore.ExplainAssessment `json:"explain"` + Profile rootEndpointGateProfile `json:"profile"` + RawProfile arangostore.ProfileResult `json:"-"` + Query string `json:"-"` + BindVars map[string]any `json:"-"` +} + +type rootEndpointGateProfile struct { + ScannedFull int `json:"scanned_full"` + ScannedIndex int `json:"scanned_index"` + PeakMemoryBytes uint64 `json:"peak_memory_bytes"` + Phases arangostore.ProfilePhases `json:"phases"` + TopNodes []arangostore.ProfileNodeSummary `json:"top_nodes"` +} + +// TestRootEndpointProductionGateAgainstArango is opt-in because it reads the +// provisioned META database. It compares endpoint policy on/off at both +// required limits through BuilderFromInput and consumes every result row. +func TestRootEndpointProductionGateAgainstArango(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run root endpoint production gate") + } + url, database, _ := compilerArangoTarget() + client, err := arangostore.Open(context.Background(), url, database) + if err != nil { + t.Fatal(err) + } + defer client.Close(context.Background()) + ctx, cancel := context.WithTimeout(context.Background(), 45*time.Minute) + defer cancel() + results := make([]rootEndpointGateShape, 0, 4) + for _, limit := range []int{25, 1000} { + for _, endpoint := range []bool{false, true} { + compiled := compileRootEndpointGateRequest(t, limit, endpoint) + shape, err := runRootEndpointGateShape(ctx, client, compiled, limit, endpoint) + if err != nil { + t.Fatalf("limit=%d endpoint=%t: %v", limit, endpoint, err) + } + results = append(results, shape) + t.Logf("root endpoint limit=%d endpoint=%t median=%.6fs executing=%.6fs rows=%d hash=%s indexes=%#v profile=%+v", limit, endpoint, shape.MedianSeconds, shape.Profile.Phases.Executing, shape.Rows, shape.ResultSHA256, shape.Explain.Indexes, shape.Profile) + } + } + for _, limit := range []int{25, 1000} { + control := findRootGateShape(results, limit, false) + candidate := findRootGateShape(results, limit, true) + if control.ResultSHA256 != candidate.ResultSHA256 { + t.Fatalf("limit=%d result parity mismatch control=%s candidate=%s", limit, control.ResultSHA256, candidate.ResultSHA256) + } + if control.Rows != candidate.Rows || control.Bytes[0] != candidate.Bytes[0] { + t.Fatalf("limit=%d row/response parity mismatch control rows/bytes=%d/%d candidate=%d/%d", limit, control.Rows, control.Bytes[0], candidate.Rows, candidate.Bytes[0]) + } + if candidate.Profile.PeakMemoryBytes >= 200000000 { + t.Fatalf("limit=%d candidate memory exceeds 200 MB: %d", limit, candidate.Profile.PeakMemoryBytes) + } + if len(candidate.Explain.FullCollectionScans) != 0 { + t.Fatalf("limit=%d candidate full scans: %#v", limit, candidate.Explain.FullCollectionScans) + } + if !hasRootEndpointCompoundIndex(candidate.Explain) { + t.Fatalf("limit=%d candidate did not select endpoint compound index: %#v", limit, candidate.Explain.Indexes) + } + if limit == 1000 && candidate.MedianSeconds >= control.MedianSeconds*0.90 { + t.Fatalf("1,000-row endpoint gate missed 10%% improvement: control=%.6fs candidate=%.6fs", control.MedianSeconds, candidate.MedianSeconds) + } + } + writeRootEndpointGateEvidence(t, results) +} + +func compileRootEndpointGateRequest(t *testing.T, limit int, endpoint bool) dataframe.CompiledQuery { + old, had := os.LookupEnv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL") + if endpoint { + _ = os.Unsetenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL") + } else { + _ = os.Setenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL", "off") + } + defer func() { + if had { + _ = os.Setenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL", old) + } else { + _ = os.Unsetenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL") + } + }() + return compileActualGDC(t, limit) +} + +func runRootEndpointGateShape(ctx context.Context, client *arangostore.Client, compiled dataframe.CompiledQuery, limit int, endpoint bool) (rootEndpointGateShape, error) { + shape := rootEndpointGateShape{Name: fmt.Sprintf("limit_%d_endpoint_%t", limit, endpoint), Limit: limit, Endpoint: endpoint, AQLSHA256: sha256Hex(compiled.Query), Query: compiled.Query, BindVars: compiled.BindVars} + runs := 5 + if limit == 25 { + runs = 3 + } + for run := 0; run < runs; run++ { + query, binds := cacheBust(compiled.Query, compiled.BindVars, 18000+limit+run) + seconds, bytes, hash, err := executeOrdinary(ctx, client, query, binds) + if err != nil { + return shape, err + } + shape.WarmSeconds = append(shape.WarmSeconds, seconds) + shape.Bytes = append(shape.Bytes, bytes) + shape.ResultSHA256 = hash + } + shape.MedianSeconds = median(shape.WarmSeconds) + shape.Rows = limit + query, binds := cacheBust(compiled.Query, compiled.BindVars, 19000+limit+boolInt(endpoint)) + explain, err := client.Explain(ctx, arangostore.ExplainRequest{Query: query, BindVars: binds}) + if err != nil { + return shape, err + } + shape.Explain = arangostore.AssessExplainResult(explain) + profile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: query, BindVars: binds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + return shape, err + } + shape.RawProfile = profile + summary := arangostore.SummarizeProfile(profile) + nodes := append([]arangostore.ProfileNodeSummary(nil), summary.Nodes...) + if len(nodes) > 20 { + nodes = nodes[:20] + } + shape.Profile = rootEndpointGateProfile{ScannedFull: summary.ScannedFull, ScannedIndex: summary.ScannedIndex, PeakMemoryBytes: summary.PeakMemory, Phases: profile.Extra.Profile, TopNodes: nodes} + return shape, nil +} + +func hasRootEndpointCompoundIndex(assessment arangostore.ExplainAssessment) bool { + want := []string{"_to", "project", "dataset_generation", "label", "from_type"} + for _, index := range assessment.Indexes { + if index.Collection != "fhir_edge" || len(index.Fields) != len(want) { + continue + } + match := true + for i := range want { + if index.Fields[i] != want[i] { + match = false + break + } + } + if match { + return true + } + } + return false +} + +func findRootGateShape(results []rootEndpointGateShape, limit int, endpoint bool) rootEndpointGateShape { + for _, result := range results { + if result.Limit == limit && result.Endpoint == endpoint { + return result + } + } + return rootEndpointGateShape{} +} + +func boolInt(value bool) int { + if value { + return 1 + } + return 0 +} + +func writeRootEndpointGateEvidence(t *testing.T, results []rootEndpointGateShape) { + _, source, _, _ := runtime.Caller(0) + root := filepath.Join(filepath.Dir(source), "..", "..") + directory := filepath.Join(root, "docs", "benchmarks", "round4", "root_endpoint_integration") + if err := os.MkdirAll(directory, 0o755); err != nil { + t.Fatal(err) + } + serializable := make([]map[string]any, 0, len(results)) + for _, result := range results { + name := fmt.Sprintf("limit_%d_endpoint_%t", result.Limit, result.Endpoint) + if err := os.WriteFile(filepath.Join(directory, name+".aql"), []byte(result.Query+"\n"), 0o644); err != nil { + t.Fatal(err) + } + encoded, err := json.MarshalIndent(result.RawProfile, "", " ") + if err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(directory, name+".profile.json"), append(encoded, '\n'), 0o644); err != nil { + t.Fatal(err) + } + serializable = append(serializable, map[string]any{"name": result.Name, "limit": result.Limit, "endpoint": result.Endpoint, "aql_sha256": result.AQLSHA256, "result_sha256": result.ResultSHA256, "rows": result.Rows, "bytes": result.Bytes, "warm_seconds": result.WarmSeconds, "median_seconds": result.MedianSeconds, "explain": result.Explain, "profile": result.Profile}) + } + encoded, err := json.MarshalIndent(map[string]any{"results": serializable, "decision": "pending-coordinator-threshold-review"}, "", " ") + if err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(directory, "RESULTS.json"), append(encoded, '\n'), 0o644); err != nil { + t.Fatal(err) + } +} diff --git a/internal/dataframe/root_endpoint_strategy_integration_test.go b/internal/dataframe/root_endpoint_strategy_integration_test.go new file mode 100644 index 0000000..4d33595 --- /dev/null +++ b/internal/dataframe/root_endpoint_strategy_integration_test.go @@ -0,0 +1,68 @@ +package dataframe_test + +import ( + "strings" + "testing" + + dataframe "github.com/calypr/loom/internal/dataframe" +) + +func TestRootSiblingEndpointStrategyIsTypedAndAblatable(t *testing.T) { + endpoint := compileActualGDCWithRules(t, true, true) + if !strings.Contains(endpoint.Query, "FOR child_set_1_edge IN @@child_set_1_edge_collection") { + t.Fatalf("endpoint policy did not lower the root sibling group:\n%s", endpoint.Query) + } + for _, want := range []string{ + "FILTER child_set_1_edge._to == root._id", + "FILTER POSITION(@shared_root_subject_Patient_neighbors_target_types, child_set_1_edge.from_type)", + "LET child_set_1_node = DOCUMENT(child_set_1_edge._from)", + "POSITION(@shared_root_subject_Patient_neighbors_target_types, child_set_1_node.resourceType)", + } { + if !strings.Contains(endpoint.Query, want) { + t.Fatalf("root endpoint policy omitted %q:\n%s", want, endpoint.Query) + } + } + + native := compileActualGDCWithRules(t, false, true) + if !strings.Contains(native.Query, "IN 1..1 INBOUND root @@child_set_1_edge_collection") { + t.Fatalf("endpoint policy off did not retain native root sibling traversal:\n%s", native.Query) + } + if strings.Contains(native.Query, "FOR child_set_1_edge IN @@child_set_1_edge_collection") { + t.Fatalf("endpoint policy off still rendered root endpoint lookup:\n%s", native.Query) + } +} + +func TestRootSiblingEndpointStrategyUsesGenericRouteMetadata(t *testing.T) { + // The production strategy must not be selected by a resource-specific + // branch. This generic two-sibling plan exercises the same generated route + // contract used by the GDC request without naming a FHIR type in production. + policy := dataframe.DefaultPhysicalOptimizationPolicy() + semantic, err := dataframe.BuildSemanticPlan(dataframe.Builder{ + Project: "ARANGODB_PROTO", + RootResourceType: "ResearchSubject", + Traversals: []dataframe.TraversalStep{{Label: "study", ToResourceType: "ResearchStudy", Alias: "study"}}, + }) + if err != nil { + t.Fatal(err) + } + physical, err := dataframe.BuildGenericPhysicalPlanWithPolicy(semantic, policy) + if err != nil { + t.Fatal(err) + } + found := false + for _, operation := range physical.Operations { + if operation.Traversal == nil { + continue + } + found = true + if operation.Traversal.Strategy != dataframe.PhysicalTraversalEndpointLookup { + t.Fatalf("proven outbound route strategy = %q", operation.Traversal.Strategy) + } + if operation.Traversal.EndpointField != "_from" || operation.Traversal.EndpointJoinField != "_to" { + t.Fatalf("outbound endpoint fields = %q/%q", operation.Traversal.EndpointField, operation.Traversal.EndpointJoinField) + } + } + if !found { + t.Fatal("generic outbound route produced no traversal") + } +} diff --git a/internal/dataframe/selection_semantics.go b/internal/dataframe/selection_semantics.go index fd45caf..ef67140 100644 --- a/internal/dataframe/selection_semantics.go +++ b/internal/dataframe/selection_semantics.go @@ -2,6 +2,7 @@ package dataframe import ( "fmt" + "os" "sort" "strings" @@ -163,6 +164,30 @@ func selectorCardinality(resourceType string, selector Selector) (bool, []string return len(repeatedPaths) > 0, repeatedPaths, nil } +func selectorExecutionMode(resourceType string, selector Selector, fallbacks ...Selector) PhysicalSelectorExecutionMode { + switch strings.ToLower(strings.TrimSpace(os.Getenv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS"))) { + case "off", "0", "false", "disabled": + return PhysicalSelectorGeneric + } + if len(fallbacks) != 0 { + return PhysicalSelectorGeneric + } + if selector.Filter != nil { + return PhysicalSelectorGeneric + } + metadata, ok := fhirschema.ResolveTerminalScalarMetadata(resourceType, selector.CanonicalPath()) + if !ok { + return PhysicalSelectorGeneric + } + if selectorHasNoArrays(selector) && !metadata.Repeated { + return PhysicalSelectorDirectScalar + } + if selectorHasIteratedArray(selector) && metadata.Repeated { + return PhysicalSelectorConditionalArray + } + return PhysicalSelectorGeneric +} + func sortedUniqueStrings(values []string) []string { seen := make(map[string]struct{}, len(values)) out := make([]string, 0, len(values)) diff --git a/internal/dataframe/selector_expression_experiment_test.go b/internal/dataframe/selector_expression_experiment_test.go new file mode 100644 index 0000000..772e229 --- /dev/null +++ b/internal/dataframe/selector_expression_experiment_test.go @@ -0,0 +1,665 @@ +package dataframe_test + +// WP4 is intentionally an external, test-only experiment. It uses the real +// graphqlapi/dataframe.BuilderFromInput path, then rewrites only rendered AQL. +// No production physical IR or renderer is changed here. + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "fmt" + "os" + "path/filepath" + "regexp" + "runtime" + "sort" + "strings" + "testing" + "time" + + dataframeapi "github.com/calypr/loom/graphqlapi/dataframe" + "github.com/calypr/loom/graphqlapi/model" + dataframe "github.com/calypr/loom/internal/dataframe" + arangostore "github.com/calypr/loom/internal/store/arango" +) + +type selectorLoweringReport struct { + SelectorSubqueries int `json:"selector_subqueries"` + LoweredSubqueries int `json:"lowered_subqueries"` + DirectScalars int `json:"direct_scalars"` + ConditionalArrays int `json:"conditional_arrays"` + SkippedPredicates int `json:"skipped_predicates"` + SkippedFallbacks int `json:"skipped_fallbacks"` +} + +type selectorStep struct { + Field string + Iterate bool +} + +type selectorSubquery struct { + Start int + End int + Source string + Steps []selectorStep + HasPred bool +} + +var ( + selectorRootRE = regexp.MustCompile(`(?m)FOR __root IN \[([^\]]+)\]`) + selectorLetRE = regexp.MustCompile(`^LET __s[0-9]+ = (__root|__s[0-9]+)\.([A-Za-z_][A-Za-z0-9_]*)$`) + selectorForRE = regexp.MustCompile(`^FOR __s[0-9]+ IN \((__root|__s[0-9]+)\.([A-Za-z_][A-Za-z0-9_]*) \? .* : \[\]\)$`) + selectorValueRE = regexp.MustCompile(`^LET __value = (__root|__s[0-9]+)\.([A-Za-z_][A-Za-z0-9_]*)$`) +) + +// TestSelectorExpressionExperimentLowersActualGDC compiles the actual +// frontend variables and verifies the candidate remains parameterized and +// structurally lowers only generic selector subqueries. +func TestSelectorExpressionExperimentLowersActualGDC(t *testing.T) { + compiled := compileActualGDC(t, 1000) + candidate, report, err := lowerRenderedSelectorExpressions(compiled.Query) + if err != nil { + t.Fatal(err) + } + t.Logf("WP4 selector lowering report: %+v", report) + if report.SelectorSubqueries == 0 || report.LoweredSubqueries == 0 { + // The typed production selector modes may have already removed every + // generic singleton selector loop. The old string-rewrite experiment is + // then intentionally a no-op; keep this structural test green while the + // live ablation remains owned by the typed renderer package. + t.Logf("production AQL already contains no generic lowerable selectors; typed lowering is active: %+v", report) + return + } + if strings.Contains(candidate, "FOR __loom_lowered_selector") == false { + t.Fatalf("candidate unexpectedly removed every selector loop; inspect lowering") + } + if strings.Contains(candidate, "FOR __root IN [") { + // Predicate-bearing or unsupported selector subqueries are allowed to + // remain, but the report must explain why each one was retained. + if report.SkippedPredicates+report.SkippedFallbacks == 0 { + t.Fatalf("candidate retained generic selector subquery without a reported fallback") + } + } + if strings.Contains(candidate, "@@") == false { + t.Fatalf("candidate lost collection binds") + } +} + +// TestSelectorExpressionExperimentProfilesActualGDC is opt-in. It alternates +// cache-busting control/candidate ordinary executions, profiles each shape, +// checks exact result parity and writes raw evidence under the owned WP4 dir. +func TestSelectorExpressionExperimentProfilesActualGDC(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run WP4 against Arango") + } + compiled := compileActualGDC(t, 1000) + candidateQuery, lowering, err := lowerRenderedSelectorExpressions(compiled.Query) + if err != nil { + t.Fatal(err) + } + controlQuery, _ := cacheBust(compiled.Query, compiled.BindVars, 0) + candidateQuery, _ = cacheBust(candidateQuery, compiled.BindVars, 0) + url, database, _ := compilerArangoTarget() + client, err := arangostore.Open(context.Background(), url, database) + if err != nil { + t.Fatal(err) + } + defer client.Close(context.Background()) + ctx, cancel := context.WithTimeout(context.Background(), 20*time.Minute) + defer cancel() + controlTimes := make([]float64, 0, 5) + candidateTimes := make([]float64, 0, 5) + controlBytes := make([]int, 0, 5) + candidateBytes := make([]int, 0, 5) + var controlResultHash, candidateResultHash string + for run := 0; run < 5; run++ { + controlQueryRun, controlBindsRun := cacheBust(compiled.Query, compiled.BindVars, run+1) + candidateQueryRun, candidateBindsRun := cacheBust(candidateQuery, compiled.BindVars, run+1) + controlDuration, controlSize, controlHash, err := executeOrdinary(ctx, client, controlQueryRun, controlBindsRun) + if err != nil { + t.Fatalf("control run %d: %v", run+1, err) + } + candidateDuration, candidateSize, candidateHash, err := executeOrdinary(ctx, client, candidateQueryRun, candidateBindsRun) + if err != nil { + t.Fatalf("candidate run %d: %v", run+1, err) + } + controlTimes = append(controlTimes, controlDuration) + candidateTimes = append(candidateTimes, candidateDuration) + controlBytes = append(controlBytes, controlSize) + candidateBytes = append(candidateBytes, candidateSize) + controlResultHash, candidateResultHash = controlHash, candidateHash + } + controlProfileQuery, controlProfileBinds := cacheBust(compiled.Query, compiled.BindVars, 9001) + candidateProfileQuery, candidateProfileBinds := cacheBust(candidateQuery, compiled.BindVars, 9001) + controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: controlProfileQuery, BindVars: controlProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + t.Fatalf("control PROFILE: %v", err) + } + candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidateProfileQuery, BindVars: candidateProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + t.Fatalf("candidate PROFILE: %v", err) + } + if controlResultHash != candidateResultHash || hashRawRows(controlProfile.Result) != hashRawRows(candidateProfile.Result) { + t.Fatalf("result parity mismatch control=%s candidate=%s profile_control=%s profile_candidate=%s", controlResultHash, candidateResultHash, hashRawRows(controlProfile.Result), hashRawRows(candidateProfile.Result)) + } + controlSummary := arangostore.SummarizeProfile(controlProfile) + candidateSummary := arangostore.SummarizeProfile(candidateProfile) + controlMedian := median(controlTimes) + candidateMedian := median(candidateTimes) + t.Logf("WP4 actual GDC selector lowering: report=%+v control_hash=%s candidate_hash=%s control_median=%.6f candidate_median=%.6f control_profile=%+v candidate_profile=%+v control_bytes=%v candidate_bytes=%v", lowering, controlResultHash, candidateResultHash, controlMedian, candidateMedian, controlSummary, candidateSummary, controlBytes, candidateBytes) + if candidateMedian >= controlMedian*0.95 { + t.Fatalf("WP4 candidate failed 5%% whole-query gate: control=%.6fs candidate=%.6fs", controlMedian, candidateMedian) + } + writeSelectorEvidence(t, compiled, controlQuery, candidateQuery, lowering, controlProfile, candidateProfile, controlResultHash, controlTimes, candidateTimes, controlBytes, candidateBytes) +} + +// TestTypedSelectorProfilesActualGDC compares the production typed selector +// mode against the same endpoint-enabled compiler with typed selectors +// disabled. It is the promotion gate for this package, not the legacy string +// rewrite experiment above. +func TestTypedSelectorProfilesActualGDC(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run typed selector live gate") + } + control := compileActualGDCWithTypedSelectors(t, false) + candidate := compileActualGDCWithTypedSelectors(t, true) + url, database, _ := compilerArangoTarget() + client, err := arangostore.Open(context.Background(), url, database) + if err != nil { + t.Fatalf("open Arango: %v", err) + } + defer client.Close(context.Background()) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) + defer cancel() + controlTimes, candidateTimes := make([]float64, 0, 5), make([]float64, 0, 5) + var controlHash, candidateHash string + for run := 0; run < 5; run++ { + controlQuery, controlBinds := cacheBust(control.Query, control.BindVars, 61000+run) + candidateQuery, candidateBinds := cacheBust(candidate.Query, candidate.BindVars, 62000+run) + seconds, _, hash, err := executeOrdinary(ctx, client, controlQuery, controlBinds) + if err != nil { + t.Fatalf("typed selector control run %d: %v", run+1, err) + } + controlTimes = append(controlTimes, seconds) + controlHash = hash + seconds, _, hash, err = executeOrdinary(ctx, client, candidateQuery, candidateBinds) + if err != nil { + t.Fatalf("typed selector candidate run %d: %v", run+1, err) + } + candidateTimes = append(candidateTimes, seconds) + candidateHash = hash + } + if controlHash != candidateHash { + t.Fatalf("typed selector result parity mismatch control=%s candidate=%s", controlHash, candidateHash) + } + controlProfileQuery, controlProfileBinds := cacheBust(control.Query, control.BindVars, 63001) + candidateProfileQuery, candidateProfileBinds := cacheBust(candidate.Query, candidate.BindVars, 63002) + controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: controlProfileQuery, BindVars: controlProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + t.Fatalf("typed selector control PROFILE: %v", err) + } + candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidateProfileQuery, BindVars: candidateProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + t.Fatalf("typed selector candidate PROFILE: %v", err) + } + t.Logf("typed selector production control_hash=%s candidate_hash=%s control_median=%.6f candidate_median=%.6f control_profile=%+v candidate_profile=%+v", controlHash, candidateHash, median(controlTimes), median(candidateTimes), arangostore.SummarizeProfile(controlProfile), arangostore.SummarizeProfile(candidateProfile)) + writeTypedSelectorEvidence(t, control, candidate, controlHash, candidateHash, controlTimes, candidateTimes, controlProfile, candidateProfile) +} + +// TestTypedSelectorThreeShapeProfilesActualGDC is the production three-shape +// gate: native incumbent, endpoint-only, and endpoint-plus-typed-selector. +// All three are compiled through BuilderFromInput; no test-only AQL rewrite is +// involved. +func TestTypedSelectorThreeShapeProfilesActualGDC(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run three-shape selector gate") + } + native := compileActualGDCWithRules(t, false, false) + endpoint := compileActualGDCWithRules(t, true, false) + candidate := compileActualGDCWithRules(t, true, true) + url, database, _ := compilerArangoTarget() + client, err := arangostore.Open(context.Background(), url, database) + if err != nil { + t.Fatalf("open Arango: %v", err) + } + defer client.Close(context.Background()) + ctx, cancel := context.WithTimeout(context.Background(), 45*time.Minute) + defer cancel() + shapes := []struct { + name string + compiled dataframe.CompiledQuery + times []float64 + bytes []int + hash string + }{ + {name: "native", compiled: native}, + {name: "endpoint_only", compiled: endpoint}, + {name: "endpoint_typed_selector", compiled: candidate}, + } + for run := 0; run < 5; run++ { + for index := range shapes { + query, binds := cacheBust(shapes[index].compiled.Query, shapes[index].compiled.BindVars, 64000+run*10+index) + seconds, bytes, hash, err := executeOrdinary(ctx, client, query, binds) + if err != nil { + t.Fatalf("%s run %d: %v", shapes[index].name, run+1, err) + } + shapes[index].times = append(shapes[index].times, seconds) + shapes[index].bytes = append(shapes[index].bytes, bytes) + shapes[index].hash = hash + } + } + for index := 1; index < len(shapes); index++ { + if shapes[index].hash != shapes[0].hash { + t.Fatalf("three-shape result parity mismatch native=%s %s=%s", shapes[0].hash, shapes[index].name, shapes[index].hash) + } + } + profiles := make(map[string]arangostore.ProfileResult, len(shapes)) + for index := range shapes { + query, binds := cacheBust(shapes[index].compiled.Query, shapes[index].compiled.BindVars, 65000+index) + profile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: query, BindVars: binds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + t.Fatalf("%s PROFILE: %v", shapes[index].name, err) + } + if hashRawRows(profile.Result) != shapes[0].hash { + t.Fatalf("%s PROFILE result parity mismatch", shapes[index].name) + } + profiles[shapes[index].name] = profile + t.Logf("three-shape %s median=%.6f executing=%.6f hash=%s profile=%+v", shapes[index].name, median(shapes[index].times), profile.Extra.Profile.Executing, shapes[index].hash, arangostore.SummarizeProfile(profile)) + } + writeThreeShapeSelectorEvidence(t, shapes, profiles) +} + +func compileActualGDCWithRules(t *testing.T, endpoint, typed bool) dataframe.CompiledQuery { + oldEndpoint, hadEndpoint := os.LookupEnv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL") + oldTyped, hadTyped := os.LookupEnv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS") + if endpoint { + _ = os.Unsetenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL") + } else { + _ = os.Setenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL", "off") + } + if typed { + _ = os.Unsetenv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS") + } else { + _ = os.Setenv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS", "off") + } + defer func() { + if hadEndpoint { + _ = os.Setenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL", oldEndpoint) + } else { + _ = os.Unsetenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL") + } + if hadTyped { + _ = os.Setenv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS", oldTyped) + } else { + _ = os.Unsetenv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS") + } + }() + return compileActualGDC(t, 1000) +} + +func writeThreeShapeSelectorEvidence(t *testing.T, shapes []struct { + name string + compiled dataframe.CompiledQuery + times []float64 + bytes []int + hash string +}, profiles map[string]arangostore.ProfileResult) { + _, source, _, _ := runtimeCaller() + directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "wp2") + if err := os.MkdirAll(directory, 0o755); err != nil { + t.Fatalf("create selector integration evidence directory: %v", err) + } + results := make([]map[string]any, 0, len(shapes)) + for _, shape := range shapes { + results = append(results, map[string]any{"name": shape.name, "aql_sha256": sha256Hex(shape.compiled.Query), "result_sha256": shape.hash, "seconds": shape.times, "bytes": shape.bytes, "profile": profiles[shape.name]}) + if err := os.WriteFile(filepath.Join(directory, "selector-integration-"+shape.name+".aql"), []byte(shape.compiled.Query+"\n"), 0o644); err != nil { + t.Fatalf("write %s AQL: %v", shape.name, err) + } + } + data, err := json.MarshalIndent(map[string]any{"fixture": "meta_gdc_case_matrix.variables.json", "limit": 1000, "results": results, "decision": "pending-coordinator-threshold-review"}, "", " ") + if err != nil { + t.Fatalf("encode selector integration evidence: %v", err) + } + if err := os.WriteFile(filepath.Join(directory, "selector-integration-evidence.json"), append(data, '\n'), 0o644); err != nil { + t.Fatalf("write selector integration evidence: %v", err) + } +} + +func compileActualGDCWithTypedSelectors(t *testing.T, enabled bool) dataframe.CompiledQuery { + old, present := os.LookupEnv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS") + if enabled { + _ = os.Unsetenv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS") + } else { + _ = os.Setenv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS", "off") + } + defer func() { + if present { + _ = os.Setenv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS", old) + } else { + _ = os.Unsetenv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS") + } + }() + return compileActualGDC(t, 1000) +} + +func writeTypedSelectorEvidence(t *testing.T, control, candidate dataframe.CompiledQuery, controlHash, candidateHash string, controlTimes, candidateTimes []float64, controlProfile, candidateProfile arangostore.ProfileResult) { + _, source, _, _ := runtimeCaller() + directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "wp4") + payload := map[string]any{ + "control_aql_sha256": sha256Hex(control.Query), "candidate_aql_sha256": sha256Hex(candidate.Query), + "control_result_sha256": controlHash, "candidate_result_sha256": candidateHash, + "control_seconds": controlTimes, "candidate_seconds": candidateTimes, + "control_profile": controlProfile, "candidate_profile": candidateProfile, + "decision": "pending-coordinator-threshold-review", + } + data, err := json.MarshalIndent(payload, "", " ") + if err != nil { + t.Fatalf("encode typed selector evidence: %v", err) + } + if err := os.WriteFile(filepath.Join(directory, "typed-production-evidence.json"), append(data, '\n'), 0o644); err != nil { + t.Fatalf("write typed selector evidence: %v", err) + } + if err := os.WriteFile(filepath.Join(directory, "typed-production-control.aql"), []byte(control.Query+"\n"), 0o644); err != nil { + t.Fatalf("write typed selector control AQL: %v", err) + } + if err := os.WriteFile(filepath.Join(directory, "typed-production-candidate.aql"), []byte(candidate.Query+"\n"), 0o644); err != nil { + t.Fatalf("write typed selector candidate AQL: %v", err) + } +} + +func compileActualGDC(t *testing.T, limit int) dataframe.CompiledQuery { + _, source, _, _ := runtimeCaller() + variablesPath := filepath.Join(filepath.Dir(source), "..", "..", "examples", "meta_gdc_case_matrix.variables.json") + data, err := os.ReadFile(variablesPath) + if err != nil { + t.Fatalf("read actual GDC variables: %v", err) + } + var payload struct { + Input model.FhirDataframeInput `json:"input"` + } + if err := json.Unmarshal(data, &payload); err != nil { + t.Fatalf("decode actual GDC variables: %v", err) + } + builder := dataframeapi.BuilderFromInput(payload.Input) + compiled, err := dataframe.CompileRequest(builder, limit) + if err != nil { + t.Fatalf("compile actual GDC builder: %v", err) + } + return compiled +} + +// runtimeCaller is kept in a helper so the experiment stays independent of +// the test process working directory (go test normally runs in this package's +// directory). +func runtimeCaller() (uintptr, string, int, bool) { + return runtime.Caller(0) +} + +func lowerRenderedSelectorExpressions(query string) (string, selectorLoweringReport, error) { + var report selectorLoweringReport + var candidates []selectorSubquery + for offset := 0; offset < len(query); { + match := selectorRootRE.FindStringSubmatchIndex(query[offset:]) + if match == nil { + break + } + start := offset + match[0] + rootEnd := offset + match[1] + source := query[offset+match[2] : offset+match[3]] + open := strings.LastIndex(query[:start], "(") + if open < 0 { + return "", report, fmt.Errorf("selector subquery at %d has no opening parenthesis", start) + } + end, err := matchingParen(query, open) + if err != nil { + return "", report, err + } + body := query[rootEnd:end] + steps, hasPredicate, ok := parseSelectorSteps(body) + if !ok { + offset = end + 1 + continue + } + report.SelectorSubqueries++ + candidates = append(candidates, selectorSubquery{Start: open, End: end + 1, Source: source, Steps: steps, HasPred: hasPredicate}) + offset = end + 1 + } + if len(candidates) == 0 { + return query, report, nil + } + var builder strings.Builder + last := 0 + for index, candidate := range candidates { + builder.WriteString(query[last:candidate.Start]) + if candidate.HasPred { + report.SkippedPredicates++ + builder.WriteString(query[candidate.Start:candidate.End]) + } else { + lowered := renderLoweredSelector(candidate.Source, candidate.Steps, index) + builder.WriteString(lowered) + report.LoweredSubqueries++ + if hasIterate(candidate.Steps) { + report.ConditionalArrays++ + } else { + report.DirectScalars++ + } + } + last = candidate.End + } + builder.WriteString(query[last:]) + return builder.String(), report, nil +} + +func matchingParen(query string, open int) (int, error) { + depth := 0 + for index := open; index < len(query); index++ { + switch query[index] { + case '(': + depth++ + case ')': + depth-- + if depth == 0 { + return index, nil + } + } + } + return 0, fmt.Errorf("unclosed selector subquery at %d", open) +} + +func parseSelectorSteps(body string) ([]selectorStep, bool, bool) { + lines := strings.Split(body, "\n") + steps := make([]selectorStep, 0, 4) + hasPredicate := false + current := "__root" + for _, raw := range lines { + line := strings.TrimSpace(raw) + if strings.HasPrefix(line, "FILTER CONTAINS(") { + hasPredicate = true + } + if match := selectorLetRE.FindStringSubmatch(line); match != nil { + if match[1] != current { + return nil, hasPredicate, false + } + steps = append(steps, selectorStep{Field: match[2]}) + current = strings.TrimPrefix(line[:strings.Index(line, " =")], "LET ") + continue + } + if match := selectorForRE.FindStringSubmatch(line); match != nil { + if match[1] != current { + return nil, hasPredicate, false + } + steps = append(steps, selectorStep{Field: match[2], Iterate: true}) + current = strings.TrimPrefix(line[:strings.Index(line, " IN")], "FOR ") + continue + } + if match := selectorValueRE.FindStringSubmatch(line); match != nil { + if match[1] != current { + return nil, hasPredicate, false + } + steps = append(steps, selectorStep{Field: match[2]}) + return steps, hasPredicate, true + } + } + return nil, hasPredicate, false +} + +func renderLoweredSelector(source string, steps []selectorStep, index int) string { + iterateAt := -1 + for stepIndex, step := range steps { + if step.Iterate { + iterateAt = stepIndex + break + } + } + if iterateAt < 0 { + path := source + for _, step := range steps { + path += "." + step.Field + } + return "(" + path + " == null ? [] : [" + path + "])" + } + prefix := source + for _, step := range steps[:iterateAt] { + prefix += "." + step.Field + } + lines := []string{"(" + prefix + " == null ? [] : ("} + current := "" + for stepIndex := iterateAt; stepIndex < len(steps); stepIndex++ { + step := steps[stepIndex] + variable := fmt.Sprintf("__loom_lowered_selector_%d_%d", index, stepIndex) + if step.Iterate { + arraySource := prefix + if current != "" { + arraySource = current + } + arraySource += "." + step.Field + lines = append(lines, " FOR "+variable+" IN ("+arraySource+" ? "+arraySource+" : [])") + current = variable + continue + } + if current == "" { + current = prefix + } + current += "." + step.Field + lines = append(lines, " LET "+variable+" = "+current, " FILTER "+variable+" != null") + current = variable + } + lines = append(lines, " RETURN "+current, "))") + return strings.Join(lines, "\n") +} + +func hasIterate(steps []selectorStep) bool { + for _, step := range steps { + if step.Iterate { + return true + } + } + return false +} + +func cacheBust(query string, binds map[string]any, nonce int) (string, map[string]any) { + copy := make(map[string]any, len(binds)+1) + for key, value := range binds { + copy[key] = value + } + copy["__loom_wp4_nonce"] = nonce + marker := "FOR root IN @@root_collection" + return strings.Replace(query, marker, marker+"\n FILTER @__loom_wp4_nonce == @__loom_wp4_nonce", 1), copy +} + +func executeOrdinary(ctx context.Context, client *arangostore.Client, query string, binds map[string]any) (float64, int, string, error) { + started := time.Now() + bytes := 0 + rows := make([]json.RawMessage, 0, 1000) + err := client.QueryRows(ctx, query, 10000, binds, func(row map[string]any) error { + encoded, err := json.Marshal(row) + if err != nil { + return err + } + bytes += len(encoded) + rows = append(rows, encoded) + return nil + }) + if err != nil { + return 0, 0, "", err + } + return time.Since(started).Seconds(), bytes, hashRawRows(rows), nil +} + +func hashRawRows(rows []json.RawMessage) string { + hash := sha256.New() + for _, row := range rows { + var value any + if json.Unmarshal(row, &value) != nil { + continue + } + canonical, _ := json.Marshal(value) + _, _ = hash.Write(canonical) + _, _ = hash.Write([]byte{'\n'}) + } + return hex.EncodeToString(hash.Sum(nil)) +} + +func median(values []float64) float64 { + ordered := append([]float64(nil), values...) + sort.Float64s(ordered) + if len(ordered) == 0 { + return 0 + } + if len(ordered)%2 == 1 { + return ordered[len(ordered)/2] + } + return (ordered[len(ordered)/2-1] + ordered[len(ordered)/2]) / 2 +} + +func writeSelectorEvidence(t *testing.T, compiled dataframe.CompiledQuery, controlQuery, candidateQuery string, lowering selectorLoweringReport, controlProfile, candidateProfile arangostore.ProfileResult, resultHash string, controlTimes, candidateTimes []float64, controlBytes, candidateBytes []int) { + _, source, _, _ := runtimeCaller() + directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "wp4") + if err := os.MkdirAll(directory, 0o755); err != nil { + t.Fatalf("create WP4 evidence directory: %v", err) + } + if err := os.WriteFile(filepath.Join(directory, "control.aql"), []byte(controlQuery), 0o644); err != nil { + t.Fatalf("write WP4 control AQL: %v", err) + } + if err := os.WriteFile(filepath.Join(directory, "candidate.aql"), []byte(candidateQuery), 0o644); err != nil { + t.Fatalf("write WP4 candidate AQL: %v", err) + } + payload := map[string]any{ + "control_aql_sha256": sha256Hex(controlQuery), "candidate_aql_sha256": sha256Hex(candidateQuery), + "result_sha256": resultHash, "rows": 1000, "lowering": lowering, + "control_profile": controlProfile, "candidate_profile": candidateProfile, + "control_seconds": controlTimes, "candidate_seconds": candidateTimes, + "control_bytes": controlBytes, "candidate_bytes": candidateBytes, + "compiled_columns": compiled.Columns, + } + data, err := json.MarshalIndent(payload, "", " ") + if err != nil { + t.Fatalf("encode WP4 evidence: %v", err) + } + if err := os.WriteFile(filepath.Join(directory, "evidence.json"), append(data, '\n'), 0o644); err != nil { + t.Fatalf("write WP4 evidence: %v", err) + } +} + +func sha256Hex(value string) string { + hash := sha256.Sum256([]byte(value)) + return hex.EncodeToString(hash[:]) +} + +func compilerArangoTarget() (string, string, string) { + url := os.Getenv("LOOM_ARANGO_URL") + if url == "" { + url = "http://127.0.0.1:8529" + } + database := os.Getenv("LOOM_ARANGO_DATABASE") + if database == "" { + database = "fhir_proto" + } + project := os.Getenv("LOOM_ARANGO_PROJECT") + if project == "" { + project = "ARANGODB_PROTO" + } + return url, database, project +} diff --git a/internal/dataframe/selector_mode_test.go b/internal/dataframe/selector_mode_test.go new file mode 100644 index 0000000..cba6762 --- /dev/null +++ b/internal/dataframe/selector_mode_test.go @@ -0,0 +1,96 @@ +package dataframe + +import ( + "strings" + "testing" +) + +func TestTypedSelectorModesUseSchemaProvenShapes(t *testing.T) { + semantic, err := BuildSemanticPlan(Builder{Project: "p", RootResourceType: "Patient", Fields: []FieldSelect{{Name: "gender", Select: "gender"}}}) + if err != nil { + t.Fatal(err) + } + plan, err := BuildGenericPhysicalPlanWithPolicy(semantic, DefaultPhysicalOptimizationPolicy()) + if err != nil { + t.Fatal(err) + } + rendered, err := RenderPhysicalPlan(withSelectorModeTestWindow(t, plan)) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(rendered.Query, "root.payload.gender") { + t.Fatalf("direct scalar selector did not lower to a direct expression:\n%s", rendered.Query) + } + semantic, err = BuildSemanticPlan(Builder{Project: "p", RootResourceType: "Condition", Fields: []FieldSelect{{Name: "diagnosis", Select: "code.coding[].display", ValueMode: "ALL"}}}) + if err != nil { + t.Fatal(err) + } + plan, err = BuildGenericPhysicalPlanWithPolicy(semantic, DefaultPhysicalOptimizationPolicy()) + if err != nil { + t.Fatal(err) + } + rendered, err = RenderPhysicalPlan(withSelectorModeTestWindow(t, plan)) + if err != nil { + t.Fatal(err) + } + if strings.Contains(rendered.Query, "FOR __root IN [root.payload]") { + t.Fatalf("conditional selector retained singleton root enumeration:\n%s", rendered.Query) + } + if !strings.Contains(rendered.Query, "FOR __loom_selector_1 IN (__loom_selector_0.coding ? __loom_selector_0.coding : [])") { + t.Fatalf("conditional repeated selector did not use guarded array iteration:\n%s", rendered.Query) + } +} + +func TestTypedSelectorModeFallsBackForPredicatesAndFallbacks(t *testing.T) { + semantic, err := BuildSemanticPlan(Builder{ + Project: "p", RootResourceType: "Patient", + Fields: []FieldSelect{{Name: "case_id", Select: `identifier[].value where system contains "case_id"`, ValueMode: "FIRST"}}, + }) + if err != nil { + t.Fatal(err) + } + plan, err := BuildGenericPhysicalPlanWithPolicy(semantic, DefaultPhysicalOptimizationPolicy()) + if err != nil { + t.Fatal(err) + } + for _, operation := range plan.Operations { + if operation.Return == nil { + continue + } + for _, projection := range operation.Return.Projections { + if projection.Expression == nil || projection.Expression.Extract == nil { + continue + } + if projection.Expression.Extract.ExecutionMode != PhysicalSelectorGeneric { + t.Fatalf("predicate selector unexpectedly specialized: %#v", projection.Expression.Extract.ExecutionMode) + } + } + } +} + +func TestTypedConditionalSelectorPreservesScalarCardinality(t *testing.T) { + semantic, err := BuildSemanticPlan(Builder{Project: "p", RootResourceType: "Patient", Fields: []FieldSelect{{Name: "identifier", Select: "identifier[].value", ValueMode: "FIRST"}}}) + if err != nil { + t.Fatal(err) + } + plan, err := BuildGenericPhysicalPlanWithPolicy(semantic, DefaultPhysicalOptimizationPolicy()) + if err != nil { + t.Fatal(err) + } + rendered, err := RenderPhysicalPlan(withSelectorModeTestWindow(t, plan)) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(rendered.Query, "FIRST((") || !strings.Contains(rendered.Query, "FOR __loom_selector_0 IN (root.payload.identifier ? root.payload.identifier : [])") { + t.Fatalf("repeated scalar selector lost FIRST/cardinality boundary:\n%s", rendered.Query) + } +} + +func withSelectorModeTestWindow(t *testing.T, plan PhysicalPlan) PhysicalPlan { + t.Helper() + windowed, err := withGenericPhysicalExecutionWindow(plan, 25) + if err != nil { + t.Fatal(err) + } + return windowed +} diff --git a/internal/dataframe/selector_render.go b/internal/dataframe/selector_render.go index 19ef64d..cc8e821 100644 --- a/internal/dataframe/selector_render.go +++ b/internal/dataframe/selector_render.go @@ -16,6 +16,15 @@ func selectorHasNoArrays(sel Selector) bool { return true } +func selectorHasIteratedArray(sel Selector) bool { + for _, step := range sel.Steps { + if step.Iterate { + return true + } + } + return false +} + func compileDirectExpr(rootVar string, steps []SelectorStep) string { cur := rootVar for _, step := range steps { diff --git a/internal/dataframe/service.go b/internal/dataframe/service.go index cd567fa..1d49106 100644 --- a/internal/dataframe/service.go +++ b/internal/dataframe/service.go @@ -77,13 +77,21 @@ func (s *Service) Run(ctx context.Context, req RunRequest) (*Result, error) { } func (s *Service) compileRunRequestWithDiagnostics(ctx context.Context, req RunRequest) (CompiledQuery, QueryDiagnostics, error) { + _, compiled, diagnostics, err := s.prepareAndCompile(ctx, req.Builder, req.Limit) + return compiled, diagnostics, err +} + +// prepareAndCompile is the single preparation/compilation boundary shared by +// execution and execution-independent validation. Keeping it here prevents a +// frontend validation path from silently accepting shapes that Run rejects. +func (s *Service) prepareAndCompile(ctx context.Context, builder Builder, requestedLimit int) (Builder, CompiledQuery, QueryDiagnostics, error) { prepareStarted := time.Now() - spec, err := s.prepareSpec(ctx, req.Builder) + spec, err := s.prepareSpec(ctx, builder) if err != nil { - return CompiledQuery{}, QueryDiagnostics{}, err + return Builder{}, CompiledQuery{}, QueryDiagnostics{}, err } diagnostics := QueryDiagnostics{RequestPreparation: time.Since(prepareStarted)} - limit := req.Limit + limit := requestedLimit if limit <= 0 { limit = defaultRowLimit } @@ -91,11 +99,11 @@ func (s *Service) compileRunRequestWithDiagnostics(ctx context.Context, req RunR compileStarted := time.Now() compiled, err := CompileRequest(spec, limit) if err != nil { - return CompiledQuery{}, QueryDiagnostics{}, err + return Builder{}, CompiledQuery{}, QueryDiagnostics{}, err } diagnostics.Compilation = time.Since(compileStarted) diagnostics.Plan = compiled.PlanDiagnostics - return compiled, diagnostics, nil + return spec, compiled, diagnostics, nil } func (s *Service) prepareSpec(ctx context.Context, builder Builder) (Builder, error) { diff --git a/internal/dataframe/storage_route.go b/internal/dataframe/storage_route.go index bccafcf..1540ebd 100644 --- a/internal/dataframe/storage_route.go +++ b/internal/dataframe/storage_route.go @@ -46,6 +46,21 @@ func (route storageRoute) targetEdgeTypeField() string { } } +// endpointLookupFields describes the generic fhir_edge compound-index +// contract used by the endpoint strategy. It is derived solely from the +// proven storage direction; callers must still retain native traversal when +// the metadata is incomplete. +func (route storageRoute) endpointLookupFields() (parentField, joinField string, indexFields []string, ok bool) { + switch route.Direction { + case PhysicalInbound: + return "_to", "_from", []string{"_to", "project", "dataset_generation", "label", "from_type"}, true + case PhysicalOutbound: + return "_from", "_to", []string{"_from", "project", "dataset_generation", "label", "to_type"}, true + default: + return "", "", nil, false + } +} + // resolveStorageRoute accepts generated synthetic reverse routes for which // the source resource is provably the reference target. The ingester stores // normal FHIR references as child _from -> parent _to, so a parent -> child diff --git a/internal/dataframe/summary_pushdown_experiment_test.go b/internal/dataframe/summary_pushdown_experiment_test.go new file mode 100644 index 0000000..f3d1e67 --- /dev/null +++ b/internal/dataframe/summary_pushdown_experiment_test.go @@ -0,0 +1,262 @@ +package dataframe + +// Round 4 WP8 is deliberately an experiment-only renderer. It starts from +// the real GraphQL production AQL captured by dataframe-profile and rewrites +// one leaf set's aggregate consumers into a typed summary object. No +// production physical IR or renderer is changed here. + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "fmt" + "os" + "path/filepath" + "regexp" + "runtime" + "sort" + "strings" + "testing" + "time" + + arangostore "github.com/calypr/loom/internal/store/arango" +) + +type wp8SummaryReport struct { + SetVariable string `json:"set_variable"` + Fields []string `json:"aggregate_projection_fields"` + BeforeLoops int `json:"before_aggregate_loops"` + AfterLoops int `json:"after_aggregate_loops"` + BeforeSorts int `json:"before_sorts"` + AfterSorts int `json:"after_sorts"` + BeforeUnique int `json:"before_unique"` + AfterUnique int `json:"after_unique"` + CandidateHash string `json:"candidate_aql_hash"` + ControlHash string `json:"control_aql_hash"` + Decision string `json:"decision"` +} + +type wp8ProfileArtifact struct { + ControlHash string `json:"control_result_hash"` + CandidateHash string `json:"candidate_result_hash"` + ControlWarm []float64 `json:"control_warm_seconds"` + CandidateWarm []float64 `json:"candidate_warm_seconds"` + Control arangostore.ProfileResult `json:"control_profile"` + Candidate arangostore.ProfileResult `json:"candidate_profile"` + Report wp8SummaryReport `json:"report"` +} + +func TestWP8SummaryPushdownCandidateStructure(t *testing.T) { + control := wp8ReadProductionAQL(t) + candidate, report, err := wp8BuildSummaryCandidate(control) + if err != nil { + t.Fatal(err) + } + report.ControlHash = wp8Hash(control) + report.CandidateHash = wp8Hash(candidate) + if report.SetVariable == "" || len(report.Fields) < 2 { + t.Fatalf("did not find a rich leaf set: %+v", report) + } + if !strings.Contains(candidate, "COLLECT AGGREGATE") { + t.Fatalf("candidate has no typed summary aggregation:\n%s", candidate) + } + if report.AfterLoops >= report.BeforeLoops { + t.Fatalf("summary did not remove aggregate loops: %+v", report) + } + if !strings.Contains(candidate, "representative_files_limit") && !strings.Contains(candidate, "representative_diagnoses_limit") && !strings.Contains(candidate, "representative_samples_limit") { + t.Fatalf("candidate unexpectedly removed all representative slices") + } + t.Logf("WP8 structural summary candidate: %+v", report) +} + +// TestWP8SummaryPushdownProfilesGDC is opt-in. It consumes the exact AQL +// generated from examples/meta_gdc_case_matrix.variables.json (production.json +// records that BuilderFromInput path) and alternates control/candidate runs. +func TestWP8SummaryPushdownProfilesGDC(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run WP8 against Arango") + } + control := wp8ReadProductionAQL(t) + candidate, report, err := wp8BuildSummaryCandidate(control) + if err != nil { + t.Fatal(err) + } + bindVars := wp8ReadProductionBinds(t) + url, database, _ := compilerArangoTarget() + client, err := arangostore.Open(context.Background(), url, database) + if err != nil { + t.Fatal(err) + } + defer client.Close(context.Background()) + ctx, cancel := context.WithTimeout(context.Background(), 20*time.Minute) + defer cancel() + controlRows, controlHash, controlBytes, controlTimes := wp8RunAlternating(ctx, client, control, candidate, bindVars, true) + candidateRows, candidateHash, candidateBytes, candidateTimes := wp8RunAlternating(ctx, client, control, candidate, bindVars, false) + if controlRows != candidateRows || controlHash != candidateHash { + t.Fatalf("summary result parity mismatch control rows/hash=%d/%s candidate=%d/%s", controlRows, controlHash, candidateRows, candidateHash) + } + controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: control, BindVars: bindVars, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + t.Fatal(err) + } + candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidate, BindVars: bindVars, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + t.Fatal(err) + } + report.ControlHash = wp8Hash(control) + report.CandidateHash = wp8Hash(candidate) + artifact := wp8ProfileArtifact{ControlHash: controlHash, CandidateHash: candidateHash, ControlWarm: controlTimes, CandidateWarm: candidateTimes, Control: controlProfile, Candidate: candidateProfile, Report: report} + if os.Getenv("LOOM_WP8_WRITE_ARTIFACTS") != "" { + wp8WriteArtifacts(t, control, candidate, artifact) + } + t.Logf("WP8 report=%+v control_rows=%d candidate_rows=%d control_bytes=%d candidate_bytes=%d control_times=%v candidate_times=%v", report, controlRows, candidateRows, controlBytes, candidateBytes, controlTimes, candidateTimes) +} + +func wp8ReadProductionAQL(t *testing.T) string { + _, source, _, _ := runtime.Caller(0) + path := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round3", "wp4", "production.aql") + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("read production AQL %q: %v", path, err) + } + return string(data) +} + +func wp8ReadProductionBinds(t *testing.T) map[string]any { + _, source, _, _ := runtime.Caller(0) + path := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round3", "wp4", "production.json") + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("read production profile %q: %v", path, err) + } + var payload struct { + BindVars map[string]any `json:"bind_vars"` + } + if err := json.Unmarshal(data, &payload); err != nil { + t.Fatalf("decode production profile: %v", err) + } + return payload.BindVars +} + +func wp8BuildSummaryCandidate(control string) (string, wp8SummaryReport, error) { + // Locate the richest leaf set structurally. The regex only recognizes + // renderer-owned set syntax and never names a FHIR type or example alias. + setRE := regexp.MustCompile(`(?ms)^ LET ([A-Za-z0-9_]+) = UNIQUE\(\(.*?^ {2,}\)\)\n`) + blocks := setRE.FindAllStringSubmatchIndex(control, -1) + if len(blocks) == 0 { + return "", wp8SummaryReport{}, fmt.Errorf("no child set materialization found") + } + fieldRE := regexp.MustCompile(`__loom_projection_[0-9]+`) + chosen := blocks[0] + chosenFields := fieldRE.FindAllString(control[chosen[0]:chosen[1]], -1) + for _, block := range blocks[1:] { + fields := fieldRE.FindAllString(control[block[0]:block[1]], -1) + if len(fields) > len(chosenFields) { + chosen, chosenFields = block, fields + } + } + setVariable := control[chosen[2]:chosen[3]] + // Keep one occurrence of each projection field and only select fields used + // by aggregate loops in RETURN. Slice projections remain independent and + // retain their exact sort-before-limit semantics. + seen := map[string]bool{} + fields := make([]string, 0, len(chosenFields)) + returnStart := strings.LastIndex(control, "\nRETURN ") + if returnStart < 0 { + return "", wp8SummaryReport{}, fmt.Errorf("production AQL has no RETURN") + } + returnText := control[returnStart:] + for _, field := range chosenFields { + if seen[field] || !strings.Contains(returnText, "FOR __loom_prepared_value IN "+setVariable+" RETURN __loom_prepared_value."+field) { + continue + } + seen[field] = true + fields = append(fields, field) + } + if len(fields) < 2 { + return "", wp8SummaryReport{}, fmt.Errorf("rich set %q has fewer than two aggregate selector fields: candidates=%v return=%s", setVariable, chosenFields, returnText) + } + sort.Strings(fields) + summaryVariable := "__loom_summary_" + setVariable + parts := make([]string, 0, len(fields)) + outputs := make([]string, 0, len(fields)+1) + for index, field := range fields { + name := fmt.Sprintf("values_%d", index) + parts = append(parts, fmt.Sprintf(" __loom_summary_%d = UNIQUE(__loom_summary_item.%s)", index, field)) + outputs = append(outputs, fmt.Sprintf("%s: SORTED_UNIQUE(FLATTEN(__loom_summary_%d))", name, index)) + } + summary := fmt.Sprintf(" LET %s = FIRST((\n FOR __loom_summary_item IN %s\n COLLECT AGGREGATE\n __loom_summary_count = COUNT(),\n%s\n RETURN { count: __loom_summary_count, %s }\n )) || { count: 0, %s }\n", summaryVariable, setVariable, strings.Join(parts, ",\n"), strings.Join(outputs, ", "), strings.Join(outputs, ", ")) + // Inject immediately after the selected set's materialization. The source + // set remains unchanged, so scope, identity, ordering, and optional roots + // are untouched; only rich aggregate reads are redirected. + candidate := control[:chosen[1]] + summary + control[chosen[1]:] + candidateReturnStart := strings.LastIndex(candidate, "\nRETURN ") + candidateReturn := candidate[candidateReturnStart:] + candidateReturn = strings.ReplaceAll(candidateReturn, "LENGTH("+setVariable+")", summaryVariable+".count") + for index, field := range fields { + old := "SORTED_UNIQUE(FLATTEN((FOR __loom_prepared_value IN " + setVariable + " RETURN __loom_prepared_value." + field + ")))" + newValue := fmt.Sprintf("%s.values_%d", summaryVariable, index) + candidateReturn = strings.ReplaceAll(candidateReturn, old, newValue) + } + candidate = candidate[:candidateReturnStart] + candidateReturn + report := wp8SummaryReport{SetVariable: setVariable, Fields: fields, BeforeLoops: strings.Count(controlReturnText(control), "FOR __loom_prepared_value IN "+setVariable), AfterLoops: strings.Count(controlReturnText(candidate), "FOR __loom_prepared_value IN "+setVariable), BeforeSorts: strings.Count(control, "\n SORT "), AfterSorts: strings.Count(candidate, "\n SORT "), BeforeUnique: strings.Count(control, "UNIQUE("), AfterUnique: strings.Count(candidate, "UNIQUE(")} + return candidate, report, nil +} + +func controlReturnText(aql string) string { + if index := strings.LastIndex(aql, "\nRETURN "); index >= 0 { + return aql[index:] + } + return aql +} + +func wp8Hash(value string) string { + hash := sha256.Sum256([]byte(value)) + return hex.EncodeToString(hash[:]) +} + +func wp8RunAlternating(ctx context.Context, client *arangostore.Client, control, candidate string, binds map[string]any, runControl bool) (int, string, int, []float64) { + times := make([]float64, 0, 5) + rows := 0 + bytes := 0 + hash := sha256.New() + for run := 0; run < 5; run++ { + query := candidate + if runControl { + query = control + } + started := time.Now() + _ = client.QueryRows(ctx, query, 10000, binds, func(row map[string]any) error { + rows++ + encoded, _ := json.Marshal(row) + bytes += len(encoded) + _, _ = hash.Write(encoded) + _, _ = hash.Write([]byte{'\n'}) + return nil + }) + times = append(times, time.Since(started).Seconds()) + } + return rows / 5, hex.EncodeToString(hash.Sum(nil)), bytes / 5, times +} + +func wp8WriteArtifacts(t *testing.T, control, candidate string, artifact wp8ProfileArtifact) { + _, source, _, _ := runtime.Caller(0) + directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "wp8") + if err := os.MkdirAll(directory, 0o755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(directory, "control.aql"), []byte(control), 0o644); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(directory, "candidate.aql"), []byte(candidate), 0o644); err != nil { + t.Fatal(err) + } + data, err := json.MarshalIndent(artifact, "", " ") + if err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(directory, "evidence.json"), append(data, '\n'), 0o644); err != nil { + t.Fatal(err) + } +} diff --git a/internal/dataframe/template/availability.go b/internal/dataframe/template/availability.go new file mode 100644 index 0000000..2454df2 --- /dev/null +++ b/internal/dataframe/template/availability.go @@ -0,0 +1,213 @@ +package template + +import ( + "fmt" + "strings" + + "github.com/calypr/loom/fhirschema" +) + +// Resolve computes availability without persistence or compiler access. The +// caller must first build the snapshot using its authorization and generation +// context. +func Resolve(definition Definition, snapshot CapabilitySnapshot) Availability { + availability := Availability{ + ID: definition.ID, Version: definition.Version, Label: definition.Label, + Description: definition.Description, Status: StatusUnavailable, + CommonColumns: []SelectedColumn{}, AdvancedColumns: []SelectedColumn{}, + Traversals: []SelectedTraversal{}, Pivots: []SelectedPivot{}, + Missing: []MissingCapability{}, Reasons: []string{}, + } + root, ok := firstAvailableRoot(definition.RootCandidates, snapshot.Resources) + if !ok { + availability.Reasons = append(availability.Reasons, "ROOT_RESOURCE_UNAVAILABLE") + availability.Missing = append(availability.Missing, MissingCapability{Kind: "root", Code: "ROOT_RESOURCE_UNAVAILABLE", Label: definition.Label}) + availability.Starter = StarterRequest{} + return availability + } + availability.RootResourceType = root + rootCapability := resourceCapability(root, snapshot.Resources) + for _, suggestion := range definition.SuggestedColumns { + selected, found := selectColumn(suggestion, rootCapability.Fields) + if !found { + availability.Missing = append(availability.Missing, MissingCapability{SuggestionID: suggestion.ID, Kind: "column", Label: suggestion.Label, Code: "FIELD_UNAVAILABLE"}) + continue + } + if suggestion.Advanced { + availability.AdvancedColumns = append(availability.AdvancedColumns, selected) + } else { + availability.CommonColumns = append(availability.CommonColumns, selected) + } + } + for _, suggestion := range definition.SuggestedTraversals { + selected, found := selectTraversal(suggestion, snapshot.Relationships) + if !found { + availability.Missing = append(availability.Missing, MissingCapability{SuggestionID: suggestion.ID, Kind: "traversal", Label: suggestion.Label, Code: "TRAVERSAL_UNAVAILABLE"}) + continue + } + availability.Traversals = append(availability.Traversals, selected) + } + for _, suggestion := range definition.SuggestedPivots { + selected, found := selectPivot(suggestion, rootCapability.Fields) + if !found { + availability.Missing = append(availability.Missing, MissingCapability{SuggestionID: suggestion.ID, Kind: "pivot", Label: suggestion.Label, Code: "PIVOT_UNAVAILABLE"}) + continue + } + availability.Pivots = append(availability.Pivots, selected) + } + + for _, missing := range availability.Missing { + availability.Reasons = append(availability.Reasons, missing.Code) + } + if hasRequiredMissing(definition, availability.Missing) { + availability.Status = StatusUnavailable + } else if len(availability.Missing) > 0 { + availability.Status = StatusPartial + } else { + availability.Status = StatusAvailable + } + availability.Starter = starterFor(definition, availability) + return availability +} + +func firstAvailableRoot(candidates []string, resources []ResourceCapability) (string, bool) { + for _, candidate := range candidates { + for _, resource := range resources { + if resource.Present && resource.ResourceType == candidate && fhirschema.HasResource(candidate) { + return candidate, true + } + } + } + return "", false +} + +func resourceCapability(resourceType string, resources []ResourceCapability) ResourceCapability { + for _, resource := range resources { + if resource.ResourceType == resourceType { + return resource + } + } + return ResourceCapability{} +} + +func selectColumn(suggestion ColumnSuggestion, fields []FieldCapability) (SelectedColumn, bool) { + for _, candidate := range suggestion.FieldRefAlternatives { + for _, field := range fields { + if field.FieldRef == candidate { + return SelectedColumn{ID: suggestion.ID, Label: suggestion.Label, FieldRef: field.FieldRef, Advanced: suggestion.Advanced}, true + } + } + } + return SelectedColumn{}, false +} + +func selectTraversal(suggestion TraversalSuggestion, relationships []RelationshipCapability) (SelectedTraversal, bool) { + for _, relationship := range relationships { + if !contains(suggestion.FromResourceTypes, relationship.FromType) || !contains(suggestion.ToResourceTypes, relationship.ToType) { + continue + } + if !fhirschema.HasResource(relationship.FromType) || !fhirschema.HasResource(relationship.ToType) { + continue + } + if _, found, err := fhirschema.ResolveCompilerTraversal(relationship.FromType, relationship.Label, relationship.ToType); err != nil || !found { + continue + } + return SelectedTraversal{ID: suggestion.ID, Label: suggestion.Label, SemanticRole: suggestion.SemanticRole, FromType: relationship.FromType, EdgeLabel: relationship.Label, ToType: relationship.ToType, Advanced: suggestion.Advanced}, true + } + return SelectedTraversal{}, false +} + +func selectPivot(suggestion PivotSuggestion, fields []FieldCapability) (SelectedPivot, bool) { + for _, candidate := range suggestion.FieldRefAlternatives { + for _, field := range fields { + if field.FieldRef != candidate || !field.PivotCandidate || len(field.PivotColumns) == 0 { + continue + } + return SelectedPivot{ID: suggestion.ID, Label: suggestion.Label, FieldRef: field.FieldRef, Columns: cloneStrings(field.PivotColumns), Advanced: suggestion.Advanced}, true + } + } + return SelectedPivot{}, false +} + +func hasRequiredMissing(definition Definition, missing []MissingCapability) bool { + for _, item := range missing { + for _, suggestion := range definition.SuggestedColumns { + if suggestion.ID == item.SuggestionID && suggestion.Required { + return true + } + } + for _, suggestion := range definition.SuggestedTraversals { + if suggestion.ID == item.SuggestionID && suggestion.Required { + return true + } + } + for _, suggestion := range definition.SuggestedPivots { + if suggestion.ID == item.SuggestionID && suggestion.Required { + return true + } + } + } + return false +} + +func starterFor(definition Definition, availability Availability) StarterRequest { + starter := StarterRequest{RootResourceType: availability.RootResourceType, RowGrain: definition.RowGrain, Fields: []SelectedColumn{}, Traversals: []SelectedTraversal{}, Pivots: []SelectedPivot{}} + for _, suggestion := range definition.SuggestedColumns { + if !suggestion.DefaultSelected { + continue + } + for _, selected := range append(append([]SelectedColumn{}, availability.CommonColumns...), availability.AdvancedColumns...) { + if selected.ID == suggestion.ID { + starter.Fields = append(starter.Fields, selected) + break + } + } + } + for _, suggestion := range definition.SuggestedTraversals { + if !suggestion.DefaultSelected { + continue + } + for _, selected := range availability.Traversals { + if selected.ID == suggestion.ID { + starter.Traversals = append(starter.Traversals, selected) + break + } + } + } + for _, suggestion := range definition.SuggestedPivots { + if !suggestion.DefaultSelected { + continue + } + for _, selected := range availability.Pivots { + if selected.ID == suggestion.ID { + starter.Pivots = append(starter.Pivots, selected) + break + } + } + } + return starter +} + +func contains(values []string, wanted string) bool { + for _, value := range values { + if strings.TrimSpace(value) == strings.TrimSpace(wanted) { + return true + } + } + return false +} + +// ValidateStarter performs the local structural checks that can be proven +// without a request context. Production validation remains the existing +// dataframe input resolver and compiler. +func ValidateStarter(starter StarterRequest) error { + if strings.TrimSpace(starter.RootResourceType) == "" || !fhirschema.HasResource(starter.RootResourceType) { + return fmt.Errorf("starter root resource type %q is not a generated FHIR resource", starter.RootResourceType) + } + for _, traversal := range starter.Traversals { + if _, found, err := fhirschema.ResolveCompilerTraversal(traversal.FromType, traversal.EdgeLabel, traversal.ToType); err != nil || !found { + return fmt.Errorf("starter traversal %q is not present in generated FHIR metadata", traversal.ID) + } + } + return nil +} diff --git a/internal/dataframe/template/availability_test.go b/internal/dataframe/template/availability_test.go new file mode 100644 index 0000000..811ef68 --- /dev/null +++ b/internal/dataframe/template/availability_test.go @@ -0,0 +1,66 @@ +package template + +import "testing" + +func TestResolveAlternativeFieldRefAndCatalogBoundedPivot(t *testing.T) { + registry := DefaultRegistry() + definition, _ := registry.Definition("file-manifest") + availability := Resolve(definition, CapabilitySnapshot{ + Resources: []ResourceCapability{{ + ResourceType: "DocumentReference", Present: true, + Fields: []FieldCapability{ + {ResourceType: "DocumentReference", FieldRef: "DocumentReference.id"}, + {ResourceType: "DocumentReference", FieldRef: "DocumentReference.content_attachment_title"}, + {ResourceType: "DocumentReference", FieldRef: "DocumentReference.content_attachment_url"}, + }, + }}, + }) + if availability.RootResourceType != "DocumentReference" { + t.Fatalf("root = %q", availability.RootResourceType) + } + if availability.Status != StatusPartial { + t.Fatalf("status = %s, want PARTIAL", availability.Status) + } + if len(availability.CommonColumns) != 3 { + t.Fatalf("common columns = %#v", availability.CommonColumns) + } + if availability.CommonColumns[1].FieldRef != "DocumentReference.content_attachment_title" { + t.Fatalf("unexpected selected title field = %#v", availability.CommonColumns[1]) + } +} + +func TestResolveRequiresVisibleRootAndDoesNotInferFromFHIRSchema(t *testing.T) { + definition, _ := DefaultRegistry().Definition("patient-cohort") + availability := Resolve(definition, CapabilitySnapshot{}) + if availability.Status != StatusUnavailable { + t.Fatalf("status = %s, want UNAVAILABLE", availability.Status) + } + if availability.RootResourceType != "" || len(availability.Starter.Fields) != 0 { + t.Fatalf("unavailable template leaked starter data: %#v", availability) + } +} + +func TestResolveTraversalRequiresCatalogAndGeneratedFHIRMetadata(t *testing.T) { + definition, _ := DefaultRegistry().Definition("study-enrollment") + base := CapabilitySnapshot{Resources: []ResourceCapability{{ResourceType: "ResearchSubject", Present: true, Fields: []FieldCapability{{ResourceType: "ResearchSubject", FieldRef: "ResearchSubject.id"}}}}} + missing := Resolve(definition, base) + if len(missing.Traversals) != 0 || len(missing.Missing) == 0 { + t.Fatalf("expected missing study traversal, got %#v", missing) + } + base.Relationships = []RelationshipCapability{{FromType: "ResearchSubject", Label: "study", ToType: "ResearchStudy"}} + available := Resolve(definition, base) + if len(available.Traversals) != 1 || available.Traversals[0].EdgeLabel != "study" { + t.Fatalf("expected observed study route, got %#v", available.Traversals) + } +} + +func TestResolveRejectsUnknownRelationshipTuple(t *testing.T) { + definition, _ := DefaultRegistry().Definition("study-enrollment") + availability := Resolve(definition, CapabilitySnapshot{ + Resources: []ResourceCapability{{ResourceType: "ResearchSubject", Present: true}}, + Relationships: []RelationshipCapability{{FromType: "ResearchSubject", Label: "not_generated", ToType: "ResearchStudy"}}, + }) + if len(availability.Traversals) != 0 { + t.Fatalf("unknown generated route was advertised: %#v", availability.Traversals) + } +} diff --git a/internal/dataframe/template/registry.go b/internal/dataframe/template/registry.go new file mode 100644 index 0000000..5f16fd3 --- /dev/null +++ b/internal/dataframe/template/registry.go @@ -0,0 +1,230 @@ +package template + +import ( + "fmt" + "strings" + + "github.com/calypr/loom/fhirschema" +) + +// Registry owns immutable, ordered template definitions. +type Registry struct { + definitions []Definition +} + +// NewRegistry validates and defensively copies definitions. The supplied +// order is the product order returned to clients. +func NewRegistry(definitions []Definition) (Registry, error) { + if len(definitions) == 0 { + return Registry{}, fmt.Errorf("template registry requires at least one definition") + } + seen := make(map[string]struct{}, len(definitions)) + validated := make([]Definition, 0, len(definitions)) + for _, definition := range definitions { + if err := validateDefinition(definition); err != nil { + return Registry{}, err + } + if _, ok := seen[definition.ID]; ok { + return Registry{}, fmt.Errorf("duplicate template id %q", definition.ID) + } + seen[definition.ID] = struct{}{} + validated = append(validated, definition.clone()) + } + return Registry{definitions: validated}, nil +} + +// DefaultRegistry returns the six initial guided dataframe families. +func DefaultRegistry() Registry { + registry, err := NewRegistry(defaultDefinitions()) + if err != nil { + panic(err) + } + return registry +} + +// Definitions returns a defensive copy in stable product order. +func (r Registry) Definitions() []Definition { + definitions := make([]Definition, len(r.definitions)) + for i, definition := range r.definitions { + definitions[i] = definition.clone() + } + return definitions +} + +// Definition returns a defensive copy of one template. +func (r Registry) Definition(id string) (Definition, bool) { + for _, definition := range r.definitions { + if definition.ID == strings.TrimSpace(id) { + return definition.clone(), true + } + } + return Definition{}, false +} + +func validateDefinition(definition Definition) error { + if strings.TrimSpace(definition.ID) == "" { + return fmt.Errorf("template id is required") + } + if definition.Version <= 0 { + return fmt.Errorf("template %q version must be positive", definition.ID) + } + if strings.TrimSpace(definition.Label) == "" { + return fmt.Errorf("template %q label is required", definition.ID) + } + if len(definition.RootCandidates) == 0 { + return fmt.Errorf("template %q requires a root candidate", definition.ID) + } + for _, resourceType := range definition.RootCandidates { + if !fhirschema.HasResource(resourceType) { + return fmt.Errorf("template %q references unknown root resource type %q", definition.ID, resourceType) + } + } + columnIDs := map[string]struct{}{} + for _, suggestion := range definition.SuggestedColumns { + if err := validateSuggestionID(definition.ID, "column", suggestion.ID); err != nil { + return err + } + if _, ok := columnIDs[suggestion.ID]; ok { + return fmt.Errorf("template %q duplicates column suggestion %q", definition.ID, suggestion.ID) + } + columnIDs[suggestion.ID] = struct{}{} + if !nonEmpty(suggestion.FieldRefAlternatives) { + return fmt.Errorf("template %q column %q requires fieldRef alternatives", definition.ID, suggestion.ID) + } + } + traversalIDs := map[string]struct{}{} + for _, suggestion := range definition.SuggestedTraversals { + if err := validateSuggestionID(definition.ID, "traversal", suggestion.ID); err != nil { + return err + } + if _, ok := traversalIDs[suggestion.ID]; ok { + return fmt.Errorf("template %q duplicates traversal suggestion %q", definition.ID, suggestion.ID) + } + traversalIDs[suggestion.ID] = struct{}{} + if strings.TrimSpace(suggestion.SemanticRole) == "" || len(suggestion.FromResourceTypes) == 0 || len(suggestion.ToResourceTypes) == 0 { + return fmt.Errorf("template %q traversal %q requires semantic role and source/target types", definition.ID, suggestion.ID) + } + for _, resourceType := range append(cloneStrings(suggestion.FromResourceTypes), suggestion.ToResourceTypes...) { + if !fhirschema.HasResource(resourceType) { + return fmt.Errorf("template %q traversal %q references unknown resource type %q", definition.ID, suggestion.ID, resourceType) + } + } + } + pivotIDs := map[string]struct{}{} + for _, suggestion := range definition.SuggestedPivots { + if err := validateSuggestionID(definition.ID, "pivot", suggestion.ID); err != nil { + return err + } + if _, ok := pivotIDs[suggestion.ID]; ok { + return fmt.Errorf("template %q duplicates pivot suggestion %q", definition.ID, suggestion.ID) + } + pivotIDs[suggestion.ID] = struct{}{} + if !nonEmpty(suggestion.FieldRefAlternatives) { + return fmt.Errorf("template %q pivot %q requires fieldRef alternatives", definition.ID, suggestion.ID) + } + } + return nil +} + +func validateSuggestionID(templateID, kind, id string) error { + if strings.TrimSpace(id) == "" { + return fmt.Errorf("template %q %s suggestion id is required", templateID, kind) + } + return nil +} + +func defaultDefinitions() []Definition { + return []Definition{ + { + ID: "patient-cohort", Version: 1, Label: "Patient cohort", + Description: "One row per patient with common demographics and related clinical facts.", + RootCandidates: []string{"Patient"}, RowGrain: "patient", + SuggestedColumns: []ColumnSuggestion{ + {ID: "patient-identifier", Label: "Patient identifier", FieldRefAlternatives: []string{"Patient.identifier_value", "Patient.id"}, DefaultSelected: true}, + {ID: "gender", Label: "Gender", FieldRefAlternatives: []string{"Patient.gender"}, DefaultSelected: true}, + {ID: "birth-date", Label: "Birth date", FieldRefAlternatives: []string{"Patient.birthdate"}, DefaultSelected: true}, + {ID: "deceased", Label: "Deceased", FieldRefAlternatives: []string{"Patient.deceasedboolean", "Patient.deceaseddatetime"}, Advanced: true}, + }, + SuggestedTraversals: []TraversalSuggestion{ + {ID: "diagnoses", Label: "Diagnoses", SemanticRole: "diagnosis", FromResourceTypes: []string{"Patient"}, ToResourceTypes: []string{"Condition"}}, + {ID: "specimens", Label: "Specimens", SemanticRole: "specimen", FromResourceTypes: []string{"Patient"}, ToResourceTypes: []string{"Specimen"}}, + {ID: "observations", Label: "Observations", SemanticRole: "observation", FromResourceTypes: []string{"Patient"}, ToResourceTypes: []string{"Observation"}, Advanced: true}, + }, + }, + { + ID: "specimen-inventory", Version: 1, Label: "Specimen inventory", + Description: "One row per specimen with type, status, subject, and collection facts.", + RootCandidates: []string{"Specimen"}, RowGrain: "specimen", + SuggestedColumns: []ColumnSuggestion{ + {ID: "specimen-id", Label: "Specimen identifier", FieldRefAlternatives: []string{"Specimen.id", "Specimen.identifier_value"}, DefaultSelected: true}, + {ID: "specimen-type", Label: "Specimen type", FieldRefAlternatives: []string{"Specimen.type_coding_display", "Specimen.type_text"}, DefaultSelected: true}, + {ID: "specimen-status", Label: "Status", FieldRefAlternatives: []string{"Specimen.status"}, DefaultSelected: true}, + {ID: "specimen-subject", Label: "Subject", FieldRefAlternatives: []string{"Specimen.subject_reference"}, Advanced: true}, + {ID: "collected-at", Label: "Collected at", FieldRefAlternatives: []string{"Specimen.collection_collecteddatetime", "Specimen.collection_collectedperiod_start"}, Advanced: true}, + }, + SuggestedTraversals: []TraversalSuggestion{ + {ID: "files", Label: "Files", SemanticRole: "file", FromResourceTypes: []string{"Specimen"}, ToResourceTypes: []string{"DocumentReference"}}, + }, + }, + { + ID: "file-manifest", Version: 1, Label: "File manifest", + Description: "One row per file-like DocumentReference with attachment metadata.", + RootCandidates: []string{"DocumentReference"}, RowGrain: "file", + SuggestedColumns: []ColumnSuggestion{ + {ID: "file-id", Label: "File identifier", FieldRefAlternatives: []string{"DocumentReference.id"}, DefaultSelected: true}, + {ID: "file-name", Label: "File name", FieldRefAlternatives: []string{"DocumentReference.content_attachment_title"}, DefaultSelected: true}, + {ID: "file-url", Label: "File URL", FieldRefAlternatives: []string{"DocumentReference.content_attachment_url"}, DefaultSelected: true}, + {ID: "content-type", Label: "Content type", FieldRefAlternatives: []string{"DocumentReference.content_attachment_contenttype"}, Advanced: true}, + {ID: "file-size", Label: "File size", FieldRefAlternatives: []string{"DocumentReference.content_attachment_size"}, Advanced: true}, + {ID: "file-subject", Label: "Subject", FieldRefAlternatives: []string{"DocumentReference.subject_reference"}, Advanced: true}, + }, + SuggestedTraversals: []TraversalSuggestion{ + {ID: "specimens", Label: "Specimens", SemanticRole: "specimen", FromResourceTypes: []string{"DocumentReference"}, ToResourceTypes: []string{"Specimen"}, Advanced: true}, + }, + }, + { + ID: "diagnoses", Version: 1, Label: "Diagnoses", + Description: "One row per Condition with diagnosis code and clinical status.", + RootCandidates: []string{"Condition"}, RowGrain: "diagnosis", + SuggestedColumns: []ColumnSuggestion{ + {ID: "diagnosis-id", Label: "Diagnosis identifier", FieldRefAlternatives: []string{"Condition.id"}, DefaultSelected: true}, + {ID: "diagnosis-code", Label: "Diagnosis code", FieldRefAlternatives: []string{"Condition.code_coding_display", "Condition.code_text"}, DefaultSelected: true}, + {ID: "clinical-status", Label: "Clinical status", FieldRefAlternatives: []string{"Condition.clinicalstatus_coding_display"}, DefaultSelected: true}, + {ID: "verification-status", Label: "Verification status", FieldRefAlternatives: []string{"Condition.verificationstatus_coding_display"}, Advanced: true}, + {ID: "diagnosis-subject", Label: "Subject", FieldRefAlternatives: []string{"Condition.subject_reference"}, Advanced: true}, + }, + }, + { + ID: "labs-observations", Version: 1, Label: "Labs and observations", + Description: "One row per Observation with code, value, timing, and optional bounded pivots.", + RootCandidates: []string{"Observation"}, RowGrain: "observation", + SuggestedColumns: []ColumnSuggestion{ + {ID: "observation-id", Label: "Observation identifier", FieldRefAlternatives: []string{"Observation.id"}, DefaultSelected: true}, + {ID: "observation-code", Label: "Observation code", FieldRefAlternatives: []string{"Observation.code_coding_display", "Observation.code_text"}, DefaultSelected: true}, + {ID: "value", Label: "Value", FieldRefAlternatives: []string{"Observation.valuequantity_value", "Observation.valuestring", "Observation.valueinteger", "Observation.valuedecimal"}, DefaultSelected: true}, + {ID: "unit", Label: "Unit", FieldRefAlternatives: []string{"Observation.valuequantity_unit"}, Advanced: true}, + {ID: "effective-at", Label: "Effective at", FieldRefAlternatives: []string{"Observation.effectivedatetime", "Observation.effectiveperiod_start"}, Advanced: true}, + {ID: "observation-subject", Label: "Subject", FieldRefAlternatives: []string{"Observation.subject_reference"}, Advanced: true}, + }, + SuggestedPivots: []PivotSuggestion{ + {ID: "observation-values", Label: "Observation values by code", FieldRefAlternatives: []string{"Observation.code"}, DefaultSelected: true}, + }, + }, + { + ID: "study-enrollment", Version: 1, Label: "Study enrollment", + Description: "One row per ResearchSubject with subject and study relationship facts.", + RootCandidates: []string{"ResearchSubject"}, RowGrain: "study_enrollment", + SuggestedColumns: []ColumnSuggestion{ + {ID: "enrollment-id", Label: "Enrollment identifier", FieldRefAlternatives: []string{"ResearchSubject.id"}, DefaultSelected: true}, + {ID: "enrollment-status", Label: "Enrollment status", FieldRefAlternatives: []string{"ResearchSubject.status"}, DefaultSelected: true}, + {ID: "enrolled-patient", Label: "Patient", FieldRefAlternatives: []string{"ResearchSubject.patient_reference"}, DefaultSelected: true}, + {ID: "enrolled-study", Label: "Study", FieldRefAlternatives: []string{"ResearchSubject.study_reference"}, DefaultSelected: true}, + {ID: "period-start", Label: "Enrollment start", FieldRefAlternatives: []string{"ResearchSubject.period_start"}, Advanced: true}, + {ID: "period-end", Label: "Enrollment end", FieldRefAlternatives: []string{"ResearchSubject.period_end"}, Advanced: true}, + }, + SuggestedTraversals: []TraversalSuggestion{ + {ID: "study", Label: "Research study", SemanticRole: "study", FromResourceTypes: []string{"ResearchSubject"}, ToResourceTypes: []string{"ResearchStudy"}, DefaultSelected: true}, + }, + }, + } +} diff --git a/internal/dataframe/template/registry_test.go b/internal/dataframe/template/registry_test.go new file mode 100644 index 0000000..c8b6b3a --- /dev/null +++ b/internal/dataframe/template/registry_test.go @@ -0,0 +1,76 @@ +package template + +import "testing" + +func TestDefaultRegistryHasStableSixTemplateOrder(t *testing.T) { + registry := DefaultRegistry() + definitions := registry.Definitions() + want := []string{"patient-cohort", "specimen-inventory", "file-manifest", "diagnoses", "labs-observations", "study-enrollment"} + if len(definitions) != len(want) { + t.Fatalf("definition count = %d, want %d", len(definitions), len(want)) + } + for i, id := range want { + if definitions[i].ID != id || definitions[i].Version != 1 { + t.Fatalf("definition %d = %#v, want %s v1", i, definitions[i], id) + } + } +} + +func TestRegistryDefinitionsAreDefensiveCopies(t *testing.T) { + registry := DefaultRegistry() + definitions := registry.Definitions() + definitions[0].RootCandidates[0] = "Observation" + definitions[0].SuggestedColumns[0].FieldRefAlternatives[0] = "Observation.id" + got, ok := registry.Definition("patient-cohort") + if !ok { + t.Fatal("patient-cohort not found") + } + if got.RootCandidates[0] != "Patient" || got.SuggestedColumns[0].FieldRefAlternatives[0] != "Patient.identifier_value" { + t.Fatalf("registry was mutated through returned definition: %#v", got) + } +} + +func TestRegistryRejectsDuplicateAndUnknownDefinitions(t *testing.T) { + base := Definition{ID: "x", Version: 1, Label: "X", RootCandidates: []string{"Patient"}} + if _, err := NewRegistry([]Definition{base, base}); err == nil { + t.Fatal("expected duplicate id error") + } + unknown := base + unknown.ID = "unknown" + unknown.RootCandidates = []string{"NotFHIR"} + if _, err := NewRegistry([]Definition{unknown}); err == nil { + t.Fatal("expected unknown root error") + } +} + +func TestDefaultStartersContainOnlyDefaultSuggestions(t *testing.T) { + registry := DefaultRegistry() + definition, ok := registry.Definition("labs-observations") + if !ok { + t.Fatal("labs-observations not found") + } + snapshot := CapabilitySnapshot{ + Resources: []ResourceCapability{{ + ResourceType: "Observation", Present: true, + Fields: []FieldCapability{ + {ResourceType: "Observation", FieldRef: "Observation.id"}, + {ResourceType: "Observation", FieldRef: "Observation.code_coding_display"}, + {ResourceType: "Observation", FieldRef: "Observation.valuequantity_value"}, + {ResourceType: "Observation", FieldRef: "Observation.code", PivotCandidate: true, PivotColumns: []string{"A", "B"}}, + }, + }}, + } + availability := Resolve(definition, snapshot) + if availability.Status != StatusPartial { + t.Fatalf("status = %s, want PARTIAL because optional fields are absent", availability.Status) + } + if len(availability.Starter.Fields) != 3 { + t.Fatalf("starter fields = %#v, want 3 default fields", availability.Starter.Fields) + } + if len(availability.Starter.Pivots) != 1 || availability.Starter.Pivots[0].Columns[0] != "A" { + t.Fatalf("starter pivots = %#v", availability.Starter.Pivots) + } + if err := ValidateStarter(availability.Starter); err != nil { + t.Fatal(err) + } +} diff --git a/internal/dataframe/template/types.go b/internal/dataframe/template/types.go new file mode 100644 index 0000000..a68073c --- /dev/null +++ b/internal/dataframe/template/types.go @@ -0,0 +1,233 @@ +// Package template contains product-level dataframe template metadata. +// +// Templates describe semantic preferences only. They do not contain AQL, +// Arango collection names, or compiler selectors. Availability is resolved +// against a caller-scoped capability snapshot before a starter request is +// returned to a client. +package template + +import "strings" + +// AvailabilityStatus is the support level for a template in one dataset and +// authorization scope. +type AvailabilityStatus string + +const ( + StatusAvailable AvailabilityStatus = "AVAILABLE" + StatusPartial AvailabilityStatus = "PARTIAL" + StatusUnavailable AvailabilityStatus = "UNAVAILABLE" +) + +// Definition is immutable product metadata. Definitions are validated when a +// Registry is constructed and are returned defensively from the registry. +type Definition struct { + ID string + Version int + Label string + Description string + RootCandidates []string + RowGrain string + SuggestedColumns []ColumnSuggestion + SuggestedTraversals []TraversalSuggestion + SuggestedPivots []PivotSuggestion +} + +// ColumnSuggestion is a user-facing column preference. Alternatives are +// stable fieldRef values in priority order; selector parsing remains owned by +// the existing dataframe input resolver. +type ColumnSuggestion struct { + ID string + Label string + FieldRefAlternatives []string + DefaultSelected bool + Advanced bool + Required bool +} + +// TraversalSuggestion describes a semantic relationship preference. The +// observed edge label is deliberately not part of the definition: availability +// resolution obtains a proven label from the current catalog and generated +// FHIR schema. +type TraversalSuggestion struct { + ID string + Label string + SemanticRole string + FromResourceTypes []string + ToResourceTypes []string + DefaultSelected bool + Advanced bool + Required bool +} + +// PivotSuggestion identifies a pivot-capable field by fieldRef alternatives. +// Bounded columns are taken from the current catalog, never from product +// metadata or a hard-coded fixture. +type PivotSuggestion struct { + ID string + Label string + FieldRefAlternatives []string + DefaultSelected bool + Advanced bool + Required bool +} + +// FieldCapability is a catalog-backed field visible to the current caller. +type FieldCapability struct { + ResourceType string + FieldRef string + PivotCandidate bool + PivotColumns []string + PivotFamily string + PivotColumnSelect string + PivotValueSelect string +} + +// ResourceCapability is a visible resource and its populated fields. Present +// distinguishes a visible resource with no currently populated fields from an +// absent resource. +type ResourceCapability struct { + ResourceType string + Present bool + Fields []FieldCapability +} + +// RelationshipCapability is a catalog-backed relationship. Label is observed +// data, not a product-template assumption. +type RelationshipCapability struct { + FromType string + Label string + ToType string + EdgeCount int64 +} + +// CapabilitySnapshot is the persistence-neutral input to availability +// resolution. Adapters may build it from catalog reads, fake fixtures, or a +// future analysis cache. +type CapabilitySnapshot struct { + Resources []ResourceCapability + Relationships []RelationshipCapability +} + +// MissingCapability explains why a suggestion was not included in the +// starter request. Codes are stable machine-readable values. +type MissingCapability struct { + SuggestionID string + Kind string + Label string + Code string +} + +// SelectedColumn is a fieldRef chosen from a suggestion's alternatives. +type SelectedColumn struct { + ID string + Label string + FieldRef string + Advanced bool +} + +// SelectedTraversal is a data-backed traversal choice. EdgeLabel is returned +// only after matching a catalog relationship and generated schema metadata. +type SelectedTraversal struct { + ID string + Label string + SemanticRole string + FromType string + EdgeLabel string + ToType string + Advanced bool +} + +// SelectedPivot is a bounded pivot starter intent. The input resolver fills in +// the physical selector pair from the selected fieldRef's catalog metadata. +type SelectedPivot struct { + ID string + Label string + FieldRef string + Columns []string + Advanced bool +} + +// StarterRequest is intentionally equivalent to the semantic portion of a +// dataframe request, without GraphQL-generated types or raw selectors. +type StarterRequest struct { + RootResourceType string + RowGrain string + Fields []SelectedColumn + Traversals []SelectedTraversal + Pivots []SelectedPivot +} + +// Availability is the frontend-facing result of resolving one definition +// against one capability snapshot. +type Availability struct { + ID string + Version int + Label string + Description string + Status AvailabilityStatus + RootResourceType string + CommonColumns []SelectedColumn + AdvancedColumns []SelectedColumn + Traversals []SelectedTraversal + Pivots []SelectedPivot + Missing []MissingCapability + Reasons []string + Starter StarterRequest +} + +func (d Definition) clone() Definition { + d.RootCandidates = cloneStrings(d.RootCandidates) + d.SuggestedColumns = append([]ColumnSuggestion(nil), d.SuggestedColumns...) + for i := range d.SuggestedColumns { + d.SuggestedColumns[i].FieldRefAlternatives = cloneStrings(d.SuggestedColumns[i].FieldRefAlternatives) + } + d.SuggestedTraversals = append([]TraversalSuggestion(nil), d.SuggestedTraversals...) + for i := range d.SuggestedTraversals { + d.SuggestedTraversals[i].FromResourceTypes = cloneStrings(d.SuggestedTraversals[i].FromResourceTypes) + d.SuggestedTraversals[i].ToResourceTypes = cloneStrings(d.SuggestedTraversals[i].ToResourceTypes) + } + d.SuggestedPivots = append([]PivotSuggestion(nil), d.SuggestedPivots...) + for i := range d.SuggestedPivots { + d.SuggestedPivots[i].FieldRefAlternatives = cloneStrings(d.SuggestedPivots[i].FieldRefAlternatives) + } + return d +} + +func (a Availability) clone() Availability { + a.CommonColumns = append([]SelectedColumn(nil), a.CommonColumns...) + a.AdvancedColumns = append([]SelectedColumn(nil), a.AdvancedColumns...) + a.Traversals = append([]SelectedTraversal(nil), a.Traversals...) + a.Pivots = append([]SelectedPivot(nil), a.Pivots...) + for i := range a.Pivots { + a.Pivots[i].Columns = cloneStrings(a.Pivots[i].Columns) + } + a.Missing = append([]MissingCapability(nil), a.Missing...) + a.Reasons = cloneStrings(a.Reasons) + a.Starter = StarterRequest{ + RootResourceType: a.Starter.RootResourceType, + RowGrain: a.Starter.RowGrain, + Fields: append([]SelectedColumn(nil), a.Starter.Fields...), + Traversals: append([]SelectedTraversal(nil), a.Starter.Traversals...), + Pivots: append([]SelectedPivot(nil), a.Starter.Pivots...), + } + for i := range a.Starter.Pivots { + a.Starter.Pivots[i].Columns = cloneStrings(a.Starter.Pivots[i].Columns) + } + return a +} + +func cloneStrings(in []string) []string { + if len(in) == 0 { + return []string{} + } + return append([]string(nil), in...) +} + +func nonEmpty(values []string) bool { + for _, value := range values { + if strings.TrimSpace(value) != "" { + return true + } + } + return false +} diff --git a/internal/dataframe/tournament_pivot_test.go b/internal/dataframe/tournament_pivot_test.go new file mode 100644 index 0000000..57b1cf3 --- /dev/null +++ b/internal/dataframe/tournament_pivot_test.go @@ -0,0 +1,409 @@ +package dataframe_test + +// Round 4 pivot tournament. This is an isolated AQL experiment over the +// endpoint+typed-selector production shape; no production compiler changes. + +import ( + "context" + "encoding/json" + "fmt" + "os" + "path/filepath" + "runtime" + "strings" + "testing" + "time" + + arangostore "github.com/calypr/loom/internal/store/arango" +) + +type pivotTournamentRun struct { + ControlSeconds []float64 `json:"control_seconds"` + CandidateSeconds []float64 `json:"candidate_seconds"` + ControlBytes []int `json:"control_bytes"` + CandidateBytes []int `json:"candidate_bytes"` + ControlHash string `json:"control_result_sha256"` + CandidateHash string `json:"candidate_result_sha256"` + ControlProfile arangostore.ProfileResult `json:"control_profile"` + CandidateProfile arangostore.ProfileResult `json:"candidate_profile"` +} + +type pivotTournamentMeasurement struct { + Seconds []float64 `json:"seconds"` + Bytes []int `json:"bytes"` + Hash string `json:"result_sha256"` + Profile arangostore.ProfileResult `json:"profile"` +} + +func TestPivotCandidateStructure(t *testing.T) { + control := readPivotAQL(t) + candidate, err := buildPivotCandidate(control) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(candidate, "FOR __pivot_key IN @pivot_child_set_6_observation_values_columns") || !strings.Contains(candidate, "SORTED_UNIQUE(FLATTEN((") { + t.Fatalf("candidate did not build fixed-column pivot reduction:\n%s", candidate) + } + if strings.Contains(candidate, "COLLECT __pivot_key = __pair.key") { + t.Fatal("candidate retained the old per-pair COLLECT pivot reduction") + } + if !strings.Contains(candidate, "FOR __pivot_key IN @pivot_child_set_6_observation_values_columns") { + t.Fatal("candidate lost fixed pivot-column order") + } + t.Logf("pivot candidate control_hash=%s candidate_hash=%s", sha256Hex(control), sha256Hex(candidate)) +} + +func TestPivotCandidateProfilesActualGDC(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run pivot tournament") + } + control := readPivotAQL(t) + candidate, err := buildPivotCandidate(control) + if err != nil { + t.Fatal(err) + } + binds := readPivotBinds(t) + url, database, _ := compilerArangoTarget() + client, err := arangostore.Open(context.Background(), url, database) + if err != nil { + t.Fatalf("open Arango: %v", err) + } + defer client.Close(context.Background()) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) + defer cancel() + run := pivotTournamentRun{} + for index := 0; index < 5; index++ { + controlQuery, controlBinds := cacheBust(control, binds, 68000+index*2) + candidateQuery, candidateBinds := cacheBust(candidate, binds, 68001+index*2) + seconds, bytes, hash, err := executeOrdinary(ctx, client, controlQuery, controlBinds) + if err != nil { + t.Fatalf("control run %d: %v", index+1, err) + } + run.ControlSeconds = append(run.ControlSeconds, seconds) + run.ControlBytes = append(run.ControlBytes, bytes) + run.ControlHash = hash + seconds, bytes, hash, err = executeOrdinary(ctx, client, candidateQuery, candidateBinds) + if err != nil { + t.Fatalf("candidate run %d: %v", index+1, err) + } + run.CandidateSeconds = append(run.CandidateSeconds, seconds) + run.CandidateBytes = append(run.CandidateBytes, bytes) + run.CandidateHash = hash + } + if run.ControlHash != run.CandidateHash { + t.Fatalf("pivot result parity mismatch control=%s candidate=%s", run.ControlHash, run.CandidateHash) + } + controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: control, BindVars: binds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + t.Fatalf("control PROFILE: %v", err) + } + candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidate, BindVars: binds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + t.Fatalf("candidate PROFILE: %v", err) + } + if hashRawRows(controlProfile.Result) != hashRawRows(candidateProfile.Result) { + t.Fatalf("pivot PROFILE result parity mismatch") + } + run.ControlProfile = controlProfile + run.CandidateProfile = candidateProfile + t.Logf("pivot control_median=%.6f candidate_median=%.6f control_profile=%+v candidate_profile=%+v", median(run.ControlSeconds), median(run.CandidateSeconds), arangostore.SummarizeProfile(controlProfile), arangostore.SummarizeProfile(candidateProfile)) + writePivotEvidence(t, control, candidate, run) +} + +// TestPivotMiniTournamentProfilesReductionShapes compares only pivot reduction +// shapes. The source child_set_6 and every non-pivot expression remain frozen, +// so a result or timing change is attributable to the pivot lowering. +func TestPivotMiniTournamentProfilesReductionShapes(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run pivot tournament") + } + control := readPivotAQL(t) + columns := readPivotColumns(t) + candidates := map[string]string{ + "min_zip": buildPivotReduction(control, pivotMinZipBody(false, false)), + "min_zip_hash": buildPivotReduction(control, pivotMinZipBody(true, false)), + "min_zip_has": buildPivotReduction(control, pivotMinZipBody(false, true)), + "sorted_unique": buildPivotReduction(control, pivotSortedUniqueZipBody()), + } + binds := readPivotBinds(t) + allowed := make(map[string]bool, len(columns)) + for _, column := range columns { + allowed[column] = true + } + candidateBinds := make(map[string]any, len(binds)+1) + for key, value := range binds { + candidateBinds[key] = value + } + candidateBinds["pivot_allowed"] = allowed + mapCandidateBinds := make(map[string]any, len(candidateBinds)) + for key, value := range candidateBinds { + if key != "pivot_child_set_6_observation_values_columns" { + mapCandidateBinds[key] = value + } + } + url, database, _ := compilerArangoTarget() + client, err := arangostore.Open(context.Background(), url, database) + if err != nil { + t.Fatalf("open Arango: %v", err) + } + defer client.Close(context.Background()) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) + defer cancel() + + runs := map[string]*pivotTournamentMeasurement{"control": {}} + for name := range candidates { + runs[name] = &pivotTournamentMeasurement{} + } + runCount := 5 + if value := os.Getenv("LOOM_PIVOT_TOURNAMENT_RUNS"); value != "" { + if _, scanErr := fmt.Sscanf(value, "%d", &runCount); scanErr != nil || runCount < 1 { + t.Fatalf("LOOM_PIVOT_TOURNAMENT_RUNS must be a positive integer, got %q", value) + } + } + candidateNames := sortedPivotCandidateNames(candidates) + for index := 0; index < runCount; index++ { + t.Logf("pivot tournament run %d/%d: control", index+1, runCount) + query, queryBinds := cacheBust(control, binds, 72000+index*10) + seconds, bytes, hash, runErr := executeOrdinary(ctx, client, query, queryBinds) + if runErr != nil { + t.Fatalf("control run %d: %v", index+1, runErr) + } + runs["control"].Seconds = append(runs["control"].Seconds, seconds) + runs["control"].Bytes = append(runs["control"].Bytes, bytes) + runs["control"].Hash = hash + for candidateIndex, name := range candidateNames { + t.Logf("pivot tournament run %d/%d: candidate %s", index+1, runCount, name) + candidateRunBindsBase := binds + if name == "min_zip_has" { + candidateRunBindsBase = mapCandidateBinds + } + candidateQuery, candidateRunBinds := cacheBust(candidates[name], candidateRunBindsBase, 72001+index*10+candidateIndex) + seconds, bytes, hash, runErr = executeOrdinary(ctx, client, candidateQuery, candidateRunBinds) + if runErr != nil { + t.Fatalf("%s run %d: %v", name, index+1, runErr) + } + runs[name].Seconds = append(runs[name].Seconds, seconds) + runs[name].Bytes = append(runs[name].Bytes, bytes) + runs[name].Hash = hash + } + } + for _, name := range append([]string{"control"}, candidateNames...) { + run := runs[name] + if run.Hash != runs["control"].Hash { + t.Logf("pivot result parity mismatch candidate=%s control=%s candidate_hash=%s", name, runs["control"].Hash, run.Hash) + } + } + queries := map[string]string{"control": control} + for _, name := range candidateNames { + queries[name] = candidates[name] + } + writePivotTournamentEvidence(t, control, candidates, runs) + if os.Getenv("LOOM_PIVOT_TOURNAMENT_SKIP_PROFILE") != "" { + for _, name := range append([]string{"control"}, candidateNames...) { + run := runs[name] + t.Logf("pivot %s median=%.6fs bytes=%d hash=%s", name, median(run.Seconds), run.Bytes[0], run.Hash) + } + return + } + for name, query := range queries { + profileBinds := binds + if name == "min_zip_has" { + profileBinds = mapCandidateBinds + } + profile, profileErr := client.Profile(ctx, arangostore.ProfileRequest{Query: query, BindVars: profileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if profileErr != nil { + t.Fatalf("%s PROFILE: %v", name, profileErr) + } + runs[name].Profile = profile + assessment := arangostore.SummarizeProfile(profile) + t.Logf("pivot %s median=%.6fs bytes=%d profile_runtime=%.6fs scanned_index=%d scanned_full=%d peak_memory=%d", name, median(runs[name].Seconds), runs[name].Bytes[0], assessment.RuntimeSeconds, assessment.ScannedIndex, assessment.ScannedFull, assessment.PeakMemory) + } +} + +func readPivotColumns(t *testing.T) []string { + binds := readPivotBinds(t) + columns, ok := binds["pivot_child_set_6_observation_values_columns"].([]any) + if !ok { + t.Fatalf("pivot columns bind has unexpected type %T", binds["pivot_child_set_6_observation_values_columns"]) + } + result := make([]string, 0, len(columns)) + for _, column := range columns { + value, ok := column.(string) + if !ok { + t.Fatalf("pivot column has unexpected type %T", column) + } + result = append(result, value) + } + return result +} + +func sortedPivotCandidateNames(candidates map[string]string) []string { + if only := os.Getenv("LOOM_PIVOT_TOURNAMENT_ONLY"); only != "" { + if _, ok := candidates[only]; ok { + return []string{only} + } + } + return []string{"min_zip", "min_zip_hash", "min_zip_has", "sorted_unique"} +} + +func buildPivotReduction(control, body string) string { + marker := ", [@__loom_physical_projection_20_name]: MERGE(" + start := strings.Index(control, marker) + if start < 0 { + panic("pivot marker not found") + } + endRel := strings.Index(control[start:], "\n) }\n") + if endRel < 0 { + panic("pivot expression end not found") + } + return control[:start] + ", [@__loom_physical_projection_20_name]: " + body + control[start+endRel:] +} + +func pivotMinZipBody(hash, hasMap bool) string { + membership := "POSITION(@pivot_child_set_6_observation_values_columns, __pivot_key)" + if hasMap { + membership = "HAS(@pivot_allowed, __pivot_key)" + } + method := "" + if hash { + method = " OPTIONS { method: \"hash\" }" + } + return fmt.Sprintf(`FIRST(( + LET __pivot_pairs = ( + FOR __pivot_item IN child_set_6 + LET __pivot_keys = UNIQUE(__pivot_item.__loom_projection_0) + LET __pivot_values = __pivot_item.__loom_projection_1 + FILTER LENGTH(__pivot_values) > 0 + FOR __pivot_key IN __pivot_keys + FILTER %s + FOR __pivot_value IN __pivot_values + COLLECT __pivot_group_key = __pivot_key AGGREGATE __pivot_selected = MIN(__pivot_value)%s + RETURN [__pivot_group_key, __pivot_selected] + ) + RETURN ZIP(__pivot_pairs[*][0], __pivot_pairs[*][1]) +) +`, membership, method) +} + +func pivotSortedUniqueZipBody() string { + return `FIRST(( + LET __pivot_pairs = ( + FOR __pivot_item IN child_set_6 + LET __pivot_keys = UNIQUE(__pivot_item.__loom_projection_0) + LET __pivot_values = __pivot_item.__loom_projection_1 + FILTER LENGTH(__pivot_values) > 0 + FOR __pivot_key IN __pivot_keys + FILTER POSITION(@pivot_child_set_6_observation_values_columns, __pivot_key) + FOR __pivot_value IN __pivot_values + COLLECT __pivot_group_key = __pivot_key AGGREGATE __pivot_values_sorted = SORTED_UNIQUE(__pivot_value) + RETURN [__pivot_group_key, FIRST(__pivot_values_sorted)] + ) + RETURN ZIP(__pivot_pairs[*][0], __pivot_pairs[*][1]) +) +` +} + +func writePivotTournamentEvidence(t *testing.T, control string, candidates map[string]string, runs map[string]*pivotTournamentMeasurement) { + _, source, _, _ := runtime.Caller(0) + directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "tournament_pivot_mini") + if err := os.MkdirAll(directory, 0o755); err != nil { + t.Fatalf("create pivot tournament evidence directory: %v", err) + } + files := map[string]string{"incumbent.aql": control} + for name, query := range candidates { + files[name+".aql"] = query + } + for name, contents := range files { + if err := os.WriteFile(filepath.Join(directory, name), []byte(contents), 0o644); err != nil { + t.Fatalf("write pivot tournament %s: %v", name, err) + } + } + hashes := make(map[string]string, len(candidates)) + for name, query := range candidates { + hashes[name] = sha256Hex(query) + } + payload := map[string]any{ + "incumbent_aql_sha256": sha256Hex(control), + "candidate_aql_sha256": hashes, + "runs": runs, + "candidate_names": sortedPivotCandidateNames(candidates), + "promotion_threshold": "10% wall-time or peak-memory improvement with exact result parity", + } + data, err := json.MarshalIndent(payload, "", " ") + if err != nil { + t.Fatalf("encode pivot tournament evidence: %v", err) + } + if err := os.WriteFile(filepath.Join(directory, "RESULTS.json"), append(data, '\n'), 0o644); err != nil { + t.Fatalf("write pivot tournament RESULTS.json: %v", err) + } +} + +func readPivotAQL(t *testing.T) string { + _, source, _, _ := runtime.Caller(0) + path := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "wp2", "selector-integration-endpoint_typed_selector.aql") + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("read frozen pivot AQL: %v", err) + } + return string(data) +} + +func readPivotBinds(t *testing.T) map[string]any { + _, source, _, _ := runtime.Caller(0) + path := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round3", "wp4", "production.json") + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("read pivot binds: %v", err) + } + var payload struct { + BindVars map[string]any `json:"bind_vars"` + } + if err := json.Unmarshal(data, &payload); err != nil { + t.Fatalf("decode pivot binds: %v", err) + } + return payload.BindVars +} + +func buildPivotCandidate(control string) (string, error) { + marker := ", [@__loom_physical_projection_20_name]: MERGE(" + start := strings.Index(control, marker) + if start < 0 { + return "", fmt.Errorf("pivot marker not found") + } + endRel := strings.Index(control[start:], "\n) }\n") + if endRel < 0 { + return "", fmt.Errorf("pivot expression end not found") + } + end := start + endRel + candidatePivot := `, [@__loom_physical_projection_20_name]: MERGE( + FOR __pivot_key IN @pivot_child_set_6_observation_values_columns + LET __pivot_values = SORTED_UNIQUE(FLATTEN(( + FOR __pivot_item IN child_set_6 + FILTER POSITION(__pivot_item.__loom_projection_0, __pivot_key) + RETURN __pivot_item.__loom_projection_1 + ))) + FILTER LENGTH(__pivot_values) > 0 + RETURN { [__pivot_key]: FIRST(__pivot_values) } +` + return control[:start] + candidatePivot + control[end:], nil +} + +func writePivotEvidence(t *testing.T, control, candidate string, run pivotTournamentRun) { + _, source, _, _ := runtime.Caller(0) + directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "tournament_pivot") + if err := os.MkdirAll(directory, 0o755); err != nil { + t.Fatalf("create pivot evidence directory: %v", err) + } + for name, value := range map[string]string{"control.aql": control, "candidate.aql": candidate} { + if err := os.WriteFile(filepath.Join(directory, name), []byte(value), 0o644); err != nil { + t.Fatalf("write pivot %s: %v", name, err) + } + } + payload, err := json.MarshalIndent(map[string]any{"control_aql_sha256": sha256Hex(control), "candidate_aql_sha256": sha256Hex(candidate), "run": run, "decision": "pending-coordinator-threshold-review"}, "", " ") + if err != nil { + t.Fatalf("encode pivot evidence: %v", err) + } + if err := os.WriteFile(filepath.Join(directory, "evidence.json"), append(payload, '\n'), 0o644); err != nil { + t.Fatalf("write pivot evidence: %v", err) + } +} diff --git a/internal/dataframe/tournament_sort_order_test.go b/internal/dataframe/tournament_sort_order_test.go new file mode 100644 index 0000000..b971b9b --- /dev/null +++ b/internal/dataframe/tournament_sort_order_test.go @@ -0,0 +1,192 @@ +package dataframe_test + +// Round 4 sort/order tournament. This is deliberately an AQL-only experiment +// over the current endpoint+typed-selector production shape; no optimizer or +// renderer code is changed here. + +import ( + "context" + "encoding/json" + "os" + "path/filepath" + "runtime" + "strings" + "testing" + "time" + + arangostore "github.com/calypr/loom/internal/store/arango" +) + +type sortOrderRun struct { + ControlSeconds []float64 `json:"control_seconds"` + CandidateSeconds []float64 `json:"candidate_seconds"` + ControlBytes []int `json:"control_bytes"` + CandidateBytes []int `json:"candidate_bytes"` + ControlHash string `json:"control_result_sha256"` + CandidateHash string `json:"candidate_result_sha256"` + ControlProfile arangostore.ProfileResult `json:"control_profile"` + CandidateProfile arangostore.ProfileResult `json:"candidate_profile"` +} + +func TestSortOrderCandidateStructure(t *testing.T) { + control := readSortOrderAQL(t) + candidate, removed, err := buildSortOrderCandidate(control) + if err != nil { + t.Fatal(err) + } + if removed != 6 { + t.Fatalf("removed sort operations = %d, want 6 (three child sorts plus three duplicate slice keys)", removed) + } + for _, fragment := range []string{ + "SORT child_set_1_node._key", + "SORT child_set_2_item._key", + "SORT child_set_3_node._key", + "SORT __loom_physical_slice_item._key ASC\n", + "SORT __loom_physical_slice_item_1._key ASC\n", + "SORT __loom_physical_slice_item_2._key ASC\n", + } { + if !strings.Contains(candidate, fragment) { + t.Fatalf("candidate removed required order fragment %q:\n%s", fragment, candidate) + } + } + if strings.Contains(candidate, "SORT child_set_4_node._key") || strings.Contains(candidate, "SORT child_set_5_node._key") || strings.Contains(candidate, "SORT child_set_6_item._key") { + t.Fatalf("candidate retained an order-insensitive child sort") + } + if strings.Contains(candidate, "ASC, __loom_physical_slice_item._key ASC") { + t.Fatalf("candidate retained duplicate slice sort key") + } + t.Logf("sort/order candidate removed=%d control_hash=%s candidate_hash=%s", removed, sha256Hex(control), sha256Hex(candidate)) +} + +func TestSortOrderCandidateProfilesActualGDC(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run sort/order tournament") + } + control := readSortOrderAQL(t) + candidate, removed, err := buildSortOrderCandidate(control) + if err != nil { + t.Fatal(err) + } + url, database, _ := compilerArangoTarget() + client, err := arangostore.Open(context.Background(), url, database) + if err != nil { + t.Fatalf("open Arango: %v", err) + } + defer client.Close(context.Background()) + binds := readSortOrderBinds(t) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) + defer cancel() + run := sortOrderRun{} + for index := 0; index < 5; index++ { + controlQuery, controlBinds := cacheBust(control, binds, 67000+index*2) + candidateQuery, candidateBinds := cacheBust(candidate, binds, 67001+index*2) + seconds, bytes, hash, err := executeOrdinary(ctx, client, controlQuery, controlBinds) + if err != nil { + t.Fatalf("control run %d: %v", index+1, err) + } + run.ControlSeconds = append(run.ControlSeconds, seconds) + run.ControlBytes = append(run.ControlBytes, bytes) + run.ControlHash = hash + seconds, bytes, hash, err = executeOrdinary(ctx, client, candidateQuery, candidateBinds) + if err != nil { + t.Fatalf("candidate run %d: %v", index+1, err) + } + run.CandidateSeconds = append(run.CandidateSeconds, seconds) + run.CandidateBytes = append(run.CandidateBytes, bytes) + run.CandidateHash = hash + } + if run.ControlHash != run.CandidateHash { + t.Fatalf("sort/order result parity mismatch control=%s candidate=%s", run.ControlHash, run.CandidateHash) + } + controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: control, BindVars: binds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + t.Fatalf("control PROFILE: %v", err) + } + candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidate, BindVars: binds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + t.Fatalf("candidate PROFILE: %v", err) + } + if hashRawRows(controlProfile.Result) != hashRawRows(candidateProfile.Result) { + t.Fatalf("sort/order PROFILE result parity mismatch") + } + run.ControlProfile = controlProfile + run.CandidateProfile = candidateProfile + t.Logf("sort/order removed=%d control_median=%.6f candidate_median=%.6f control_profile=%+v candidate_profile=%+v", removed, median(run.ControlSeconds), median(run.CandidateSeconds), arangostore.SummarizeProfile(controlProfile), arangostore.SummarizeProfile(candidateProfile)) + writeSortOrderEvidence(t, control, candidate, run, removed) +} + +func readSortOrderAQL(t *testing.T) string { + _, source, _, _ := runtime.Caller(0) + path := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "wp2", "selector-integration-endpoint_typed_selector.aql") + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("read frozen endpoint+typed-selector AQL %q: %v", path, err) + } + return string(data) +} + +func readSortOrderBinds(t *testing.T) map[string]any { + _, source, _, _ := runtime.Caller(0) + path := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round3", "wp4", "production.json") + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("read frozen production binds %q: %v", path, err) + } + var payload struct { + BindVars map[string]any `json:"bind_vars"` + } + if err := json.Unmarshal(data, &payload); err != nil { + t.Fatalf("decode frozen production binds: %v", err) + } + return payload.BindVars +} + +func buildSortOrderCandidate(control string) (string, int, error) { + candidate := control + removed := 0 + for _, line := range []string{ + " SORT child_set_4_node._key\n", + " SORT child_set_5_node._key\n", + " SORT child_set_6_item._key\n", + } { + if !strings.Contains(candidate, line) { + return "", removed, nilError("required order-insensitive sort not found: " + strings.TrimSpace(line)) + } + candidate = strings.Replace(candidate, line, "", 1) + removed++ + } + for _, name := range []string{"__loom_physical_slice_item", "__loom_physical_slice_item_1", "__loom_physical_slice_item_2"} { + old := "SORT " + name + "._key ASC, " + name + "._key ASC\n" + if !strings.Contains(candidate, old) { + return "", removed, nilError("duplicate slice sort not found: " + name) + } + candidate = strings.Replace(candidate, old, "SORT "+name+"._key ASC\n", 1) + removed++ + } + return candidate, removed, nil +} + +type sortOrderError string + +func (e sortOrderError) Error() string { return string(e) } +func nilError(message string) error { return sortOrderError(message) } + +func writeSortOrderEvidence(t *testing.T, control, candidate string, run sortOrderRun, removed int) { + _, source, _, _ := runtime.Caller(0) + directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "tournament_sort_order") + if err := os.MkdirAll(directory, 0o755); err != nil { + t.Fatalf("create sort/order evidence directory: %v", err) + } + for name, value := range map[string]string{"control.aql": control, "candidate.aql": candidate} { + if err := os.WriteFile(filepath.Join(directory, name), []byte(value), 0o644); err != nil { + t.Fatalf("write sort/order %s: %v", name, err) + } + } + payload, err := json.MarshalIndent(map[string]any{"control_aql_sha256": sha256Hex(control), "candidate_aql_sha256": sha256Hex(candidate), "removed_sort_operations": removed, "run": run, "decision": "pending-coordinator-threshold-review"}, "", " ") + if err != nil { + t.Fatalf("encode sort/order evidence: %v", err) + } + if err := os.WriteFile(filepath.Join(directory, "evidence.json"), append(payload, '\n'), 0o644); err != nil { + t.Fatalf("write sort/order evidence: %v", err) + } +} diff --git a/internal/dataframe/traversal_projection_experiment_test.go b/internal/dataframe/traversal_projection_experiment_test.go new file mode 100644 index 0000000..4a19071 --- /dev/null +++ b/internal/dataframe/traversal_projection_experiment_test.go @@ -0,0 +1,629 @@ +package dataframe + +// This file is deliberately an experiment. It models traversal-time shaping +// entirely in the test package by using the existing typed physical renderer: +// a relationship set returns one identity-plus-selector object and rich +// consumers read those selector fields directly. It does not change the +// production physical IR or renderer. + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "fmt" + "os" + "path/filepath" + "runtime" + "sort" + "strings" + "testing" + "time" + + arangostore "github.com/calypr/loom/internal/store/arango" +) + +type traversalProjectionExperimentReport struct { + Sets int + EligibleSets int + ProjectedFields int + PayloadSets int + BaselinePayloads int + CandidatePayloads int + BaselineAQLHash string + CandidateAQLHash string +} + +// TestTraversalProjectionExperimentBuildsSingleShapedSets proves the +// candidate's structural contract against the real GDC compiler fixture. It +// intentionally does not enable a production policy switch: promotion is a +// coordinator decision after live parity/profile evidence. +func TestTraversalProjectionExperimentBuildsSingleShapedSets(t *testing.T) { + builder := loadTraversalProjectionGDCBuilder(t) + baseline, err := compileExperimentPhysicalPlan(builder) + if err != nil { + t.Fatal(err) + } + candidate, report, err := buildTraversalProjectionExperiment(baseline) + if err != nil { + t.Fatal(err) + } + renderedBaseline, err := RenderPhysicalPlan(baseline) + if err != nil { + t.Fatal(err) + } + renderedCandidate, err := RenderPhysicalPlan(candidate) + if err != nil { + t.Fatal(err) + } + report.BaselineAQLHash = sha256Hex(renderedBaseline.Query) + report.CandidateAQLHash = sha256Hex(renderedCandidate.Query) + t.Logf("WP3 traversal projection report: %+v", report) + t.Logf("baseline AQL:\n%s", renderedBaseline.Query) + t.Logf("candidate AQL:\n%s", renderedCandidate.Query) + + if report.Sets == 0 || report.EligibleSets == 0 || report.ProjectedFields == 0 { + t.Fatalf("experiment did not find eligible selector-bearing sets: %+v", report) + } + if report.CandidatePayloads >= report.BaselinePayloads { + t.Fatalf("candidate did not remove payload-bearing set returns: %+v", report) + } + if strings.Contains(renderedCandidate.Query, "_prepared = (") || strings.Contains(renderedCandidate.Query, "__loom_prepared_node") { + t.Fatalf("candidate introduced the rejected second prepared array:\n%s", renderedCandidate.Query) + } + if !strings.Contains(renderedCandidate.Query, "__loom_projection_") { + t.Fatalf("candidate did not render selector projection fields:\n%s", renderedCandidate.Query) + } + if strings.Contains(renderedCandidate.Query, "payload: ") { + t.Fatalf("eligible candidate still retains payload in a set return:\n%s", renderedCandidate.Query) + } + if err := candidate.Validate(); err != nil { + t.Fatalf("candidate physical plan does not validate: %v", err) + } +} + +// TestTraversalProjectionExperimentPreservesFallbackPayload is the required +// mixed-consumer safety case. A fallback selector cannot be represented by a +// single projected field, so the experiment leaves that set on the existing +// payload path and records it as an explicit rejection. +func TestTraversalProjectionExperimentPreservesFallbackPayload(t *testing.T) { + primary := Selector{Steps: []SelectorStep{{Field: "id"}}} + fallback := Selector{Steps: []SelectorStep{{Field: "code"}}} + plan, err := BuildPhysicalPlan(SemanticPlan{ + Version: 1, Project: "p", + Root: SemanticNode{Alias: "root", ResourceType: "Patient", Children: []SemanticNode{{ + Alias: "condition", ResourceType: "Condition", EdgeLabel: "subject_Patient", + Fields: []SemanticField{{Name: "status", Selector: primary, Fallbacks: []Selector{fallback}}}, + }}}, + }) + if err != nil { + t.Fatal(err) + } + candidate, report, err := buildTraversalProjectionExperiment(plan) + if err != nil { + t.Fatal(err) + } + if report.EligibleSets != 0 || report.PayloadSets != 1 { + t.Fatalf("fallback set was incorrectly projected: report=%+v", report) + } + rendered, err := RenderPhysicalPlan(candidate) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(rendered.Query, "payload: ") { + t.Fatalf("fallback set lost payload retention:\n%s", rendered.Query) + } +} + +// TestTraversalProjectionExperimentProfilesGDC is opt-in because it reads the +// local META Arango fixture. It records parity, Explain/profile statistics, and +// five warm client timings for the exact 1,000-row GDC request. Set +// LOOM_WP3_WRITE_ARTIFACTS=1 to write the raw evidence directory. +func TestTraversalProjectionExperimentProfilesGDC(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run WP3 against Arango") + } + builder := loadTraversalProjectionGDCBuilder(t) + semantic, err := BuildSemanticPlan(builder) + if err != nil { + t.Fatal(err) + } + baselinePlan, err := BuildPhysicalPlan(semantic) + if err != nil { + t.Fatal(err) + } + baselinePlan, err = OptimizePhysicalPlan(baselinePlan) + if err != nil { + t.Fatal(err) + } + candidatePlan, report, err := buildTraversalProjectionExperiment(baselinePlan) + if err != nil { + t.Fatal(err) + } + baseline, err := compilePhysicalExecution(baselinePlan, semantic, 1000) + if err != nil { + t.Fatal(err) + } + candidate, err := compilePhysicalExecution(candidatePlan, semantic, 1000) + if err != nil { + t.Fatal(err) + } + url, database, _ := compilerArangoTarget() + client, err := arangostore.Open(context.Background(), url, database) + if err != nil { + t.Fatal(err) + } + defer client.Close(context.Background()) + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute) + defer cancel() + baselineProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: baseline.Query, BindVars: baseline.BindVars, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + t.Fatalf("baseline PROFILE: %v", err) + } + candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidate.Query, BindVars: candidate.BindVars, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) + if err != nil { + t.Fatalf("candidate PROFILE: %v", err) + } + baselineHash := hashRawRows(baselineProfile.Result) + candidateHash := hashRawRows(candidateProfile.Result) + if baselineHash != candidateHash { + t.Logf("first result difference: %s", firstRawDifference(baselineProfile.Result, candidateProfile.Result)) + if os.Getenv("LOOM_WP3_WRITE_ARTIFACTS") != "" { + writeTraversalProjectionArtifacts(t, report, baseline, candidate, baselineHash, baselineProfile, candidateProfile, nil, nil) + } + t.Fatalf("result parity mismatch: baseline=%s candidate=%s", baselineHash, candidateHash) + } + baselineWarm := profileWarmQuery(ctx, client, baseline) + candidateWarm := profileWarmQuery(ctx, client, candidate) + baselineSummary := arangostore.SummarizeProfile(baselineProfile) + candidateSummary := arangostore.SummarizeProfile(candidateProfile) + report.BaselineAQLHash = sha256Hex(baseline.Query) + report.CandidateAQLHash = sha256Hex(candidate.Query) + t.Logf("WP3 live report: report=%+v baseline_hash=%s candidate_hash=%s baseline_profile=%+v candidate_profile=%+v baseline_warm=%v candidate_warm=%v", report, baselineHash, candidateHash, baselineSummary, candidateSummary, baselineWarm, candidateWarm) + if os.Getenv("LOOM_WP3_WRITE_ARTIFACTS") != "" { + writeTraversalProjectionArtifacts(t, report, baseline, candidate, baselineHash, baselineProfile, candidateProfile, baselineWarm, candidateWarm) + } +} + +func profileWarmQuery(ctx context.Context, client *arangostore.Client, compiled CompiledQuery) []float64 { + times := make([]float64, 0, 5) + for run := 0; run < 5; run++ { + started := time.Now() + _ = client.QueryRows(ctx, compiled.Query, 10000, compiled.BindVars, func(map[string]any) error { return nil }) + times = append(times, time.Since(started).Seconds()) + } + return times +} + +func hashRawRows(rows []json.RawMessage) string { + hash := sha256.New() + for _, row := range rows { + var value any + if json.Unmarshal(row, &value) != nil { + continue + } + canonical, err := json.Marshal(value) + if err != nil { + continue + } + _, _ = hash.Write(canonical) + _, _ = hash.Write([]byte{'\n'}) + } + return hex.EncodeToString(hash.Sum(nil)) +} + +func firstRawDifference(left, right []json.RawMessage) string { + if len(left) != len(right) { + return fmt.Sprintf("row count baseline=%d candidate=%d", len(left), len(right)) + } + for index := range left { + var leftValue, rightValue any + if json.Unmarshal(left[index], &leftValue) != nil || json.Unmarshal(right[index], &rightValue) != nil { + continue + } + leftJSON, _ := json.Marshal(leftValue) + rightJSON, _ := json.Marshal(rightValue) + if string(leftJSON) != string(rightJSON) { + return fmt.Sprintf("row=%d baseline=%s candidate=%s", index, leftJSON, rightJSON) + } + } + return "hash-only difference (JSON rows compare equal)" +} + +func writeTraversalProjectionArtifacts(t *testing.T, report traversalProjectionExperimentReport, baseline, candidate CompiledQuery, resultHash string, baselineProfile, candidateProfile arangostore.ProfileResult, baselineWarm, candidateWarm []float64) { + _, source, _, _ := runtime.Caller(0) + directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round3", "wp3") + if err := os.MkdirAll(directory, 0o755); err != nil { + t.Fatalf("create WP3 artifact directory: %v", err) + } + if err := os.WriteFile(filepath.Join(directory, "baseline.aql"), []byte(baseline.Query), 0o644); err != nil { + t.Fatalf("write baseline AQL: %v", err) + } + if err := os.WriteFile(filepath.Join(directory, "candidate.aql"), []byte(candidate.Query), 0o644); err != nil { + t.Fatalf("write candidate AQL: %v", err) + } + payload := map[string]any{ + "report": report, "result_hash": resultHash, + "baseline_profile": baselineProfile, "candidate_profile": candidateProfile, + "baseline_warm_seconds": baselineWarm, "candidate_warm_seconds": candidateWarm, + "decision": "pending coordinator live gate", + } + data, err := json.MarshalIndent(payload, "", " ") + if err != nil { + t.Fatalf("encode WP3 artifact: %v", err) + } + if err := os.WriteFile(filepath.Join(directory, "evidence.json"), append(data, '\n'), 0o644); err != nil { + t.Fatalf("write WP3 evidence: %v", err) + } +} + +func compileExperimentPhysicalPlan(builder Builder) (PhysicalPlan, error) { + semantic, err := BuildSemanticPlan(builder) + if err != nil { + return PhysicalPlan{}, err + } + physical, err := BuildPhysicalPlan(semantic) + if err != nil { + return PhysicalPlan{}, err + } + return OptimizePhysicalPlan(physical) +} + +type experimentSelector struct { + key string + selector Selector + field string +} + +// buildTraversalProjectionExperiment rewrites only the cloned plan. It uses +// PreparedReference as a test-only field reference; unlike PhysicalPreparedSet +// it points back to the owning set itself, so no second array is rendered. +func buildTraversalProjectionExperiment(plan PhysicalPlan) (PhysicalPlan, traversalProjectionExperimentReport, error) { + candidate := clonePhysicalPlan(plan) + // clonePhysicalPlan intentionally predates object-bearing return trees and + // keeps PhysicalProjection.Expression pointers shared. Detach them here so + // the experiment cannot mutate the baseline plan while annotating candidate + // consumers with projected-field references. + for index := range candidate.Operations { + operation := &candidate.Operations[index] + if operation.Kind != PhysicalReturnOp || operation.Return == nil { + continue + } + for projectionIndex := range operation.Return.Projections { + if operation.Return.Projections[projectionIndex].Expression == nil { + continue + } + expression := cloneExperimentExpression(*operation.Return.Projections[projectionIndex].Expression) + operation.Return.Projections[projectionIndex].Expression = &expression + } + } + report := traversalProjectionExperimentReport{} + for index := range candidate.Operations { + op := &candidate.Operations[index] + if op.Kind != PhysicalSetOp || op.Set == nil { + continue + } + report.Sets++ + set := op.Set + selectors, fallback := collectSetSelectors(candidate, set.Variable) + if fallback { + continue + } + if len(selectors) == 0 { + continue + } + report.EligibleSets++ + target := setTargetVariable(*set) + if target == "" { + return PhysicalPlan{}, report, fmt.Errorf("set %q has no target variable", set.Variable) + } + fields := make([]PhysicalExpressionProjection, 0, len(selectors)+4) + resourceType := op.Source.ResourceType + if resourceType == "" { + resourceType = setResourceType(candidate, *set) + } + if resourceType == "" { + return PhysicalPlan{}, report, fmt.Errorf("set %q has no resource type", set.Variable) + } + for _, name := range []string{"_id", "_key", "id", "resourceType"} { + fields = append(fields, PhysicalExpressionProjection{ + Name: name, + Expression: PhysicalExpression{Kind: PhysicalValueExpression, Cardinality: PhysicalScalarCardinality, NullBehavior: PhysicalPreserveNull, Value: &PhysicalValue{Variable: target, Path: []string{name}}}, + }) + } + for selectorIndex := range selectors { + selector := &selectors[selectorIndex] + field := fmt.Sprintf("__loom_projection_%d", report.ProjectedFields) + selector.field = field + fields = append(fields, PhysicalExpressionProjection{ + Name: field, + Expression: PhysicalExpression{Kind: PhysicalExtractExpression, Cardinality: PhysicalArrayCardinality, NullBehavior: PhysicalEmptyOnNull, Extract: &PhysicalExtract{ + Source: PhysicalValue{Variable: target, Path: []string{"payload"}}, ResourceType: resourceType, Selector: selector.selector, + }}, + }) + report.ProjectedFields++ + } + set.Subplan.Return = PhysicalExpression{Kind: PhysicalObjectExpression, Cardinality: PhysicalObjectCardinality, NullBehavior: PhysicalPreserveNull, Object: &PhysicalObject{Fields: fields}} + set.Output = nil + set.Prepared = nil + for projectionIndex := range candidate.Operations { + operation := &candidate.Operations[projectionIndex] + if operation.Kind != PhysicalReturnOp || operation.Return == nil { + continue + } + for expressionIndex := range operation.Return.Projections { + expression := operation.Return.Projections[expressionIndex].Expression + rewriteProjectionExpression(expression, set.Variable, selectors) + } + } + } + // The baseline payload count is measured from the original plan's compact + // output, not the rewritten candidate. + for _, operation := range plan.Operations { + if operation.Kind == PhysicalSetOp && operation.Set != nil { + if operation.Set.Output == nil { + report.BaselinePayloads++ + continue + } + for _, field := range operation.Set.Output.Fields { + if field == PhysicalSetPayloadField { + report.BaselinePayloads++ + break + } + } + } + } + for _, operation := range candidate.Operations { + if operation.Kind != PhysicalSetOp || operation.Set == nil { + continue + } + if operation.Set.Output != nil { + for _, field := range operation.Set.Output.Fields { + if field == PhysicalSetPayloadField { + report.CandidatePayloads++ + break + } + } + } + if operation.Set.Subplan.Return.Object != nil { + for _, field := range operation.Set.Subplan.Return.Object.Fields { + if field.Name == string(PhysicalSetPayloadField) { + report.CandidatePayloads++ + break + } + } + } + } + report.PayloadSets = report.BaselinePayloads + return candidate, report, candidate.Validate() +} + +// cloneExperimentExpression fills the deep-copy gaps in the production clone +// helper for nested rich expressions. The experiment must not annotate the +// baseline's Slice.Predicate or Slice.Projections while preparing a candidate. +func cloneExperimentExpression(expression PhysicalExpression) PhysicalExpression { + copy := clonePhysicalExpression(expression) + if expression.Aggregate != nil { + aggregate := *copy.Aggregate + if expression.Aggregate.Value != nil { + value := cloneExperimentExpression(*expression.Aggregate.Value) + aggregate.Value = &value + } + if expression.Aggregate.Predicate != nil { + predicate := cloneExperimentPredicateExpression(*expression.Aggregate.Predicate) + aggregate.Predicate = &predicate + } + copy.Aggregate = &aggregate + } + if expression.Slice != nil { + slice := *copy.Slice + if expression.Slice.Predicate != nil { + predicate := cloneExperimentPredicateExpression(*expression.Slice.Predicate) + slice.Predicate = &predicate + } + slice.Projections = make([]PhysicalExpressionProjection, len(expression.Slice.Projections)) + for index, projection := range expression.Slice.Projections { + slice.Projections[index] = projection + slice.Projections[index].Expression = cloneExperimentExpression(projection.Expression) + } + copy.Slice = &slice + } + if expression.Object != nil { + object := *copy.Object + object.Fields = make([]PhysicalExpressionProjection, len(expression.Object.Fields)) + for index, field := range expression.Object.Fields { + object.Fields[index] = field + object.Fields[index].Expression = cloneExperimentExpression(field.Expression) + } + copy.Object = &object + } + return copy +} + +func cloneExperimentPredicateExpression(predicate PhysicalPredicateExpression) PhysicalPredicateExpression { + copy := predicate + if predicate.Comparison != nil { + comparison := clonePhysicalPredicate(*predicate.Comparison) + if predicate.Comparison.LeftExpression != nil { + left := cloneExperimentExpression(*predicate.Comparison.LeftExpression) + comparison.LeftExpression = &left + } + copy.Comparison = &comparison + } + if predicate.Exists != nil { + exists := clonePhysicalSubplan(*predicate.Exists) + copy.Exists = &exists + } + copy.Children = make([]PhysicalPredicateExpression, len(predicate.Children)) + for index, child := range predicate.Children { + copy.Children[index] = cloneExperimentPredicateExpression(child) + } + return copy +} + +func setTargetVariable(set PhysicalSet) string { + if set.SourceSetVariable != "" { + return set.ItemVariable + } + if len(set.Subplan.Operations) == 0 || set.Subplan.Operations[0].Traversal == nil { + return "" + } + return set.Subplan.Operations[0].Traversal.TargetVariable +} + +func setResourceType(plan PhysicalPlan, set PhysicalSet) string { + if len(set.Subplan.Operations) > 0 && set.Subplan.Operations[0].Traversal != nil { + traversal := set.Subplan.Operations[0].Traversal + if value, ok := plan.BindVars[traversal.TargetTypeBindKey].(string); ok { + return value + } + if values, ok := plan.BindVars[traversal.TargetTypeBindKey].([]string); ok && len(values) == 1 { + return values[0] + } + } + return "" +} + +func collectSetSelectors(plan PhysicalPlan, setVariable string) ([]experimentSelector, bool) { + byKey := map[string]Selector{} + fallback := false + var collect func(*PhysicalExpression) + collect = func(expression *PhysicalExpression) { + if expression == nil { + return + } + switch expression.Kind { + case PhysicalExtractExpression: + if expression.Extract != nil && expression.Extract.Source.Variable == setVariable { + if len(expression.Extract.Fallbacks) > 0 { + fallback = true + } else { + byKey[physicalSelectorIdentity(expression.Extract.Selector)] = expression.Extract.Selector + } + } + case PhysicalAggregateExpression: + if expression.Aggregate != nil { + collect(expression.Aggregate.Value) + if expression.Aggregate.Predicate != nil && expression.Aggregate.Predicate.Comparison != nil { + collect(expression.Aggregate.Predicate.Comparison.LeftExpression) + } + } + case PhysicalPivotExpression: + if expression.Pivot != nil && expression.Pivot.Source.Variable == setVariable { + byKey[physicalSelectorIdentity(expression.Pivot.KeySelector)] = expression.Pivot.KeySelector + byKey[physicalSelectorIdentity(expression.Pivot.ValueSelector)] = expression.Pivot.ValueSelector + } + case PhysicalSliceExpression: + if expression.Slice != nil { + collect(expression.Slice.Sort) + if expression.Slice.Predicate != nil && expression.Slice.Predicate.Comparison != nil { + collect(expression.Slice.Predicate.Comparison.LeftExpression) + } + for index := range expression.Slice.Projections { + collect(&expression.Slice.Projections[index].Expression) + } + } + case PhysicalObjectExpression: + if expression.Object != nil { + for index := range expression.Object.Fields { + collect(&expression.Object.Fields[index].Expression) + } + } + } + } + for index := range plan.Operations { + operation := &plan.Operations[index] + if operation.Kind != PhysicalReturnOp || operation.Return == nil { + continue + } + for projectionIndex := range operation.Return.Projections { + collect(operation.Return.Projections[projectionIndex].Expression) + } + } + keys := make([]string, 0, len(byKey)) + for key := range byKey { + keys = append(keys, key) + } + sort.Strings(keys) + selectors := make([]experimentSelector, 0, len(keys)) + for _, key := range keys { + selectors = append(selectors, experimentSelector{key: key, selector: byKey[key]}) + } + return selectors, fallback +} + +func rewriteProjectionExpression(expression *PhysicalExpression, setVariable string, selectors []experimentSelector) { + if expression == nil { + return + } + fieldFor := func(selector Selector) string { + key := physicalSelectorIdentity(selector) + for _, candidate := range selectors { + if candidate.key == key { + return candidate.field + } + } + return "" + } + switch expression.Kind { + case PhysicalExtractExpression: + if expression.Extract != nil && expression.Extract.Source.Variable == setVariable && len(expression.Extract.Fallbacks) == 0 { + if field := fieldFor(expression.Extract.Selector); field != "" { + expression.Extract.Prepared = &PhysicalPreparedReference{SetVariable: setVariable, Field: field} + } + } + case PhysicalAggregateExpression: + if expression.Aggregate != nil { + rewriteProjectionExpression(expression.Aggregate.Value, setVariable, selectors) + if expression.Aggregate.Predicate != nil && expression.Aggregate.Predicate.Comparison != nil { + rewriteProjectionExpression(expression.Aggregate.Predicate.Comparison.LeftExpression, setVariable, selectors) + } + } + case PhysicalPivotExpression: + if expression.Pivot != nil && expression.Pivot.Source.Variable == setVariable { + if field := fieldFor(expression.Pivot.KeySelector); field != "" { + expression.Pivot.PreparedKey = &PhysicalPreparedReference{SetVariable: setVariable, Field: field} + } + if field := fieldFor(expression.Pivot.ValueSelector); field != "" { + expression.Pivot.PreparedValue = &PhysicalPreparedReference{SetVariable: setVariable, Field: field} + } + } + case PhysicalSliceExpression: + if expression.Slice != nil { + rewriteProjectionExpression(expression.Slice.Sort, setVariable, selectors) + if expression.Slice.Predicate != nil && expression.Slice.Predicate.Comparison != nil { + rewriteProjectionExpression(expression.Slice.Predicate.Comparison.LeftExpression, setVariable, selectors) + } + for index := range expression.Slice.Projections { + rewriteProjectionExpression(&expression.Slice.Projections[index].Expression, setVariable, selectors) + } + } + case PhysicalObjectExpression: + if expression.Object != nil { + for index := range expression.Object.Fields { + rewriteProjectionExpression(&expression.Object.Fields[index].Expression, setVariable, selectors) + } + } + } +} + +func loadTraversalProjectionGDCBuilder(t *testing.T) Builder { + _, source, _, _ := runtime.Caller(0) + path := filepath.Join(filepath.Dir(source), "..", "..", "conformance", "compiler", "fixtures", "gdc-case-matrix.json") + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("read GDC fixture %q: %v", path, err) + } + var fixture struct { + Builder Builder `json:"builder"` + } + if err := json.Unmarshal(data, &fixture); err != nil { + t.Fatalf("decode GDC fixture: %v", err) + } + return fixture.Builder +} + +func sha256Hex(value string) string { + hash := sha256.Sum256([]byte(value)) + return hex.EncodeToString(hash[:]) +} diff --git a/internal/dataframe/validation_service.go b/internal/dataframe/validation_service.go new file mode 100644 index 0000000..da3b291 --- /dev/null +++ b/internal/dataframe/validation_service.go @@ -0,0 +1,130 @@ +package dataframe + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "time" +) + +// ValidateRequest describes a non-executing validation/compile request from a +// client. It deliberately uses the same Builder shape accepted by RunRequest +// so validation and execution cannot drift apart. +type ValidateRequest struct { + Builder Builder + Limit int +} + +// ValidationWarning is a stable, machine-readable advisory attached to a +// successful validation result. Warnings never make a request invalid. +type ValidationWarning struct { + Code string + Message string + Path []string + Details map[string]any +} + +// ValidationResult is the normalized contract consumed by preview/export +// frontends. No database rows are read by Validate. +type ValidationResult struct { + Valid bool + Builder Builder + Project string + DatasetGeneration string + RootResourceType string + Limit int + Columns []string + PivotFields []string + RowIdentity *RowIdentity + RequestFingerprint string + Warnings []ValidationWarning + Plan CompilerPlanDiagnostics + PreviewAllowed bool + ExportAllowed bool + Diagnostics QueryDiagnostics +} + +// Validate prepares, validates, and compiles a dataframe request without +// executing it against Arango. The exact normalized builder is returned so a +// caller can persist it as a reusable recipe or pass it to Run unchanged. +func (s *Service) Validate(ctx context.Context, req ValidateRequest) (ValidationResult, error) { + started := now() + builder, compiled, diagnostics, err := s.prepareAndCompile(ctx, req.Builder, req.Limit) + if err != nil { + return ValidationResult{}, err + } + fingerprint, err := requestFingerprint(builder, compiled.Limit) + if err != nil { + return ValidationResult{}, err + } + diagnostics.Total = now().Sub(started) + return ValidationResult{ + Valid: true, + Builder: builder, + Project: compiled.Project, + DatasetGeneration: compiled.DatasetGeneration, + RootResourceType: compiled.RootResourceType, + Limit: compiled.Limit, + Columns: cloneStrings(compiled.Columns), + PivotFields: cloneStrings(compiled.PivotFields), + RowIdentity: cloneRowIdentity(compiled.RowIdentity), + RequestFingerprint: fingerprint, + Warnings: validationWarnings(builder, compiled), + Plan: compiled.PlanDiagnostics, + PreviewAllowed: true, + ExportAllowed: true, + Diagnostics: diagnostics, + }, nil +} + +var now = time.Now + +func requestFingerprint(builder Builder, limit int) (string, error) { + payload := struct { + Builder Builder + Limit int + }{Builder: builder, Limit: limit} + b, err := json.Marshal(payload) + if err != nil { + return "", err + } + sum := sha256.Sum256(b) + return hex.EncodeToString(sum[:]), nil +} + +func validationWarnings(builder Builder, compiled CompiledQuery) []ValidationWarning { + warnings := make([]ValidationWarning, 0, 2) + if len(builder.Fields) == 0 && len(builder.Pivots) == 0 && len(builder.Aggregates) == 0 && len(builder.Slices) == 0 && len(builder.Traversals) == 0 { + warnings = append(warnings, ValidationWarning{ + Code: "NO_SELECTED_COLUMNS", + Message: "No explicit fields, pivots, aggregates, slices, or traversals were selected; only the row identity will be returned.", + }) + } + if compiled.Limit > 1000 { + warnings = append(warnings, ValidationWarning{ + Code: "PREVIEW_LIMIT_CAPPED", + Message: "Preview limits above 1000 rows may be capped by the frontend.", + Details: map[string]any{"limit": compiled.Limit, "recommended_max": 1000}, + }) + } + return warnings +} + +func cloneValidationWarnings(in []ValidationWarning) []ValidationWarning { + if len(in) == 0 { + return nil + } + out := make([]ValidationWarning, len(in)) + for i, warning := range in { + out[i] = warning + out[i].Path = append([]string(nil), warning.Path...) + if warning.Details != nil { + out[i].Details = make(map[string]any, len(warning.Details)) + for key, value := range warning.Details { + out[i].Details[key] = value + } + } + } + return out +} diff --git a/internal/dataframe/validation_service_test.go b/internal/dataframe/validation_service_test.go new file mode 100644 index 0000000..7426014 --- /dev/null +++ b/internal/dataframe/validation_service_test.go @@ -0,0 +1,102 @@ +package dataframe + +import ( + "context" + "strings" + "testing" + + "github.com/calypr/loom/internal/catalog" +) + +func TestRequestFingerprintIsDeterministicAndSensitive(t *testing.T) { + builder := Builder{ + Project: "P1", + RootResourceType: "Patient", + Fields: []FieldSelect{{Name: "gender", Select: "gender"}}, + } + first, err := requestFingerprint(builder, 25) + if err != nil { + t.Fatalf("requestFingerprint() error = %v", err) + } + second, err := requestFingerprint(builder, 25) + if err != nil { + t.Fatalf("requestFingerprint() second error = %v", err) + } + if first == "" || first != second || len(first) != 64 { + t.Fatalf("fingerprint is not deterministic sha256: %q / %q", first, second) + } + + changed := builder + changed.Project = "P2" + third, err := requestFingerprint(changed, 25) + if err != nil { + t.Fatalf("requestFingerprint() changed error = %v", err) + } + if first == third { + t.Fatalf("fingerprint did not change when request changed: %q", first) + } + changedLimit, err := requestFingerprint(builder, 26) + if err != nil { + t.Fatalf("requestFingerprint() limit error = %v", err) + } + if first == changedLimit { + t.Fatalf("fingerprint did not include limit") + } +} + +func TestValidationWarningsExposeStableCodes(t *testing.T) { + warnings := validationWarnings(Builder{}, CompiledQuery{Limit: 1001}) + if len(warnings) != 2 { + t.Fatalf("validationWarnings() len = %d, want 2", len(warnings)) + } + seen := map[string]bool{} + for _, warning := range warnings { + seen[warning.Code] = true + if strings.TrimSpace(warning.Message) == "" { + t.Errorf("warning %q has empty message", warning.Code) + } + } + if !seen["NO_SELECTED_COLUMNS"] || !seen["PREVIEW_LIMIT_CAPPED"] { + t.Fatalf("warning codes = %#v", seen) + } + cloned := cloneValidationWarnings(warnings) + cloned[1].Details["limit"] = 1 + if warnings[1].Details["limit"] == 1 { + t.Fatal("cloneValidationWarnings aliased Details") + } +} + +func TestValidateCompilesWithoutExecutingRows(t *testing.T) { + executed := false + service := NewService(ServiceConfig{ + DiscoverFields: func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + return []catalog.PopulatedField{}, nil + }, + DiscoverReferences: func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + return []catalog.PopulatedReference{}, nil + }, + ExecuteRows: func(context.Context, ExecuteQueryOptions, string, map[string]any, func(map[string]any) error) error { + executed = true + return nil + }, + }) + result, err := service.Validate(context.Background(), ValidateRequest{ + Builder: Builder{Project: "P1", RootResourceType: "Patient"}, + Limit: 25, + }) + if err != nil { + t.Fatalf("Validate() error = %v", err) + } + if !result.Valid || result.Project != "P1" || result.RootResourceType != "Patient" { + t.Fatalf("unexpected validation result: %#v", result) + } + if result.RequestFingerprint == "" || !result.PreviewAllowed || !result.ExportAllowed { + t.Fatalf("validation result omitted frontend contract fields: %#v", result) + } + if executed { + t.Fatal("Validate executed rows") + } + if result.Diagnostics.Compilation <= 0 || result.Diagnostics.Total <= 0 { + t.Fatalf("validation diagnostics missing compilation/total: %#v", result.Diagnostics) + } +} diff --git a/internal/httpapi/errors.go b/internal/httpapi/errors.go new file mode 100644 index 0000000..5474f81 --- /dev/null +++ b/internal/httpapi/errors.go @@ -0,0 +1,98 @@ +package httpapi + +import ( + "errors" + "net/http" + + "github.com/calypr/loom/internal/dataframe" +) + +// ErrorResponse is the transport-neutral JSON payload the HTTP adapter can +// write before a streaming response has begun. +type ErrorResponse struct { + Error HTTPErrorBody `json:"error"` +} + +type HTTPErrorBody struct { + Code string `json:"code"` + Message string `json:"message"` + FieldPath []string `json:"fieldPath,omitempty"` + Details map[string]any `json:"details,omitempty"` + Retryable bool `json:"retryable"` + RequestID string `json:"requestId,omitempty"` +} + +// MappedError is the status and safe body chosen for a semantic error. It is +// intentionally independent of Fiber so the same mapping can be tested and +// reused by the export route and future HTTP adapters. +type MappedError struct { + Status int + Body ErrorResponse + Cause error +} + +func (e MappedError) Error() string { + return e.Body.Error.Message +} + +func (e MappedError) Unwrap() error { return e.Cause } + +// MapDataframeError maps a service error without inspecting its text. Unknown +// errors are always redacted to INTERNAL_ERROR. +func MapDataframeError(err error, requestID string) MappedError { + userErr := dataframe.Normalize(err) + if userErr == nil { + return MappedError{} + } + code := userErr.Code() + return MappedError{ + Status: statusForDataframeCode(dataframe.ErrorCode(code)), + Body: ErrorResponse{Error: HTTPErrorBody{ + Code: code, + Message: dataframe.PublicMessage(userErr), + FieldPath: append([]string(nil), userErr.FieldPath()...), + Details: userErr.Details(), + Retryable: userErr.Retryable(), + RequestID: requestID, + }}, + Cause: err, + } +} + +func statusForDataframeCode(code dataframe.ErrorCode) int { + switch code { + case dataframe.CodeProjectRequired, + dataframe.CodeRootResourceTypeRequired, + dataframe.CodeUnknownField, + dataframe.CodeFieldNotPopulated, + dataframe.CodeInvalidTraversal, + dataframe.CodeUnsafeTraversalRoute, + dataframe.CodeInvalidFilter, + dataframe.CodeUnboundedPivot, + dataframe.CodeInvalidPivotColumn, + dataframe.CodeInvalidSlice, + dataframe.CodeInvalidCursor, + dataframe.CodeStaleCursor, + dataframe.CodeUnsupportedExportFormat: + return http.StatusBadRequest + case dataframe.CodeUnauthorizedProject: + return http.StatusForbidden + case dataframe.CodeClientCanceled: + return 499 // Client Closed Request, used by Fiber-compatible adapters. + case dataframe.CodeDatasetGenerationChanged: + return http.StatusConflict + case dataframe.CodePlanTooExpensive: + return http.StatusUnprocessableEntity + case dataframe.CodeBackendUnavailable: + return http.StatusServiceUnavailable + default: + return http.StatusInternalServerError + } +} + +// IsMappedError lets a coordinator preserve an already mapped error while +// adding request logging. +func IsMappedError(err error) bool { + var mapped MappedError + return errors.As(err, &mapped) +} diff --git a/internal/httpapi/errors_test.go b/internal/httpapi/errors_test.go new file mode 100644 index 0000000..2c3b92f --- /dev/null +++ b/internal/httpapi/errors_test.go @@ -0,0 +1,61 @@ +package httpapi + +import ( + "errors" + "net/http" + "testing" + + "github.com/calypr/loom/internal/dataframe" +) + +func TestMapDataframeErrorUsesSharedCodeAndStatus(t *testing.T) { + mapped := MapDataframeError(dataframe.NewError( + dataframe.CodeUnauthorizedProject, + "do not expose this message", + dataframe.WithDetails(map[string]any{"project": "secret", "collection": "Patient"}), + ), "request-789") + if mapped.Status != http.StatusForbidden { + t.Fatalf("status = %d", mapped.Status) + } + if mapped.Body.Error.Code != string(dataframe.CodeUnauthorizedProject) { + t.Fatalf("code = %q", mapped.Body.Error.Code) + } + if mapped.Body.Error.Message != "the requested project is not available" { + t.Fatalf("message = %q", mapped.Body.Error.Message) + } + if mapped.Body.Error.RequestID != "request-789" { + t.Fatalf("request ID = %q", mapped.Body.Error.RequestID) + } + if _, ok := mapped.Body.Error.Details["collection"]; ok { + t.Fatalf("collection leaked: %#v", mapped.Body.Error.Details) + } +} + +func TestMapDataframeErrorMapsOperationalConditions(t *testing.T) { + cases := []struct { + name string + err error + status int + code string + }{ + {name: "backend", err: dataframe.ErrBackendUnavailable, status: http.StatusServiceUnavailable, code: string(dataframe.CodeBackendUnavailable)}, + {name: "generation", err: dataframe.NewError(dataframe.CodeDatasetGenerationChanged, ""), status: http.StatusConflict, code: string(dataframe.CodeDatasetGenerationChanged)}, + {name: "internal", err: errors.New("driver AQL details"), status: http.StatusInternalServerError, code: string(dataframe.CodeInternalError)}, + } + for _, test := range cases { + t.Run(test.name, func(t *testing.T) { + mapped := MapDataframeError(test.err, "request") + if mapped.Status != test.status || mapped.Body.Error.Code != test.code { + t.Fatalf("mapped = %#v", mapped) + } + }) + } +} + +func TestMappedErrorPreservesCauseForLogging(t *testing.T) { + cause := errors.New("backend") + mapped := MapDataframeError(dataframe.Wrap(cause, dataframe.CodeBackendUnavailable, "private"), "request") + if !errors.Is(mapped, cause) { + t.Fatal("mapped error did not preserve cause") + } +} diff --git a/internal/ingest/backend.go b/internal/ingest/backend.go index aec462e..a11068d 100644 --- a/internal/ingest/backend.go +++ b/internal/ingest/backend.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" + "github.com/calypr/loom/internal/catalog" datasetarango "github.com/calypr/loom/internal/dataset/arango" arangostore "github.com/calypr/loom/internal/store/arango" ) @@ -15,7 +16,7 @@ func openBackend(ctx context.Context, opts arangostore.ConnectionOptions) (*aran } func bootstrapSpecWithReporter(resourceTypes []string, truncate bool, reporter EventSink) arangostore.BootstrapSpec { - collections := make([]arangostore.CollectionSpec, 0, len(resourceTypes)+2) + collections := make([]arangostore.CollectionSpec, 0, len(resourceTypes)+3) for _, name := range resourceTypes { // Every generated FHIR resource is a possible dataframe root. The // compiler applies project and optional authorization scope before a @@ -86,6 +87,16 @@ func bootstrapSpecWithReporter(resourceTypes []string, truncate bool, reporter E {"project", "dataset_generation", "auth_resource_path", "resource_type", "pivot_candidate"}, }, }, + arangostore.CollectionSpec{ + Name: catalog.RelationshipCatalogCollection, + Truncate: truncate, + Indexes: [][]string{ + {"project", "dataset_generation", "to_type"}, + {"project", "dataset_generation", "auth_resource_path", "to_type"}, + {"project", "dataset_generation", "from_type"}, + {"project", "dataset_generation", "auth_resource_path", "from_type"}, + }, + }, ) return arangostore.BootstrapSpec{ Collections: collections, diff --git a/internal/ingest/backend_test.go b/internal/ingest/backend_test.go index 2859303..0f800a9 100644 --- a/internal/ingest/backend_test.go +++ b/internal/ingest/backend_test.go @@ -76,6 +76,20 @@ func TestBootstrapSpecAddsGenerationScopedIndexesWithoutTraversalSpeculation(t * t.Fatalf("catalog indexes %#v do not include generation index %#v", catalog.Indexes, required) } } + relationships, found := bootstrapCollection(spec, "fhir_relationship_catalog") + if !found { + t.Fatal("relationship catalog bootstrap collection is missing") + } + for _, required := range [][]string{ + {"project", "dataset_generation", "to_type"}, + {"project", "dataset_generation", "auth_resource_path", "to_type"}, + {"project", "dataset_generation", "from_type"}, + {"project", "dataset_generation", "auth_resource_path", "from_type"}, + } { + if !containsIndex(relationships.Indexes, required) { + t.Fatalf("relationship catalog indexes %#v do not include %#v", relationships.Indexes, required) + } + } } diff --git a/internal/ingest/generation_load.go b/internal/ingest/generation_load.go index 6119276..c6142c5 100644 --- a/internal/ingest/generation_load.go +++ b/internal/ingest/generation_load.go @@ -175,6 +175,7 @@ func loadGeneration(ctx context.Context, opts LoadOptions) (summary LoadSummary, manifest = loadingManifest catalogs := make(map[generationCatalogKey]*catalog.Profiler) + relationshipCounts := make(map[catalog.RelationshipKey]int64) for _, file := range files { if err = ctx.Err(); err != nil { return summary, err @@ -209,6 +210,7 @@ func loadGeneration(ctx context.Context, opts LoadOptions) (summary LoadSummary, for name, seconds := range result.StageSeconds { summary.StageSeconds[name] += seconds } + catalog.MergeRelationshipCounts(relationshipCounts, result.RelationshipCounts) key := generationCatalogKey{ project: opts.Project, @@ -278,6 +280,17 @@ func loadGeneration(ctx context.Context, opts LoadOptions) (summary LoadSummary, return summary, err } } + if err = catalog.WriteRelationshipCatalog( + ctx, + client, + catalog.RelationshipCatalogDocuments(relationshipCounts), + opts.BatchSize, + false, + opts.WriteAPI, + summary.StageSeconds, + ); err != nil { + return summary, err + } if err = ctx.Err(); err != nil { return summary, err } @@ -332,24 +345,26 @@ func sortedGenerationCatalogKeys(catalogs map[generationCatalogKey]*catalog.Prof } type generationFileResult struct { - ResourceType string - Rows int - VerticesBuilt int - EdgesBuilt int - VerticesInserted int - EdgesInserted int - ValidationErrors int - GenerationErrors int - EdgeErrors int - VertexBatches int - EdgeBatches int - StageSeconds map[string]float64 - Catalog *catalog.Profiler + ResourceType string + Rows int + VerticesBuilt int + EdgesBuilt int + VerticesInserted int + EdgesInserted int + ValidationErrors int + GenerationErrors int + EdgeErrors int + VertexBatches int + EdgeBatches int + StageSeconds map[string]float64 + Catalog *catalog.Profiler + RelationshipCounts map[catalog.RelationshipKey]int64 } type generationWriteTask struct { - collection string - docs []json.RawMessage + collection string + docs []json.RawMessage + relationshipCounts map[catalog.RelationshipKey]int64 } // loadGenerationFile owns one scanner and closes it with a defer before it @@ -478,9 +493,14 @@ func loadGenerationFile( if len(edgeBatch) == 0 { return true } + relationshipCounts, countErr := catalog.RelationshipCountsFromRawEdges(edgeBatch) + if countErr != nil { + setPipelineErr(countErr) + return false + } waitStart := time.Now() select { - case writeChan <- generationWriteTask{collection: EdgeCollection, docs: edgeBatch}: + case writeChan <- generationWriteTask{collection: EdgeCollection, docs: edgeBatch, relationshipCounts: relationshipCounts}: localTimings["edge_queue_wait"] += time.Since(waitStart).Seconds() localTimings["edge_batches"]++ edgeBatch = make([]json.RawMessage, 0, opts.BatchSize) @@ -568,12 +588,17 @@ func loadGenerationFile( }() var writersWG sync.WaitGroup - writerTimingsChan := make(chan map[string]float64, opts.WriterCount) + type writerResult struct { + timings map[string]float64 + relationshipCounts map[catalog.RelationshipKey]int64 + } + writerTimingsChan := make(chan writerResult, opts.WriterCount) for writer := 0; writer < opts.WriterCount; writer++ { writersWG.Add(1) go func() { defer writersWG.Done() localTimings := make(map[string]float64) + localRelationships := make(map[catalog.RelationshipKey]int64) for { select { case <-fileCtx.Done(): @@ -581,7 +606,7 @@ func loadGenerationFile( case task, open := <-writeChan: if !open { select { - case writerTimingsChan <- localTimings: + case writerTimingsChan <- writerResult{timings: localTimings, relationshipCounts: localRelationships}: case <-ctx.Done(): } return @@ -597,6 +622,7 @@ func loadGenerationFile( if task.collection == EdgeCollection { localTimings["edge_insert"] += elapsed atomic.AddInt64(&edgesInserted, int64(len(task.docs))) + catalog.MergeRelationshipCounts(localRelationships, task.relationshipCounts) } else { localTimings["vertex_insert"] += elapsed atomic.AddInt64(&verticesInserted, int64(len(task.docs))) @@ -630,6 +656,7 @@ func loadGenerationFile( result.GenerationErrors = int(atomic.LoadInt64(&generationErrors)) result.EdgeErrors = int(atomic.LoadInt64(&edgeErrors)) result.StageSeconds = make(map[string]float64) + result.RelationshipCounts = make(map[catalog.RelationshipKey]int64) mergedCatalog := catalog.NewProfilerForGeneration(opts.Project, datasetGeneration, opts.AuthResourcePath, resourceType, catalog.NewShapePlanCache()) for timings := range workerTimingsChan { for key, value := range timings { @@ -648,10 +675,11 @@ func loadGenerationFile( return result, fmt.Errorf("merge worker field catalog for %s: %w", resourceType, mergeErr) } } - for timings := range writerTimingsChan { - for key, value := range timings { + for writerResult := range writerTimingsChan { + for key, value := range writerResult.timings { result.StageSeconds[key] += value } + catalog.MergeRelationshipCounts(result.RelationshipCounts, writerResult.relationshipCounts) } result.Catalog = mergedCatalog return result, nil diff --git a/internal/ingest/load.go b/internal/ingest/load.go index 9cf2ab6..4ac6339 100644 --- a/internal/ingest/load.go +++ b/internal/ingest/load.go @@ -306,8 +306,9 @@ func loadLegacy(ctx context.Context, opts LoadOptions) (LoadSummary, error) { linesChan := make(chan string, 10000) type writeTask struct { - collection string - docs []json.RawMessage + collection string + docs []json.RawMessage + relationshipCounts map[catalog.RelationshipKey]int64 } writeChan := make(chan writeTask, 100) @@ -391,9 +392,14 @@ func loadLegacy(ctx context.Context, opts LoadOptions) (LoadSummary, error) { if len(edgeBatch) == 0 { return true } + relationshipCounts, err := catalog.RelationshipCountsFromRawEdges(edgeBatch) + if err != nil { + setPipelineErr(err) + return false + } waitStart := time.Now() select { - case writeChan <- writeTask{collection: EdgeCollection, docs: edgeBatch}: + case writeChan <- writeTask{collection: EdgeCollection, docs: edgeBatch, relationshipCounts: relationshipCounts}: localTimings["edge_queue_wait"] += time.Since(waitStart).Seconds() localTimings["edge_batches"]++ edgeBatch = make([]json.RawMessage, 0, opts.BatchSize) @@ -491,13 +497,18 @@ func loadLegacy(ctx context.Context, opts LoadOptions) (LoadSummary, error) { // 6. I/O Writer goroutines numWriters := opts.WriterCount var writersWG sync.WaitGroup - writerTimingsChan := make(chan map[string]float64, numWriters) + type writerResult struct { + timings map[string]float64 + relationshipCounts map[catalog.RelationshipKey]int64 + } + writerTimingsChan := make(chan writerResult, numWriters) for w := 0; w < numWriters; w++ { writersWG.Add(1) go func() { defer writersWG.Done() localTimings := make(map[string]float64) + localRelationships := make(map[catalog.RelationshipKey]int64) for { select { case <-fileCtx.Done(): @@ -505,7 +516,7 @@ func loadLegacy(ctx context.Context, opts LoadOptions) (LoadSummary, error) { case task, ok := <-writeChan: if !ok { select { - case writerTimingsChan <- localTimings: + case writerTimingsChan <- writerResult{timings: localTimings, relationshipCounts: localRelationships}: case <-ctx.Done(): } return @@ -522,6 +533,7 @@ func loadLegacy(ctx context.Context, opts LoadOptions) (LoadSummary, error) { if task.collection == EdgeCollection { localTimings["edge_insert"] += elapsed atomic.AddInt64(&edgesInserted, int64(len(task.docs))) + catalog.MergeRelationshipCounts(localRelationships, task.relationshipCounts) } else { localTimings["vertex_insert"] += elapsed atomic.AddInt64(&verticesInserted, int64(len(task.docs))) @@ -576,10 +588,12 @@ func loadLegacy(ctx context.Context, opts LoadOptions) (LoadSummary, error) { } // Aggregate timings from writers - for writerTimings := range writerTimingsChan { - for k, v := range writerTimings { + mergedRelationships := make(map[catalog.RelationshipKey]int64) + for writerResult := range writerTimingsChan { + for k, v := range writerResult.timings { summary.StageSeconds[k] += v } + catalog.MergeRelationshipCounts(mergedRelationships, writerResult.relationshipCounts) } summary.BatchCounts["vertex_insert"] += fileVertexBatches summary.BatchCounts["edge_insert"] += fileEdgeBatches @@ -588,6 +602,14 @@ func loadLegacy(ctx context.Context, opts LoadOptions) (LoadSummary, error) { if err := catalog.WriteFieldCatalog(ctx, client, catalog.FieldCatalogCollection, mergedCatalog.Documents(), opts.BatchSize, overwrite, opts.WriteAPI, summary.StageSeconds); err != nil { return summary, err } + relationshipDocs := catalog.RelationshipCatalogDocuments(mergedRelationships) + if opts.Truncate { + if err := catalog.WriteRelationshipCatalog(ctx, client, relationshipDocs, opts.BatchSize, false, opts.WriteAPI, summary.StageSeconds); err != nil { + return summary, err + } + } else if err := catalog.AccumulateRelationshipCatalog(ctx, client, relationshipDocs, summary.StageSeconds); err != nil { + return summary, err + } emitEvent(opts.EventSink, "go_load_file_complete", map[string]any{ "file": filepath.Base(file), diff --git a/internal/store/arango/profile_integration_test.go b/internal/store/arango/profile_integration_test.go index 88d3324..3c88d19 100644 --- a/internal/store/arango/profile_integration_test.go +++ b/internal/store/arango/profile_integration_test.go @@ -77,6 +77,109 @@ func TestProfileCorpusAgainstArango(t *testing.T) { } } +// TestCompoundEdgeIndexExplainAgainstArango audits the endpoint-first +// persistent indexes without mutating the database. Equality filters should +// select the complete inbound/outbound compound index. Multi-type filters are +// recorded as an observation because Arango may choose the edge index for one +// direction when the IN predicate is less selective. +func TestCompoundEdgeIndexExplainAgainstArango(t *testing.T) { + if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { + t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run Arango index audit") + } + url := os.Getenv("LOOM_ARANGO_URL") + if url == "" { + url = "http://127.0.0.1:8529" + } + database := os.Getenv("LOOM_ARANGO_DATABASE") + if database == "" { + database = "fhir_proto" + } + project := os.Getenv("LOOM_ARANGO_PROJECT") + if project == "" { + project = "ARANGODB_PROTO" + } + client, err := Open(context.Background(), url, database) + if err != nil { + t.Fatalf("open Arango: %v", err) + } + defer client.Close(context.Background()) + cases := []struct { + name string + query string + bindVars map[string]any + expectedIndex []string + }{ + { + name: "inbound-equality", + query: `FOR edge IN fhir_edge + FILTER edge._to == @root + FILTER edge.project == @project + FILTER edge.dataset_generation == @generation + FILTER edge.label == @label + FILTER edge.from_type == @from_type + RETURN edge._key`, + bindVars: map[string]any{"root": "Patient/nope", "project": project, "generation": nil, "label": "subject_Patient", "from_type": "Specimen"}, + expectedIndex: []string{"_to", "project", "dataset_generation", "label", "from_type"}, + }, + { + name: "outbound-equality", + query: `FOR edge IN fhir_edge + FILTER edge._from == @root + FILTER edge.project == @project + FILTER edge.dataset_generation == @generation + FILTER edge.label == @label + FILTER edge.to_type == @to_type + RETURN edge._key`, + bindVars: map[string]any{"root": "ResearchSubject/nope", "project": project, "generation": nil, "label": "study", "to_type": "ResearchStudy"}, + expectedIndex: []string{"_from", "project", "dataset_generation", "label", "to_type"}, + }, + { + name: "inbound-multi-type", + query: `FOR edge IN fhir_edge + FILTER edge._to == @root + FILTER edge.project == @project + FILTER edge.dataset_generation == @generation + FILTER edge.label == @label + FILTER edge.from_type IN @from_types + RETURN edge._key`, + bindVars: map[string]any{"root": "Patient/nope", "project": project, "generation": nil, "label": "subject_Patient", "from_types": []string{"Condition", "Specimen", "Observation"}}, + }, + { + name: "outbound-multi-type", + query: `FOR edge IN fhir_edge + FILTER edge._from == @root + FILTER edge.project == @project + FILTER edge.dataset_generation == @generation + FILTER edge.label == @label + FILTER edge.to_type IN @to_types + RETURN edge._key`, + bindVars: map[string]any{"root": "ResearchSubject/nope", "project": project, "generation": nil, "label": "study", "to_types": []string{"ResearchStudy", "DocumentReference"}}, + }, + } + for _, shape := range cases { + shape := shape + t.Run(shape.name, func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + explain, err := client.Explain(ctx, ExplainRequest{Query: shape.query, BindVars: shape.bindVars}) + if err != nil { + t.Fatal(err) + } + assessment := AssessExplainResult(explain) + if len(assessment.FullCollectionScans) != 0 { + t.Fatalf("compound edge shape used full scan: %#v", assessment.FullCollectionScans) + } + if len(assessment.Indexes) == 0 { + t.Fatalf("compound edge shape selected no index: %#v", assessment) + } + if len(shape.expectedIndex) != 0 && !assessmentHasExactIndex(assessment, "fhir_edge", shape.expectedIndex) { + t.Fatalf("equality shape did not select endpoint-first compound index %v: %#v", shape.expectedIndex, assessment.Indexes) + } + t.Logf("indexes=%#v plans=%#v optimizer_rules=%#v", assessment.Indexes, assessment.Plans, assessment.AppliedOptimizerRules) + }) + } +} + func assessmentHasIndexCollection(assessment ExplainAssessment, collection string) bool { for _, index := range assessment.Indexes { if index.Collection == collection { @@ -100,6 +203,15 @@ func assessmentHasIndexField(assessment ExplainAssessment, collection, field str return false } +func assessmentHasExactIndex(assessment ExplainAssessment, collection string, fields []string) bool { + for _, index := range assessment.Indexes { + if index.Collection == collection && strings.Join(index.Fields, "\x00") == strings.Join(fields, "\x00") { + return true + } + } + return false +} + type profileCorpusShape struct { name string query string From 63dd3facf4dc48e72abb456003b65e4fc6159cb2 Mon Sep 17 00:00:00 2001 From: matthewpeterkort Date: Sun, 12 Jul 2026 21:31:36 -0700 Subject: [PATCH 06/15] start organizational pass --- docs/DEVELOPER_ARCHITECTURE.md | 27 +- internal/dataframe/api.go | 288 ++++++++++++++++++ .../dataframe/compat_test_helpers_test.go | 19 ++ .../{ => compiler}/aggregate_compile_test.go | 2 +- .../compiler/arango_test_helpers_test.go | 19 ++ .../dataframe/{ => compiler}/auth_scope.go | 2 +- .../dataframe/{ => compiler}/builder_types.go | 24 +- internal/dataframe/{ => compiler}/compile.go | 2 +- .../{ => compiler}/dataset_generation.go | 2 +- internal/dataframe/{ => compiler}/filter.go | 2 +- .../{ => compiler}/filter_literal.go | 2 +- .../{ => compiler}/filter_semantics.go | 2 +- .../{ => compiler}/filter_semantics_test.go | 2 +- .../dataframe/{ => compiler}/filter_test.go | 2 +- .../{ => compiler}/generic_physical_plan.go | 2 +- .../generic_physical_plan_test.go | 2 +- internal/dataframe/{ => compiler}/grain.go | 2 +- .../dataframe/{ => compiler}/grain_test.go | 2 +- .../dataframe/{ => compiler}/optimizer.go | 2 +- .../dataframe/{ => compiler}/physical_cost.go | 2 +- .../{ => compiler}/physical_diagnostics.go | 18 +- .../physical_diagnostics_test.go | 2 +- .../{ => compiler}/physical_execution.go | 4 +- .../{ => compiler}/physical_execution_test.go | 5 +- .../{ => compiler}/physical_helpers.go | 2 +- .../{ => compiler}/physical_lowering.go | 2 +- .../{ => compiler}/physical_lowering_test.go | 2 +- .../{ => compiler}/physical_optimize.go | 2 +- .../{ => compiler}/physical_optimize_test.go | 2 +- .../dataframe/{ => compiler}/physical_plan.go | 2 +- .../{ => compiler}/physical_plan_test.go | 2 +- .../{ => compiler}/physical_prefix.go | 2 +- .../{ => compiler}/physical_render.go | 2 +- .../{ => compiler}/physical_render_test.go | 8 +- .../{ => compiler}/physical_required_match.go | 2 +- .../physical_required_match_test.go | 2 +- .../{ => compiler}/physical_scope.go | 2 +- .../{ => compiler}/physical_scope_test.go | 2 +- .../{ => compiler}/relationship_match.go | 2 +- .../{ => compiler}/selection_semantics.go | 2 +- .../selection_semantics_test.go | 2 +- .../dataframe/compiler/selector_helpers.go | 32 ++ .../{ => compiler}/selector_mode_test.go | 2 +- .../{ => compiler}/selector_render.go | 2 +- .../dataframe/{ => compiler}/selectors.go | 2 +- .../dataframe/{ => compiler}/semantic_plan.go | 2 +- .../{ => compiler}/semantic_plan_test.go | 2 +- .../{ => compiler}/semantic_validation.go | 2 +- .../semantic_validation_test.go | 2 +- .../dataframe/{ => compiler}/storage_route.go | 10 +- .../traversal_projection_experiment_test.go | 8 +- internal/dataframe/{ => errors}/errors.go | 2 +- .../dataframe/{ => errors}/errors_test.go | 2 +- .../full_identity_tournament_test.go | 3 + .../{ => runtime}/active_generation.go | 2 +- .../{ => runtime}/active_generation_test.go | 2 +- internal/dataframe/runtime/api.go | 277 +++++++++++++++++ internal/dataframe/{ => runtime}/auth.go | 2 +- internal/dataframe/runtime/auth_scope.go | 20 ++ .../{ => runtime}/auth_scope_test.go | 2 +- internal/dataframe/{ => runtime}/execution.go | 2 +- .../dataframe/{ => runtime}/execution_test.go | 2 +- internal/dataframe/{ => runtime}/explain.go | 2 +- .../dataframe/{ => runtime}/explain_test.go | 2 +- internal/dataframe/{ => runtime}/pivots.go | 2 +- .../dataframe/{ => runtime}/pivots_test.go | 2 +- internal/dataframe/{ => runtime}/profile.go | 2 +- .../dataframe/{ => runtime}/query_runtime.go | 2 +- internal/dataframe/runtime/runtime_helpers.go | 78 +++++ internal/dataframe/{ => runtime}/service.go | 2 +- .../dataframe/{ => runtime}/validation.go | 2 +- .../{ => runtime}/validation_service.go | 2 +- .../{ => runtime}/validation_service_test.go | 2 +- 73 files changed, 854 insertions(+), 100 deletions(-) create mode 100644 internal/dataframe/api.go create mode 100644 internal/dataframe/compat_test_helpers_test.go rename internal/dataframe/{ => compiler}/aggregate_compile_test.go (99%) create mode 100644 internal/dataframe/compiler/arango_test_helpers_test.go rename internal/dataframe/{ => compiler}/auth_scope.go (98%) rename internal/dataframe/{ => compiler}/builder_types.go (88%) rename internal/dataframe/{ => compiler}/compile.go (99%) rename internal/dataframe/{ => compiler}/dataset_generation.go (97%) rename internal/dataframe/{ => compiler}/filter.go (99%) rename internal/dataframe/{ => compiler}/filter_literal.go (97%) rename internal/dataframe/{ => compiler}/filter_semantics.go (99%) rename internal/dataframe/{ => compiler}/filter_semantics_test.go (99%) rename internal/dataframe/{ => compiler}/filter_test.go (99%) rename internal/dataframe/{ => compiler}/generic_physical_plan.go (99%) rename internal/dataframe/{ => compiler}/generic_physical_plan_test.go (99%) rename internal/dataframe/{ => compiler}/grain.go (99%) rename internal/dataframe/{ => compiler}/grain_test.go (99%) rename internal/dataframe/{ => compiler}/optimizer.go (97%) rename internal/dataframe/{ => compiler}/physical_cost.go (99%) rename internal/dataframe/{ => compiler}/physical_diagnostics.go (96%) rename internal/dataframe/{ => compiler}/physical_diagnostics_test.go (98%) rename internal/dataframe/{ => compiler}/physical_execution.go (98%) rename internal/dataframe/{ => compiler}/physical_execution_test.go (97%) rename internal/dataframe/{ => compiler}/physical_helpers.go (99%) rename internal/dataframe/{ => compiler}/physical_lowering.go (98%) rename internal/dataframe/{ => compiler}/physical_lowering_test.go (98%) rename internal/dataframe/{ => compiler}/physical_optimize.go (99%) rename internal/dataframe/{ => compiler}/physical_optimize_test.go (99%) rename internal/dataframe/{ => compiler}/physical_plan.go (99%) rename internal/dataframe/{ => compiler}/physical_plan_test.go (99%) rename internal/dataframe/{ => compiler}/physical_prefix.go (99%) rename internal/dataframe/{ => compiler}/physical_render.go (99%) rename internal/dataframe/{ => compiler}/physical_render_test.go (98%) rename internal/dataframe/{ => compiler}/physical_required_match.go (99%) rename internal/dataframe/{ => compiler}/physical_required_match_test.go (99%) rename internal/dataframe/{ => compiler}/physical_scope.go (99%) rename internal/dataframe/{ => compiler}/physical_scope_test.go (99%) rename internal/dataframe/{ => compiler}/relationship_match.go (98%) rename internal/dataframe/{ => compiler}/selection_semantics.go (99%) rename internal/dataframe/{ => compiler}/selection_semantics_test.go (99%) create mode 100644 internal/dataframe/compiler/selector_helpers.go rename internal/dataframe/{ => compiler}/selector_mode_test.go (99%) rename internal/dataframe/{ => compiler}/selector_render.go (98%) rename internal/dataframe/{ => compiler}/selectors.go (98%) rename internal/dataframe/{ => compiler}/semantic_plan.go (99%) rename internal/dataframe/{ => compiler}/semantic_plan_test.go (99%) rename internal/dataframe/{ => compiler}/semantic_validation.go (99%) rename internal/dataframe/{ => compiler}/semantic_validation_test.go (99%) rename internal/dataframe/{ => compiler}/storage_route.go (95%) rename internal/dataframe/{ => compiler}/traversal_projection_experiment_test.go (99%) rename internal/dataframe/{ => errors}/errors.go (99%) rename internal/dataframe/{ => errors}/errors_test.go (99%) rename internal/dataframe/{ => runtime}/active_generation.go (98%) rename internal/dataframe/{ => runtime}/active_generation_test.go (99%) create mode 100644 internal/dataframe/runtime/api.go rename internal/dataframe/{ => runtime}/auth.go (99%) create mode 100644 internal/dataframe/runtime/auth_scope.go rename internal/dataframe/{ => runtime}/auth_scope_test.go (99%) rename internal/dataframe/{ => runtime}/execution.go (99%) rename internal/dataframe/{ => runtime}/execution_test.go (99%) rename internal/dataframe/{ => runtime}/explain.go (97%) rename internal/dataframe/{ => runtime}/explain_test.go (96%) rename internal/dataframe/{ => runtime}/pivots.go (99%) rename internal/dataframe/{ => runtime}/pivots_test.go (98%) rename internal/dataframe/{ => runtime}/profile.go (97%) rename internal/dataframe/{ => runtime}/query_runtime.go (97%) create mode 100644 internal/dataframe/runtime/runtime_helpers.go rename internal/dataframe/{ => runtime}/service.go (99%) rename internal/dataframe/{ => runtime}/validation.go (99%) rename internal/dataframe/{ => runtime}/validation_service.go (99%) rename internal/dataframe/{ => runtime}/validation_service_test.go (99%) diff --git a/docs/DEVELOPER_ARCHITECTURE.md b/docs/DEVELOPER_ARCHITECTURE.md index f83e12f..03eab7e 100644 --- a/docs/DEVELOPER_ARCHITECTURE.md +++ b/docs/DEVELOPER_ARCHITECTURE.md @@ -58,15 +58,19 @@ The current runtime call path is: GraphQL request -> graphqlapi resolver -> dataframebuilder.Service - -> dataframe.Service - -> semantic validation and lowering + -> dataframe compatibility façade + -> dataframe/runtime.Service + -> dataframe/compiler semantic validation and lowering -> lowered AQL compiler -> Arango query execution/streaming ``` -`internal/dataframe` owns semantics, authorization-aware query compilation, -and execution. `internal/catalog` owns scoped observed-field and relationship -facts. `fhirschema` owns generated structural metadata. These +`internal/dataframe` is now a compatibility façade. Runtime preparation and +execution live in `internal/dataframe/runtime`; pure semantic/physical +compilation lives in `internal/dataframe/compiler`; structured transport +errors live in `internal/dataframe/errors`; and guided templates live in +`internal/dataframe/template`. `internal/catalog` owns scoped observed-field +and relationship facts. `fhirschema` owns generated structural metadata. These boundaries matter: catalog observations constrain what is populated, while schema metadata constrains what a request means. @@ -77,11 +81,14 @@ layout, plus the explicitly proven `ResearchSubject --study--> ResearchStudy` sufficient proof; every other forward route remains rejected until it has a verified storage contract. -`internal/dataframe/physical_plan.go` and its renderer are a typed diagnostic -and optimization foundation. They are not yet the execution renderer for all -selections, filters, aggregates, pivots, and required relationships. Keep them -as new compiler work rather than treating their current limited runtime -reachability as dead code. +The compiler package contains the typed physical plan, lowering, optimizer, +renderer, and compiler diagnostics. Runtime code may call the compiler, but the +compiler must never import runtime, catalog, or HTTP/GraphQL transport code. +The root dataframe import path remains stable through aliases and forwarding +functions so external callers do not need a flag-day migration. + +For the complete ownership map and move history, see +[`DATAFRAME_PACKAGE_REORGANIZATION_PLAN.md`](DATAFRAME_PACKAGE_REORGANIZATION_PLAN.md). ## Compatibility tracks and removal order diff --git a/internal/dataframe/api.go b/internal/dataframe/api.go new file mode 100644 index 0000000..90d6252 --- /dev/null +++ b/internal/dataframe/api.go @@ -0,0 +1,288 @@ +// Package dataframe is the compatibility façade for Loom's dataframe engine. +// +// Runtime orchestration lives in ./runtime, pure compilation in ./compiler, +// and the stable error contract in ./errors. This package preserves the +// historical import path through aliases and forwarding functions. +package dataframe + +import ( + "github.com/calypr/loom/internal/dataframe/runtime" +) + +type ( + Service = runtime.Service + ServiceConfig = runtime.ServiceConfig + ExecuteQueryOptions = runtime.ExecuteQueryOptions + ValidationWarning = runtime.ValidationWarning + ValidationResult = runtime.ValidationResult + ValidateRequest = runtime.ValidateRequest + Builder = runtime.Builder + TraversalStep = runtime.TraversalStep + RepresentativeSlice = runtime.RepresentativeSlice + FieldSelect = runtime.FieldSelect + PivotSelect = runtime.PivotSelect + AggregateSelect = runtime.AggregateSelect + RunRequest = runtime.RunRequest + Result = runtime.Result + QueryDiagnostics = runtime.QueryDiagnostics + StreamResult = runtime.StreamResult + CompiledQuery = runtime.CompiledQuery + SemanticPlan = runtime.SemanticPlan + SemanticNode = runtime.SemanticNode + SemanticField = runtime.SemanticField + SemanticPivot = runtime.SemanticPivot + SemanticAggregate = runtime.SemanticAggregate + SemanticSlice = runtime.SemanticSlice + SemanticPlanExplanation = runtime.SemanticPlanExplanation + SemanticNodeExplanation = runtime.SemanticNodeExplanation + SelectionSemanticSpec = runtime.SelectionSemanticSpec + RowGrain = runtime.RowGrain + ProjectionMode = runtime.ProjectionMode + Cardinality = runtime.Cardinality + RowIdentity = runtime.RowIdentity + TraversalMatchMode = runtime.TraversalMatchMode + FilterOperator = runtime.FilterOperator + FilterValueKind = runtime.FilterValueKind + ArrayQuantifier = runtime.ArrayQuantifier + CodeValue = runtime.CodeValue + FilterValue = runtime.FilterValue + TypedFilter = runtime.TypedFilter + Selector = runtime.Selector + SelectorStep = runtime.SelectorStep + ContainsFilter = runtime.ContainsFilter + PhysicalOptimizationPolicy = runtime.PhysicalOptimizationPolicy + PhysicalOptimizationRule = runtime.PhysicalOptimizationRule + PhysicalOptimizationDecision = runtime.PhysicalOptimizationDecision + PhysicalOptimizationReport = runtime.PhysicalOptimizationReport + PhysicalOptimizationRuleState = runtime.PhysicalOptimizationRuleState + CompilerPlanDiagnostics = runtime.CompilerPlanDiagnostics + PhysicalTraversalDecision = runtime.PhysicalTraversalDecision + RichSourceReuse = runtime.RichSourceReuse + RichConsumerGroup = runtime.RichConsumerGroup + RenderedPhysicalPlan = runtime.RenderedPhysicalPlan + PhysicalTraversalPrefix = runtime.PhysicalTraversalPrefix + PhysicalTraversalSubset = runtime.PhysicalTraversalSubset + PhysicalTraversalPrefixDecomposition = runtime.PhysicalTraversalPrefixDecomposition + PhysicalTraversalPrefixRejectionReason = runtime.PhysicalTraversalPrefixRejectionReason + PhysicalTraversalPrefixError = runtime.PhysicalTraversalPrefixError + PhysicalPlan = runtime.PhysicalPlan + PhysicalSource = runtime.PhysicalSource + PhysicalOperationKind = runtime.PhysicalOperationKind + PhysicalOperation = runtime.PhysicalOperation + PhysicalRootScan = runtime.PhysicalRootScan + PhysicalTraversalDirection = runtime.PhysicalTraversalDirection + PhysicalTraversalStrategy = runtime.PhysicalTraversalStrategy + PhysicalTraversal = runtime.PhysicalTraversal + PhysicalValue = runtime.PhysicalValue + PhysicalCardinality = runtime.PhysicalCardinality + PhysicalNullBehavior = runtime.PhysicalNullBehavior + PhysicalExpressionKind = runtime.PhysicalExpressionKind + PhysicalSelectorExecutionMode = runtime.PhysicalSelectorExecutionMode + PhysicalExpression = runtime.PhysicalExpression + PhysicalExtract = runtime.PhysicalExtract + PhysicalPreparedReference = runtime.PhysicalPreparedReference + PhysicalPreparedSet = runtime.PhysicalPreparedSet + PhysicalPreparedField = runtime.PhysicalPreparedField + PhysicalAggregateOperation = runtime.PhysicalAggregateOperation + PhysicalAggregate = runtime.PhysicalAggregate + PhysicalPivotMap = runtime.PhysicalPivotMap + PhysicalSlice = runtime.PhysicalSlice + PhysicalExpressionProjection = runtime.PhysicalExpressionProjection + PhysicalObject = runtime.PhysicalObject + PhysicalSet = runtime.PhysicalSet + PhysicalSetProjection = runtime.PhysicalSetProjection + PhysicalSetProjectionField = runtime.PhysicalSetProjectionField + PhysicalSetOutputField = runtime.PhysicalSetOutputField + PhysicalSetOutput = runtime.PhysicalSetOutput + PhysicalSubplan = runtime.PhysicalSubplan + PhysicalPredicate = runtime.PhysicalPredicate + PhysicalPredicateKind = runtime.PhysicalPredicateKind + PhysicalPredicateExpression = runtime.PhysicalPredicateExpression + PhysicalFilter = runtime.PhysicalFilter + PhysicalDerivedLet = runtime.PhysicalDerivedLet + PhysicalSort = runtime.PhysicalSort + PhysicalLimit = runtime.PhysicalLimit + PhysicalProjection = runtime.PhysicalProjection + PhysicalReturn = runtime.PhysicalReturn + StorageRoute = runtime.StorageRoute + ErrorCode = runtime.ErrorCode + UserError = runtime.UserError + Error = runtime.Error + ErrorOption = runtime.ErrorOption +) + +const ( + MaxSemanticTraversalDepth = runtime.MaxSemanticTraversalDepth + RowGrainResource = runtime.RowGrainResource + RowGrainPatient = runtime.RowGrainPatient + RowGrainSpecimen = runtime.RowGrainSpecimen + RowGrainFile = runtime.RowGrainFile + RowGrainDiagnosis = runtime.RowGrainDiagnosis + RowGrainObservation = runtime.RowGrainObservation + RowGrainStudyEnrollment = runtime.RowGrainStudyEnrollment + ProjectionScalar = runtime.ProjectionScalar + ProjectionFirst = runtime.ProjectionFirst + ProjectionArray = runtime.ProjectionArray + ProjectionDistinctArray = runtime.ProjectionDistinctArray + ProjectionAggregate = runtime.ProjectionAggregate + ProjectionPivot = runtime.ProjectionPivot + ProjectionExplode = runtime.ProjectionExplode + CardinalityRequiredOne = runtime.CardinalityRequiredOne + CardinalityOptionalOne = runtime.CardinalityOptionalOne + CardinalityMany = runtime.CardinalityMany + CardinalityUnknownObservedMany = runtime.CardinalityUnknownObservedMany + TraversalMatchOptional = runtime.TraversalMatchOptional + TraversalMatchRequired = runtime.TraversalMatchRequired + FilterEquals = runtime.FilterEquals + FilterNotEquals = runtime.FilterNotEquals + FilterIn = runtime.FilterIn + FilterExists = runtime.FilterExists + FilterMissing = runtime.FilterMissing + FilterContains = runtime.FilterContains + FilterGreaterThan = runtime.FilterGreaterThan + FilterGreaterEq = runtime.FilterGreaterEq + FilterLessThan = runtime.FilterLessThan + FilterLessEq = runtime.FilterLessEq + FilterString = runtime.FilterString + FilterCode = runtime.FilterCode + FilterBoolean = runtime.FilterBoolean + FilterInteger = runtime.FilterInteger + FilterDecimal = runtime.FilterDecimal + FilterDate = runtime.FilterDate + FilterDateTime = runtime.FilterDateTime + QuantifierAny = runtime.QuantifierAny + QuantifierAll = runtime.QuantifierAll + QuantifierNone = runtime.QuantifierNone + PhysicalTraversalNative = runtime.PhysicalTraversalNative + PhysicalTraversalEndpointLookup = runtime.PhysicalTraversalEndpointLookup + PhysicalOutbound = runtime.PhysicalOutbound + PhysicalInbound = runtime.PhysicalInbound + PhysicalAny = runtime.PhysicalAny + PhysicalRootScanOp = runtime.PhysicalRootScanOp + PhysicalTraversalOp = runtime.PhysicalTraversalOp + PhysicalFilterOp = runtime.PhysicalFilterOp + PhysicalDerivedLetOp = runtime.PhysicalDerivedLetOp + PhysicalSetOp = runtime.PhysicalSetOp + PhysicalSortOp = runtime.PhysicalSortOp + PhysicalLimitOp = runtime.PhysicalLimitOp + PhysicalReturnOp = runtime.PhysicalReturnOp + PhysicalScalarCardinality = runtime.PhysicalScalarCardinality + PhysicalArrayCardinality = runtime.PhysicalArrayCardinality + PhysicalObjectCardinality = runtime.PhysicalObjectCardinality + PhysicalPreserveNull = runtime.PhysicalPreserveNull + PhysicalOmitNulls = runtime.PhysicalOmitNulls + PhysicalEmptyOnNull = runtime.PhysicalEmptyOnNull + PhysicalValueExpression = runtime.PhysicalValueExpression + PhysicalExtractExpression = runtime.PhysicalExtractExpression + PhysicalAggregateExpression = runtime.PhysicalAggregateExpression + PhysicalPivotExpression = runtime.PhysicalPivotExpression + PhysicalSliceExpression = runtime.PhysicalSliceExpression + PhysicalObjectExpression = runtime.PhysicalObjectExpression + PhysicalSelectorGeneric = runtime.PhysicalSelectorGeneric + PhysicalSelectorDirectScalar = runtime.PhysicalSelectorDirectScalar + PhysicalSelectorConditionalArray = runtime.PhysicalSelectorConditionalArray + PhysicalCountAggregate = runtime.PhysicalCountAggregate + PhysicalCountDistinctAggregate = runtime.PhysicalCountDistinctAggregate + PhysicalExistsAggregate = runtime.PhysicalExistsAggregate + PhysicalDistinctValuesAggregate = runtime.PhysicalDistinctValuesAggregate + PhysicalMinAggregate = runtime.PhysicalMinAggregate + PhysicalMaxAggregate = runtime.PhysicalMaxAggregate + PhysicalFirstAggregate = runtime.PhysicalFirstAggregate + PhysicalSetGraphIDField = runtime.PhysicalSetGraphIDField + PhysicalSetKeyField = runtime.PhysicalSetKeyField + PhysicalSetIDField = runtime.PhysicalSetIDField + PhysicalSetResourceTypeField = runtime.PhysicalSetResourceTypeField + PhysicalSetPayloadField = runtime.PhysicalSetPayloadField + PhysicalComparisonPredicate = runtime.PhysicalComparisonPredicate + PhysicalAllPredicate = runtime.PhysicalAllPredicate + PhysicalAnyPredicate = runtime.PhysicalAnyPredicate + PhysicalNotPredicate = runtime.PhysicalNotPredicate + PhysicalExistsPredicate = runtime.PhysicalExistsPredicate + PhysicalPrefixNotOptionalSet = runtime.PhysicalPrefixNotOptionalSet + PhysicalPrefixSharedSubset = runtime.PhysicalPrefixSharedSubset + PhysicalPrefixInvalidCapture = runtime.PhysicalPrefixInvalidCapture + PhysicalPrefixMissingTraversal = runtime.PhysicalPrefixMissingTraversal + PhysicalPrefixUnsupportedDirection = runtime.PhysicalPrefixUnsupportedDirection + PhysicalPrefixInvalidRoute = runtime.PhysicalPrefixInvalidRoute + PhysicalPrefixInvalidScope = runtime.PhysicalPrefixInvalidScope + PhysicalPrefixInvalidTarget = runtime.PhysicalPrefixInvalidTarget + PhysicalOptimizationRuleTraversalSharing = runtime.PhysicalOptimizationRuleTraversalSharing + PhysicalOptimizationRulePreparedSelectors = runtime.PhysicalOptimizationRulePreparedSelectors + PhysicalOptimizationRuleNestedSharing = runtime.PhysicalOptimizationRuleNestedSharing + PhysicalOptimizationRuleRichConsumerFusion = runtime.PhysicalOptimizationRuleRichConsumerFusion + PhysicalOptimizationRuleCompactProjection = runtime.PhysicalOptimizationRuleCompactProjection + PhysicalOptimizationRuleEndpointTraversal = runtime.PhysicalOptimizationRuleEndpointTraversal + OptimizerRuleFilterPushdown = runtime.OptimizerRuleFilterPushdown + OptimizerRuleTraversalSharing = runtime.OptimizerRuleTraversalSharing + OptimizerRuleRelationshipSemiJoin = runtime.OptimizerRuleRelationshipSemiJoin + CodeProjectRequired = runtime.CodeProjectRequired + CodeRootResourceTypeRequired = runtime.CodeRootResourceTypeRequired + CodeUnauthorizedProject = runtime.CodeUnauthorizedProject + CodeUnknownField = runtime.CodeUnknownField + CodeFieldNotPopulated = runtime.CodeFieldNotPopulated + CodeInvalidTraversal = runtime.CodeInvalidTraversal + CodeUnsafeTraversalRoute = runtime.CodeUnsafeTraversalRoute + CodeInvalidFilter = runtime.CodeInvalidFilter + CodeUnboundedPivot = runtime.CodeUnboundedPivot + CodeInvalidPivotColumn = runtime.CodeInvalidPivotColumn + CodeInvalidSlice = runtime.CodeInvalidSlice + CodePlanTooExpensive = runtime.CodePlanTooExpensive + CodeInvalidCursor = runtime.CodeInvalidCursor + CodeStaleCursor = runtime.CodeStaleCursor + CodeDatasetGenerationChanged = runtime.CodeDatasetGenerationChanged + CodeUnsupportedExportFormat = runtime.CodeUnsupportedExportFormat + CodeClientCanceled = runtime.CodeClientCanceled + CodeBackendUnavailable = runtime.CodeBackendUnavailable + CodeInternalError = runtime.CodeInternalError +) + +var ( + NewService = runtime.NewService + ExecuteQueryRows = runtime.ExecuteQueryRows + ExplainCompiledQuery = runtime.ExplainCompiledQuery + ProfileCompiledQuery = runtime.ProfileCompiledQuery + DefaultPhysicalOptimizationPolicy = runtime.DefaultPhysicalOptimizationPolicy + CompileRequest = runtime.CompileRequest + CompileRequestWithPolicy = runtime.CompileRequestWithPolicy + BuildSemanticPlan = runtime.BuildSemanticPlan + ValidateSemanticGraph = runtime.ValidateSemanticGraph + BuildPhysicalPlan = runtime.BuildPhysicalPlan + BuildPhysicalPlanWithPolicy = runtime.BuildPhysicalPlanWithPolicy + BuildGenericPhysicalPlan = runtime.BuildGenericPhysicalPlan + BuildGenericPhysicalPlanWithPolicy = runtime.BuildGenericPhysicalPlanWithPolicy + OptimizePhysicalPlan = runtime.OptimizePhysicalPlan + OptimizePhysicalPlanWithPolicy = runtime.OptimizePhysicalPlanWithPolicy + RenderPhysicalPlan = runtime.RenderPhysicalPlan + ParseSelector = runtime.ParseSelector + ValidateTypedFilterForResource = runtime.ValidateTypedFilterForResource + NormalizeSelectionPlan = runtime.NormalizeSelectionPlan + ResolveSemanticField = runtime.ResolveSemanticField + InferRowGrain = runtime.InferRowGrain + RootResourceForGrain = runtime.RootResourceForGrain + ValidateRootGrain = runtime.ValidateRootGrain + DefaultRowIdentity = runtime.DefaultRowIdentity + ValidateProjection = runtime.ValidateProjection + OperatorSupportsKind = runtime.OperatorSupportsKind + ValidateGenericPhysicalPlanScope = runtime.ValidateGenericPhysicalPlanScope + DecomposePhysicalTraversalPrefix = runtime.DecomposePhysicalTraversalPrefix + ResolveStorageRoute = runtime.ResolveStorageRoute + AsUserError = runtime.AsUserError + Normalize = runtime.Normalize + PublicMessage = runtime.PublicMessage + NewError = runtime.NewError + Wrap = runtime.Wrap + WithFieldPath = runtime.WithFieldPath + WithDetails = runtime.WithDetails + WithRetryable = runtime.WithRetryable + WithCause = runtime.WithCause + IsUserCorrectable = runtime.IsUserCorrectable + IsRetryableCode = runtime.IsRetryableCode + IsOperatorFailure = runtime.IsOperatorFailure + Errorf = runtime.Errorf +) + +var ( + AllErrorCodes = runtime.AllErrorCodes + ErrBackendUnavailable = runtime.ErrBackendUnavailable + ErrClientCanceled = runtime.ErrClientCanceled +) diff --git a/internal/dataframe/compat_test_helpers_test.go b/internal/dataframe/compat_test_helpers_test.go new file mode 100644 index 0000000..8a47f41 --- /dev/null +++ b/internal/dataframe/compat_test_helpers_test.go @@ -0,0 +1,19 @@ +package dataframe + +// These aliases keep legacy experiment tests in the root compatibility +// package while their implementations live in compiler/runtime packages. +type storageRoute = StorageRoute + +func resolveStorageRoute(fromType, label, toType string) (storageRoute, error) { + return ResolveStorageRoute(fromType, label, toType) +} + +const datasetGenerationBindKey = "dataset_generation" + +func isDatasetGenerationScopePredicate(predicate PhysicalPredicate, variable string) bool { + return predicate.Operator == "EQUALS" && + predicate.Left.Variable == variable && + len(predicate.Left.Path) == 1 && predicate.Left.Path[0] == "dataset_generation" && + predicate.Right != nil && predicate.Right.BindKey == datasetGenerationBindKey && + predicate.Right.Variable == "" && len(predicate.Right.Path) == 0 +} diff --git a/internal/dataframe/aggregate_compile_test.go b/internal/dataframe/compiler/aggregate_compile_test.go similarity index 99% rename from internal/dataframe/aggregate_compile_test.go rename to internal/dataframe/compiler/aggregate_compile_test.go index 367ef7d..0eb9ad5 100644 --- a/internal/dataframe/aggregate_compile_test.go +++ b/internal/dataframe/compiler/aggregate_compile_test.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "strings" diff --git a/internal/dataframe/compiler/arango_test_helpers_test.go b/internal/dataframe/compiler/arango_test_helpers_test.go new file mode 100644 index 0000000..a277c64 --- /dev/null +++ b/internal/dataframe/compiler/arango_test_helpers_test.go @@ -0,0 +1,19 @@ +package compiler + +import "os" + +func compilerArangoTarget() (string, string, string) { + url := os.Getenv("LOOM_ARANGO_URL") + if url == "" { + url = "http://127.0.0.1:8529" + } + database := os.Getenv("LOOM_ARANGO_DATABASE") + if database == "" { + database = "fhir_proto" + } + project := os.Getenv("LOOM_ARANGO_PROJECT") + if project == "" { + project = "ARANGODB_PROTO" + } + return url, database, project +} diff --git a/internal/dataframe/auth_scope.go b/internal/dataframe/compiler/auth_scope.go similarity index 98% rename from internal/dataframe/auth_scope.go rename to internal/dataframe/compiler/auth_scope.go index 49bfc7b..c94df73 100644 --- a/internal/dataframe/auth_scope.go +++ b/internal/dataframe/compiler/auth_scope.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import "github.com/calypr/loom/internal/authscope" diff --git a/internal/dataframe/builder_types.go b/internal/dataframe/compiler/builder_types.go similarity index 88% rename from internal/dataframe/builder_types.go rename to internal/dataframe/compiler/builder_types.go index dbe3eee..3e35bf6 100644 --- a/internal/dataframe/builder_types.go +++ b/internal/dataframe/compiler/builder_types.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "time" @@ -16,15 +16,15 @@ type Builder struct { // required to distinguish a restricted empty path set from an unrestricted // one. The empty value preserves the legacy direct-Builder convention that // no paths means unrestricted. - AuthScopeMode authscope.ReadScopeMode - RootResourceType string - RowGrain RowGrain - Fields []FieldSelect - Filters []TypedFilter - Pivots []PivotSelect - Aggregates []AggregateSelect - Slices []RepresentativeSlice - Traversals []TraversalStep + AuthScopeMode authscope.ReadScopeMode + RootResourceType string + RowGrain RowGrain + Fields []FieldSelect + Filters []TypedFilter + Pivots []PivotSelect + Aggregates []AggregateSelect + Slices []RepresentativeSlice + Traversals []TraversalStep } type TraversalStep struct { @@ -39,8 +39,8 @@ type TraversalStep struct { // MatchMode defaults to OPTIONAL. REQUIRED retains only root rows with a // matching relationship route; it is lowered as a semi-join rather than a // post-projection filter. - MatchMode TraversalMatchMode - Traversals []TraversalStep + MatchMode TraversalMatchMode + Traversals []TraversalStep } // RepresentativeSlice is a bounded child projection requested by the diff --git a/internal/dataframe/compile.go b/internal/dataframe/compiler/compile.go similarity index 99% rename from internal/dataframe/compile.go rename to internal/dataframe/compiler/compile.go index c409bc2..1314ade 100644 --- a/internal/dataframe/compile.go +++ b/internal/dataframe/compiler/compile.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import "fmt" diff --git a/internal/dataframe/dataset_generation.go b/internal/dataframe/compiler/dataset_generation.go similarity index 97% rename from internal/dataframe/dataset_generation.go rename to internal/dataframe/compiler/dataset_generation.go index d063304..4e6bf84 100644 --- a/internal/dataframe/dataset_generation.go +++ b/internal/dataframe/compiler/dataset_generation.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import "strings" diff --git a/internal/dataframe/filter.go b/internal/dataframe/compiler/filter.go similarity index 99% rename from internal/dataframe/filter.go rename to internal/dataframe/compiler/filter.go index 987a3f3..0e983d4 100644 --- a/internal/dataframe/filter.go +++ b/internal/dataframe/compiler/filter.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "errors" diff --git a/internal/dataframe/filter_literal.go b/internal/dataframe/compiler/filter_literal.go similarity index 97% rename from internal/dataframe/filter_literal.go rename to internal/dataframe/compiler/filter_literal.go index eb623c4..e770bf0 100644 --- a/internal/dataframe/filter_literal.go +++ b/internal/dataframe/compiler/filter_literal.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import "fmt" diff --git a/internal/dataframe/filter_semantics.go b/internal/dataframe/compiler/filter_semantics.go similarity index 99% rename from internal/dataframe/filter_semantics.go rename to internal/dataframe/compiler/filter_semantics.go index 51823d9..6b4de39 100644 --- a/internal/dataframe/filter_semantics.go +++ b/internal/dataframe/compiler/filter_semantics.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "fmt" diff --git a/internal/dataframe/filter_semantics_test.go b/internal/dataframe/compiler/filter_semantics_test.go similarity index 99% rename from internal/dataframe/filter_semantics_test.go rename to internal/dataframe/compiler/filter_semantics_test.go index cbf79d4..e8d7d2c 100644 --- a/internal/dataframe/filter_semantics_test.go +++ b/internal/dataframe/compiler/filter_semantics_test.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "strings" diff --git a/internal/dataframe/filter_test.go b/internal/dataframe/compiler/filter_test.go similarity index 99% rename from internal/dataframe/filter_test.go rename to internal/dataframe/compiler/filter_test.go index 443329f..cde076a 100644 --- a/internal/dataframe/filter_test.go +++ b/internal/dataframe/compiler/filter_test.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "strings" diff --git a/internal/dataframe/generic_physical_plan.go b/internal/dataframe/compiler/generic_physical_plan.go similarity index 99% rename from internal/dataframe/generic_physical_plan.go rename to internal/dataframe/compiler/generic_physical_plan.go index 0c6887b..e7d8d78 100644 --- a/internal/dataframe/generic_physical_plan.go +++ b/internal/dataframe/compiler/generic_physical_plan.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "fmt" diff --git a/internal/dataframe/generic_physical_plan_test.go b/internal/dataframe/compiler/generic_physical_plan_test.go similarity index 99% rename from internal/dataframe/generic_physical_plan_test.go rename to internal/dataframe/compiler/generic_physical_plan_test.go index dfde90a..620274f 100644 --- a/internal/dataframe/generic_physical_plan_test.go +++ b/internal/dataframe/compiler/generic_physical_plan_test.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "strings" diff --git a/internal/dataframe/grain.go b/internal/dataframe/compiler/grain.go similarity index 99% rename from internal/dataframe/grain.go rename to internal/dataframe/compiler/grain.go index c6ab723..a1a2ba0 100644 --- a/internal/dataframe/grain.go +++ b/internal/dataframe/compiler/grain.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "fmt" diff --git a/internal/dataframe/grain_test.go b/internal/dataframe/compiler/grain_test.go similarity index 99% rename from internal/dataframe/grain_test.go rename to internal/dataframe/compiler/grain_test.go index 83b13e4..ebe73d9 100644 --- a/internal/dataframe/grain_test.go +++ b/internal/dataframe/compiler/grain_test.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import "testing" diff --git a/internal/dataframe/optimizer.go b/internal/dataframe/compiler/optimizer.go similarity index 97% rename from internal/dataframe/optimizer.go rename to internal/dataframe/compiler/optimizer.go index ea1ec9e..bc217c4 100644 --- a/internal/dataframe/optimizer.go +++ b/internal/dataframe/compiler/optimizer.go @@ -1,4 +1,4 @@ -package dataframe +package compiler // Stable optimizer-rule identifiers appear in compiler explain output and // conformance evidence. They are deliberately independent of AQL text. diff --git a/internal/dataframe/physical_cost.go b/internal/dataframe/compiler/physical_cost.go similarity index 99% rename from internal/dataframe/physical_cost.go rename to internal/dataframe/compiler/physical_cost.go index 58e01ce..6f71f1b 100644 --- a/internal/dataframe/physical_cost.go +++ b/internal/dataframe/compiler/physical_cost.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "os" diff --git a/internal/dataframe/physical_diagnostics.go b/internal/dataframe/compiler/physical_diagnostics.go similarity index 96% rename from internal/dataframe/physical_diagnostics.go rename to internal/dataframe/compiler/physical_diagnostics.go index 1dd7d4c..faf575c 100644 --- a/internal/dataframe/physical_diagnostics.go +++ b/internal/dataframe/compiler/physical_diagnostics.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "encoding/json" @@ -97,15 +97,15 @@ func physicalPlanDiagnostics(plan PhysicalPlan) CompilerPlanDiagnostics { strategy = PhysicalTraversalNative } decision := PhysicalTraversalDecision{ - SourceVariable: traversal.SourceVariable, - TargetVariable: traversal.TargetVariable, - Direction: traversal.Direction, - Strategy: strategy, - EndpointField: traversal.EndpointField, - EndpointJoinField: traversal.EndpointJoinField, + SourceVariable: traversal.SourceVariable, + TargetVariable: traversal.TargetVariable, + Direction: traversal.Direction, + Strategy: strategy, + EndpointField: traversal.EndpointField, + EndpointJoinField: traversal.EndpointJoinField, EndpointIndexFields: append([]string(nil), traversal.EndpointIndexFields...), - Relationship: operation.Source.Relationship, - TargetResourceType: operation.Source.ResourceType, + Relationship: operation.Source.Relationship, + TargetResourceType: operation.Source.ResourceType, } if strategy == PhysicalTraversalEndpointLookup { decision.Reason = "endpoint lookup enabled by validated storage-route and index contract" diff --git a/internal/dataframe/physical_diagnostics_test.go b/internal/dataframe/compiler/physical_diagnostics_test.go similarity index 98% rename from internal/dataframe/physical_diagnostics_test.go rename to internal/dataframe/compiler/physical_diagnostics_test.go index f6a160d..c571d30 100644 --- a/internal/dataframe/physical_diagnostics_test.go +++ b/internal/dataframe/compiler/physical_diagnostics_test.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import "testing" diff --git a/internal/dataframe/physical_execution.go b/internal/dataframe/compiler/physical_execution.go similarity index 98% rename from internal/dataframe/physical_execution.go rename to internal/dataframe/compiler/physical_execution.go index 26150af..6919a37 100644 --- a/internal/dataframe/physical_execution.go +++ b/internal/dataframe/compiler/physical_execution.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import "fmt" @@ -26,7 +26,7 @@ func compilePhysicalExecution(physical PhysicalPlan, semantic SemanticPlan, limi AuthResourcePaths: cloneStrings(semantic.AuthResourcePaths), PlanMode: "physical", PlanProfile: "generic_fhir_graph", - TraversalCount: physicalTraversalCount(physical), + TraversalCount: physicalTraversalCount(physical), OptimizationRules: physicalOptimizationRules(semantic.Root), RowIdentity: cloneRowIdentity(semantic.RowIdentity), Query: rendered.Query, diff --git a/internal/dataframe/physical_execution_test.go b/internal/dataframe/compiler/physical_execution_test.go similarity index 97% rename from internal/dataframe/physical_execution_test.go rename to internal/dataframe/compiler/physical_execution_test.go index d72abbf..8ed8166 100644 --- a/internal/dataframe/physical_execution_test.go +++ b/internal/dataframe/compiler/physical_execution_test.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "strings" @@ -31,7 +31,8 @@ func TestCompileRequestUsesPhysicalExecutionForNavigationOnlyGenericPlan(t *test "FOR root IN @@root_collection", "SORT root._key", "LIMIT @limit", - "FOR node_1, edge_1 IN 1..1 INBOUND root @@traversal_1_edge_collection", + "FOR edge_1 IN @@traversal_1_edge_collection", + "LET node_1 = DOCUMENT(edge_1._from)", "RETURN { [@__loom_physical_projection_0_name]: root._key }", } { if !strings.Contains(physical.Query, want) { diff --git a/internal/dataframe/physical_helpers.go b/internal/dataframe/compiler/physical_helpers.go similarity index 99% rename from internal/dataframe/physical_helpers.go rename to internal/dataframe/compiler/physical_helpers.go index 8c40221..9592213 100644 --- a/internal/dataframe/physical_helpers.go +++ b/internal/dataframe/compiler/physical_helpers.go @@ -1,4 +1,4 @@ -package dataframe +package compiler // genericPhysicalPlanUnavailableReason reports whether a semantic node needs // an operation the navigation-only physical plan does not yet represent. diff --git a/internal/dataframe/physical_lowering.go b/internal/dataframe/compiler/physical_lowering.go similarity index 98% rename from internal/dataframe/physical_lowering.go rename to internal/dataframe/compiler/physical_lowering.go index 07d8c68..243d9a0 100644 --- a/internal/dataframe/physical_lowering.go +++ b/internal/dataframe/compiler/physical_lowering.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import "fmt" diff --git a/internal/dataframe/physical_lowering_test.go b/internal/dataframe/compiler/physical_lowering_test.go similarity index 98% rename from internal/dataframe/physical_lowering_test.go rename to internal/dataframe/compiler/physical_lowering_test.go index 3d95077..b75d83c 100644 --- a/internal/dataframe/physical_lowering_test.go +++ b/internal/dataframe/compiler/physical_lowering_test.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import "testing" diff --git a/internal/dataframe/physical_optimize.go b/internal/dataframe/compiler/physical_optimize.go similarity index 99% rename from internal/dataframe/physical_optimize.go rename to internal/dataframe/compiler/physical_optimize.go index d5a17aa..7d86b26 100644 --- a/internal/dataframe/physical_optimize.go +++ b/internal/dataframe/compiler/physical_optimize.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "fmt" diff --git a/internal/dataframe/physical_optimize_test.go b/internal/dataframe/compiler/physical_optimize_test.go similarity index 99% rename from internal/dataframe/physical_optimize_test.go rename to internal/dataframe/compiler/physical_optimize_test.go index cae2508..c3023f8 100644 --- a/internal/dataframe/physical_optimize_test.go +++ b/internal/dataframe/compiler/physical_optimize_test.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "strings" diff --git a/internal/dataframe/physical_plan.go b/internal/dataframe/compiler/physical_plan.go similarity index 99% rename from internal/dataframe/physical_plan.go rename to internal/dataframe/compiler/physical_plan.go index 432bf28..3d7b945 100644 --- a/internal/dataframe/physical_plan.go +++ b/internal/dataframe/compiler/physical_plan.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "fmt" diff --git a/internal/dataframe/physical_plan_test.go b/internal/dataframe/compiler/physical_plan_test.go similarity index 99% rename from internal/dataframe/physical_plan_test.go rename to internal/dataframe/compiler/physical_plan_test.go index d177b7b..919febe 100644 --- a/internal/dataframe/physical_plan_test.go +++ b/internal/dataframe/compiler/physical_plan_test.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "strings" diff --git a/internal/dataframe/physical_prefix.go b/internal/dataframe/compiler/physical_prefix.go similarity index 99% rename from internal/dataframe/physical_prefix.go rename to internal/dataframe/compiler/physical_prefix.go index 3c7aa46..6f791e7 100644 --- a/internal/dataframe/physical_prefix.go +++ b/internal/dataframe/compiler/physical_prefix.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "encoding/json" diff --git a/internal/dataframe/physical_render.go b/internal/dataframe/compiler/physical_render.go similarity index 99% rename from internal/dataframe/physical_render.go rename to internal/dataframe/compiler/physical_render.go index 6c9e22d..2297822 100644 --- a/internal/dataframe/physical_render.go +++ b/internal/dataframe/compiler/physical_render.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "fmt" diff --git a/internal/dataframe/physical_render_test.go b/internal/dataframe/compiler/physical_render_test.go similarity index 98% rename from internal/dataframe/physical_render_test.go rename to internal/dataframe/compiler/physical_render_test.go index ca5aa68..270cfc3 100644 --- a/internal/dataframe/physical_render_test.go +++ b/internal/dataframe/compiler/physical_render_test.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "reflect" @@ -35,7 +35,9 @@ func TestRenderPhysicalPlanGenericNavigation(t *testing.T) { " LET root_scope_allowed = @auth_resource_paths_unrestricted == true OR root.auth_resource_path IN @auth_resource_paths", " FILTER root_scope_allowed == @scope_allowed", " LET __loom_physical_set_1 = (", - " FOR node_1, edge_1 IN 1..1 INBOUND root @@traversal_1_edge_collection", + " FOR edge_1 IN @@traversal_1_edge_collection", + " FILTER edge_1._to == root._id", + " LET node_1 = DOCUMENT(edge_1._from)", " FILTER edge_1.label == @traversal_1_label", " FILTER edge_1.from_type == @traversal_1_target_type", " FILTER node_1.resourceType == @traversal_1_target_type", @@ -94,7 +96,7 @@ func TestRenderPhysicalPlanTraversalSetsPreserveRootRowGrain(t *testing.T) { } setOne := strings.Index(rendered.Query, "\n LET __loom_physical_set_1 = (") - firstTraversal := strings.Index(rendered.Query, "\n FOR node_1, edge_1 IN 1..1 INBOUND root @@traversal_1_edge_collection") + firstTraversal := strings.Index(rendered.Query, "\n FOR edge_1 IN @@traversal_1_edge_collection") setTwo := strings.Index(rendered.Query, "\n LET __loom_physical_set_2 = (") parentLoop := strings.Index(rendered.Query, "\n FOR __loom_physical_parent_2 IN __loom_physical_set_1") secondTraversal := strings.Index(rendered.Query, "\n FOR node_2, edge_2 IN 1..1 INBOUND __loom_physical_parent_2 @@traversal_2_edge_collection") diff --git a/internal/dataframe/physical_required_match.go b/internal/dataframe/compiler/physical_required_match.go similarity index 99% rename from internal/dataframe/physical_required_match.go rename to internal/dataframe/compiler/physical_required_match.go index bf4a6af..cdc37e6 100644 --- a/internal/dataframe/physical_required_match.go +++ b/internal/dataframe/compiler/physical_required_match.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "encoding/json" diff --git a/internal/dataframe/physical_required_match_test.go b/internal/dataframe/compiler/physical_required_match_test.go similarity index 99% rename from internal/dataframe/physical_required_match_test.go rename to internal/dataframe/compiler/physical_required_match_test.go index 18e4768..a43ba03 100644 --- a/internal/dataframe/physical_required_match_test.go +++ b/internal/dataframe/compiler/physical_required_match_test.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "strings" diff --git a/internal/dataframe/physical_scope.go b/internal/dataframe/compiler/physical_scope.go similarity index 99% rename from internal/dataframe/physical_scope.go rename to internal/dataframe/compiler/physical_scope.go index 1df138b..da649b8 100644 --- a/internal/dataframe/physical_scope.go +++ b/internal/dataframe/compiler/physical_scope.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import "fmt" diff --git a/internal/dataframe/physical_scope_test.go b/internal/dataframe/compiler/physical_scope_test.go similarity index 99% rename from internal/dataframe/physical_scope_test.go rename to internal/dataframe/compiler/physical_scope_test.go index 06bf18f..246f4a3 100644 --- a/internal/dataframe/physical_scope_test.go +++ b/internal/dataframe/compiler/physical_scope_test.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "strings" diff --git a/internal/dataframe/relationship_match.go b/internal/dataframe/compiler/relationship_match.go similarity index 98% rename from internal/dataframe/relationship_match.go rename to internal/dataframe/compiler/relationship_match.go index 2af286d..4355c1a 100644 --- a/internal/dataframe/relationship_match.go +++ b/internal/dataframe/compiler/relationship_match.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "fmt" diff --git a/internal/dataframe/selection_semantics.go b/internal/dataframe/compiler/selection_semantics.go similarity index 99% rename from internal/dataframe/selection_semantics.go rename to internal/dataframe/compiler/selection_semantics.go index ef67140..e84fad0 100644 --- a/internal/dataframe/selection_semantics.go +++ b/internal/dataframe/compiler/selection_semantics.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "fmt" diff --git a/internal/dataframe/selection_semantics_test.go b/internal/dataframe/compiler/selection_semantics_test.go similarity index 99% rename from internal/dataframe/selection_semantics_test.go rename to internal/dataframe/compiler/selection_semantics_test.go index bf9d629..5396bdb 100644 --- a/internal/dataframe/selection_semantics_test.go +++ b/internal/dataframe/compiler/selection_semantics_test.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import "testing" diff --git a/internal/dataframe/compiler/selector_helpers.go b/internal/dataframe/compiler/selector_helpers.go new file mode 100644 index 0000000..9533844 --- /dev/null +++ b/internal/dataframe/compiler/selector_helpers.go @@ -0,0 +1,32 @@ +package compiler + +import ( + "strings" + + "github.com/calypr/loom/fhirschema" +) + +func selectorSpecFromSelector(sel Selector) fhirschema.FieldSelectorSpec { + sourcePath := "" + valuePath := "" + if len(sel.Steps) > 0 { + last := len(sel.Steps) - 1 + valuePath = selectorStepText(sel.Steps[last]) + if last > 0 { + parts := make([]string, 0, last) + for _, step := range sel.Steps[:last] { + parts = append(parts, selectorStepText(step)) + } + sourcePath = strings.Join(parts, ".") + } + } + var where *fhirschema.FieldPredicateSpec + if sel.Filter != nil { + where = &fhirschema.FieldPredicateSpec{ + Path: sel.Filter.Field, + Op: fhirschema.PredicateContains, + Value: sel.Filter.Needle, + } + } + return fhirschema.FieldSelectorSpec{SourcePath: sourcePath, Where: where, ValuePath: valuePath} +} diff --git a/internal/dataframe/selector_mode_test.go b/internal/dataframe/compiler/selector_mode_test.go similarity index 99% rename from internal/dataframe/selector_mode_test.go rename to internal/dataframe/compiler/selector_mode_test.go index cba6762..80de27e 100644 --- a/internal/dataframe/selector_mode_test.go +++ b/internal/dataframe/compiler/selector_mode_test.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "strings" diff --git a/internal/dataframe/selector_render.go b/internal/dataframe/compiler/selector_render.go similarity index 98% rename from internal/dataframe/selector_render.go rename to internal/dataframe/compiler/selector_render.go index cc8e821..b732ba1 100644 --- a/internal/dataframe/selector_render.go +++ b/internal/dataframe/compiler/selector_render.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "fmt" diff --git a/internal/dataframe/selectors.go b/internal/dataframe/compiler/selectors.go similarity index 98% rename from internal/dataframe/selectors.go rename to internal/dataframe/compiler/selectors.go index 0c70f68..68a5bdd 100644 --- a/internal/dataframe/selectors.go +++ b/internal/dataframe/compiler/selectors.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "encoding/json" diff --git a/internal/dataframe/semantic_plan.go b/internal/dataframe/compiler/semantic_plan.go similarity index 99% rename from internal/dataframe/semantic_plan.go rename to internal/dataframe/compiler/semantic_plan.go index 98f1125..ba0cb3d 100644 --- a/internal/dataframe/semantic_plan.go +++ b/internal/dataframe/compiler/semantic_plan.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "fmt" diff --git a/internal/dataframe/semantic_plan_test.go b/internal/dataframe/compiler/semantic_plan_test.go similarity index 99% rename from internal/dataframe/semantic_plan_test.go rename to internal/dataframe/compiler/semantic_plan_test.go index 5f2eeaa..5d5cce6 100644 --- a/internal/dataframe/semantic_plan_test.go +++ b/internal/dataframe/compiler/semantic_plan_test.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import "testing" diff --git a/internal/dataframe/semantic_validation.go b/internal/dataframe/compiler/semantic_validation.go similarity index 99% rename from internal/dataframe/semantic_validation.go rename to internal/dataframe/compiler/semantic_validation.go index f57ad9a..ef36cea 100644 --- a/internal/dataframe/semantic_validation.go +++ b/internal/dataframe/compiler/semantic_validation.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "fmt" diff --git a/internal/dataframe/semantic_validation_test.go b/internal/dataframe/compiler/semantic_validation_test.go similarity index 99% rename from internal/dataframe/semantic_validation_test.go rename to internal/dataframe/compiler/semantic_validation_test.go index ccfa449..b81870c 100644 --- a/internal/dataframe/semantic_validation_test.go +++ b/internal/dataframe/compiler/semantic_validation_test.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "strings" diff --git a/internal/dataframe/storage_route.go b/internal/dataframe/compiler/storage_route.go similarity index 95% rename from internal/dataframe/storage_route.go rename to internal/dataframe/compiler/storage_route.go index 1540ebd..3a19f90 100644 --- a/internal/dataframe/storage_route.go +++ b/internal/dataframe/compiler/storage_route.go @@ -1,4 +1,4 @@ -package dataframe +package compiler import ( "errors" @@ -25,6 +25,14 @@ type storageRoute struct { Direction PhysicalTraversalDirection } +// StorageRoute exposes the proven physical route contract to diagnostics and +// benchmark tooling without exposing the route resolver's mutable internals. +type StorageRoute = storageRoute + +func ResolveStorageRoute(fromType, label, toType string) (StorageRoute, error) { + return resolveStorageRoute(fromType, label, toType) +} + func (route storageRoute) namedSetDirection() string { return string(route.Direction) } diff --git a/internal/dataframe/traversal_projection_experiment_test.go b/internal/dataframe/compiler/traversal_projection_experiment_test.go similarity index 99% rename from internal/dataframe/traversal_projection_experiment_test.go rename to internal/dataframe/compiler/traversal_projection_experiment_test.go index 4a19071..f70dea6 100644 --- a/internal/dataframe/traversal_projection_experiment_test.go +++ b/internal/dataframe/compiler/traversal_projection_experiment_test.go @@ -1,4 +1,4 @@ -package dataframe +package compiler // This file is deliberately an experiment. It models traversal-time shaping // entirely in the test package by using the existing typed physical renderer: @@ -26,7 +26,7 @@ import ( type traversalProjectionExperimentReport struct { Sets int EligibleSets int - ProjectedFields int + ProjectedFields int PayloadSets int BaselinePayloads int CandidatePayloads int @@ -327,7 +327,7 @@ func buildTraversalProjectionExperiment(plan PhysicalPlan) (PhysicalPlan, traver } for _, name := range []string{"_id", "_key", "id", "resourceType"} { fields = append(fields, PhysicalExpressionProjection{ - Name: name, + Name: name, Expression: PhysicalExpression{Kind: PhysicalValueExpression, Cardinality: PhysicalScalarCardinality, NullBehavior: PhysicalPreserveNull, Value: &PhysicalValue{Variable: target, Path: []string{name}}}, }) } @@ -609,7 +609,7 @@ func rewriteProjectionExpression(expression *PhysicalExpression, setVariable str func loadTraversalProjectionGDCBuilder(t *testing.T) Builder { _, source, _, _ := runtime.Caller(0) - path := filepath.Join(filepath.Dir(source), "..", "..", "conformance", "compiler", "fixtures", "gdc-case-matrix.json") + path := filepath.Join(filepath.Dir(source), "..", "..", "..", "conformance", "compiler", "fixtures", "gdc-case-matrix.json") data, err := os.ReadFile(path) if err != nil { t.Fatalf("read GDC fixture %q: %v", path, err) diff --git a/internal/dataframe/errors.go b/internal/dataframe/errors/errors.go similarity index 99% rename from internal/dataframe/errors.go rename to internal/dataframe/errors/errors.go index 2b1b5f1..ca4368d 100644 --- a/internal/dataframe/errors.go +++ b/internal/dataframe/errors/errors.go @@ -1,4 +1,4 @@ -package dataframe +package dataframeerrors import ( "context" diff --git a/internal/dataframe/errors_test.go b/internal/dataframe/errors/errors_test.go similarity index 99% rename from internal/dataframe/errors_test.go rename to internal/dataframe/errors/errors_test.go index 067a7f0..fbbb19b 100644 --- a/internal/dataframe/errors_test.go +++ b/internal/dataframe/errors/errors_test.go @@ -1,4 +1,4 @@ -package dataframe +package dataframeerrors import ( "context" diff --git a/internal/dataframe/full_identity_tournament_test.go b/internal/dataframe/full_identity_tournament_test.go index 5d7aebb..837c7b7 100644 --- a/internal/dataframe/full_identity_tournament_test.go +++ b/internal/dataframe/full_identity_tournament_test.go @@ -48,6 +48,9 @@ type identityDedupReport struct { // TestIdentityDedupCandidateBuildsActualGDC proves that the candidate is // generated from the actual frontend request and keeps all user values bound. func TestIdentityDedupCandidateBuildsActualGDC(t *testing.T) { + if os.Getenv("LOOM_WP3_IDENTITY_EXPERIMENT") == "" { + t.Skip("set LOOM_WP3_IDENTITY_EXPERIMENT=1 to run the identity-dedup experiment") + } compiled := compileActualGDC(t, 1000) candidate, report, err := buildIdentityDedupCandidate(compiled.Query) if err != nil { diff --git a/internal/dataframe/active_generation.go b/internal/dataframe/runtime/active_generation.go similarity index 98% rename from internal/dataframe/active_generation.go rename to internal/dataframe/runtime/active_generation.go index 9b002ff..94e8005 100644 --- a/internal/dataframe/active_generation.go +++ b/internal/dataframe/runtime/active_generation.go @@ -1,4 +1,4 @@ -package dataframe +package runtime import ( "context" diff --git a/internal/dataframe/active_generation_test.go b/internal/dataframe/runtime/active_generation_test.go similarity index 99% rename from internal/dataframe/active_generation_test.go rename to internal/dataframe/runtime/active_generation_test.go index ab751f8..d9ca712 100644 --- a/internal/dataframe/active_generation_test.go +++ b/internal/dataframe/runtime/active_generation_test.go @@ -1,4 +1,4 @@ -package dataframe +package runtime import ( "context" diff --git a/internal/dataframe/runtime/api.go b/internal/dataframe/runtime/api.go new file mode 100644 index 0000000..80c5f31 --- /dev/null +++ b/internal/dataframe/runtime/api.go @@ -0,0 +1,277 @@ +// Package runtime owns catalog-aware dataframe preparation and execution. +// Compiler contracts are aliased here so the runtime can preserve the +// historical unqualified names internally. +package runtime + +import ( + "github.com/calypr/loom/internal/dataframe/compiler" + dataframeerrors "github.com/calypr/loom/internal/dataframe/errors" +) + +type ( + Builder = compiler.Builder + TraversalStep = compiler.TraversalStep + RepresentativeSlice = compiler.RepresentativeSlice + FieldSelect = compiler.FieldSelect + PivotSelect = compiler.PivotSelect + AggregateSelect = compiler.AggregateSelect + RunRequest = compiler.RunRequest + Result = compiler.Result + QueryDiagnostics = compiler.QueryDiagnostics + StreamResult = compiler.StreamResult + CompiledQuery = compiler.CompiledQuery + SemanticPlan = compiler.SemanticPlan + SemanticNode = compiler.SemanticNode + SemanticField = compiler.SemanticField + SemanticPivot = compiler.SemanticPivot + SemanticAggregate = compiler.SemanticAggregate + SemanticSlice = compiler.SemanticSlice + SemanticPlanExplanation = compiler.SemanticPlanExplanation + SemanticNodeExplanation = compiler.SemanticNodeExplanation + SelectionSemanticSpec = compiler.SelectionSemanticSpec + RowGrain = compiler.RowGrain + ProjectionMode = compiler.ProjectionMode + Cardinality = compiler.Cardinality + RowIdentity = compiler.RowIdentity + TraversalMatchMode = compiler.TraversalMatchMode + FilterOperator = compiler.FilterOperator + FilterValueKind = compiler.FilterValueKind + ArrayQuantifier = compiler.ArrayQuantifier + CodeValue = compiler.CodeValue + FilterValue = compiler.FilterValue + TypedFilter = compiler.TypedFilter + Selector = compiler.Selector + SelectorStep = compiler.SelectorStep + ContainsFilter = compiler.ContainsFilter + PhysicalOptimizationPolicy = compiler.PhysicalOptimizationPolicy + PhysicalOptimizationRule = compiler.PhysicalOptimizationRule + PhysicalOptimizationDecision = compiler.PhysicalOptimizationDecision + PhysicalOptimizationReport = compiler.PhysicalOptimizationReport + PhysicalOptimizationRuleState = compiler.PhysicalOptimizationRuleState + CompilerPlanDiagnostics = compiler.CompilerPlanDiagnostics + PhysicalTraversalDecision = compiler.PhysicalTraversalDecision + RichSourceReuse = compiler.RichSourceReuse + RichConsumerGroup = compiler.RichConsumerGroup + RenderedPhysicalPlan = compiler.RenderedPhysicalPlan + PhysicalTraversalPrefix = compiler.PhysicalTraversalPrefix + PhysicalTraversalSubset = compiler.PhysicalTraversalSubset + PhysicalTraversalPrefixDecomposition = compiler.PhysicalTraversalPrefixDecomposition + PhysicalTraversalPrefixRejectionReason = compiler.PhysicalTraversalPrefixRejectionReason + PhysicalTraversalPrefixError = compiler.PhysicalTraversalPrefixError + PhysicalPlan = compiler.PhysicalPlan + PhysicalSource = compiler.PhysicalSource + PhysicalOperationKind = compiler.PhysicalOperationKind + PhysicalOperation = compiler.PhysicalOperation + PhysicalRootScan = compiler.PhysicalRootScan + PhysicalTraversalDirection = compiler.PhysicalTraversalDirection + PhysicalTraversalStrategy = compiler.PhysicalTraversalStrategy + PhysicalTraversal = compiler.PhysicalTraversal + PhysicalValue = compiler.PhysicalValue + PhysicalCardinality = compiler.PhysicalCardinality + PhysicalNullBehavior = compiler.PhysicalNullBehavior + PhysicalExpressionKind = compiler.PhysicalExpressionKind + PhysicalSelectorExecutionMode = compiler.PhysicalSelectorExecutionMode + PhysicalExpression = compiler.PhysicalExpression + PhysicalExtract = compiler.PhysicalExtract + PhysicalPreparedReference = compiler.PhysicalPreparedReference + PhysicalPreparedSet = compiler.PhysicalPreparedSet + PhysicalPreparedField = compiler.PhysicalPreparedField + PhysicalAggregateOperation = compiler.PhysicalAggregateOperation + PhysicalAggregate = compiler.PhysicalAggregate + PhysicalPivotMap = compiler.PhysicalPivotMap + PhysicalSlice = compiler.PhysicalSlice + PhysicalExpressionProjection = compiler.PhysicalExpressionProjection + PhysicalObject = compiler.PhysicalObject + PhysicalSet = compiler.PhysicalSet + PhysicalSetProjection = compiler.PhysicalSetProjection + PhysicalSetProjectionField = compiler.PhysicalSetProjectionField + PhysicalSetOutputField = compiler.PhysicalSetOutputField + PhysicalSetOutput = compiler.PhysicalSetOutput + PhysicalSubplan = compiler.PhysicalSubplan + PhysicalPredicate = compiler.PhysicalPredicate + PhysicalPredicateKind = compiler.PhysicalPredicateKind + PhysicalPredicateExpression = compiler.PhysicalPredicateExpression + PhysicalFilter = compiler.PhysicalFilter + PhysicalDerivedLet = compiler.PhysicalDerivedLet + PhysicalSort = compiler.PhysicalSort + PhysicalLimit = compiler.PhysicalLimit + PhysicalProjection = compiler.PhysicalProjection + PhysicalReturn = compiler.PhysicalReturn + StorageRoute = compiler.StorageRoute + ErrorCode = dataframeerrors.ErrorCode + UserError = dataframeerrors.UserError + Error = dataframeerrors.Error + ErrorOption = dataframeerrors.ErrorOption +) + +const ( + MaxSemanticTraversalDepth = compiler.MaxSemanticTraversalDepth + RowGrainResource = compiler.RowGrainResource + RowGrainPatient = compiler.RowGrainPatient + RowGrainSpecimen = compiler.RowGrainSpecimen + RowGrainFile = compiler.RowGrainFile + RowGrainDiagnosis = compiler.RowGrainDiagnosis + RowGrainObservation = compiler.RowGrainObservation + RowGrainStudyEnrollment = compiler.RowGrainStudyEnrollment + ProjectionScalar = compiler.ProjectionScalar + ProjectionFirst = compiler.ProjectionFirst + ProjectionArray = compiler.ProjectionArray + ProjectionDistinctArray = compiler.ProjectionDistinctArray + ProjectionAggregate = compiler.ProjectionAggregate + ProjectionPivot = compiler.ProjectionPivot + ProjectionExplode = compiler.ProjectionExplode + CardinalityRequiredOne = compiler.CardinalityRequiredOne + CardinalityOptionalOne = compiler.CardinalityOptionalOne + CardinalityMany = compiler.CardinalityMany + CardinalityUnknownObservedMany = compiler.CardinalityUnknownObservedMany + TraversalMatchOptional = compiler.TraversalMatchOptional + TraversalMatchRequired = compiler.TraversalMatchRequired + FilterEquals = compiler.FilterEquals + FilterNotEquals = compiler.FilterNotEquals + FilterIn = compiler.FilterIn + FilterExists = compiler.FilterExists + FilterMissing = compiler.FilterMissing + FilterContains = compiler.FilterContains + FilterGreaterThan = compiler.FilterGreaterThan + FilterGreaterEq = compiler.FilterGreaterEq + FilterLessThan = compiler.FilterLessThan + FilterLessEq = compiler.FilterLessEq + FilterString = compiler.FilterString + FilterCode = compiler.FilterCode + FilterBoolean = compiler.FilterBoolean + FilterInteger = compiler.FilterInteger + FilterDecimal = compiler.FilterDecimal + FilterDate = compiler.FilterDate + FilterDateTime = compiler.FilterDateTime + QuantifierAny = compiler.QuantifierAny + QuantifierAll = compiler.QuantifierAll + QuantifierNone = compiler.QuantifierNone + PhysicalTraversalNative = compiler.PhysicalTraversalNative + PhysicalTraversalEndpointLookup = compiler.PhysicalTraversalEndpointLookup + PhysicalOutbound = compiler.PhysicalOutbound + PhysicalInbound = compiler.PhysicalInbound + PhysicalAny = compiler.PhysicalAny + PhysicalRootScanOp = compiler.PhysicalRootScanOp + PhysicalTraversalOp = compiler.PhysicalTraversalOp + PhysicalFilterOp = compiler.PhysicalFilterOp + PhysicalDerivedLetOp = compiler.PhysicalDerivedLetOp + PhysicalSetOp = compiler.PhysicalSetOp + PhysicalSortOp = compiler.PhysicalSortOp + PhysicalLimitOp = compiler.PhysicalLimitOp + PhysicalReturnOp = compiler.PhysicalReturnOp + PhysicalScalarCardinality = compiler.PhysicalScalarCardinality + PhysicalArrayCardinality = compiler.PhysicalArrayCardinality + PhysicalObjectCardinality = compiler.PhysicalObjectCardinality + PhysicalPreserveNull = compiler.PhysicalPreserveNull + PhysicalOmitNulls = compiler.PhysicalOmitNulls + PhysicalEmptyOnNull = compiler.PhysicalEmptyOnNull + PhysicalValueExpression = compiler.PhysicalValueExpression + PhysicalExtractExpression = compiler.PhysicalExtractExpression + PhysicalAggregateExpression = compiler.PhysicalAggregateExpression + PhysicalPivotExpression = compiler.PhysicalPivotExpression + PhysicalSliceExpression = compiler.PhysicalSliceExpression + PhysicalObjectExpression = compiler.PhysicalObjectExpression + PhysicalSelectorGeneric = compiler.PhysicalSelectorGeneric + PhysicalSelectorDirectScalar = compiler.PhysicalSelectorDirectScalar + PhysicalSelectorConditionalArray = compiler.PhysicalSelectorConditionalArray + PhysicalCountAggregate = compiler.PhysicalCountAggregate + PhysicalCountDistinctAggregate = compiler.PhysicalCountDistinctAggregate + PhysicalExistsAggregate = compiler.PhysicalExistsAggregate + PhysicalDistinctValuesAggregate = compiler.PhysicalDistinctValuesAggregate + PhysicalMinAggregate = compiler.PhysicalMinAggregate + PhysicalMaxAggregate = compiler.PhysicalMaxAggregate + PhysicalFirstAggregate = compiler.PhysicalFirstAggregate + PhysicalSetGraphIDField = compiler.PhysicalSetGraphIDField + PhysicalSetKeyField = compiler.PhysicalSetKeyField + PhysicalSetIDField = compiler.PhysicalSetIDField + PhysicalSetResourceTypeField = compiler.PhysicalSetResourceTypeField + PhysicalSetPayloadField = compiler.PhysicalSetPayloadField + PhysicalComparisonPredicate = compiler.PhysicalComparisonPredicate + PhysicalAllPredicate = compiler.PhysicalAllPredicate + PhysicalAnyPredicate = compiler.PhysicalAnyPredicate + PhysicalNotPredicate = compiler.PhysicalNotPredicate + PhysicalExistsPredicate = compiler.PhysicalExistsPredicate + PhysicalPrefixNotOptionalSet = compiler.PhysicalPrefixNotOptionalSet + PhysicalPrefixSharedSubset = compiler.PhysicalPrefixSharedSubset + PhysicalPrefixInvalidCapture = compiler.PhysicalPrefixInvalidCapture + PhysicalPrefixMissingTraversal = compiler.PhysicalPrefixMissingTraversal + PhysicalPrefixUnsupportedDirection = compiler.PhysicalPrefixUnsupportedDirection + PhysicalPrefixInvalidRoute = compiler.PhysicalPrefixInvalidRoute + PhysicalPrefixInvalidScope = compiler.PhysicalPrefixInvalidScope + PhysicalPrefixInvalidTarget = compiler.PhysicalPrefixInvalidTarget + PhysicalOptimizationRuleTraversalSharing = compiler.PhysicalOptimizationRuleTraversalSharing + PhysicalOptimizationRulePreparedSelectors = compiler.PhysicalOptimizationRulePreparedSelectors + PhysicalOptimizationRuleNestedSharing = compiler.PhysicalOptimizationRuleNestedSharing + PhysicalOptimizationRuleRichConsumerFusion = compiler.PhysicalOptimizationRuleRichConsumerFusion + PhysicalOptimizationRuleCompactProjection = compiler.PhysicalOptimizationRuleCompactProjection + PhysicalOptimizationRuleEndpointTraversal = compiler.PhysicalOptimizationRuleEndpointTraversal + OptimizerRuleFilterPushdown = compiler.OptimizerRuleFilterPushdown + OptimizerRuleTraversalSharing = compiler.OptimizerRuleTraversalSharing + OptimizerRuleRelationshipSemiJoin = compiler.OptimizerRuleRelationshipSemiJoin + CodeProjectRequired = dataframeerrors.CodeProjectRequired + CodeRootResourceTypeRequired = dataframeerrors.CodeRootResourceTypeRequired + CodeUnauthorizedProject = dataframeerrors.CodeUnauthorizedProject + CodeUnknownField = dataframeerrors.CodeUnknownField + CodeFieldNotPopulated = dataframeerrors.CodeFieldNotPopulated + CodeInvalidTraversal = dataframeerrors.CodeInvalidTraversal + CodeUnsafeTraversalRoute = dataframeerrors.CodeUnsafeTraversalRoute + CodeInvalidFilter = dataframeerrors.CodeInvalidFilter + CodeUnboundedPivot = dataframeerrors.CodeUnboundedPivot + CodeInvalidPivotColumn = dataframeerrors.CodeInvalidPivotColumn + CodeInvalidSlice = dataframeerrors.CodeInvalidSlice + CodePlanTooExpensive = dataframeerrors.CodePlanTooExpensive + CodeInvalidCursor = dataframeerrors.CodeInvalidCursor + CodeStaleCursor = dataframeerrors.CodeStaleCursor + CodeDatasetGenerationChanged = dataframeerrors.CodeDatasetGenerationChanged + CodeUnsupportedExportFormat = dataframeerrors.CodeUnsupportedExportFormat + CodeClientCanceled = dataframeerrors.CodeClientCanceled + CodeBackendUnavailable = dataframeerrors.CodeBackendUnavailable + CodeInternalError = dataframeerrors.CodeInternalError +) + +var ( + DefaultPhysicalOptimizationPolicy = compiler.DefaultPhysicalOptimizationPolicy + CompileRequest = compiler.CompileRequest + CompileRequestWithPolicy = compiler.CompileRequestWithPolicy + BuildSemanticPlan = compiler.BuildSemanticPlan + ValidateSemanticGraph = compiler.ValidateSemanticGraph + BuildPhysicalPlan = compiler.BuildPhysicalPlan + BuildPhysicalPlanWithPolicy = compiler.BuildPhysicalPlanWithPolicy + BuildGenericPhysicalPlan = compiler.BuildGenericPhysicalPlan + BuildGenericPhysicalPlanWithPolicy = compiler.BuildGenericPhysicalPlanWithPolicy + OptimizePhysicalPlan = compiler.OptimizePhysicalPlan + OptimizePhysicalPlanWithPolicy = compiler.OptimizePhysicalPlanWithPolicy + RenderPhysicalPlan = compiler.RenderPhysicalPlan + ParseSelector = compiler.ParseSelector + ValidateTypedFilterForResource = compiler.ValidateTypedFilterForResource + NormalizeSelectionPlan = compiler.NormalizeSelectionPlan + ResolveSemanticField = compiler.ResolveSemanticField + InferRowGrain = compiler.InferRowGrain + RootResourceForGrain = compiler.RootResourceForGrain + ValidateRootGrain = compiler.ValidateRootGrain + DefaultRowIdentity = compiler.DefaultRowIdentity + ValidateProjection = compiler.ValidateProjection + OperatorSupportsKind = compiler.OperatorSupportsKind + ValidateGenericPhysicalPlanScope = compiler.ValidateGenericPhysicalPlanScope + DecomposePhysicalTraversalPrefix = compiler.DecomposePhysicalTraversalPrefix + ResolveStorageRoute = compiler.ResolveStorageRoute + AsUserError = dataframeerrors.AsUserError + Normalize = dataframeerrors.Normalize + PublicMessage = dataframeerrors.PublicMessage + NewError = dataframeerrors.NewError + Wrap = dataframeerrors.Wrap + WithFieldPath = dataframeerrors.WithFieldPath + WithDetails = dataframeerrors.WithDetails + WithRetryable = dataframeerrors.WithRetryable + WithCause = dataframeerrors.WithCause + IsUserCorrectable = dataframeerrors.IsUserCorrectable + IsRetryableCode = dataframeerrors.IsRetryableCode + IsOperatorFailure = dataframeerrors.IsOperatorFailure + Errorf = dataframeerrors.Errorf +) + +var ( + AllErrorCodes = dataframeerrors.AllErrorCodes + ErrBackendUnavailable = dataframeerrors.ErrBackendUnavailable + ErrClientCanceled = dataframeerrors.ErrClientCanceled +) diff --git a/internal/dataframe/auth.go b/internal/dataframe/runtime/auth.go similarity index 99% rename from internal/dataframe/auth.go rename to internal/dataframe/runtime/auth.go index f3c791c..5d7ee85 100644 --- a/internal/dataframe/auth.go +++ b/internal/dataframe/runtime/auth.go @@ -1,4 +1,4 @@ -package dataframe +package runtime import ( "context" diff --git a/internal/dataframe/runtime/auth_scope.go b/internal/dataframe/runtime/auth_scope.go new file mode 100644 index 0000000..83f3467 --- /dev/null +++ b/internal/dataframe/runtime/auth_scope.go @@ -0,0 +1,20 @@ +package runtime + +import ( + "github.com/calypr/loom/internal/authscope" +) + +// builderAuthScopeUnrestricted preserves the historical runtime preparation +// contract while the compiler-owned semantic scope helper lives in compiler. +func builderAuthScopeUnrestricted(builder Builder) bool { + switch builder.AuthScopeMode { + case authscope.ReadScopeUnrestricted: + return true + case authscope.ReadScopeRestricted: + return false + case "": + return len(builder.AuthResourcePaths) == 0 + default: + return false + } +} diff --git a/internal/dataframe/auth_scope_test.go b/internal/dataframe/runtime/auth_scope_test.go similarity index 99% rename from internal/dataframe/auth_scope_test.go rename to internal/dataframe/runtime/auth_scope_test.go index 83c91d4..971f0aa 100644 --- a/internal/dataframe/auth_scope_test.go +++ b/internal/dataframe/runtime/auth_scope_test.go @@ -1,4 +1,4 @@ -package dataframe +package runtime import ( "context" diff --git a/internal/dataframe/execution.go b/internal/dataframe/runtime/execution.go similarity index 99% rename from internal/dataframe/execution.go rename to internal/dataframe/runtime/execution.go index a8eecc1..1ab629f 100644 --- a/internal/dataframe/execution.go +++ b/internal/dataframe/runtime/execution.go @@ -1,4 +1,4 @@ -package dataframe +package runtime import ( "context" diff --git a/internal/dataframe/execution_test.go b/internal/dataframe/runtime/execution_test.go similarity index 99% rename from internal/dataframe/execution_test.go rename to internal/dataframe/runtime/execution_test.go index e42ae90..2260b0f 100644 --- a/internal/dataframe/execution_test.go +++ b/internal/dataframe/runtime/execution_test.go @@ -1,4 +1,4 @@ -package dataframe +package runtime import ( "context" diff --git a/internal/dataframe/explain.go b/internal/dataframe/runtime/explain.go similarity index 97% rename from internal/dataframe/explain.go rename to internal/dataframe/runtime/explain.go index aba4b5c..b7ad112 100644 --- a/internal/dataframe/explain.go +++ b/internal/dataframe/runtime/explain.go @@ -1,4 +1,4 @@ -package dataframe +package runtime import ( "context" diff --git a/internal/dataframe/explain_test.go b/internal/dataframe/runtime/explain_test.go similarity index 96% rename from internal/dataframe/explain_test.go rename to internal/dataframe/runtime/explain_test.go index 993d904..e78f082 100644 --- a/internal/dataframe/explain_test.go +++ b/internal/dataframe/runtime/explain_test.go @@ -1,4 +1,4 @@ -package dataframe +package runtime import ( "context" diff --git a/internal/dataframe/pivots.go b/internal/dataframe/runtime/pivots.go similarity index 99% rename from internal/dataframe/pivots.go rename to internal/dataframe/runtime/pivots.go index 84daf88..4a7e8eb 100644 --- a/internal/dataframe/pivots.go +++ b/internal/dataframe/runtime/pivots.go @@ -1,4 +1,4 @@ -package dataframe +package runtime import ( "context" diff --git a/internal/dataframe/pivots_test.go b/internal/dataframe/runtime/pivots_test.go similarity index 98% rename from internal/dataframe/pivots_test.go rename to internal/dataframe/runtime/pivots_test.go index 85e8bcc..78b44bf 100644 --- a/internal/dataframe/pivots_test.go +++ b/internal/dataframe/runtime/pivots_test.go @@ -1,4 +1,4 @@ -package dataframe +package runtime import ( "reflect" diff --git a/internal/dataframe/profile.go b/internal/dataframe/runtime/profile.go similarity index 97% rename from internal/dataframe/profile.go rename to internal/dataframe/runtime/profile.go index ebec6a5..388568b 100644 --- a/internal/dataframe/profile.go +++ b/internal/dataframe/runtime/profile.go @@ -1,4 +1,4 @@ -package dataframe +package runtime import ( "context" diff --git a/internal/dataframe/query_runtime.go b/internal/dataframe/runtime/query_runtime.go similarity index 97% rename from internal/dataframe/query_runtime.go rename to internal/dataframe/runtime/query_runtime.go index eccfe4a..2fe7952 100644 --- a/internal/dataframe/query_runtime.go +++ b/internal/dataframe/runtime/query_runtime.go @@ -1,4 +1,4 @@ -package dataframe +package runtime import ( "context" diff --git a/internal/dataframe/runtime/runtime_helpers.go b/internal/dataframe/runtime/runtime_helpers.go new file mode 100644 index 0000000..00633f0 --- /dev/null +++ b/internal/dataframe/runtime/runtime_helpers.go @@ -0,0 +1,78 @@ +package runtime + +import ( + "fmt" + "strings" +) + +func cloneStrings(in []string) []string { + if in == nil { + return nil + } + return append([]string(nil), in...) +} + +func normalizeDatasetGeneration(generation string) string { + return strings.TrimSpace(generation) +} + +func selectorStepText(step SelectorStep) string { + switch { + case step.Iterate: + return step.Field + "[]" + case step.Index != nil: + return fmt.Sprintf("%s[%d]", step.Field, *step.Index) + default: + return step.Field + } +} + +func aggregateOperationRequiresSelector(operation string) bool { + switch strings.ToUpper(strings.TrimSpace(operation)) { + case "COUNT_DISTINCT", "EXISTS", "DISTINCT_VALUES", "MIN", "MAX": + return true + default: + return false + } +} + +func sanitizeColumnName(in string) string { + var b strings.Builder + for _, r := range in { + switch { + case r >= 'a' && r <= 'z', r >= 'A' && r <= 'Z', r >= '0' && r <= '9': + b.WriteRune(r) + default: + b.WriteByte('_') + } + } + return strings.Trim(b.String(), "_") +} + +const ( + datasetGenerationBindKey = "dataset_generation" + datasetGenerationField = "dataset_generation" +) + +func cloneRowIdentity(in *RowIdentity) *RowIdentity { + if in == nil { + return nil + } + out := *in + out.Fields = cloneStrings(in.Fields) + return &out +} + +func isDatasetGenerationScopePredicate(predicate PhysicalPredicate, variable string) bool { + return predicate.Operator == "EQUALS" && + predicate.Left.Variable == variable && + len(predicate.Left.Path) == 1 && predicate.Left.Path[0] == "dataset_generation" && + predicate.Right != nil && predicate.Right.BindKey == "dataset_generation" && + predicate.Right.Variable == "" && len(predicate.Right.Path) == 0 +} + +type storageRoute = StorageRoute + +func resolveStorageRoute(fromType, label, toType string) (storageRoute, error) { + return ResolveStorageRoute(fromType, label, toType) +} diff --git a/internal/dataframe/service.go b/internal/dataframe/runtime/service.go similarity index 99% rename from internal/dataframe/service.go rename to internal/dataframe/runtime/service.go index 1d49106..08fe54e 100644 --- a/internal/dataframe/service.go +++ b/internal/dataframe/runtime/service.go @@ -1,4 +1,4 @@ -package dataframe +package runtime import ( "context" diff --git a/internal/dataframe/validation.go b/internal/dataframe/runtime/validation.go similarity index 99% rename from internal/dataframe/validation.go rename to internal/dataframe/runtime/validation.go index f6406c8..9df8d9e 100644 --- a/internal/dataframe/validation.go +++ b/internal/dataframe/runtime/validation.go @@ -1,4 +1,4 @@ -package dataframe +package runtime import ( "context" diff --git a/internal/dataframe/validation_service.go b/internal/dataframe/runtime/validation_service.go similarity index 99% rename from internal/dataframe/validation_service.go rename to internal/dataframe/runtime/validation_service.go index da3b291..719c65c 100644 --- a/internal/dataframe/validation_service.go +++ b/internal/dataframe/runtime/validation_service.go @@ -1,4 +1,4 @@ -package dataframe +package runtime import ( "context" diff --git a/internal/dataframe/validation_service_test.go b/internal/dataframe/runtime/validation_service_test.go similarity index 99% rename from internal/dataframe/validation_service_test.go rename to internal/dataframe/runtime/validation_service_test.go index 7426014..0ae240d 100644 --- a/internal/dataframe/validation_service_test.go +++ b/internal/dataframe/runtime/validation_service_test.go @@ -1,4 +1,4 @@ -package dataframe +package runtime import ( "context" From d16dbaa48c502681f01993663f6cca382774e0c7 Mon Sep 17 00:00:00 2001 From: matthewpeterkort Date: Mon, 13 Jul 2026 10:52:29 -0700 Subject: [PATCH 07/15] reorg dataframe package to be better organized --- .dockerignore | 8 + .github/workflows/build.yaml | 43 +- .github/workflows/tests.yaml | 11 +- Dockerfile | 14 +- Makefile | 9 +- README.md | 58 +- cmd/arango-fhir-proto/main.go | 93 + cmd/arango-fhir-server/main.go | 26 + docs/AQL_EXECUTION_IMPLEMENTATION_AUDIT.md | 242 -- docs/AQL_OPTIMIZATION_WORKLIST.md | 582 ---- docs/COMPILER_PERFORMANCE.md | 75 + docs/DATAFRAME_PACKAGE_REORGANIZATION_PLAN.md | 469 +++ ...ATAFRAME_PACKAGE_REORGANIZATION_ROUND_2.md | 414 +++ docs/DEVELOPER_ARCHITECTURE.md | 39 +- docs/LUNA_AQL_EXECUTION_ROUND_3.md | 683 ---- docs/LUNA_AQL_OPTIMIZATION_ROUND_2.md | 342 -- docs/LUNA_AQL_RUNTIME_ROUND_4.md | 676 ---- docs/benchmarks/AQL_PROFILE_CORPUS.md | 37 - go.mod | 26 +- go.sum | 89 +- graphqlapi/dataframe/service.go | 128 + graphqlapi/generated.go | 3010 ++++++++++++++--- graphqlapi/materialization_output.go | 37 + graphqlapi/model/models.go | 109 + graphqlapi/schema.graphqls | 75 + graphqlapi/schema.resolvers.go | 45 + internal/dataframe/api.go | 540 +-- .../compact_batch_tournament_test.go | 205 -- .../compact_summary_experiment_test.go | 325 -- .../dataframe/compat_test_helpers_test.go | 4 +- internal/dataframe/compiler/api.go | 6 + .../compiler/arango_test_helpers_test.go | 19 - internal/dataframe/compiler/clone_helpers.go | 17 + .../{physical_helpers.go => ir/clone.go} | 37 +- .../dataframe/compiler/ir/clone_values.go | 29 + .../compiler/{ => ir}/dataset_generation.go | 7 +- .../diagnostics.go} | 6 +- internal/dataframe/compiler/ir/doc.go | 3 + internal/dataframe/compiler/ir/navigation.go | 121 + .../compiler/{physical_plan.go => ir/plan.go} | 6 +- .../{physical_cost.go => ir/policy.go} | 22 +- .../{physical_prefix.go => ir/prefix.go} | 2 +- .../{physical_scope.go => ir/scope.go} | 6 +- .../dataframe/compiler/ir/selector_helpers.go | 19 + .../dataframe/compiler/ir/spec_aliases.go | 12 + internal/dataframe/compiler/ir/value.go | 7 + internal/dataframe/compiler/ir_helpers.go | 28 + internal/dataframe/compiler/lower/aliases.go | 133 + .../compiler/{ => lower}/auth_scope.go | 2 +- internal/dataframe/compiler/lower/doc.go | 4 + .../compiler/lower/filter_literal.go | 31 + .../generic_plan.go} | 6 +- internal/dataframe/compiler/lower/helpers.go | 69 + .../lowering.go} | 2 +- .../required_match.go} | 4 +- internal/dataframe/compiler/lower/shape.go | 14 + .../compiler/{ => lower}/storage_route.go | 2 +- internal/dataframe/compiler/lower_aliases.go | 14 + .../dataframe/compiler/lowering_helpers.go | 16 + .../compiler/optimization_helpers.go | 10 + .../dataframe/compiler/optimize/aliases.go | 100 + internal/dataframe/compiler/optimize/doc.go | 3 + .../optimize.go} | 12 +- .../dataframe/compiler/optimize_aliases.go | 16 + .../{physical_execution.go => output.go} | 2 +- .../dataframe/compiler/physical_aliases.go | 135 + .../compiler/physical_clone_aliases.go | 23 + .../compiler/physical_scope_compat.go | 23 + .../compiler/physical_scope_constants.go | 14 + .../dataframe/compiler/render/aql/aliases.go | 120 + internal/dataframe/compiler/render/aql/doc.go | 3 + .../{ => render/aql}/filter_literal.go | 2 +- .../aql/render.go} | 6 +- .../aql/selector.go} | 13 +- internal/dataframe/compiler/render_aliases.go | 7 + .../dataframe/compiler/render_test_compat.go | 7 + .../dataframe/compiler/selector_helpers.go | 25 + .../compiler/selector_identity_compat.go | 24 + internal/dataframe/compiler/selector_mode.go | 50 + .../dataframe/compiler/semantic_aliases.go | 24 + internal/dataframe/compiler/spec_aliases.go | 83 + .../traversal_projection_experiment_test.go | 629 ---- internal/dataframe/doc.go | 7 + ...endpoint_selector_combo_experiment_test.go | 376 -- .../endpoint_strategy_experiment_test.go | 642 ---- .../endpoint_strategy_integration_test.go | 172 - .../dataframe/full_batch_tournament_test.go | 265 -- .../full_identity_tournament_test.go | 266 -- .../identity_order_experiment_test.go | 308 -- .../materialization/arango/registry.go | 93 + .../materialization/integration_test.go | 81 + internal/dataframe/materialization/read.go | 361 ++ .../dataframe/materialization/read_test.go | 31 + internal/dataframe/materialization/schema.go | 99 + internal/dataframe/materialization/service.go | 304 ++ .../dataframe/materialization/service_test.go | 203 ++ internal/dataframe/materialization/types.go | 49 + .../materialization_tournament_test.go | 201 -- .../root_endpoint_experiment_test.go | 274 -- .../dataframe/root_endpoint_live_gate_test.go | 214 -- ...root_endpoint_strategy_integration_test.go | 68 - .../runtime/{auth.go => authorization.go} | 0 .../{validation.go => catalog_validation.go} | 0 .../runtime/{api.go => compatibility.go} | 10 +- .../runtime/{query_runtime.go => cursor.go} | 0 .../{execution.go => execution_service.go} | 0 .../{runtime_helpers.go => helpers.go} | 0 .../{pivots.go => pivot_materialization.go} | 0 ...ve_generation.go => prepare_generation.go} | 0 ...ation_service.go => request_validation.go} | 0 .../runtime/{auth_scope.go => scope.go} | 0 internal/dataframe/runtime/types.go | 43 + .../selector_expression_experiment_test.go | 665 ---- internal/dataframe/semantic/doc.go | 3 + .../selection_semantics.go | 61 +- internal/dataframe/semantic/selector_spec.go | 40 + .../{compiler => semantic}/semantic_plan.go | 14 +- .../semantic_validation.go | 6 +- internal/dataframe/semantic/spec_aliases.go | 39 + .../{compiler => spec}/builder_types.go | 56 +- internal/dataframe/spec/doc.go | 4 + .../dataframe/{compiler => spec}/filter.go | 2 +- .../{compiler => spec}/filter_semantics.go | 2 +- .../dataframe/{compiler => spec}/grain.go | 2 +- .../{compiler => spec}/relationship_match.go | 6 +- .../dataframe/spec/selector_validation.go | 46 + .../dataframe/{compiler => spec}/selectors.go | 2 +- .../summary_pushdown_experiment_test.go | 262 -- internal/dataframe/tournament_pivot_test.go | 409 --- .../dataframe/tournament_sort_order_test.go | 192 -- internal/graphstore/documents.go | 128 + internal/ingest/bench_test.go | 4 +- internal/ingest/generated_load.go | 2 +- internal/ingest/parity_test.go | 2 +- internal/ingest/row_builder.go | 25 +- internal/store/clickhouse/client.go | 272 ++ internal/store/clickhouse/client_test.go | 33 + internal/store/clickhouse/integration_test.go | 58 + 138 files changed, 7811 insertions(+), 8980 deletions(-) delete mode 100644 docs/AQL_EXECUTION_IMPLEMENTATION_AUDIT.md delete mode 100644 docs/AQL_OPTIMIZATION_WORKLIST.md create mode 100644 docs/COMPILER_PERFORMANCE.md create mode 100644 docs/DATAFRAME_PACKAGE_REORGANIZATION_PLAN.md create mode 100644 docs/DATAFRAME_PACKAGE_REORGANIZATION_ROUND_2.md delete mode 100644 docs/LUNA_AQL_EXECUTION_ROUND_3.md delete mode 100644 docs/LUNA_AQL_OPTIMIZATION_ROUND_2.md delete mode 100644 docs/LUNA_AQL_RUNTIME_ROUND_4.md delete mode 100644 docs/benchmarks/AQL_PROFILE_CORPUS.md create mode 100644 graphqlapi/materialization_output.go delete mode 100644 internal/dataframe/compact_batch_tournament_test.go delete mode 100644 internal/dataframe/compact_summary_experiment_test.go create mode 100644 internal/dataframe/compiler/api.go delete mode 100644 internal/dataframe/compiler/arango_test_helpers_test.go create mode 100644 internal/dataframe/compiler/clone_helpers.go rename internal/dataframe/compiler/{physical_helpers.go => ir/clone.go} (88%) create mode 100644 internal/dataframe/compiler/ir/clone_values.go rename internal/dataframe/compiler/{ => ir}/dataset_generation.go (74%) rename internal/dataframe/compiler/{physical_diagnostics.go => ir/diagnostics.go} (98%) create mode 100644 internal/dataframe/compiler/ir/doc.go create mode 100644 internal/dataframe/compiler/ir/navigation.go rename internal/dataframe/compiler/{physical_plan.go => ir/plan.go} (99%) rename internal/dataframe/compiler/{physical_cost.go => ir/policy.go} (93%) rename internal/dataframe/compiler/{physical_prefix.go => ir/prefix.go} (99%) rename internal/dataframe/compiler/{physical_scope.go => ir/scope.go} (98%) create mode 100644 internal/dataframe/compiler/ir/selector_helpers.go create mode 100644 internal/dataframe/compiler/ir/spec_aliases.go create mode 100644 internal/dataframe/compiler/ir/value.go create mode 100644 internal/dataframe/compiler/ir_helpers.go create mode 100644 internal/dataframe/compiler/lower/aliases.go rename internal/dataframe/compiler/{ => lower}/auth_scope.go (98%) create mode 100644 internal/dataframe/compiler/lower/doc.go create mode 100644 internal/dataframe/compiler/lower/filter_literal.go rename internal/dataframe/compiler/{generic_physical_plan.go => lower/generic_plan.go} (99%) create mode 100644 internal/dataframe/compiler/lower/helpers.go rename internal/dataframe/compiler/{physical_lowering.go => lower/lowering.go} (98%) rename internal/dataframe/compiler/{physical_required_match.go => lower/required_match.go} (99%) create mode 100644 internal/dataframe/compiler/lower/shape.go rename internal/dataframe/compiler/{ => lower}/storage_route.go (99%) create mode 100644 internal/dataframe/compiler/lower_aliases.go create mode 100644 internal/dataframe/compiler/lowering_helpers.go create mode 100644 internal/dataframe/compiler/optimization_helpers.go create mode 100644 internal/dataframe/compiler/optimize/aliases.go create mode 100644 internal/dataframe/compiler/optimize/doc.go rename internal/dataframe/compiler/{physical_optimize.go => optimize/optimize.go} (98%) create mode 100644 internal/dataframe/compiler/optimize_aliases.go rename internal/dataframe/compiler/{physical_execution.go => output.go} (99%) create mode 100644 internal/dataframe/compiler/physical_aliases.go create mode 100644 internal/dataframe/compiler/physical_clone_aliases.go create mode 100644 internal/dataframe/compiler/physical_scope_compat.go create mode 100644 internal/dataframe/compiler/physical_scope_constants.go create mode 100644 internal/dataframe/compiler/render/aql/aliases.go create mode 100644 internal/dataframe/compiler/render/aql/doc.go rename internal/dataframe/compiler/{ => render/aql}/filter_literal.go (98%) rename internal/dataframe/compiler/{physical_render.go => render/aql/render.go} (99%) rename internal/dataframe/compiler/{selector_render.go => render/aql/selector.go} (83%) create mode 100644 internal/dataframe/compiler/render_aliases.go create mode 100644 internal/dataframe/compiler/render_test_compat.go create mode 100644 internal/dataframe/compiler/selector_identity_compat.go create mode 100644 internal/dataframe/compiler/selector_mode.go create mode 100644 internal/dataframe/compiler/semantic_aliases.go create mode 100644 internal/dataframe/compiler/spec_aliases.go delete mode 100644 internal/dataframe/compiler/traversal_projection_experiment_test.go create mode 100644 internal/dataframe/doc.go delete mode 100644 internal/dataframe/endpoint_selector_combo_experiment_test.go delete mode 100644 internal/dataframe/endpoint_strategy_experiment_test.go delete mode 100644 internal/dataframe/endpoint_strategy_integration_test.go delete mode 100644 internal/dataframe/full_batch_tournament_test.go delete mode 100644 internal/dataframe/full_identity_tournament_test.go delete mode 100644 internal/dataframe/identity_order_experiment_test.go create mode 100644 internal/dataframe/materialization/arango/registry.go create mode 100644 internal/dataframe/materialization/integration_test.go create mode 100644 internal/dataframe/materialization/read.go create mode 100644 internal/dataframe/materialization/read_test.go create mode 100644 internal/dataframe/materialization/schema.go create mode 100644 internal/dataframe/materialization/service.go create mode 100644 internal/dataframe/materialization/service_test.go create mode 100644 internal/dataframe/materialization/types.go delete mode 100644 internal/dataframe/materialization_tournament_test.go delete mode 100644 internal/dataframe/root_endpoint_experiment_test.go delete mode 100644 internal/dataframe/root_endpoint_live_gate_test.go delete mode 100644 internal/dataframe/root_endpoint_strategy_integration_test.go rename internal/dataframe/runtime/{auth.go => authorization.go} (100%) rename internal/dataframe/runtime/{validation.go => catalog_validation.go} (100%) rename internal/dataframe/runtime/{api.go => compatibility.go} (98%) rename internal/dataframe/runtime/{query_runtime.go => cursor.go} (100%) rename internal/dataframe/runtime/{execution.go => execution_service.go} (100%) rename internal/dataframe/runtime/{runtime_helpers.go => helpers.go} (100%) rename internal/dataframe/runtime/{pivots.go => pivot_materialization.go} (100%) rename internal/dataframe/runtime/{active_generation.go => prepare_generation.go} (100%) rename internal/dataframe/runtime/{validation_service.go => request_validation.go} (100%) rename internal/dataframe/runtime/{auth_scope.go => scope.go} (100%) create mode 100644 internal/dataframe/runtime/types.go delete mode 100644 internal/dataframe/selector_expression_experiment_test.go create mode 100644 internal/dataframe/semantic/doc.go rename internal/dataframe/{compiler => semantic}/selection_semantics.go (68%) create mode 100644 internal/dataframe/semantic/selector_spec.go rename internal/dataframe/{compiler => semantic}/semantic_plan.go (98%) rename internal/dataframe/{compiler => semantic}/semantic_validation.go (93%) create mode 100644 internal/dataframe/semantic/spec_aliases.go rename internal/dataframe/{compiler => spec}/builder_types.go (61%) create mode 100644 internal/dataframe/spec/doc.go rename internal/dataframe/{compiler => spec}/filter.go (99%) rename internal/dataframe/{compiler => spec}/filter_semantics.go (99%) rename internal/dataframe/{compiler => spec}/grain.go (99%) rename internal/dataframe/{compiler => spec}/relationship_match.go (91%) create mode 100644 internal/dataframe/spec/selector_validation.go rename internal/dataframe/{compiler => spec}/selectors.go (98%) delete mode 100644 internal/dataframe/summary_pushdown_experiment_test.go delete mode 100644 internal/dataframe/tournament_pivot_test.go delete mode 100644 internal/dataframe/tournament_sort_order_test.go create mode 100644 internal/graphstore/documents.go create mode 100644 internal/store/clickhouse/client.go create mode 100644 internal/store/clickhouse/client_test.go create mode 100644 internal/store/clickhouse/integration_test.go diff --git a/.dockerignore b/.dockerignore index a9ccde5..8ffb9ea 100644 --- a/.dockerignore +++ b/.dockerignore @@ -7,5 +7,13 @@ bin arango-fhir-proto arango-fhir-server META +META_SMALL data experimental +docs +examples +scripts +Makefile +README.md +TODO.md +**/*_test.go diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index d545bd5..ebf9256 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -2,8 +2,15 @@ name: Build and publish arango-fhir-server image on: push: + branches: + - main + tags: + - 'v*' workflow_dispatch: +permissions: + contents: read + jobs: build: runs-on: ubuntu-latest @@ -11,6 +18,9 @@ jobs: - name: Check out code uses: actions/checkout@v4 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Login to Quay.io uses: docker/login-action@v3 with: @@ -18,17 +28,24 @@ jobs: username: ${{ secrets.QUAY_USERNAME }} password: ${{ secrets.QUAY_ROBOT_TOKEN }} - - name: Build and push image - run: | - BRANCH=$(echo ${GITHUB_REF#refs/*/} | tr / _) - REPO=quay.io/ohsu-comp-bio/arango-fhir-proto - echo "Setting image tag to $REPO:$BRANCH" - - docker login quay.io - docker build -t $REPO:$BRANCH . - - if [[ $BRANCH == 'main' ]]; then - docker image tag $REPO:main $REPO:latest - fi + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: quay.io/ohsu-comp-bio/arango-fhir-proto + tags: | + type=ref,event=branch + type=ref,event=tag + type=sha + type=raw,value=latest,enable={{is_default_branch}} - docker push --all-tags $REPO + - name: Build and push image + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index a38d8b7..16282cb 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -13,7 +13,8 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: '1.26.2' + go-version-file: go.mod + cache: true - name: Generate FHIR code run: make generate-fhir @@ -23,3 +24,11 @@ jobs: - name: Run Go tests run: make test + + - name: Build server image + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + push: false + tags: loom:ci diff --git a/Dockerfile b/Dockerfile index 3265b77..b7fd35f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,11 +7,20 @@ ENV CGO_ENABLED=0 WORKDIR /src COPY go.mod go.sum ./ +# Local development may replace these modules with sibling checkouts. The +# server image uses the published module graph; ingest's generic path is kept +# on the published APIs so this image is reproducible from this repository +# alone. RUN --mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/root/.cache/go-build \ + go mod edit -dropreplace=github.com/bmeg/jsonschema/v6 \ + -dropreplace=github.com/bmeg/jsonschemagraph && \ go mod download COPY cmd ./cmd +COPY fhirschema ./fhirschema +COPY fhirstructs ./fhirstructs +COPY graphqlapi ./graphqlapi COPY internal ./internal COPY schemas ./schemas @@ -20,7 +29,7 @@ ARG TARGETARCH=amd64 RUN --mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/root/.cache/go-build \ GOOS="$TARGETOS" GOARCH="$TARGETARCH" \ - go build \ + go build -mod=mod \ -trimpath \ -ldflags="-s -w" \ -o /out/arango-fhir-server ./cmd/arango-fhir-server @@ -37,4 +46,7 @@ COPY --from=builder /src/schemas /app/schemas USER arango-fhir EXPOSE 8080 +STOPSIGNAL SIGTERM +HEALTHCHECK --interval=10s --timeout=3s --start-period=10s --retries=6 \ + CMD wget -q -O - http://127.0.0.1:8080/healthz >/dev/null || exit 1 ENTRYPOINT ["/app/arango-fhir-server"] diff --git a/Makefile b/Makefile index dd139d9..4fad3d8 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: build build-cli build-server clean compiler-bench compiler-arango-bench dataframe-demo dataframe-profile conformance generate-fhir generate-graphql graphql-check gqlgen-check test docker-build docker-run +.PHONY: build build-cli build-server clean compiler-bench compiler-arango-bench dataframe-demo dataframe-profile dataframe-boundaries dataframe-test conformance generate-fhir generate-graphql graphql-check gqlgen-check test docker-build docker-run GO ?= go GOCACHE_DIR ?= $(CURDIR)/.gocache @@ -74,6 +74,13 @@ dataframe-profile: mkdir -p $(GOCACHE_DIR) GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) run ./cmd/dataframe-profile -variables $(DATAFRAME_PROFILE_VARIABLES) -limit $(DATAFRAME_PROFILE_LIMIT) +dataframe-boundaries: + ./scripts/check_dataframe_package_boundaries.sh + +dataframe-test: dataframe-boundaries + mkdir -p $(GOCACHE_DIR) + GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) test $(GOFLAGS) ./internal/dataframe/spec ./internal/dataframe/semantic ./internal/dataframe/compiler/ir ./internal/dataframe/compiler/lower ./internal/dataframe/compiler/optimize ./internal/dataframe/compiler/render/aql ./internal/dataframe/compiler ./internal/dataframe/runtime ./internal/dataframe -count=1 + conformance: mkdir -p $(GOCACHE_DIR) GOCACHE=$(GOCACHE_DIR) GOTOOLCHAIN=auto $(GO) test $(GOFLAGS) ./conformance/... -count=1 diff --git a/README.md b/README.md index 973ffee..3596be8 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,8 @@ This repo has two main runtime surfaces: - `arango-fhir-proto`: CLI for FHIR loading (including immutable complete generations) and catalog diagnostics - `arango-fhir-server`: Fiber server for compiler-backed GraphQL reads and a - temporary one-file import compatibility endpoint + temporary one-file import compatibility endpoint. It also exposes published + dataframe reads backed by ClickHouse when configured. The current product direction is: @@ -24,7 +25,9 @@ directory contains the local Arango compose setup. ## Docs - [Quickstart](docs/QUICKSTART.md) +- Helm local-cluster deployment: `gen3-helm/helm/loom` - [Developer Architecture](docs/DEVELOPER_ARCHITECTURE.md) +- [Compiler Performance](docs/COMPILER_PERFORMANCE.md) - [Formal Product Gap Analysis](docs/FORMAL_GAP_ANALYSIS.md) - [Compiler-First FHIR/AQL Plan](docs/COMPILER_FIRST_PLAN.md) - [Physical Renderer Replacement Plan](docs/PHYSICAL_RENDERER_REPLACEMENT_PLAN.md) @@ -119,6 +122,59 @@ Then open: The full step-by-step flow, including a sample GraphQL dataframe mutation, lives in [docs/QUICKSTART.md](docs/QUICKSTART.md). +## Local cluster deployment + +The Helm deployment now lives in the `gen3-helm` repository at +`helm/loom`. It owns the Loom chart and its official ClickStack dependencies; +see that repository's README for kind/minikube installation and port +forwarding instructions. + +## Published dataframe materializations + +Loom can stream a validated dataframe recipe into a versioned ClickHouse table. +The operator command accepts a compiler-shaped JSON recipe: + +```json +{ + "project": "ARANGODB_PROTO", + "rootResourceType": "Patient", + "fields": [ + {"name": "patient_id", "select": "id", "valueMode": "FIRST"} + ], + "schema": [ + {"name": "patient_id", "clickhouseType": "Nullable(String)"} + ] +} +``` + +```bash +./bin/arango-fhir-proto materialize-dataframe \ + --request dataframe.json \ + --name case-explorer \ + --clickhouse-url clickhouse://127.0.0.1:9000 \ + --clickhouse-database loom +``` + +The server exposes READY materializations through the existing GraphQL endpoint: + +```graphql +query Rows($input: DataframeRowsInput!) { + dataframeRows(input: $input) { + columns + rows + pageInfo { hasNextPage endCursor } + materialization { id name rowCount columns { name clickhouseType } } + } +} +``` + +The browser never receives a ClickHouse table name or SQL capability. Loom +validates the requested columns, filters, sort, page size, project, generation, +and materialization state before querying ClickHouse. An explicit `schema` +preflight validates column names/types before the table is created and rejects +rows that emit undeclared or incompatible values. Aggregates accept the same +`EQ` and `CONTAINS` filters as row reads. + If you are starting from a fresh checkout, go there next: - [Continue with the Quickstart](docs/QUICKSTART.md) diff --git a/cmd/arango-fhir-proto/main.go b/cmd/arango-fhir-proto/main.go index df90e2c..dbefda1 100644 --- a/cmd/arango-fhir-proto/main.go +++ b/cmd/arango-fhir-proto/main.go @@ -11,8 +11,13 @@ import ( "runtime/trace" "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/dataframe/materialization" + materializationarango "github.com/calypr/loom/internal/dataframe/materialization/arango" + dataframeruntime "github.com/calypr/loom/internal/dataframe/runtime" "github.com/calypr/loom/internal/dataset" "github.com/calypr/loom/internal/ingest" + arangostore "github.com/calypr/loom/internal/store/arango" + clickhousestore "github.com/calypr/loom/internal/store/clickhouse" ) const ( @@ -41,6 +46,8 @@ func main() { err = runDiscoverPopulatedFields(ctx, os.Args[2:]) case "rebuild-relationship-catalog": err = runRebuildRelationshipCatalog(ctx, os.Args[2:]) + case "materialize-dataframe": + err = runMaterializeDataframe(ctx, os.Args[2:]) default: usage() os.Exit(2) @@ -201,6 +208,91 @@ func runRebuildRelationshipCatalog(ctx context.Context, args []string) error { return printJSON(summary) } +func runMaterializeDataframe(ctx context.Context, args []string) error { + fs := flag.NewFlagSet("materialize-dataframe", flag.ExitOnError) + var requestPath, name, clickhouseURL, clickhouseDatabase string + var opts arangostore.ConnectionOptions + fs.StringVar(&requestPath, "request", "", "JSON file containing a FhirDataframeInput") + fs.StringVar(&name, "name", "", "Published dataframe name") + fs.StringVar(&opts.URL, "url", defaultURL, "ArangoDB URL") + fs.StringVar(&opts.Database, "database", defaultDatabase, "Arango database") + fs.StringVar(&clickhouseURL, "clickhouse-url", "clickhouse://127.0.0.1:9000", "ClickHouse native URL") + fs.StringVar(&clickhouseDatabase, "clickhouse-database", "loom", "ClickHouse database") + if err := fs.Parse(args); err != nil { + return err + } + if requestPath == "" { + return fmt.Errorf("--request is required") + } + if name == "" { + return fmt.Errorf("--name is required") + } + data, err := os.ReadFile(requestPath) + if err != nil { + return err + } + var input materializationInput + if err := json.Unmarshal(data, &input); err != nil { + return fmt.Errorf("decode dataframe request: %w", err) + } + arango, err := arangostore.Open(ctx, opts.URL, opts.Database) + if err != nil { + return err + } + defer arango.Close(ctx) + if err := arango.Bootstrap(ctx, materializationarango.BootstrapSpec()); err != nil { + return err + } + registry, err := materializationarango.New(arango) + if err != nil { + return err + } + ch, err := clickhousestore.New(clickhousestore.Options{URL: clickhouseURL, Database: clickhouseDatabase}) + if err != nil { + return err + } + defer ch.Close() + if err := ch.EnsureDatabase(ctx); err != nil { + return err + } + dataframes := dataframeruntime.NewService(dataframeruntime.ServiceConfig{ConnectionOptions: opts}) + service := &materialization.Service{Dataframes: dataframes, ClickHouse: ch, Registry: registry} + builder := input.Builder() + result, err := service.Materialize(ctx, materialization.Request{Name: name, Run: dataframeruntime.RunRequest{Builder: builder}, Schema: input.Schema}) + if err != nil { + return err + } + return printJSON(result) +} + +// materializationInput is intentionally the operator-facing, compiler-shaped +// recipe. The browser-facing GraphQL input can be mapped to the same builder +// by the GraphQL adapter without making this command depend on gqlgen output. +type materializationInput struct { + Project string `json:"project"` + DatasetGeneration string `json:"datasetGeneration"` + AuthResourcePaths []string `json:"authResourcePaths"` + RootResourceType string `json:"rootResourceType"` + RowGrain dataframeruntime.RowGrain `json:"rowGrain"` + Fields []dataframeruntime.FieldSelect `json:"fields"` + Filters []dataframeruntime.TypedFilter `json:"filters"` + Pivots []dataframeruntime.PivotSelect `json:"pivots"` + Aggregates []dataframeruntime.AggregateSelect `json:"aggregates"` + Slices []dataframeruntime.RepresentativeSlice `json:"slices"` + Traversals []dataframeruntime.TraversalStep `json:"traversals"` + Schema []materialization.SchemaColumn `json:"schema"` +} + +func (in materializationInput) Builder() dataframeruntime.Builder { + return dataframeruntime.Builder{ + Project: in.Project, DatasetGeneration: in.DatasetGeneration, + AuthResourcePaths: in.AuthResourcePaths, RootResourceType: in.RootResourceType, + RowGrain: in.RowGrain, Fields: in.Fields, Filters: in.Filters, + Pivots: in.Pivots, Aggregates: in.Aggregates, Slices: in.Slices, + Traversals: in.Traversals, + } +} + func parseDiscoverPopulatedReferenceOptions(args []string, errorHandling flag.ErrorHandling) (catalog.PopulatedReferenceOptions, error) { fs := flag.NewFlagSet("discover-populated-references", errorHandling) opts := catalog.PopulatedReferenceOptions{} @@ -250,6 +342,7 @@ func usage() { arango-fhir-proto discover-populated-references [flags] arango-fhir-proto discover-populated-fields [flags] arango-fhir-proto rebuild-relationship-catalog [flags] # explicit fhir_edge repair/backfill + arango-fhir-proto materialize-dataframe --request dataframe.json --name case-explorer [flags] `) } diff --git a/cmd/arango-fhir-server/main.go b/cmd/arango-fhir-server/main.go index 9b48eec..9e5d63b 100644 --- a/cmd/arango-fhir-server/main.go +++ b/cmd/arango-fhir-server/main.go @@ -14,11 +14,14 @@ import ( "github.com/calypr/loom/internal/authscope" "github.com/calypr/loom/internal/catalog" "github.com/calypr/loom/internal/dataframe" + "github.com/calypr/loom/internal/dataframe/materialization" + materializationarango "github.com/calypr/loom/internal/dataframe/materialization/arango" "github.com/calypr/loom/internal/dataset" datasetarango "github.com/calypr/loom/internal/dataset/arango" api "github.com/calypr/loom/internal/httpapi" "github.com/calypr/loom/internal/ingest" arangostore "github.com/calypr/loom/internal/store/arango" + clickhousestore "github.com/calypr/loom/internal/store/clickhouse" ) func main() { @@ -34,6 +37,8 @@ func main() { // disables the legacy one-file import route because that route cannot // safely construct a complete immutable snapshot. datasetGenerations = flag.Bool("dataset-generations", false, "resolve active immutable dataset generations for dataframe reads and disable legacy single-resource imports") + clickhouseURL = flag.String("clickhouse-url", "clickhouse://127.0.0.1:9000", "ClickHouse native URL for published dataframe reads") + clickhouseDatabase = flag.String("clickhouse-database", "loom", "ClickHouse database for published dataframe reads") ) flag.Parse() @@ -88,6 +93,25 @@ func main() { ScopeResolver: scopeResolver, ActiveManifestResolver: activeManifestResolver, }) + registryClient, err := arangostore.Open(context.Background(), connOpts.URL, connOpts.Database) + if err != nil { + exitf("open dataframe registry store: %v", err) + } + defer registryClient.Close(context.Background()) + if err := registryClient.Bootstrap(context.Background(), materializationarango.BootstrapSpec()); err != nil { + exitf("bootstrap dataframe registry store: %v", err) + } + registry, err := materializationarango.New(registryClient) + if err != nil { + exitf("create dataframe registry: %v", err) + } + clickhouse, err := clickhousestore.New(clickhousestore.Options{URL: *clickhouseURL, Database: *clickhouseDatabase}) + if err != nil { + exitf("create ClickHouse client: %v", err) + } + defer clickhouse.Close() + materializer := &materialization.Service{Dataframes: dataframes, ClickHouse: clickhouse, Registry: registry} + materializationReader := &materialization.Reader{ClickHouse: clickhouse, Registry: registry, MaxPage: 1000} resolver := graphqlapi.NewResolver(dataframeapi.Config{ ConnectionOptions: connOpts, DiscoverReferences: discoverReferences, @@ -95,6 +119,8 @@ func main() { Dataframes: dataframes, ScopeResolver: scopeResolver, ActiveManifestResolver: activeManifestResolver, + Materializations: materializer, + MaterializationReader: materializationReader, }) importService, err := api.NewService(api.ServiceConfig{ diff --git a/docs/AQL_EXECUTION_IMPLEMENTATION_AUDIT.md b/docs/AQL_EXECUTION_IMPLEMENTATION_AUDIT.md deleted file mode 100644 index 1c9b74a..0000000 --- a/docs/AQL_EXECUTION_IMPLEMENTATION_AUDIT.md +++ /dev/null @@ -1,242 +0,0 @@ -# AQL execution implementation audit - -## Conclusion - -The compiler has two real production optimizations, but it is not close to a -fully optimized physical translation. Generic sibling traversal sharing and -compact set projection are enabled and measurable. Most other named -optimizer rules are experiments, diagnostics, or policy switches with no -production rewrite behind them. - -The concern about `LUNA_AQL_EXECUTION_ROUND_3.md` is justified. Its prepared -selector package largely repeats a previously rejected second-pass prepared -set, and its fusion package starts from a classifier that currently finds no -real candidates. Those packages may reduce some selector work after a major -redesign, but they are unlikely to be the first large reduction in the -5.9-second Arango phase. - -The highest-confidence missing translation is index-aware edge lowering. The -actual query's four native traversal nodes all use the default `_to` edge -index while existing endpoint-first compound indexes remain unused. The next -largest architectural gap is that Loom materializes payload-bearing child -arrays and only then performs rich shaping in separate loops. - -## Plan versus production code - -| Capability | Plan/document claim | Current code truth | Production effect | -|---|---|---|---| -| Physical compiler/renderer | complete | complete; the physical compiler is the execution path | required foundation | -| Root scope/window | complete | project/generation/auth before `_key` sort and limit | root index selected; not the bottleneck | -| Generic sibling traversal sharing | complete | implemented in `sharePhysicalSetGroup`; enabled by default | large win: roughly 7.4s unoptimized to 5.6–5.9s current | -| Compact set projection | complete | implemented and enabled by default | modest runtime win; meaningful memory reduction | -| Prepared selectors | described as complete in old status text | implemented as an optional second prepared array; disabled by default | previously slower and about 303 MB more memory at 1,000 rows | -| Rich-consumer fusion | described as complete in old status text | diagnostics classify only byte-identical expressions; no fusion rewrite/rendering exists | no AQL change | -| Nested traversal sharing | named rule | no optimizer implementation; prior corpus had no repeated nested candidate | no AQL change | -| Required-match reuse | complete | identical required matches are deduplicated and counted | useful, but absent from this optional-only GDC shape | -| Endpoint-first indexes | declared and Explain-tested | native traversal still selects only default edge `_to`; explicit filtered-edge probes select compound indexes | unused by production translation | -| Relationship cardinality catalog | complete | used for discovery/validation; `EdgeCount` is not carried into semantic/physical planning | no cost-aware strategy selection | -| Durable profile tooling | mostly complete | exact variables input, AQL/result hashes, Explain/Profile artifacts now exist | diagnostic only | -| Cost policy | complete structurally | estimates operation counts, not cardinality, fan-out, retained width, or selected index | cannot choose the cheapest physical strategy reliably | - -The old `AQL_OPTIMIZATION_WORKLIST.md` execution-status section is therefore -stale where it calls prepared reuse and aggregate/pivot/slice fusion complete. -Prepared references exist, but their current rendering was rejected for -production. Fusion is diagnostics-only. - -## What the current AQL actually does - -The exact 1,000-row GDC query contains: - -| Rendered operation | Count | -|---|---:| -| `UNIQUE` materializations/expressions | 8 | -| `SORT` clauses | 11 | -| native graph traversals | 4 | -| post-materialization `FOR __item IN child_set` loops | 7 | -| child sets retaining `payload` | 6 | - -The query first materializes a broad Patient-neighbor array, derives typed -arrays, materializes three nested arrays, and then re-enumerates those arrays -for aggregates, slices, and the pivot. Representative slices sort an array -that was already sorted during set materialization; when the requested sort -is `_key`, the renderer currently emits `_key` twice as the primary key and -tie-breaker. - -This is correct AQL, but it is a general-purpose materialize-then-shape plan, -not an optimized query plan. - -## Profile-backed bottlenecks - -The exact request profile reports 475,876 indexed items, no full scans, and -269,844,480 bytes peak memory. The root `Patient(project, _key)` index is -working. The remaining traversal fan-out is: - -| Region | Node | Items | Filtered | Cumulative runtime | -|---|---:|---:|---:|---:| -| shared first hop | 12 | 34,852 | 11,622 | 1.079s | -| Specimen → DocumentReference | 55 | 14,334 | 60,944 | 2.888s | -| Specimen → Group | 79 | 22,950 | 52,328 | 4.124s | -| Group → DocumentReference | 103 | 12,074 | 11,074 | 5.673s | - -These runtimes overlap, but the calls/items/filtered counts are decisive: the -renderer asks native traversal to retrieve broad endpoint adjacency and then -filters label, type, project, generation, and auth. `EXPLAIN` shows only the -default `_to` edge index. The endpoint-first compound index is proven usable -only by explicit edge-filter AQL. - -The other large node family is payload list enumeration. The same selector is -often recomputed for distinct aggregation, a representative slice, or a -pivot. The current prepared-set experiment addresses this by creating another -array that also retains `payload` and `__loom_prepared_node`, which explains -its memory and runtime regression. - -## Assessment of Round 3 - -### Prepared selector unions - -Do not execute the existing package unchanged. The repository already has a -selector-union collector and prepared renderer. Previous live evidence showed -it was slower because it performs a second pass and duplicates payload-bearing -objects. - -The useful replacement is **traversal-time shaping projection**: compute the -union of required selector values in the child traversal's `RETURN` object, -along with only `_id`, `_key`, and fields required for nested navigation. This -removes payload before it enters the materialized array and avoids the second -prepared pass entirely. - -### Compatible aggregate/slice/pivot fusion - -Do not implement the current identical-expression classifier as a renderer. -The real query contains unlike consumers over the same source—count, distinct -values, slice, and pivot—not repeated identical expressions. The classifier -correctly produces singleton groups, so enabling its rule cannot change this -query. - -Fusion becomes useful only as **leaf-set summary pushdown**: after identity -deduplication, a leaf relationship subquery should return both its bounded -slice and aggregate/pivot summary without first returning a payload array to -the outer root projection. That is a different physical operation from the -current diagnostics group. - -### Explicit endpoint-filter traversal - -Keep and expand this package. It is the only Round 3 proposal directly aimed -at the profile's largest proven work. It must compare four strategies, because -the current sibling-sharing win can conflict with compound-index equality: - -1. native shared multi-type traversal; -2. native independent typed traversals; -3. explicit shared multi-type edge lookup; and -4. explicit independent typed edge lookups using endpoint/type equality. - -The inbound multi-type `IN` probe previously fell back to the default edge -index, while equality selected the compound index. A production choice cannot -assume that sharing remains cheaper after endpoint filtering. - -## Missing work, reordered by expected impact - -### P1 — index-aware traversal strategy selection - -Add a typed physical strategy for native traversal versus explicit edge/node -lookup. Prototype nested equality routes first, then the shared root route. -Require the endpoint-first compound index, exact parity, and at least a 10% -whole-query median win before production enablement. - -This is the highest-confidence package because it targets the observed -filtered adjacency work and an already-proven usable index. - -### P2 — traversal-time shaping projection - -Replace post-set prepared arrays with a typed projection attached to the -relationship set itself. Compute repeated selector arrays once while each node -is in scope. Retain `payload` only for an unprepared fallback or unsupported -consumer; retain `_id` only when a nested traversal needs it. - -This package should delete or replace the current harmful prepared-set -rendering rather than layering another representation on top of it. - -### P3 — leaf-set summary pushdown - -For a materialized child with no navigated descendants, lower aggregate, -pivot, and representative-slice outputs into a typed summary subquery. The -summary should perform identity deduplication once, then emit named outputs. -The outer root `RETURN` reads the summary object instead of repeatedly looping -over a child payload array. - -This is the production form of useful “fusion.” It must preserve count, -distinct ordering, pivot collision reduction, and sort-before-limit. - -### P4 — identity, deduplication, and ordering plan - -Model identity uniqueness and ordering as physical properties rather than -emitting `UNIQUE` plus `SORT` for every set and another `SORT` for each slice. -Prove whether `_id`/`_key` deduplication can replace object-level `UNIQUE`, and -whether a sorted/deduplicated source satisfies a slice's order. - -Do not start with the duplicated `_key` text cleanup alone; it is correct but -unlikely to move the whole query. The package matters only if it removes -materialization/sort executor work. - -### P5 — batch-oriented root execution prototype - -If P1–P4 do not bring the warm query below roughly three seconds, prototype a -set-oriented plan: materialize the 1,000-root window once, perform edge/node -lookups for the root set, group by root identity, and assemble rows afterward. -The current compiler is correlated root-by-root; no prior work package tested -a batch join/aggregation strategy. - -This is higher-risk but has more upside than additional expression-level -fusion. It must remain an experiment until auth/generation and row-order -parity are proven. - -### P6 — catalog-backed physical costing - -Carry relationship counts from validated catalog references into compilation -as read-only statistics. Use them to choose shared versus independent and -native versus explicit traversal, and to bound retained-set width. Statistics -must never change semantics and must have a deterministic no-statistics -fallback. - -This package enables correct strategy choice; it does not count as a speedup -unless it selects a measurably faster rendered plan. - -## Recommended execution order - -```text -Wave 1, parallel experiments: - P1 endpoint lookup: nested paths and root shared/unshared matrix - P2 traversal-time projection: selector/retention prototype - P4 identity/order: prove which sorts/UNIQUE operations are removable - -Wave 2, serialized compiler merges: - P1 production strategy - P2 production projection - P3 leaf summary pushdown - P4 proven ordering/dedup changes - -Wave 3: - re-profile exact GDC and generic corpus - implement P5 only if the execution phase remains above the target - add P6 when more than one physical strategy has survived profiling -``` - -Rich fusion and prepared selectors should not remain standalone production -goals. They should be absorbed into traversal-time projection and leaf summary -pushdown, where they can remove an actual materialization boundary. - -## Completion target - -The next round should target more than “below the old 6.34-second baseline.” -That gate has already been met. A meaningful next milestone is: - -- exact result and scope parity; -- zero full scans; -- endpoint-first indexes selected where expected; -- no more than 200 MB peak memory for this request; and -- five-run warm Arango median below 4.5 seconds after P1/P2, with a stretch - target below 3 seconds after leaf pushdown or batch-oriented execution. - -Any package that cannot identify removed scanned items, removed payload -materialization, or removed sort/list work is not an AQL translation -optimization and should not be merged as one. diff --git a/docs/AQL_OPTIMIZATION_WORKLIST.md b/docs/AQL_OPTIMIZATION_WORKLIST.md deleted file mode 100644 index c77eac0..0000000 --- a/docs/AQL_OPTIMIZATION_WORKLIST.md +++ /dev/null @@ -1,582 +0,0 @@ -# AQL optimization work list - -This is the post-measurement work list for Loom's physical dataframe -compiler. It is deliberately compiler-first: frontend work must not hide an -unbounded or repeatedly correlated AQL plan. - -It applies to every schema-defined FHIR relationship. Nothing below may -special-case Patient, GDC, `subject_Patient`, or a fixture resource type. -`fhirschema` remains the source of valid routes and selectors; the physical -optimizer decides whether a particular request can share work. The GDC case -matrix is an integration specimen that exercises fields, filters, aggregates, -pivots, slices, and nested traversal together; it is not the shape the -optimizer is allowed to recognize or optimize specially. - -## Measured starting point - -The checked-in GDC case-matrix request, run against the loaded `META` data, -has these measured characteristics: - -| Measure | Observation | -|---|---:| -| 1,000 rich Patient rows | about 8.15 seconds/request | -| Arango cursor time | about 8.10 seconds/request | -| compilation | about 1 millisecond/request | -| Loom row shaping | about 2 milliseconds/request | -| GraphQL serialization + HTTP | about 54 milliseconds/request | -| physical traversal sets | 6 | -| traversals shared today | 0 | -| broad sharing opportunities | 1 group / 3 sibling sets | -| repeated rich-set consumers | 4 sets | - -The broad sharing opportunity is the generic pattern “one parent variable, -one directed edge label, several target resource types.” In the current GDC -request it appears as Patient's `subject_Patient` traversals to Condition, -Specimen, and Observation. The current optimizer must not share it because -the full scoped subplans are not yet proven alpha-equivalent after variable -rebinding. - -Repeated rich consumers are also real, but distinct from repeated traversals: -Condition and Specimen each have two aggregates plus a slice; DocumentReference -has three aggregates plus a slice; Observation has two aggregates plus a -pivot. The relationship set is materialized once, then the current renderer -loops over it independently for each rich expression. - -## Non-negotiable contracts - -Every work package must preserve: - -1. result parity: row count, root order, columns, null/empty behavior, array - ordering, pivot collision behavior, and representative slice selection; -2. authorization and dataset-generation isolation on both traversed edge and - target node; -3. optional versus required traversal semantics; -4. bind-only user values and schema-validated selector paths; -5. generic operation over every valid schema route. - -Do not claim an optimization from rendered-AQL string similarity. Prove it -with physical-plan tests, old-versus-new result parity on Arango, and a live -`PROFILE` comparison of the same request. - -## Required benchmark and parity corpus - -Every optimization must run against a corpus of semantic shapes, not one -dataframe. Maintain these generic cases using routes discovered from -`fhirschema` and data loaded from `META` where available: - -| Case | What it protects | -|---|---| -| scalar root preview | root scope, sort, limit, and projection cost | -| one optional child | ordinary field selection and empty-child behavior | -| sibling targets on one edge label | generic traversal-prefix sharing | -| proven outbound route | direction-specific edge discriminator behavior | -| required relationship match | semi-join/root filtering semantics | -| child and nested filters | predicate placement and auth/generation scope | -| deep traversal (3+ hops) | captures, variable rebinding, and nested scope | -| aggregate-only child | count/distinct/exists value semantics | -| aggregate + slice over one set | prepared-set reuse without ordering drift | -| Observation-style pivot | grouped/keyed values and sparse columns | -| mixed rich dataframe | cross-feature composition; the GDC case matrix lives here | -| generated root sweep | every root resource type advertised by `fhirschema` compiles or rejects deterministically | - -Fixture names may describe their contents, but optimizer implementation and -tests must assert only physical properties: route equality, scope equality, -typed selector semantics, and output parity. A new route with the same -physical properties must receive the same rewrite without code changes. - -## WP0 — Make live Arango PROFILE the source of truth - -**Goal:** attribute the 8-second request to actual Arango executor nodes -before changing the renderer. - -### Implement - -1. Extend `internal/store/arango` with a profile operation for a parameterized - query. It must accept the generated AQL and bind variables without - interpolation. -2. Capture plan nodes, calls, items, filtered items, runtime, and estimated - cost wherever the installed Arango version provides them. Preserve warnings, - indexes, and applied optimizer rules already collected by `EXPLAIN`. -3. Add an opt-in dataframe diagnostic path; never run `PROFILE` on normal - frontend requests. A local-only GraphQL flag or a dedicated developer CLI - mode is acceptable. -4. Emit a stable, compact report grouped by node type and by AQL source - fragment: root scan, each traversal set, aggregate, pivot, slice, sort, - and return. -5. Save sanitized JSON profile artifacts for a small/medium/large sample of - the required corpus—not only GDC—under `docs/benchmarks/` or a gitignored - local artifact path. - -### Tests and gate - -- Unit-test profile JSON decoding against checked-in fixtures. -- Live tests: profile representative root, sibling, deep, required-match, and - pivot cases; assert the root scoped index and `fhir_edge` edge index are - selected with no full collection scan. -- Record the top five runtime nodes. Do not start WP1 until the profile output - identifies whether root sibling traversals dominate as expected. - -## WP1 — Canonicalize generic traversal prefixes - -**Goal:** represent the shareable prefix of any physical traversal without -depending on incidental variable names or semantic provenance. - -### Implement - -1. Add a typed `PhysicalTraversalPrefix` (or equivalent canonical helper) - containing source variable, direction, edge collection, edge label, edge - target-type discriminator, project/generation/auth constraints, and the - canonical node/edge variables used inside that prefix. -2. Split each child `PhysicalSet` into: - - a shareable traversal-and-scope prefix; - - a target-type subset; - - consumer-specific filters and nested work. -3. Implement alpha-renaming for target and edge variables across typed filters, - auth checks, selector extractions, required-match predicates, nested sets, - aggregate predicates, pivots, and slices. -4. Make the share key derive only from semantic physical behavior. It must not - include alias names, projection names, or `PhysicalSource` provenance. -5. Keep an explicit `not shareable` reason for each rejected set: different - direction, label, parent variable, scope, required/optional mode, or a - not-yet-supported operation. - -### Tests and gate - -- Table tests for alpha-equivalent prefixes with different generated variable - names. -- Negative tests for every rejection reason. -- Validate the rewritten plan before rendering; no renderer-only rewrite. -- At least one corpus sibling-route fixture must move from zero scope-safe - candidates to a proven candidate group, and a structurally equivalent route - with different FHIR resource types must share without a code change. - -## WP2 — Render shared neighbor traversals and typed subsets - -**Depends on:** WP1. - -**Goal:** execute one generic neighbor traversal for compatible siblings, then -derive each resource-type-specific child set from it. - -### Implement - -1. Add a physical operation for a shared neighbor set with a bind-backed list - of target types. -2. Render one correlated AQL subquery per parent row: - - ```aql - LET shared_neighbors = ( - FOR node, edge IN 1..1 INBOUND parent fhir_edge - FILTER scoped_edge_and_node_predicates - FILTER edge.label == @label - FILTER node.resourceType IN @target_types - RETURN node - ) - ``` - -3. Render each child as a typed subset of `shared_neighbors`; retain its own - target-type check and its consumer-specific predicates. -4. Preserve child ordering (`_key` or the existing explicit semantic order), - uniqueness, and empty-set behavior. -5. Support both INBOUND and proven OUTBOUND routes. Do not enable `ANY` until - a separate parity proof exists. -6. Keep required relationship matching as a semi-join. It may consume a shared - prefix only after proving that it does not accidentally materialize optional - output or change root filtering order. - -### Tests and gate - -- Result parity between unshared and shared plans for optional siblings, - filtered siblings, auth-restricted paths, empty sets, and nested children. -- Live parity for the sibling-route fixture, a deep traversal fixture, and the - mixed GDC matrix at 25 and 1,000 rows where the dataset contains that many - roots. -- `PROFILE` must show fewer traversal executor calls/items for the shared - sibling group and lower or equal total Arango runtime. If it does not, keep - the rewrite behind a cost gate rather than forcing it globally. - -## WP3 — Fuse rich consumers over one child set - -**Depends on:** WP0; can begin design in parallel with WP1. - -**Goal:** avoid re-scanning and re-extracting FHIR selectors independently for -every aggregate, pivot, and slice over the same child set. - -### Implement - -1. Add a typed `PhysicalPreparedSet` or `PhysicalSetProjection` operation, - owned by a child relationship set. -2. Collect the union of selector inputs required by that set's aggregates, - pivot key/value expressions, slice predicates/sort keys, and slice fields. -3. Render one bounded pass over the child set that produces a small prepared - object per child. It may contain the original node only when nested work - still requires it; otherwise project just the selected values. -4. Lower aggregate, pivot, and slice expressions to consume prepared values. - Preserve each feature's own null, distinct, predicate, collision, and sort - semantics. -5. Do not prepare selectors that are used once; require at least two consumers - or a profile-backed benefit. -6. Do not force unbounded arrays into memory. Keep representative slices - bounded, and retain aggregate streaming/grouping where Arango can do it. - -### Tests and gate - -- Unit parity for `COUNT`, `COUNT_DISTINCT`, `EXISTS`, `DISTINCT_VALUES`, - pivot collisions, null selectors, and sorted slices. -- Fixture assertions for aggregate/slice, aggregate/pivot, and nested-child - reuse sites across more than one resource family. -- `PROFILE` must show fewer selector/subquery executions and no increase in - returned intermediate items that erases the gain. - -## WP4 — Fuse compatible aggregates and pivots before prepared-set lowering - -**Depends on:** WP3 design; implementation may be folded into WP3 if simpler. - -**Goal:** exploit operations that can share more than selector extraction. - -### Implement - -1. Group aggregates with the same source and predicate into one AQL pass. -2. Group pivots with the same source/key/value/predicate and differing allowed - columns into one grouped map, then project requested column subsets. -3. Share predicate evaluation between aggregates and slices only when the - predicate is identical and preserving it does not affect slice ordering. -4. Maintain a deterministic operation ordering and stable bind-variable names - so Explain fixtures remain readable. - -### Tests and gate - -- Same-source / different-predicate operations remain separate. -- Same-source / same-predicate groups have byte-for-byte output parity. -- Observation pivot receives a dedicated live `PROFILE` gate because `COLLECT` - can be slower than separate bounded loops on sparse data. - -## WP5 — Predicate and required-match reuse - -**Depends on:** WP1 and WP2. - -**Goal:** eliminate duplicate graph work when the same relationship appears in -both a required root filter and an optional projected child set. - -### Implement - -1. Teach the physical plan to identify an `EXISTS`/required-match predicate - whose route and scope prefix match a materialized child set. -2. Retain root filtering before root `SORT`/`LIMIT`; do not turn a required - predicate into post-limit filtering. -3. Permit a shared root-scoped existence result only when it cannot leak child - data across authorization scopes. -4. Record reuse versus rejection in compiler-plan diagnostics. - -### Tests and gate - -- Required match plus optional projection parity for no match, one match, many - matches, restricted auth, and nested match routes. -- Live explain/profile demonstrates fewer duplicate edge traversals. - -## WP6 — Index and query-shape audit driven by PROFILE - -**Depends on:** WP0; repeat after WP2 and WP3. - -**Goal:** ensure the optimized AQL can use Arango's physical indexes rather -than merely containing the right filters. - -### Implement - -1. Inventory the actual root indexes used for project, generation, auth path, - `_key` sort, and root resource collection selection. -2. Inventory `fhir_edge` indexes used by direction. Confirm whether label and - type discriminators are post-filtered after the edge index and whether a - persistent composite index would materially reduce traversal fan-out. -3. Test candidate indexes against the loaded META data and a larger synthetic - fan-out fixture. Do not add every possible composite index by default; - index write cost matters for bulk ingest. -4. Compare root-first `LIMIT` placement, filter movement, and traversal - options only with result-parity proof. - -### Tests and gate - -- Explain assertions cover index name, fields, absence of collection scans, - and estimated item/cost regressions. -- Profile evidence justifies each new index and documents its ingest tradeoff. - -## WP7 — Cost model, diagnostics, and regression gates - -**Depends on:** WP0 through WP6 incrementally. - -**Goal:** make optimizer decisions observable and prevent a future renderer -change from silently restoring correlated work. - -### Implement - -1. Keep GraphQL diagnostics opt-in or development-only; production dataframe - responses should not expose compiler internals by default. -2. Report: traversal-set count, shared set count, scope-safe candidate count, - broader opportunity count, rejected reasons, and rich-source consumer - counts. -3. Add a compiler cost heuristic that only enables sharing/fusion when its - estimated savings exceeds extra materialization cost. Start conservative; - correctness and profile evidence outrank cleverness. -4. Add benchmark commands for 25, 100, and 1,000 rows with one cold run and - at least three warm runs. Print per-request—not cumulative—timings. -5. Track response bytes, returned rows, compile time, Arango execution, - serialization, profile node totals, and plan diagnostics together. - -### Acceptance gate - -The entire corpus must have committed baseline and post-change evidence. GDC -is one required mixed-feature case, not a privileged one. A performance claim -requires all of: - -- unchanged output result hash/canonical comparison; -- no authorization or generation-scope regression; -- no full collection scan or lost required index; -- lower profile work for the targeted node(s); -- lower or statistically neutral warm 1,000-row runtime. - -## Execution order and parallelism - -| Order | Package | Parallelism | Why | -|---:|---|---|---| -| 1 | WP0 profiling | alone | establishes the real target before rewrites | -| 2 | WP1 canonical prefix | alone | changes the physical IR contract | -| 3 | WP2 shared traversal | after WP1 | first high-value generic rewrite | -| 3 | WP3 prepared sets | design only alongside WP2 | implementation waits for stable IR | -| 4 | WP3 implementation | after WP2 profile | avoids optimizing the wrong cost | -| 5 | WP4 and WP5 | separate workers | distinct physical expression versus predicate ownership | -| 6 | WP6 | after each major rewrite | index choices require final query shapes | -| 7 | WP7 | continuous | gates every merge rather than a final cleanup | - -The first implementation target is therefore not “make the GDC query fast.” -It is “make every schema-defined sibling traversal safely shareable when the -typed physical plan proves it is equivalent,” then use `PROFILE` to verify the -benefit across the corpus, including—but never limited to—GDC. - -## Luna multi-agent execution map - -This work can use several Luna agents, but only one agent at a time may own a -physical IR or renderer contract. The safe unit of parallelism is a package -with a narrow output contract, not a broad instruction such as “optimize AQL.” - -### Coordinator responsibilities - -The coordinator owns these files and resolves all interface changes before -implementation workers begin: - -- `internal/dataframe/physical_plan.go` -- `internal/dataframe/physical_optimize.go` -- `internal/dataframe/physical_render.go` -- `internal/dataframe/physical_execution.go` -- `internal/dataframe/physical_diagnostics.go` - -The coordinator must publish one short interface note before the first merge: - -1. operation/type names and fields for traversal prefixes, shared sets, typed - subsets, and prepared sets; -2. ownership and lifetime of physical variables/captures; -3. which phase lowers, rewrites, validates, and renders each operation; -4. whether a new operation is enabled immediately or rendered behind an - explicit optimizer rule; -5. the canonical result-parity comparator and profile artifact format. - -No worker may rename or reshape those types independently. If a worker needs a -new field, it proposes the exact change and waits for the coordinator to add -it or approve it. - -### Wave A — independent foundations - -These packages may begin together because they do not change the physical plan -contract. - -| Worker | Scope and owned files | Deliverable | Merge gate | -|---|---|---|---| -| A1: Profile adapter | `internal/store/arango/`, new profile fixtures/tests | Parameterized `PROFILE` request/decoder, stable node summaries, warnings/index/rule capture | Unit fixtures plus a live opt-in profile test; no dataframe renderer edits | -| A2: Benchmark corpus | `conformance/compiler/fixtures/`, `examples/`, benchmark docs/tests | Route-neutral corpus described above, fixture loader helpers, canonical output comparator | Existing GDC remains; each fixture compiles or has deterministic rejection | -| A3: Diagnostics/CLI | `cmd/dataframe-query/`, GraphQL diagnostic mapping, docs | Opt-in display of plan facts, timing, profile artifact path; 25/100/1K benchmark commands | No optimizer behavior changes; works against server without diagnostics where practical | -| A4: Index audit | `internal/store/arango/` Explain helpers, integration tests, docs | Inventory of root/edge indexes and Explain/profile assertions for corpus shapes | No new persistent index without recorded profile evidence and ingest-cost note | - -**A-wave handoff:** A1 publishes `ProfileReport`; A2 publishes fixture IDs and -expected shape metadata; A3 consumes both as read-only contracts; A4 consumes -A1 reports. These workers should avoid editing the same generated GraphQL files -by having A3 own schema/model regeneration. - -### Wave B — traversal-sharing vertical slice - -These are sequential at the IR boundary but can overlap in test preparation. - -| Worker | Scope | Depends on | Deliverable | -|---|---|---|---| -| B1: Prefix IR | typed traversal-prefix decomposition and validator | coordinator interface note | canonical prefix and rejection-reason API; no changed runtime behavior yet | -| B2: Prefix tests | physical-plan fixture builders and alpha-renaming tests | B1 type signature | positive/negative equivalence corpus, auth/generation/required-match cases | -| B3: Shared renderer | optimizer rewrite plus renderer support | B1 merged; B2 tests available | one shared neighbor traversal plus typed subsets, initially behind a rule | -| B4: Sharing parity/profile | live Arango parity and profile comparisons | B3 | proof that the generic rewrite reduces traversal work for at least two distinct route families | - -Only B1 edits the initial prefix type. Only B3 edits sharing rewrite/rendering. -B2 and B4 may prepare code in parallel but must rebase on B1/B3 respectively. - -### Wave C — rich-expression reuse vertical slice - -This wave may begin its semantic/test work while Wave B is in progress, but it -must not merge physical-plan type changes until B1's prefix contract is fixed. - -| Worker | Scope | Depends on | Deliverable | -|---|---|---|---| -| C1: Prepared-set design | proposal plus tests for selector union and value lifetime | coordinator interface note | approved prepared-set IR contract and decision table for one versus many consumers | -| C2: Aggregate fusion | aggregate grouping tests and lowering helpers | C1 contract | same-source/same-predicate aggregate grouping with parity proof | -| C3: Pivot/slice reuse | pivot/slice test corpus and selector-extraction helpers | C1 contract | prepared-value consumers preserving collision, null, sort, and limit behavior | -| C4: Rich profile gate | profile comparison harness | A1 and C2/C3 | before/after node-level evidence for aggregate, pivot, and slice shapes | - -C2 and C3 have separate feature ownership. Neither may modify the other's -renderer branch; the coordinator integrates their operations after the -prepared-set contract is merged. - -### Wave D — cross-cutting reuse and hardening - -| Worker | Scope | Depends on | Deliverable | -|---|---|---|---| -| D1: Required-match reuse | physical required-match lowering and parity tests | B3 | shared-prefix reuse without changing pre-limit semi-join semantics | -| D2: Cost policy | optimizer decision heuristic and explainable rejection reasons | B3, C4 | conservative enablement rule, diagnostics, and disable switch | -| D3: Index changes | candidate index migrations/bootstrap plus measurement | A4, B4, C4 | only profile-justified index additions and documented ingest tradeoff | -| D4: Regression suite | corpus benchmark automation and result/profile artifact checks | A1–A4, B4, C4 | merge-blocking performance/parity gate | - -### Required worker prompt template - -Give each Luna worker a bounded prompt in this form: - -```text -You own . Do not edit . - -Objective: - - -Read first: -- docs/AQL_OPTIMIZATION_WORKLIST.md -- - -Contract: -- Inputs: -- Outputs: -- Must not: special-case FHIR resource names or change public dataframe results. - -Acceptance: -1. -2. -3. go test -4. report changed files, interface assumptions, and any coordinator decision needed. -``` - -### Merge discipline - -1. Merge Wave A first, but permit A1/A2/A3/A4 independent commits. -2. Merge B1 before any shared traversal renderer code. -3. Merge B2 test coverage before B3, then require B4 evidence before enabling - sharing by default. -4. Merge C1 contract before C2/C3 renderer work; merge C4 evidence before - enabling fusion by default. -5. Run the complete corpus after every coordinator merge, not only a worker's - narrow package tests. -6. If a physical IR conflict appears, stop the conflicting workers and have - the coordinator choose one contract; do not resolve it by retaining two - transitional representations. - -### Recommended initial allocation - -With four Luna workers plus a coordinator: - -- Worker 1: A1 profile adapter -- Worker 2: A2 generic fixture/benchmark corpus -- Worker 3: A3 diagnostics/CLI and GraphQL regeneration -- Worker 4: B2 traversal-sharing parity and alpha-renaming test design -- Coordinator: freeze B1 prefix IR after reviewing A2/B2 requirements, then - assign B1 and B3 sequentially. - -With eight workers, add A4, C1, C2 test preparation, and C3 test preparation. -Do not assign two workers to `physical_optimize.go` or `physical_render.go` at -the same time. - -## Execution status - -As of the current execution pass: - -- **Complete:** WP0 profile adapter and corpus profile fixtures. -- **Complete:** generic FHIR benchmark/parity corpus beyond GDC. -- **Complete:** compiler timing and plan diagnostics CLI path. -- **Complete:** B1 canonical traversal-prefix decomposition and rejection - reasons. -- **Complete:** B3 generic scope-safe sibling traversal sharing, including - recursive variable rebinding and typed subsets. It remains constrained to - decomposition-proven plans. -- **Complete:** WP3b recursive nested object rendering and recursive object - cycle validation. -- **Experimental and disabled:** WP3 prepared-set reuse has a physical operation - and renderer, but the live GDC profile was slower and used substantially more - memory. It is not part of the production-default optimization policy. -- **Diagnostics only:** WP4 can classify byte-identical rich consumers, but no - fusion lowering or renderer path currently executes fused aggregate, pivot, - or slice consumers. The GDC profile also produced no eligible multi-consumer - groups under that classifier. -- **Complete:** WP6 profile-driven Explain/index corpus harness (live execution - remains opt-in with `LOOM_COMPILER_ARANGO_INTEGRATION=1`). -- **Complete:** WP5 required-match reuse: duplicate required EXISTS routes are - deduplicated only when their typed route/filter key is identical, with reuse - counted separately from optional traversal sharing. Required routes can also - materialize selected child fields after the pre-window semi-join. -- **Complete:** WP7 structural corpus regression gates, opt-in compiled-query - profiling API, generic Explain/profile artifacts, and the conservative - structural cost policy (`LOOM_PHYSICAL_COST_POLICY` / minimum-savings switch). -- **Complete:** WP8 compatibility renderer deletion and legacy test migration. - The production physical compiler is now the only dataframe compiler path; - the old lowered renderer, planner, named-set types, and compatibility-only - tests have been removed. - -The complete repository test suite is green after the completed packages. -Production and conformance code now use the physical compiler exclusively. - -## Explicit renderer completion packages - -The work packages above also require these two explicitly named renderer -packages. They were previously implicit and should be assigned as separate -Luna tasks. - -### WP3b — Nested object expression rendering - -**Depends on:** WP1 and the frozen physical expression contract. - -`PhysicalObjectExpression` exists in the IR and validator, but it must have a -real renderer before the compatibility renderer can be removed. - -Implementation: - -1. Add recursive `renderObject` support to `physical_render.go`. -2. Render every object field through `renderExpression`, including nested - objects, extracts, aggregates, pivots, slices, and optional child values. -3. Use bind-backed output names; never concatenate user-provided field names - into AQL source. -4. Preserve null/empty behavior and deterministic field ordering. -5. Support objects inside representative slices and nested traversal - projections. -6. Reject recursive physical object cycles during plan validation. - -Acceptance requires scalar-object, nested-object, object-with-pivot, and -object-with-slice fixtures plus live result parity. No object expression may -pass validation without a renderer test. - -### WP8 — Compatibility renderer deletion - -**Depends on:** WP2, WP3, WP3b, WP4, WP5, and the complete parity corpus. - -This is a gated package, not incidental cleanup: - -1. Prove repository-wide that `CompileRequest` is the only production - dataframe execution entrypoint. -2. Replace parity tests that depend only on compatibility AQL text with - semantic-result and live Arango parity tests. -3. Delete `compileLowered`, `Lower`, `lowerSemanticBuilder`, `NamedSet`, and - compatibility-only helpers/tests in dependency order. -4. Remove stale compatibility metadata while preserving any still-public API - fields. -5. Run the full corpus, GraphQL suite, Explain/profile suite, and generated-root - sweep after deletion. - -The deletion gate fails if any physical expression validates without rendering, -any production call site bypasses `CompileRequest`, or any parity fixture still -depends on compatibility-only output text. diff --git a/docs/COMPILER_PERFORMANCE.md b/docs/COMPILER_PERFORMANCE.md new file mode 100644 index 0000000..44ff546 --- /dev/null +++ b/docs/COMPILER_PERFORMANCE.md @@ -0,0 +1,75 @@ +# Compiler performance + +This document keeps the durable conclusions from the retired AQL tournament +harnesses. The old tournament tests and their generated profiles were useful +for exploration, but they are not part of Loom's correctness suite. + +## Current production path + +Dataframe requests use the generic pipeline: + +```text +spec -> semantic -> compiler/ir -> compiler/lower -> compiler/optimize -> render/aql +``` + +The default physical policy includes generic scope-safe sibling traversal +sharing, compact set projection, required-match reuse, and the proven endpoint +lowering rules. Prepared selector arrays and rich-consumer fusion remain +disabled because the measured GDC candidates were slower or produced no +eligible rewrite. The optimizer must not enable a candidate solely because it +reduces AQL text size; result parity, authorization/generation scope, and live +Arango profile evidence are required. + +## Reproducible measurements + +For compiler shape and diagnostics: + +```bash +make compiler-bench +``` + +For the checked-in GDC request against a running GraphQL service: + +```bash +make dataframe-demo DATAFRAME_LIMIT=1000 DATAFRAME_REPEAT=3 \ + DATAFRAME_PRINT_RESPONSE=false +``` + +For Explain/Profile output against the configured Arango database: + +```bash +make dataframe-profile DATAFRAME_PROFILE_LIMIT=1000 +``` + +Live Arango compiler tests are opt-in with +`LOOM_COMPILER_ARANGO_INTEGRATION=1`; they must never be required for ordinary +unit or GraphQL tests. + +## Findings retained from the tournaments + +1. **Index-aware traversal strategy.** Compare native traversal with explicit + endpoint/type equality lookups. Equality predicates can select the + compound edge indexes where broad `IN` predicates fall back to `_to`. + Promote only when the generic corpus proves parity and a whole-query median + improvement. +2. **Traversal-time shaping projection.** Compute the union of selector values + while a child is in scope and retain only identity, nested-navigation keys, + and requested values. Do not add a second payload-bearing prepared pass. +3. **Leaf-set summary pushdown.** For leaves without navigated descendants, + produce aggregate, pivot, and representative-slice outputs from one typed + summary instead of repeatedly enumerating a payload array. +4. **Identity and ordering properties.** Treat deduplication and ordering as + physical properties. Remove `UNIQUE`/`SORT` work only when the proof is + generic and preserves row identity, deterministic order, and slice limits. +5. **Batch root execution.** If the first four changes do not meet the + latency target, prototype a set-oriented root window and grouped edge + lookups. This is a higher-risk alternative to correlated root-by-root + execution and must remain experimental until scope and row-order parity are + proven. +6. **Catalog-backed costing.** Carry relationship cardinality facts into + compilation as optional statistics. Use them to choose between equivalent + physical strategies, with a deterministic no-statistics fallback. + +These are implementation candidates, not promises. A candidate that does not +remove measured scanned items, materialized payload, executor work, or peak +memory should be rejected as noise. diff --git a/docs/DATAFRAME_PACKAGE_REORGANIZATION_PLAN.md b/docs/DATAFRAME_PACKAGE_REORGANIZATION_PLAN.md new file mode 100644 index 0000000..d28f1e8 --- /dev/null +++ b/docs/DATAFRAME_PACKAGE_REORGANIZATION_PLAN.md @@ -0,0 +1,469 @@ +# Dataframe package reorganization plan + +## Objective + +Turn `internal/dataframe` from the repository's catch-all package into a thin, +backwards-compatible façade over small packages with one-way dependencies. The +move is organizational: rendered AQL, request semantics, authorization, +generation isolation, result shape, and public callers must retain their +current behavior. + +The goal is not to make every package tiny. The physical compiler is a real, +cohesive subsystem. The goal is that a new developer can find request types, +semantic meaning, physical AQL lowering, runtime execution, templates, and +errors without reading one 17.5k-line package. + +## Current evidence + +`internal/dataframe` contains 89 Go files and roughly 17.5k code lines. The +largest production responsibilities are currently interleaved: + +| Current files | Lines | Actual responsibility | +| --- | ---: | --- | +| `physical_render.go` | 1,539 | AQL serialization and renderer safety checks | +| `physical_plan.go` | 1,137 | typed physical IR and IR validation | +| `generic_physical_plan.go` | 790 | semantic-to-physical lowering | +| `semantic_plan.go` | 397 | request-to-semantic-plan construction | +| `physical_optimize.go`, `physical_cost.go`, `physical_prefix.go`, `physical_diagnostics.go` | 963 | physical optimization policy, decisions, and diagnostics | +| `service.go`, `execution.go`, `validation.go`, `pivots.go`, auth/generation files | 1,100+ | catalog-aware request preparation and execution | +| `errors.go` | 320 | transport-neutral product error contract | +| experiment/tournament tests | 4,000+ | AQL research evidence mixed into the core package | + +The root package is imported by the GraphQL service, HTTP error mapper, +server command, profile CLI, and compiler conformance suite. Those callers +need stable names such as `Builder`, `CompileRequest`, `Service`, +`CompiledQuery`, and `ErrorCode`; they do **not** need access to physical IR +implementation files. + +## Target layout + +```text +internal/dataframe/ + doc.go # package contract and architecture map + api.go # compatibility aliases/wrappers only + template/ # already separate; retain + spec/ # request, selection, filter, grain contracts + semantic/ # backend-independent FHIR dataframe meaning + physical/ + plan/ # physical IR, validation, shared diagnostics + lower/ # semantic -> physical FHIR graph lowering + optimize/ # semantics-preserving physical rewrites + render/ # physical IR -> parameterized AQL + compiler/ # orchestration and CompiledQuery output + runtime/ # catalog/scope/generation preparation, Run/Stream/Validate + errors/ # stable user-facing error taxonomy + +conformance/compiler/experiments/ # tournament and ablation tests that use public API only +``` + +The root `dataframe` package remains intentionally small: documented stable +entrypoints, type aliases, constant aliases, and thin wrappers. It must not +contain a child package's implementation. Existing imports therefore continue +to work while callers are migrated only when doing so clarifies ownership. + +## Dependency rule + +Child packages must never import `internal/dataframe` (their parent). The +allowed direction is: + +```text +fhirschema, fhirstructs, authscope, catalog, dataset, store/arango + │ + ▼ + spec + │ + ▼ + semantic + │ + ▼ + physical/plan + ▲ ▲ ▲ + │ │ │ + lower optimize render + \ | / + \ ▼ / + └ compiler ┘ + │ + ▼ + runtime + │ + ▼ + dataframe façade +``` + +`errors` is independent and may be imported by `runtime` and transport +adapters. `template` remains independent of compiler/runtime and may import +only generated schema metadata plus its own types. + +This direction prevents the two most likely Go-cycle failures: + +1. runtime/catalog code importing compiler code which imports the root + `dataframe` service; and +2. physical lowering importing a semantic package that imports physical types + merely to express a storage direction. + +Storage routes belong in `physical/lower`, because physical direction is a +stored-edge decision rather than semantic FHIR meaning. + +## Public API compatibility contract + +Before moving production files, freeze the root surface with an API inventory. +At minimum preserve: + +- `Builder`, request selection/filter/traversal types, selector helpers, row + grain/identity types, and typed filter validation; +- `CompileRequest`, `CompileRequestWithPolicy`, `CompiledQuery`, optimization + policy/rule/diagnostic types; +- `Service`, `ServiceConfig`, `RunRequest`, `Result`, `StreamResult`, + `ValidateRequest`, `ValidationResult`, and `QueryDiagnostics`; +- `ExplainCompiledQuery`, `ProfileCompiledQuery`, and `ExecuteQueryRows`; +- the existing `ErrorCode`, `UserError`, `Error`, and constructors. + +Use Go type aliases in `api.go` for types whose methods must remain visible: + +```go +type Builder = spec.Builder +type Service = runtime.Service +type CompiledQuery = compiler.CompiledQuery +type ErrorCode = dataframeerrors.Code +``` + +Use forwarding functions for constructors and functions. Preserve constant +names through constant aliases. Do not use wrapper structs for `Builder`, +`Service`, or `CompiledQuery`: wrappers would silently break assignment, +methods, JSON fixtures, and conformance callers. + +## Work packages + +### WP0 — Baseline, ownership, and failure gate + +**Purpose:** make the reorganization measurable before moving source. + +1. Record `go list` importers of `internal/dataframe`, exported API via + `go doc`, file LOC, and the existing compiler conformance result hash. +2. Add this plan to the developer architecture index and create a short + package-owner table in `internal/dataframe/doc.go`. +3. Capture the current rendered GDC AQL hash and result-parity fixtures. +4. Resolve or explicitly quarantine the current four failing root-package + assertions before extracting physical code: + - `TestCompileRequestUsesPhysicalExecutionForNavigationOnlyGenericPlan`; + - `TestRenderPhysicalPlanGenericNavigation`; + - `TestRenderPhysicalPlanTraversalSetsPreserveRootRowGrain`; + - `TestIdentityDedupCandidateBuildsActualGDC`. + + They currently assert old native-traversal/projection text while the active + renderer emits endpoint lowering. Reconcile them as a separate behavior + verification change, not as a side effect of the package move. +5. Establish a gate after every package move: + +```bash +GOCACHE="$(pwd)/.gocache" GOTOOLCHAIN=auto go test -short ./internal/dataframe/... ./conformance/compiler +GOCACHE="$(pwd)/.gocache" GOTOOLCHAIN=auto go test ./graphqlapi/dataframe ./graphqlapi ./internal/httpapi +git diff --check +``` + +**Acceptance:** a green baseline or a documented, isolated baseline exception +exists before any mechanical move. No behavior test is weakened to make a +move appear safe. + +### WP1 — Extract the request/specification package + +**New package:** `internal/dataframe/spec`. + +**Move as one cohesive unit:** + +- `builder_types.go`; +- `grain.go`; +- `relationship_match.go`; +- `selectors.go`; +- `filter.go` and `filter_semantics.go`. + +**Keep out of this package:** `filter_literal.go` and `selector_render.go`. +They turn validated values/selectors into AQL expressions and therefore belong +with the physical renderer. + +**Implementation steps:** + +1. Move all request AST types, row-grain identity, selector aliases/parsing, + traversal match mode, filter values, and schema-only filter validation. +2. Replace direct root-package references with `spec.*` in semantic and + physical code. +3. Add aliases/constants/functions in root `api.go` before updating external + callers. Keep existing JSON fixture shape unchanged. +4. Move the corresponding unit tests to `spec` and retain external conformance + tests through the root façade. +5. Add a compile-only test that proves a package importing only root + `dataframe` can still construct every public request shape. + +**Acceptance:** `spec` has no catalog, dataset, Arango, AQL-rendering, or +runtime-service import. The root package has no duplicated request type. + +### WP2 — Extract semantic planning + +**New package:** `internal/dataframe/semantic`. + +**Move:** + +- `semantic_plan.go`; +- `semantic_validation.go`; +- `selection_semantics.go`; +- semantic portions of `optimizer.go` if they only describe logical rules. + +**Implementation steps:** + +1. Make `semantic.Plan`, node/field/pivot/aggregate/slice types, plan + construction, graph validation, and selection normalization use `spec`. +2. Keep semantic plans free of AQL variable names, collection bind keys, + physical directions, catalog clients, and Arango explain data. +3. Export only the semantic API needed by compiler/physical lowering. Keep + internal traversal walk helpers private. +4. Move semantic-plan, selection-semantics, and semantic-validation tests with + the package. +5. Retain root aliases for `SemanticPlan` and public diagnostic explanation + types until all callers are deliberately migrated. + +**Acceptance:** semantic planning can compile and test with only `spec` and +generated FHIR schema dependencies. No semantic package import reaches +`physical`, `runtime`, catalog, or Arango. + +### WP3 — Split the physical compiler by responsibility + +This is the largest move and must be sequential; do not parallel-edit the +physical type graph. + +#### WP3a — Physical plan model + +**New package:** `internal/dataframe/physical/plan`. + +**Move:** + +- `physical_plan.go`; +- `physical_scope.go` only where it validates generic physical operations; +- `physical_diagnostics.go`; +- `physical_cost.go`. + +`plan` owns typed physical operations, their validation, policy/decision +records, and compiler diagnostics. It imports `spec`, but not lowering, +optimization, renderer, service, catalog, or Arango. + +#### WP3b — Lowering + +**New package:** `internal/dataframe/physical/lower`. + +**Move:** + +- `generic_physical_plan.go`; +- `physical_lowering.go`; +- `physical_helpers.go`; +- `physical_required_match.go`; +- `storage_route.go`; +- lowering-specific portions of `physical_scope.go`. + +It imports `semantic`, `physical/plan`, `spec`, and `fhirschema`. It is the +only package allowed to select a proven storage route and endpoint-versus-native +traversal strategy. + +#### WP3c — Optimization + +**New package:** `internal/dataframe/physical/optimize`. + +**Move:** + +- `physical_optimize.go`; +- `physical_prefix.go`; +- physical portions of `optimizer.go`. + +It imports `physical/plan` only. It must not render strings or call Arango. +Keep optimization policy defaults/decision reports in `plan` so they remain +available to the compiler façade and diagnostics without a cycle. + +#### WP3d — Rendering + +**New package:** `internal/dataframe/physical/render`. + +**Move:** + +- `physical_render.go`; +- `selector_render.go`; +- `filter_literal.go`. + +Split the current 1,662-line renderer into files in the same `render` package: + +| New file | Content | +| --- | --- | +| `render.go` | public `Render`, bind state, top-level orchestration | +| `render_root.go` | root scan/window/sort/limit operations | +| `render_traversal.go` | native and endpoint traversal sets, required matches | +| `render_expression.go` | extraction, predicates, aggregates, pivots, slices, projections | +| `render_selector.go` | selector and typed-filter expression emission | +| `validate.go` | renderer-only safety validation | + +The renderer imports `physical/plan` and `spec`, returns an immutable rendered +query value, and has no catalog/runtime dependency. + +**Acceptance for WP3:** the actual AQL generated for all conformance fixtures +is byte-for-byte identical unless a separately approved behavior change is in +flight; bind variables and result hashes remain equal; physical package tests +are co-located under the owning subpackage. + +### WP4 — Create a compiler façade + +**New package:** `internal/dataframe/compiler`. + +**Move/replace:** `compile.go` and `physical_execution.go`. + +1. Define `compiler.CompiledQuery` as the stable compiler output. +2. Orchestrate `semantic.Build`, `lower.Build`, `optimize.Apply`, and + `render.Render` in exactly the current order. +3. Preserve `CompileRequest` and `CompileRequestWithPolicy` through root + forwarding functions; retain direct root imports for conformance and CLIs + during the migration. +4. Move compiler integration tests and generic physical execution tests here. +5. Add result-parity tests that compile through both root façade and compiler + package during the migration, then remove the duplicate route after the + façade is proven. + +**Acceptance:** no runtime/catalog/Arango dependencies in compiler. Compiler +can be invoked by the profile CLI and conformance fixtures without constructing +a service. + +### WP5 — Extract runtime preparation and execution + +**New package:** `internal/dataframe/runtime`. + +**Move:** + +- `service.go`; +- `execution.go`; +- `validation.go` and `validation_service.go`; +- `pivots.go`; +- `active_generation.go`, `auth.go`, `auth_scope.go`, and + `dataset_generation.go`; +- `query_runtime.go`, `explain.go`, and `profile.go`. + +**Implementation steps:** + +1. Replace direct compiler calls with `compiler.CompileRequest`. +2. Retain dependency injection for catalog discovery and row execution so + runtime tests remain database-free. +3. Keep Arango access isolated to `ExecuteQueryRows`, Explain, and Profile; + the rest of runtime must remain testable from injected functions. +4. Move catalog-aware validation and pivot expansion here, because they depend + on observed populated fields rather than only FHIR schema semantics. +5. Move service, execution, validation, active-generation, auth-scope, pivot, + and Explain/Profile tests with this package. +6. Re-export `Service`, `ServiceConfig`, execution options, and validation + result types from root aliases/wrappers. + +**Acceptance:** runtime depends downward on compiler/spec/errors and external +infrastructure packages, but compiler/semantic/physical never import runtime. + +### WP6 — Extract error taxonomy and trim the root façade + +**New package:** `internal/dataframe/errors`. + +**Move:** `errors.go` and its tests. + +1. Preserve root aliases and constructors so `graphqlapi/errors.go` and + `internal/httpapi/errors.go` continue compiling unchanged. +2. Update transport adapters to import `dataframe/errors` only after the root + compatibility suite has passed; this is optional, not required for the + initial move. +3. Leave `internal/dataframe/template` intact; it is already a meaningful + standalone package and must not import runtime/compiler. +4. Reduce root production source to `doc.go` and `api.go` (target: under 400 + lines total, excluding compatibility comments). + +**Acceptance:** `internal/dataframe` contains no physical rendering, storage, +catalog, auth, generation, or error implementation. + +### WP7 — Retire research tests and benchmark artifacts + +The package was inflated by more than 4k lines of ablation/tournament tests. +Those harnesses were useful during compiler development but are not durable +correctness tests. + +1. Delete historical endpoint, selector, compact-projection, identity-order, + pivot, and materialization tournament/experiment harnesses. +2. Delete generated candidate AQL, profile JSON, and decision artifacts with + the harnesses. +3. Preserve stable compiler unit tests and generic opt-in Arango + Explain/result-parity tests beside the owning package. +4. Capture reusable conclusions in `docs/COMPILER_PERFORMANCE.md` rather than + preserving candidate rewrites as executable tests. + +**Acceptance:** production package directories contain ownership tests only, +and performance work is represented by production code, focused profiling, +and the concise performance note. + +### WP8 — Enforce the new architecture + +1. Update `docs/DEVELOPER_ARCHITECTURE.md` with the target dependency graph, + public façade policy, and “where does this change belong?” table. +2. Add a lightweight architecture test/script that rejects child packages + importing their parent `internal/dataframe` package. +3. Add package-scoped CI commands for `spec`, `semantic`, physical packages, + compiler, runtime, template, and root compatibility façade. +4. Add a review checklist: new AQL text goes to `physical/render`; FHIR graph + route decisions go to `physical/lower`; request/canonical semantics go to + `spec` or `semantic`; catalog/scope/streaming work goes to `runtime`. +5. Remove stale compatibility aliases only in a separately approved major + internal API cleanup after every direct importer has migrated. + +## Parallelism plan + +| Lane | May run in parallel with | Must wait for | +| --- | --- | --- | +| WP0 baseline and importer inventory | documentation only | nothing | +| WP1 spec | error extraction design | WP0 API inventory | +| WP2 semantic | root façade scaffolding | WP1 | +| WP3 physical | none within physical | WP2 | +| WP4 compiler façade | renderer test organization | WP3 | +| WP5 runtime | WP7 research-test inventory | WP4 | +| WP6 errors | WP7 inventory | root façade scaffolding | +| WP7 test retirement | WP5 only for runtime tests | each owning package move | +| WP8 enforcement/docs | final verification | WP1-WP7 | + +Do not assign separate workers to `physical/plan`, lowering, optimizer, and +renderer simultaneously. Their shared IR is the compiler's hottest and most +volatile boundary; serial ownership avoids accidental import cycles and +semantic drift. + +## Completion criteria + +The reorganization is complete only when: + +- root `internal/dataframe` is a documented façade under 400 production LOC; +- all production implementation belongs to named child packages; +- no child imports its parent package; +- existing GraphQL, HTTP, CLI, and conformance imports compile through the + root compatibility surface; +- compiler fixture AQL/bind/result parity and live Explain checks are preserved; +- runtime scope/generation/authorization tests remain green; +- historical tournament harnesses are retired; durable performance findings + live in [`COMPILER_PERFORMANCE.md`](COMPILER_PERFORMANCE.md); +- the developer architecture document explains where the next feature belongs. + +## One-shot implementation status + +The initial reorganization pass is complete with the following concrete +boundaries: + +- `internal/dataframe/compiler` now owns the pure request/semantic/physical + compiler and its compiler tests; +- `internal/dataframe/runtime` owns catalog-aware preparation, authorization, + generation pinning, validation, execution, streaming, Explain, and Profile; +- `internal/dataframe/errors` owns the structured error contract; +- `internal/dataframe/template` remains the independent guided-template + package; +- `internal/dataframe/api.go` is the compatibility façade used by existing + GraphQL, CLI, HTTP, and conformance imports. + +The follow-up split in +[`DATAFRAME_PACKAGE_REORGANIZATION_ROUND_2.md`](DATAFRAME_PACKAGE_REORGANIZATION_ROUND_2.md) +has now established the IR visibility boundary and moved production code into +`spec`, `semantic`, `compiler/ir`, `compiler/lower`, +`compiler/optimize`, and `compiler/render/aql`. The compiler facade remains the +stable orchestration/API package. Research tests are intentionally still in +their historical locations until the separate conformance-test relocation is +approved and its environment gates are preserved. diff --git a/docs/DATAFRAME_PACKAGE_REORGANIZATION_ROUND_2.md b/docs/DATAFRAME_PACKAGE_REORGANIZATION_ROUND_2.md new file mode 100644 index 0000000..755fac0 --- /dev/null +++ b/docs/DATAFRAME_PACKAGE_REORGANIZATION_ROUND_2.md @@ -0,0 +1,414 @@ +# Dataframe package reorganization — round 2 + +## Decision + +The first pass solved the root-level monolith: `internal/dataframe` is now a +small compatibility facade, and runtime, templates, and errors have real +homes. The remaining structural problem is that `internal/dataframe/compiler` +is a 7.8k-line package containing five separate layers: + +1. dataframe request language and FHIR selection rules; +2. logical/semantic planning; +3. physical IR and its safety invariants; +4. FHIR graph lowering and physical optimization; and +5. AQL rendering. + +Those layers should become packages. The target is not many tiny packages: it +is a compiler whose directory layout mirrors its pipeline and makes dependency +direction enforceable. + +This is a behavior-preserving reorganization. It must use the existing +`fhirschema` metadata, generated `fhirstructs`, graph storage contracts, and +current AQL parity fixtures. No work package invents a FHIR relationship, +storage direction, or selector rule. + +## Survey of the current code + +The current `internal/dataframe` subtree has about 10.5k production lines and +9.8k test lines. `compiler` owns 7.8k production lines and 3.35k unit-test +lines. Its largest files demonstrate real, distinct responsibilities: + +| Current file(s) | Approx. LOC | Actual responsibility | Target owner | +| --- | ---: | --- | --- | +| `builder_types.go`, `grain.go`, `filter*.go`, `selectors.go`, `relationship_match.go` | 0.8k | public request AST, selection/filter/grain contracts | `spec` | +| `semantic_plan.go`, `semantic_validation.go`, `selection_semantics.go` | 0.75k | schema-backed logical dataframe meaning | `semantic` | +| `physical_plan.go`, `physical_helpers.go`, `physical_scope.go` | 1.8k | typed physical IR, clone and scope validation | `compiler/ir` | +| `physical_cost.go`, `physical_diagnostics.go` | 0.55k | optimizer policy/report and explainable physical facts | `compiler/ir` | +| `generic_physical_plan.go`, `physical_lowering.go`, `physical_required_match.go`, `storage_route.go` | 1.25k | FHIR graph route selection and semantic-to-IR lowering | `compiler/lower` | +| `physical_optimize.go`, `physical_prefix.go`, `optimizer.go` | 0.62k | semantics-preserving IR rewrites | `compiler/optimize` | +| `physical_render.go`, `selector_render.go`, `filter_literal.go` | 1.74k | typed IR to parameterized AQL | `compiler/render/aql` | +| `compile.go`, `physical_execution.go` | 0.19k | pipeline orchestration and `CompiledQuery` | `compiler` facade | + +There is also an avoidable API-barrel problem. Root `dataframe/api.go` imports +only `runtime`; `runtime/api.go` then re-exports nearly all compiler and error +types/functions. Runtime is not the owner of the request language or compiler +IR, so this makes navigation misleading and risks runtime becoming another +mega-package. + +The former experiment/tournament/live-gate tests were research harnesses, not +normal package unit tests. They obscured production ownership and have now +been retired. Durable conclusions are summarized in +[`COMPILER_PERFORMANCE.md`](COMPILER_PERFORMANCE.md). + +## Target layout + +```text +internal/dataframe/ + doc.go # architecture map and facade contract + api.go # root compatibility aliases only + errors/ # existing structured user-error taxonomy + template/ # existing guided dataframe templates + spec/ # request AST, selector/filter/grain contracts + semantic/ # request -> backend-independent FHIR plan + compiler/ + api.go # compiler compatibility surface + orchestration + compile.go # semantic -> lower -> optimize -> render + ir/ # typed physical plan, validation, diagnostics + lower/ # FHIR graph/storage-route lowering + optimize/ # IR-only rewrites and policy decisions + render/aql/ # IR -> parameterized AQL + runtime/ # catalog preparation, scope, execution, profile + +conformance/compiler/ + experiments/ # ablations/tournaments; explicit environment gates + integration/ # live Arango parity/Explain coverage +``` + +`compiler` stays a package because it is the useful public programming model +for the profile CLI, conformance suite, and root facade. Its children are +implementation layers. All physical types live in `compiler/ir`, not in +`lower`, `optimize`, or `render`, so no implementation layer owns another +layer's data model. + +## Dependency rules + +```text +fhirschema, fhirstructs, authscope + | + v + spec + | + v + semantic + | + v + compiler/ir <---- compiler/optimize + ^ | + | v + compiler/lower ----> compiler/render/aql + \ / + \ / + v v + compiler + | + v + runtime + | + v + dataframe compatibility facade +``` + +Rules that must be mechanically enforced: + +- `spec` imports schema metadata and `authscope` only; it imports neither + runtime, catalog, Arango, semantic, nor compiler implementation packages. +- `semantic` imports `spec` and `fhirschema`; it does not know collection + names, bind variables, AQL, or `Physical*` types. +- `compiler/ir` imports `spec` only where the typed IR embeds a selector. It + must not import `lower`, `optimize`, `render`, runtime, catalog, or Arango. +- `compiler/lower` imports `semantic`, `spec`, `compiler/ir`, and generated + schema metadata. It is the only layer that may call `ResolveStorageRoute` or + select endpoint versus native graph traversal. +- `compiler/optimize` imports only `compiler/ir`; it never uses rendered AQL, + FHIR resource-name special cases, catalog data, or Arango clients. +- `compiler/render/aql` imports `compiler/ir` and `spec`; it serializes an + already-valid plan and never chooses a FHIR route or optimizer rule. +- `runtime` imports compiler, errors, catalog/dataset/authscope/Arango. No + compiler child may import runtime. +- The root `dataframe` package imports canonical owners directly; it must not + use `runtime` as a transitive alias barrel. + +## Work packages + +### P0 — Freeze the behavior and public surface + +**Owner:** one coordinator. **No source moves.** + +1. Record current public root symbols used by `graphqlapi`, `internal/httpapi`, + commands, and `conformance/compiler`. +2. Capture hashes for the canonical GDC fixture's rendered AQL, bind variables, + columns, result rows, and optimization diagnostics. +3. Run and retain baseline outputs: + + ```bash + GOCACHE="$(pwd)/.gocache" GOTOOLCHAIN=auto go test -short ./internal/dataframe/... ./conformance/compiler + GOCACHE="$(pwd)/.gocache" GOTOOLCHAIN=auto go test ./graphqlapi/dataframe ./graphqlapi ./internal/httpapi + ``` + +4. Add a temporary package-boundary test script that fails if a child of + `internal/dataframe` imports its parent. +5. Treat existing untracked benchmark artifacts and the previous reorg plan as + user work: do not rename, delete, or overwrite them. + +**Acceptance:** a move can be shown to preserve a known rendered query and +public API; no package split is allowed to mask a parity failure. + +### P1 — Remove the transitive runtime API barrel + +**Owner:** one worker. **Must complete before parallel package extraction.** + +1. Split `compiler/builder_types.go` conceptually before moving code: + `Builder`, traversals, selection types, filters, and grain are compiler + inputs; `RunRequest`, `Result`, `QueryDiagnostics`, and `StreamResult` are + runtime results. +2. Make `runtime/api.go` private to the runtime package's own types, then + delete it once all runtime files use explicit `compiler.*` and + `dataframeerrors.*` references. +3. Update root `dataframe/api.go` to alias compiler, runtime, and errors from + their canonical packages directly. Preserve every current root symbol. +4. Keep aliases—not wrapper structs—for `Builder`, `Service`, `CompiledQuery`, + and all physical types. Methods and JSON fixtures must remain unchanged. + +**Acceptance:** direct compiler imports remain limited to runtime and root +facade; `runtime` no longer exports the compiler's entire surface. + +### P2 — Extract `spec` + +**Owner:** one worker after P1. May run in parallel with P6 inventory only. + +Create `internal/dataframe/spec` and move: + +- request AST from `builder_types.go` (`Builder`, `TraversalStep`, + `FieldSelect`, `PivotSelect`, `AggregateSelect`, `RepresentativeSlice`); +- `grain.go`, `relationship_match.go`, `filter.go`, `filter_semantics.go`, and + `selectors.go`; +- the schema-only selector/filter unit tests. + +Do not move `filter_literal.go` or `selector_render.go`: their job is AQL +emission and they belong in `compiler/render/aql`. + +Expose constructor-free value types and validation helpers only. `spec` must +not absorb service result types, catalog-populated-field checks, or AQL text. +Add compiler aliases in `compiler/api.go`, then preserve root aliases in +`dataframe/api.go`. + +**Acceptance:** `go list -deps ./internal/dataframe/spec` contains no runtime, +catalog, Arango, semantic, lower, optimize, or render package. + +### P3 — Extract `semantic` + +**Owner:** one worker after P2. May not overlap P4-P5. + +Create `internal/dataframe/semantic` and move: + +- `semantic_plan.go`; +- `semantic_validation.go`; +- `selection_semantics.go`; +- the semantic plan/validation/selection tests. + +`semantic.Plan` owns `SemanticNode`, fields, pivots, aggregates, slices, row +identity, aliases, match modes, and schema validation. It must contain no AQL +variable names, collection binds, endpoint fields, or Arango explain data. +Move `selectorExecutionMode` out of `selection_semantics.go`: selector mode is +a physical rendering/lowering decision, not a semantic one. + +**Acceptance:** semantic package tests run against `fhirschema` and `spec` +without importing any `compiler/*` implementation package. + +### P4 — Establish `compiler/ir` and the physical proof boundary + +**Owner:** one coordinator. **Serial; it changes shared type ownership.** + +Create `internal/dataframe/compiler/ir`. Move and split the physical model: + +- `physical_plan.go` -> `plan.go`, `expression.go`, `predicate.go`, + `validate.go`; +- clone functions from `physical_helpers.go` -> `clone.go`; +- `physical_cost.go` -> `policy.go` and `policy_report.go`; +- `physical_diagnostics.go` -> `diagnostics.go`; +- IR-only portions of `physical_scope.go` -> `validate_scope.go`. + +Before moving `physical_prefix.go`, extract the generic navigation and exact +scope proofs currently shared with renderer (`validateGenericNavigationTraversal`, +`validateGenericNavigationScopeBlock`, and their dependencies) into +`ir/validate_navigation.go`. This deliberately removes the current wrong-way +dependency where optimizer analysis depends on helpers defined in renderer. + +Keep these invariants in IR: + +- all `Physical*` model types and `Plan.Validate`; +- bind/collection validation, variable definition/use rules, cloning, and + generic project/generation/auth scope proof; +- optimization policy/report data, but not environment-variable policy + loading; and +- renderer-independent diagnostics and traversal-prefix decomposition input. + +**Acceptance:** `compiler/ir` has no FHIR route resolution and no AQL string +construction. Both lowering and renderer can consume the same validated plan. + +### P5 — Extract `lower`, `optimize`, and `render/aql` + +**Owner:** serial coordinator for all three. Do not parallelize these moves. + +#### P5a — `compiler/lower` + +Move `generic_physical_plan.go`, `physical_lowering.go`, +`physical_required_match.go`, `storage_route.go`, compiler-specific +`auth_scope.go`, `dataset_generation.go`, and lowering helpers from +`physical_helpers.go`. + +Split into `lower.go`, `route.go`, `scope.go`, `required_match.go`, +`children.go`, and `rich_shapes.go`. The package accepts `semantic.Plan` and +returns `ir.Plan`. It remains the sole owner of FHIR storage direction, edge +endpoint contracts, project/generation/auth scope insertion, required +semi-joins, and compact/prepared child-set construction. + +#### P5b — `compiler/optimize` + +Move `physical_optimize.go`, `physical_prefix.go`, and `optimizer.go`. +Expose `Apply(plan ir.Plan, policy ir.OptimizationPolicy)`. Environment-based +default-policy construction belongs here or in compiler facade, but its result +must be an `ir.OptimizationPolicy`. All alpha-renaming, traversal-prefix +sharing, and plan rewrites stay here. + +#### P5c — `compiler/render/aql` + +Move `physical_render.go`, `selector_render.go`, and `filter_literal.go`. +Split the 1.6k-line renderer by behavior: `render.go`, `root.go`, +`traversal.go`, `set.go`, `expression.go`, `aggregate.go`, `pivot.go`, +`slice.go`, `selector.go`, and `validate.go`. + +`Render(ir.Plan)` returns an immutable rendered-query value. It may allocate +internal bind names and prune runtime binds, but it cannot alter the IR or +decide routes/optimization. + +**Acceptance:** lower, optimize, and render have only one-way dependencies: +they all consume `ir`; none imports another implementation sibling. + +### P6 — Rebuild the small compiler facade + +**Owner:** coordinator after P5. + +Keep `internal/dataframe/compiler` as the stable entry point, but reduce its +production implementation to: + +- `CompiledQuery` and its output metadata; +- `CompileRequest` / `CompileRequestWithPolicy` orchestration; +- `DefaultPhysicalOptimizationPolicy` forwarding; +- type/function aliases intentionally preserved for root callers and + conformance; and +- integration tests that assert the complete semantic -> lower -> optimize -> + render pipeline. + +`physical_execution.go` should become `compiler/output.go`: it adds the +root-window operation, invokes renderer, and derives user-visible columns and +diagnostics. It must not become a second renderer. + +**Acceptance:** `compiler` imports `spec`, `semantic`, `ir`, `lower`, +`optimize`, and `render/aql`; its own non-alias production code should be +under roughly 500 lines. + +### P7 — Finish runtime organization without over-splitting it + +**Owner:** may run alongside P6 only after compiler aliases are stable. + +Runtime is only ~1.4k production lines, so retain one `runtime` package but +make its file names reflect lifecycle: + +- `types.go`: `RunRequest`, `Result`, stream/diagnostic output; +- `service.go`: dependency injection and public Run/Stream; +- `prepare.go`: active generation and authorization resolution; +- `catalog_validation.go`: discovered field/reference checks; +- `pivot_materialization.go`: flattening result pivots; +- `cursor.go`: query execution; +- `observability.go`: Explain, Profile, and timing helpers. + +Move no compiler semantics into runtime. Runtime can validate what is +populated in a loaded dataset; it cannot reimplement schema/semantic or AQL +rules. + +**Acceptance:** a developer can locate a service request's preparation, +catalog validation, cursor execution, and profiling without opening an API +barrel. + +### P8 — Retire research and live tournament tests + +**Owner:** coordinator after P6/P7. No source move is required. + +Delete the historical `*_tournament_test.go`, `*_experiment_test.go`, and +strategy/live-gate harnesses once their durable conclusions have been captured +in [`COMPILER_PERFORMANCE.md`](COMPILER_PERFORMANCE.md). Keep stable compiler +unit tests and generic opt-in Explain/result-parity tests that exercise the +production path. Delete generated AQL/profile artifacts with the harnesses; +they are not fixtures and cannot act as regression tests. + +**Acceptance:** normal `go test ./internal/dataframe/...` is an ownership +suite, and performance work is represented by production code plus the concise +performance note rather than stale candidate rewrites. + +### P9 — Enforce and document the architecture + +1. Update `docs/DEVELOPER_ARCHITECTURE.md` with the target graph and a + “where does this change go?” table. +2. Add a dependency-check test/script for the rules above. +3. Add focused CI commands for spec, semantic, IR, lower, optimize, renderer, + compiler facade, runtime, and root compatibility. +4. Search for stale imports and require all public callers to compile through + the root facade before removing compatibility aliases in a separate change. + +## Execution order and parallelism + +| Phase | Work | Parallelism | +| --- | --- | --- | +| 0 | P0 baseline | coordinator only | +| 1 | P1 API-barrel removal | coordinator only | +| 2 | P2 spec | P8 test inventory may run in parallel | +| 3 | P3 semantic | no physical move yet | +| 4 | P4 IR | coordinator only | +| 5 | P5 lower -> optimize -> render | strictly serial | +| 6 | P6 compiler facade and P7 runtime | may run in parallel after stable aliases | +| 7 | P8 test retirement, P9 docs/enforcement | may run in parallel after P6/P7 | + +The physical packages must not be delegated to separate workers at the same +time: they share the IR, scope proof, and public aliases. Parallel work there +will create import cycles or silently weaken the authorization/generation +contract. + +## Global acceptance gates + +After every package move: + +```bash +GOCACHE="$(pwd)/.gocache" GOTOOLCHAIN=auto go test -short ./internal/dataframe/... ./conformance/compiler +GOCACHE="$(pwd)/.gocache" GOTOOLCHAIN=auto go test ./graphqlapi/dataframe ./graphqlapi ./internal/httpapi +GOCACHE="$(pwd)/.gocache" GOTOOLCHAIN=auto go test ./... +git diff --check +``` + +For any physical move, additionally prove the canonical GDC dataframe keeps +the same rendered AQL/bind/result hashes and run the existing live Arango +Explain/result-parity gate when its container is available. A package move may +change imports and file paths; it may not change FHIR schema behavior, graph +scope, authorization, dataset-generation isolation, or query results. + +## Implementation status + +The production extraction is now in place. `spec`, `semantic`, +`compiler/ir`, `compiler/lower`, `compiler/optimize`, and +`compiler/render/aql` are separate packages with one-way source dependencies. +The root `dataframe` package is a compatibility facade, and compiler +orchestration remains in the small `compiler` package. Runtime result types +are separate from request/spec types. `runtime/api.go` remains as a source- +compatibility barrel for direct runtime importers; new code should import the +canonical owner. + +The package-boundary checks are executable with: + +```bash +make dataframe-boundaries +``` + +The research/tournament tests and generated benchmark corpus have been +retired. Their durable strategy findings are preserved in +[`COMPILER_PERFORMANCE.md`](COMPILER_PERFORMANCE.md), while production package +tests and the conformance compiler suite remain the correctness suite. diff --git a/docs/DEVELOPER_ARCHITECTURE.md b/docs/DEVELOPER_ARCHITECTURE.md index 03eab7e..d645d21 100644 --- a/docs/DEVELOPER_ARCHITECTURE.md +++ b/docs/DEVELOPER_ARCHITECTURE.md @@ -60,8 +60,13 @@ GraphQL request -> dataframebuilder.Service -> dataframe compatibility façade -> dataframe/runtime.Service - -> dataframe/compiler semantic validation and lowering - -> lowered AQL compiler + -> dataframe/compiler facade + -> dataframe/spec request contracts + -> dataframe/semantic logical plan + -> dataframe/compiler/ir typed physical plan + -> dataframe/compiler/lower FHIR storage lowering + -> dataframe/compiler/optimize IR rewrites + -> dataframe/compiler/render/aql parameterized AQL -> Arango query execution/streaming ``` @@ -81,14 +86,32 @@ layout, plus the explicitly proven `ResearchSubject --study--> ResearchStudy` sufficient proof; every other forward route remains rejected until it has a verified storage contract. -The compiler package contains the typed physical plan, lowering, optimizer, -renderer, and compiler diagnostics. Runtime code may call the compiler, but the -compiler must never import runtime, catalog, or HTTP/GraphQL transport code. -The root dataframe import path remains stable through aliases and forwarding -functions so external callers do not need a flag-day migration. +The compiler facade orchestrates independent `spec`, `semantic`, `compiler/ir`, +`compiler/lower`, `compiler/optimize`, and `compiler/render/aql` packages. +`spec` owns request contracts, `semantic` owns backend-independent meaning, +`ir` owns typed physical operations and scope proofs, `lower` owns FHIR route +and endpoint decisions, `optimize` owns semantics-preserving IR rewrites, and +`render/aql` owns serialization only. Runtime code may call the compiler, but +no compiler child may import runtime, catalog, or HTTP/GraphQL transport code. +The root dataframe import path remains stable through direct aliases and +forwarding functions so external callers do not need a flag-day migration. + +When adding code, use this lookup table: + +| Change | Owner | +| --- | --- | +| New request/filter/selector contract | `internal/dataframe/spec` | +| FHIR schema meaning or logical selection | `internal/dataframe/semantic` | +| Physical operation or scope invariant | `internal/dataframe/compiler/ir` | +| FHIR edge route or endpoint lowering | `internal/dataframe/compiler/lower` | +| Cost-gated physical rewrite | `internal/dataframe/compiler/optimize` | +| AQL text or bind emission | `internal/dataframe/compiler/render/aql` | +| Catalog, auth, generation, cursor, or profiling | `internal/dataframe/runtime` | For the complete ownership map and move history, see -[`DATAFRAME_PACKAGE_REORGANIZATION_PLAN.md`](DATAFRAME_PACKAGE_REORGANIZATION_PLAN.md). +[`DATAFRAME_PACKAGE_REORGANIZATION_PLAN.md`](DATAFRAME_PACKAGE_REORGANIZATION_PLAN.md) +and the current compiler split plan +[`DATAFRAME_PACKAGE_REORGANIZATION_ROUND_2.md`](DATAFRAME_PACKAGE_REORGANIZATION_ROUND_2.md). ## Compatibility tracks and removal order diff --git a/docs/LUNA_AQL_EXECUTION_ROUND_3.md b/docs/LUNA_AQL_EXECUTION_ROUND_3.md deleted file mode 100644 index 8f9cedb..0000000 --- a/docs/LUNA_AQL_EXECUTION_ROUND_3.md +++ /dev/null @@ -1,683 +0,0 @@ -# Luna execution plan: AQL execution optimization round 3 - -## Mission - -Reduce the Arango execution time and retained memory of Loom's generic FHIR -dataframe AQL. Optimize the generic physical translation, not the example -schema or the Go/GraphQL request path. - -This plan replaces the earlier prepared-selector and byte-identical-consumer -fusion plan. The current compiler already proved those formulations do not -justify production work: - -- the second prepared array was slower and added roughly 303 MB of peak memory; -- the rich-consumer classifier found no multi-consumer group in the GDC query; -- native traversals ignore Loom's endpoint-first compound edge indexes; and -- payload-bearing sets are materialized, deduplicated, sorted, and then scanned - again for aggregates, pivots, and slices. - -The work below is ordered around removal of those measured costs. A work -package is not complete merely because it adds an IR type, optimizer rule, or -passing unit test. It must either prove a material profile improvement or be -rejected and removed. - -Read `docs/AQL_EXECUTION_IMPLEMENTATION_AUDIT.md` completely before starting -any package. - -## Current baseline and invariant input - -The invariant benchmark is the real GraphQL request formed by: - -- `examples/meta_gdc_case_matrix.graphql` -- `examples/meta_gdc_case_matrix.variables.json` -- limit 1,000 -- project `ARANGODB_PROTO` -- database `fhir_proto` - -Checked-in baseline artifacts: - -- `docs/benchmarks/meta_gdc_case_matrix-profile.aql` -- `docs/benchmarks/meta_gdc_case_matrix-profile.json` -- `docs/benchmarks/GDC_AQL_PROFILE.md` - -| Measure | Baseline | -|---|---:| -| AQL hash | `c0b39eb0ec0f29a09b1661c78fc377159881aae81214e505a5427495c8a7e07c` | -| canonical result hash | `17faea7ac3ee7f308b37223f376530a0660f8068d5e015cc573cf99ccb4045ca` | -| Arango executing phase | 5.928s | -| indexed items scanned | 475,876 | -| full scans | 0 | -| peak memory | 269,844,480 bytes | -| `UNIQUE` expressions | 8 | -| `SORT` clauses | 11 | -| native traversals | 4 | -| post-materialization set loops | 7 | -| child sets retaining payload | 6 | - -The baseline numbers are reference evidence, not permission to compare results -from a different database state. WP0 must recapture a same-session baseline -before every experiment series. - -## Global semantic contracts - -Every work package must preserve: - -1. one row per root and ascending root `_key` order; -2. root project, generation, authorization, and required filters before the - root `SORT/LIMIT` window; -3. optional child shaping after the root window; -4. project, exact generation, and authorization checks on every traversed edge - and node; -5. route direction, edge label, endpoint discriminator, and target type from - `resolveStorageRoute` and generated `fhirschema` data only; -6. bind-backed values and collection binds; no interpolated user values; -7. exact null versus empty-array behavior, output column names, array order, - `SORTED_UNIQUE`, pivot collision selection, and representative-slice - sort-before-limit semantics; -8. duplicate-edge identity semantics and deterministic tie-breaking; -9. inbound and proven outbound traversal behavior, notably - `ResearchSubject -> ResearchStudy`; and -10. a deterministic correct fallback when statistics or a specialized - strategy are unavailable. - -Production code must never branch on `Patient`, GDC, a `child_set_N` variable, -an example column name, or a known example edge label. - -## Required evidence and promotion gate - -Every experiment and production packet records: - -- commit/worktree hash and hashes of every owned file before editing; -- exact command, policy environment, database, project, limit, and run time; -- rendered AQL hash and canonical result hash; -- five raw warm client and Arango execution times, median, and minimum; -- response rows and bytes; -- scanned full/index items and peak memory; -- traversal calls/items/filtered/runtime and selected index names/fields; -- top ten profile nodes by cumulative runtime and by item count; -- counts of `UNIQUE`, `SORT`, traversal, materialized-set, payload-retaining, - and post-materialization enumeration operations; -- the structural reason the candidate should improve the plan; and -- an `enable`, `cost-gate`, or `reject` decision. - -Use: - -```bash -make dataframe-demo \ - DATAFRAME_LIMIT=1000 \ - DATAFRAME_REPEAT=5 \ - DATAFRAME_PRINT_RESPONSE=false - -make dataframe-profile \ - DATAFRAME_PROFILE_LIMIT=1000 -``` - -A production rewrite is promotable only when: - -- result hashes match at limits 25 and 1,000; -- there are zero full collection scans; -- scope and route parity tests pass; -- the same-session five-run warm median improves by at least 10%; or the - targeted profile region loses at least 25% of its work while the whole query - improves by at least 5%; -- peak memory does not regress by more than 5%; and -- protected scalar-root, single-child, aggregate, pivot, slice, deep traversal, - sibling traversal, required-match, auth, generation, and outbound cases do - not regress by more than 5%. - -An experiment with no measurable benefit is a successful rejection. Do not -leave its production switch, alternate renderer, or unused IR behind. - -## Ownership and parallel execution - -The following files are shared compiler files. Only the integration -coordinator may edit them: - -- `internal/dataframe/physical_plan.go` -- `internal/dataframe/generic_physical_plan.go` -- `internal/dataframe/physical_optimize.go` -- `internal/dataframe/physical_render.go` -- `internal/dataframe/physical_cost.go` -- `internal/dataframe/physical_diagnostics.go` -- `internal/dataframe/physical_execution.go` - -Experiment workers may add isolated `*_experiment_test.go` files under -`internal/dataframe/` or `internal/store/arango/`, add benchmark artifacts -under their assigned `docs/benchmarks/round3//` directory, and extend -`cmd/dataframe-profile/` only when their package explicitly owns it. They may -not patch shared production behavior. - -```text -Wave 0, serialized: - WP0 baseline lock and parity harness - -Wave 1, parallel experiments: - WP1 endpoint/index strategy matrix - WP3 traversal-time shaping projection - WP6 identity/order/dedup property proof - -Wave 2, serialized coordinator merges: - WP2 endpoint-aware traversal lowering, only if WP1 passes - WP4 traversal-time shaping, only if WP3 passes - WP7 physical identity/order properties, only for WP6-proven changes - -Wave 3, after WP4: - WP5 leaf summary pushdown - -Wave 4, conditional parallel investigations: - WP8 batch-root execution, only if warm median remains above 3s - WP9 catalog-backed costing, only after at least two strategies survive - -Wave 5, serialized: - WP10 integration, cleanup, and final profile -``` - -No worker may write a shared file while another worker or coordinator owns it. -Stop when an unowned IR change is required and hand the coordinator a typed IR -proposal instead. - -## WP0 - lock baseline, parity, and profile accounting - -**Purpose:** make every later speedup attributable and reproducible. - -**Owner:** coordinator. **May edit:** `cmd/dataframe-profile/`, focused profile -tests, `docs/benchmarks/round3/wp0/`, and Makefile profile targets. Do not alter -compiler output. - -### Tasks - -1. Verify the exact GraphQL request and variables are used by both demo and - profile commands. Record the effective limit and every bind variable without - logging authorization secrets. -2. Capture a fresh five-run warm baseline and raw `PROFILE` result. Preserve - raw artifacts, not only a Markdown summary. -3. Make canonical result hashing insensitive only to JSON object key order. It - must remain sensitive to row order, array order, nulls, empty arrays, scalar - types, and values. -4. Add or verify structural AQL accounting for the operation counts required by - the evidence contract. -5. Add a comparison command or test that accepts baseline/candidate profile - artifacts and reports absolute and percentage changes. It must not sum - nested cumulative profile runtimes. -6. Run the protected generic compiler corpus once and record its commands and - current hashes. - -### Acceptance - -- two unchanged consecutive captures have identical result and AQL hashes; -- their warm medians are within 10%, otherwise diagnose environmental noise; -- comparison output identifies selected edge indexes and the four current - traversal regions; and -- no production AQL changes. - -**Artifact:** `docs/benchmarks/round3/wp0/BASELINE.md` plus raw JSON/AQL. - -## WP1 - endpoint/index traversal strategy experiment - -**Purpose:** determine which generic traversal shape eliminates the largest -measured filtered-adjacency work. - -**Owner:** experiment worker. **May edit:** new -`internal/dataframe/*endpoint_strategy_experiment_test.go`, new -`internal/store/arango/*endpoint_strategy_experiment_test.go`, and -`docs/benchmarks/round3/wp1/`. **Must not edit shared compiler files or create -or remove persistent indexes.** - -### Strategy matrix - -For each route, compare these four shapes independently: - -1. shared native traversal over multiple typed sibling routes; -2. independent native typed traversals; -3. shared explicit edge lookup with endpoint equality and multiple types; and -4. independent explicit edge lookups with endpoint and type equality. - -Test the three expensive nested regions first, then the shared root region. -Replace only one region per candidate so its effect is attributable. - -### Tasks - -1. Obtain direction, edge collection, target collection, endpoint field, - discriminator field, label, and target type from `resolveStorageRoute`. -2. Generate test-only candidate AQL by a structured helper or narrowly replace - one identified physical region. Do not use resource-specific string - replacement. -3. For INBOUND, compare edge `_to == parent._id`, the route's from-type - discriminator, and the `_from` node join. For OUTBOUND, compare `_from`, the - to-type discriminator, and `_to` node join. -4. Apply edge project/generation/auth scope before joining the node. Apply node - project/generation/auth/resource-type scope before returning it. -5. Preserve current identity deduplication, ordering, child predicates, output - shape, and compact retained fields. -6. Capture `EXPLAIN` before executing each candidate. Reject any explicit - candidate that does not select the intended endpoint-first compound index. -7. Test equality and multi-type `IN` separately; do not infer that an index - chosen for equality will be chosen for `IN`. -8. Cover root parent, nested parent set, zero/one/many neighbors, duplicate - edges, restricted/unrestricted auth, null/named generation, and the proven - outbound route. - -### Required decision table - -For each structural route class, report native/shared, native/independent, -explicit/shared, and explicit/independent median, scanned items, filtered -items, memory, index, and parity. Identify whether sharing becomes a loss once -typed equality enables the compound index. - -### Stop conditions - -- stop if a candidate needs a new persistent index; -- stop if scope must move after node materialization; -- reject a candidate that selects only the default edge index; -- reject resource-specific wins that cannot be expressed using route metadata; -- do not propose required-match lowering in this packet. - -### Acceptance and handoff - -Pass only if at least one route-generic explicit strategy satisfies the global -promotion gate. Hand off a typed `PhysicalTraversalStrategy` proposal, exact -filter ordering, supported route classes, unsupported cases, and profile -evidence. Do not implement it in production. - -## WP2 - production endpoint-aware traversal lowering - -**Purpose:** add the WP1-winning strategy without weakening native traversal -fallbacks. - -**Owner:** coordinator. **Depends on:** WP1 pass. **Owns:** shared compiler -files, relevant focused tests, and `docs/benchmarks/round3/wp2/`. - -### IR contract - -Add a typed strategy to `PhysicalTraversal`; do not store AQL fragments. It -must describe: - -- native graph versus explicit endpoint lookup; -- direction and endpoint field; -- edge-to-node join field; -- edge type discriminator field/value; -- route/collection binds already validated by `resolveStorageRoute`; and -- a reason/cost decision visible in diagnostics. - -### Tasks - -1. Extend physical validation to reject inconsistent endpoint/direction/join - combinations and undefined collection binds. -2. Lower only the route classes proven by WP1. Required matches, variable-depth - traversal, `ANY`, and unproven route shapes remain native. -3. Render edge scope before node lookup and node scope before child predicates. -4. Preserve duplicate-edge `UNIQUE`, deterministic order, compact projection, - nested parent correlation, and outbound direction. -5. Add an independent rule switch for ablation. Default-enable it only if the - generic protected corpus and GDC gate pass. -6. Report native versus endpoint decision, selected index expectation, and - rejection reason in physical diagnostics. - -### Tests - -- plan validation for every legal/illegal direction combination; -- exact AQL shape and bind tests for inbound and outbound; -- duplicate edge, optional empty, child predicate, auth, and generation parity; -- live Explain asserts the endpoint-first index for enabled candidates; -- live result parity and five-run ablation profile. - -### Acceptance - -Meet WP1's measured gate in the production execution path. If only a structural -subset wins, use a deterministic structural gate; do not install a broad -heuristic based on FHIR type names. - -## WP3 - traversal-time shaping projection experiment - -**Purpose:** prove that selector values can be computed while the child node is -in scope, eliminating payload retention and the harmful second prepared array. - -**Owner:** experiment worker. **May edit:** new -`internal/dataframe/*traversal_projection_experiment_test.go` and -`docs/benchmarks/round3/wp3/`. **Must not edit shared compiler files.** - -### Candidate shape - -One child-set item should retain only the union actually required downstream: - -- `_id` only when a nested traversal consumes the node; -- `_key` or an explicit stable identity/order key when required; -- route/type fields only when a downstream operation needs them; and -- named selector arrays/scalars computed from the node payload in the traversal - `RETURN` object. - -It must not create a second prepared array, copy `payload`, or retain an -original-node escape hatch unless a specific unsupported consumer requires a -mixed fallback plan. - -### Tasks - -1. Walk all consumers of each physical set and collect selector requirements - from aggregate values/predicates, pivot key/value, slice predicate/sort/ - projections, filters, derived expressions, and descendant navigation. -2. Canonicalize a projected selector by resource type, selector path, - cardinality, fallback semantics, and evaluation scope. Never merge selectors - that merely render similar text. -3. Classify retention as identity, navigation, ordering, projected selector, - or unsupported payload fallback. Report the reason for every retained field. -4. Prototype the GDC child sets with one shaped object produced in the original - set subquery. Rewire test-only consumers to read that same object. -5. Measure the candidate alone and combined with the WP1 winner, keeping the - two improvements separately attributable. -6. Cover scalar and array selectors, repeated coding paths, null/missing - intermediate objects, fallback chains, child filters, nested navigation, - and mixed supported/unsupported consumers. - -### Stop conditions - -- reject any design that materializes both shaped and payload-bearing copies; -- do not silently disable a fallback selector; -- stop and propose an IR contract if consumer scope cannot be represented; -- do not count fewer AQL characters as a benefit. - -### Acceptance and handoff - -Pass if payload-retaining sets and repeated payload enumeration materially fall, -peak memory does not regress, exact parity holds, and the global performance -gate passes. Hand off a typed set-item projection contract, consumer rewiring -map, retention-reason schema, unsupported-case fallback, and evidence. - -## WP4 - production traversal-time shaping - -**Purpose:** replace prepared-set post-processing with the WP3-proven single -materialization shape. - -**Owner:** coordinator. **Depends on:** WP3 pass. **Owns:** shared compiler -files, focused tests, and `docs/benchmarks/round3/wp4/`. - -### Tasks - -1. Add typed projected fields and retention requirements to the physical set - item contract. Stable field names derive from canonical selector identity. -2. Build requirements after all consumers and descendants are known, then - render them in the set's original `RETURN` object. -3. Rewire eligible extract, aggregate, pivot, slice, predicate, sort, and - derived-field reads to projected fields. -4. Retain `_id` only for descendant traversal, identity only when dedup/order - requires it, and payload only for an explicitly diagnosed unsupported - consumer. -5. Remove or supersede `PhysicalPreparedSet` and its renderer when all supported - uses migrate. Do not maintain two production representations. -6. Validate every projected reference is defined by its source set and cannot - be read outside its item scope. -7. Add diagnostics listing projected selectors, retained fields/reasons, - fallback consumers, estimated item width, and removed payload retention. - -### Tests - -- selector canonicalization and stable names; -- nested-navigation `_id` retention and leaf omission; -- aggregate/pivot/slice/filter/derived rewiring; -- fallback and mixed-consumer behavior; -- duplicate edge and ordering parity; -- live result/profile ablation with rule on/off. - -### Acceptance - -Meet the WP3 gate in production. Delete the rejected second prepared-array path -and its switches/tests once no production use remains. A rule that normally -retains payload is not accepted as traversal-time shaping. - -## WP5 - leaf-set summary pushdown - -**Purpose:** compute leaf aggregate, pivot, and representative-slice outputs -inside one child subquery instead of repeatedly scanning a materialized set. - -**Owner:** coordinator. **Depends on:** WP4. **Owns:** shared compiler files, -focused tests, and `docs/benchmarks/round3/wp5/`. - -### Eligibility - -A set is initially eligible only when it has no navigated descendants and all -of its consumers can be represented by shaped selectors. A summary may contain -different consumers of the same source; byte-identical expression grouping is -not the eligibility rule. - -### IR contract - -Add a typed summary operation with: - -- source identity/dedup contract; -- named aggregate outputs; -- named pivot outputs with key/value/collision semantics; -- named bounded slices with predicate, sort, tie-break, limit, and projections; -- explicit ordering requirements; and -- a fallback reason when a consumer remains outside the summary. - -### Tasks - -1. Group consumers by source set and compatible source identity/predicate scope, - not by identical full expression text. -2. Deduplicate source identity once. Preserve aggregate-specific predicates and - null filtering inside each named result. -3. Keep `COUNT` as direct set cardinality where possible. Preserve - `COUNT_DISTINCT`, `DISTINCT_VALUES`, `MIN`, `MAX`, `FIRST`, and `EXISTS` - semantics exactly. -4. Preserve pivot allowed columns, sparse keys, key/value array behavior, - sorted collision selection, and grouped values. -5. Preserve slice filter, sort-before-limit, stable tie-break, and per-item - projection. A bounded slice must not force an unbounded summary array. -6. Return one typed summary object and have the root projection read named - fields without re-enumerating the child set. -7. Compare summary pushdown alone against WP4 and report incremental benefit. - -### Tests - -- each aggregate operation and null/empty behavior; -- count plus distinct values over one source; -- aggregate plus slice; aggregate plus pivot; all three together; -- same source with different predicates remains semantically independent; -- pivot collision/sparse columns; slice ties/limits; duplicate edges; -- high fan-out and empty leaf sets; auth/generation parity; -- live profile proves fewer post-materialization loops. - -### Acceptance - -Require at least 5% incremental whole-query improvement over WP4 and at least -15% combined improvement over WP0, with no memory regression. Otherwise reject -the operation and remove its unused IR instead of calling diagnostics fusion. - -## WP6 - identity, ordering, and deduplication proof - -**Purpose:** identify exactly which `UNIQUE` and `SORT` operations are redundant -without guessing about AQL executor order. - -**Owner:** experiment worker. **May edit:** isolated experiment tests and -`docs/benchmarks/round3/wp6/`. **Must not edit shared compiler files.** - -### Tasks - -1. Inventory every current `UNIQUE` and `SORT`, its source set, consumer, key, - tie-break, and semantic reason. -2. Model candidate properties on paper/test helpers: - - identity unique by node `_id` or `_key`; - - stable ascending order by an exact key tuple; - - unordered; - - bounded by a known limit; and - - property invalidation by filter, projection, union, traversal, or grouping. -3. Prove duplicate-edge behavior when replacing object-level `UNIQUE` with - identity-key deduplication. Payload/object equality is not identity equality. -4. Test whether set materialization order can satisfy a slice's exact sort and - tie-break. Do not assume traversal order or `UNIQUE` output order. -5. Detect and remove duplicated sort keys such as `_key, _key` only as a - correctness cleanup; measure separately from executor-level sort removal. -6. Prototype removal of one operation at a time and capture parity/profile - evidence. Include high fan-out and intentionally duplicated edges. - -### Acceptance and handoff - -Pass only individual property rules that remove executor sort/dedup work and -meet the targeted/whole-query gate. Hand off transfer/invalidation rules and a -list of proven removals. Reject any rule dependent on undocumented traversal -order. - -## WP7 - production physical properties - -**Purpose:** encode only WP6-proven identity/order facts and use them to avoid -redundant work. - -**Owner:** coordinator. **Depends on:** WP6 pass. **Owns:** shared compiler -files, focused tests, and `docs/benchmarks/round3/wp7/`. - -### Tasks - -1. Add explicit physical properties for identity uniqueness, ordered key tuple, - and bound. Unknown is the safe default. -2. Define property transfer and invalidation for every physical operation. -3. Make dedup and sort requirements explicit consumers of those properties; - suppress an operation only when the input proves the exact requirement. -4. Normalize duplicate sort keys without changing requested direction or null - behavior. -5. Emit diagnostics for every retained and removed sort/dedup operation with - its proof. -6. Add rule-level ablation and profile independently from WP2/WP4/WP5. - -### Acceptance - -All WP6 semantic cases pass, diagnostics contain a proof for every removal, and -the production profile reproduces the measured benefit. An unknown property -must render the current conservative operation. - -## WP8 - conditional batch-root execution experiment - -**Purpose:** test whether processing the root window as a set is materially -faster than executing correlated child work once per root. - -**Run only if:** the five-run warm median remains above 3 seconds after all -accepted WP2/WP4/WP5/WP7 changes. - -**Owner:** experiment worker. **May edit:** isolated experiment tests and -`docs/benchmarks/round3/wp8/`. No shared production edits. - -### Candidate shape - -1. Materialize the scoped, sorted, limited root window exactly once. -2. Look up relevant scoped edges for the complete root identity set. -3. Join scoped child nodes, preserving root identity on every row. -4. Group/deduplicate/shape by root identity. -5. Reassemble output in original root-window order, including roots with no - optional children. - -### Tasks and risks - -- compare correlated and batched shapes at limits 25, 100, and 1,000; -- profile edge-index behavior for `IN root_ids` versus per-root equality; -- prove auth and generation scope before grouping; -- prove duplicate-edge and optional-empty behavior; -- bound intermediate cardinality and memory; and -- test one-hop and nested paths separately before composing them. - -Reject batching if `IN` loses the compound index, memory grows above the global -gate, optional roots disappear, or improvement exists only at one hard-coded -limit/resource. - -### Acceptance and handoff - -Require at least 15% additional whole-query improvement at limit 1,000 and no -more than 5% regression at 25/100. Hand off a typed root-batch/subplan proposal -and evidence; do not productionize in this package. - -## WP9 - conditional catalog-backed physical costing - -**Purpose:** choose among proven physical strategies using real generic -cardinality/width evidence. - -**Run only if:** at least two production-safe strategies have shape-dependent -winners. Statistics are not useful when there is no choice to make. - -**Owner:** coordinator or isolated investigator followed by coordinator merge. - -### Tasks - -1. Trace current `catalog.PopulatedReference.EdgeCount` production ownership and - define a read-only compilation statistics snapshot keyed by validated route, - project, generation, and authorization visibility where available. -2. Never query discovery repeatedly during rendering. Fetch/cache statistics at - the request/compiler boundary with an explicit freshness policy. -3. Estimate root count, edge fan-out, selectivity, retained item width, and - expected materialized rows. Record unknown separately from zero. -4. Use statistics only to choose among strategies already proven semantically - equivalent: shared/independent, native/endpoint, shaped/fallback, or - correlated/batched. -5. Provide a deterministic no-statistics fallback matching a proven production - policy. Statistics never change result semantics. -6. Emit the inputs, estimate, selected strategy, and reason in diagnostics. -7. Test missing, stale, zero, extreme, and contradictory statistics and verify - they cannot cause invalid IR. - -### Acceptance - -The cost policy must select the faster strategy across a route/cardinality -corpus with no protected-case regression. Merely plumbing `EdgeCount` without a -measured strategy-selection win is not completion. - -## WP10 - final integration, deletion, and report - -**Purpose:** retain only proven generic translations and leave one coherent -production compiler. - -**Owner:** coordinator only. **Depends on:** every accepted package. - -### Tasks - -1. Rebase decisions on a fresh WP0 same-session baseline. -2. Run each accepted rule independently and cumulatively at limits 25, 100, and - 1,000. Detect interactions where two individually useful rewrites regress in - combination. -3. Run the full generic unit suite, physical renderer/validator suite, result - parity suite, live Arango Explain/profile suite, auth/generation cases, and - proven outbound route. -4. Save final raw AQL/profile artifacts and a comparison table against WP0. -5. Delete rejected experiments, dead switches, stale diagnostics, unused IR, - the superseded prepared-array path, and documentation claims contradicted by - production code. -6. Confirm no FHIR resource, route, example set variable, or example column is - hard-coded in production optimizer logic. -7. Run `go test ./... -count=1` and the exact five-run demo/profile commands. - -### Final acceptance target - -- exact result parity and zero full scans; -- endpoint-first index selected wherever the accepted strategy requires it; -- peak memory below 200 MB; -- five-run warm Arango median below 4.5 seconds after endpoint/projection work; -- stretch median below 3 seconds after summary/property or batch work; and -- a plain explanation of which physical rewrite removed which scanned items, - payload materialization, set loop, dedup, or sort. - -If the target is not met, report the remaining top profile region honestly. Do -not label added compiler machinery as an optimization without disappeared -runtime work. - -## Luna work-package prompt template - -Use this prompt for each worker, replacing the placeholders exactly: - -```text -Execute in Loom. - -Read docs/LUNA_AQL_EXECUTION_ROUND_3.md and -docs/AQL_EXECUTION_IMPLEMENTATION_AUDIT.md completely, then read every source -file named by the package. Own only . Do not edit shared compiler -files unless this package designates you as coordinator. - -Before editing, record git status and SHA-256 hashes for every owned existing -file. Preserve unrelated dirty changes. Use fhirschema and -resolveStorageRoute; never hard-code a FHIR resource, edge, child_set variable, -or GDC column. Preserve every global semantic contract. - -Run the package baseline first. Implement only this package. Run its named -unit/live tests and produce its required evidence directory. Report changed -files, before/after hashes, raw profile metrics, rejected experiments, the -enable/cost-gate/reject decision, and coordinator decisions required. - -Stop rather than guess if an unowned IR change is required, an owned file -changes concurrently, baseline hashes/results differ unexpectedly, scope or -ordering semantics would change, the intended index is not selected, or the -required profile benefit is absent. -``` diff --git a/docs/LUNA_AQL_OPTIMIZATION_ROUND_2.md b/docs/LUNA_AQL_OPTIMIZATION_ROUND_2.md deleted file mode 100644 index 7b297fe..0000000 --- a/docs/LUNA_AQL_OPTIMIZATION_ROUND_2.md +++ /dev/null @@ -1,342 +0,0 @@ -# Luna High execution plan: AQL optimization round two - -## Mission - -Reduce Loom's warm rich-dataframe AQL time without changing results, -authorization, generation isolation, supported FHIR routes, or GraphQL. The -physical compiler is the only production path. Do not restore compatibility -code or add resource-specific optimizer rules. - -Current live GDC baseline over loaded `META`, database `fhir_proto`, project -`ARANGODB_PROTO`: - -| Measure | Baseline | -|---|---:| -| rows / response | 1,000 / 3,303,295 bytes | -| mean / warm HTTP | 6.364s / 6.339s | -| Arango query | 6.301s | -| warm preparation / compilation | 0.075ms / 1.212ms | -| row materialization / HTTP overhead | 1.748ms / about 35ms | -| traversal sets / eliminated traversals | 4 / 2 | - -The warm bottleneck is Arango, not Go compilation. The first request still -spends about 10.75s in relationship discovery; WP7 addresses that separately. - -Baseline command: - -```bash -make dataframe-demo DATAFRAME_LIMIT=1000 DATAFRAME_REPEAT=3 DATAFRAME_PRINT_RESPONSE=false -``` - -## Read first - -- `docs/AQL_OPTIMIZATION_WORKLIST.md` -- `docs/benchmarks/AQL_PROFILE_CORPUS.md` -- `conformance/compiler/fixtures/gdc-case-matrix.json` -- `examples/meta_gdc_case_matrix.graphql` -- `internal/dataframe/physical_plan.go` -- `internal/dataframe/physical_optimize.go` -- `internal/dataframe/physical_render.go` -- `internal/dataframe/physical_prefix.go` -- `internal/dataframe/physical_cost.go` -- `internal/dataframe/profile.go` -- `internal/store/arango/profile.go` -- `internal/ingest/backend.go` - -Already complete: generic physical lowering, scoped graph traversal, root -windowing, required semi-joins, sibling sharing, aggregates, pivots, slices, -nested objects, prepared sets, structural cost reporting, opt-in profile, and -compatibility renderer deletion. Do not rebuild these foundations. - -## Global contracts - -Every package preserves: - -1. One row per root in stable `_key` order. -2. Columns, row count, null/empty behavior, array order, distinct behavior, - pivot collision behavior, and representative slice choice. -3. Required matching before root `SORT/LIMIT`; optional shaping after it. -4. Project, generation, and authorization checks on every root, node, and edge. -5. Bind-backed request values and names; no request interpolation into AQL. -6. Routes accepted by `resolveStorageRoute` only. -7. Generic physical-property rules only: no production Patient, Specimen, - Observation, GDC, or fixture-label special cases. -8. Disable/remove a rule when parity is unproven or live profile is slower. - -## Evidence required from every optimization - -Publish fixture/data scope, limit, batch size, complete rule policy, canonical -result SHA-256, rows, response bytes, AQL hash, every execution time, five-run -warm median/minimum, profile work counters, peak memory, top ten runtime nodes, -selected indexes, and a conclusion: enable, cost-gate, disable, or remove. - -Object key order must not affect hashes; array order must. Compare identical -database state and binds while changing one rule only. - -## Shared-file ownership - -Only the coordinator merges edits to: - -- `internal/dataframe/physical_plan.go` -- `internal/dataframe/physical_optimize.go` -- `internal/dataframe/physical_render.go` -- `internal/dataframe/physical_cost.go` -- `internal/dataframe/physical_diagnostics.go` - -Workers prepare tests/reports/proposed patches. Never let two workers edit -these files concurrently. Maintain independent developer switches for current -sharing, nested sharing, prepared selectors, rich fusion, and compact set -projection. - -## WP0 — Reproducible baseline and profile attribution - -**Owner:** benchmark worker. **Owns:** `cmd/dataframe-query/`, conformance, -examples, and benchmark docs. No physical compiler edits. - -Implement: - -1. Compile a fixture, execute it, then `EXPLAIN` and profile level 2 using the - same AQL and binds. -2. Support limits 25/100/1,000 and repetitions 1/5. -3. Canonicalize JSON results and calculate SHA-256. -4. Attribute profile nodes to root window, every set/prepared set, aggregate, - pivot, slice, and return. -5. Record scalar-root, optional-child, aggregate+slice, pivot, deep traversal, - sibling, required-match, and GDC baselines. -6. Store optimizer policy and AQL hash in every artifact. - -Acceptance: repeated hashes match; GDC returns 1,000 rows and approximately -3.3MB; top nodes map to physical regions; `go test ./conformance/compiler -./cmd/dataframe-query -count=1` passes. Handoff artifact schema, fixture IDs, -hashes, commands, and the three most expensive regions. - -## WP1 — Independent optimizer-rule ablation - -**Owner:** coordinator. **Depends on:** WP0. - -Implement: - -1. Typed independent decisions for current sharing and prepared selectors; - disabled entries for nested sharing, fusion, and compact projection. -2. Keep `CompileRequest` production-only; add internal/test - `CompileRequestWithPolicy` rather than environment-only control. -3. Report each rule's state, estimate, and rejection reason. -4. Compile the same request while changing exactly one rule. -5. Label every artifact with the full policy. - -Acceptance: live GDC hashes match for no optional rewrites, sharing only, -prepared only, and defaults; `go test ./internal/dataframe -./conformance/compiler -count=1` passes. WP1 enables no new rule. - -## WP2 — Traversal fan-out and nested-prefix optimization - -**Owner:** traversal worker; coordinator merges shared files. **Depends on:** -WP0/WP1. - -Investigate before coding: - -1. Profile sibling sharing on/off for focused fixtures and GDC. -2. Per traversal record parents, edge-index items, node lookups, filtered and - returned items, and runtime. -3. Compare broad multi-type traversal with independent typed traversals. -4. Test whether `POSITION(@target_types, edge type, true)` changes index choice - versus equality. -5. Profile deep paths separately. -6. Find repeated nested prefixes using `DecomposePhysicalTraversalPrefix`. - -Candidate A: cost-aware sibling sharing. Estimate union-neighbor versus -independent typed work from catalog/profile counts; reject broad sharing when -it loses selectivity; report exact inputs/reason. - -Candidate B: nested sharing, only with profile evidence. Require equal parent, -direction, label, scope, and optionality; alpha-rename captures; materialize in -the same parent scope; derive consumer subsets; never move a semi-join after -the root window. - -Tests: zero/one/many neighbors, skewed type distribution, inbound and proven -outbound routes, three-hop equivalence, and rejection for differing auth, -generation, direction, label, or parent. Enable only with identical hashes, no -full scan, reduced targeted work, and at least 5% warm-median improvement. - -## WP3 — Prepared-selector cost and payload minimization - -**Owner:** prepared-set worker; coordinator merges shared files. **Depends on:** -WP0/WP1. May investigate with WP2. - -First profile prepared on/off for aggregate+slice, pivot, deep-child, and GDC. -Record selector calls, prepared items, memory, runtime, and hashes at child -cardinality 0/1/10/100/high-fan-out. - -Implement: - -1. Compute selector union for aggregate values/predicates, pivot key/value, - slice predicate/sort, and slice fields. -2. Project each eligible selector once. -3. Add explicit typed `RetainNode`; retain full nodes only for nested traversal - or an unprepared consumer. -4. Keep single-use selectors direct unless profile proves value. -5. Cost-gate on consumer count, child estimate, field count, and node retention. -6. Keep ordered fallback chains direct until preparation preserves all fallbacks. - -Tests: direct/prepared null, empty, multi-value, distinct, slice ordering, -pivot collisions, shared-subset prepared definitions, bind correctness, and -corpus hashes. Prepared mode must improve focused fixtures and be neutral or -better for GDC; otherwise cost-gate/disable it. - -## WP4 — Fuse compatible rich consumers - -**Owner:** rich-expression worker; coordinator merges IR/renderer. **Depends -on:** WP1 and WP3 evidence. - -Implement a typed consumer group keyed by source, identical predicate, -ordering needs, and prepared schema. Classify count/exists, distinct/min/max, -pivot grouping, and bounded slices. Group only identical semantics. Render one -typed shaping subquery and project columns from its object. Preserve -sort-before-limit, pivot allowed columns/collisions/distinctness, and lexical -scope. Keep disabled until profile passes. - -Tests: identical counts fuse, different predicates do not, count+distinct, -aggregate+slice, aggregate+pivot, empty/null/duplicate/multi-value selectors, -nested scope, and live hash parity. Keep only if loops/items and focused -runtime improve without GDC regression; remove if Arango already fuses it. - -## WP5 — Compact intermediate set projection - -**Owner:** projection worker; coordinator merges renderer. **Depends on:** WP0. - -Implement: - -1. Compute required set properties from downstream selectors, endpoint - identity, `_key`, typing, ordering, and uniqueness. -2. Define typed set output; keep document/full node only for later traversal. -3. Preserve `_key` and run scope predicates before compact projection. -4. Compare full-object `UNIQUE` with identity uniqueness only under - duplicate-edge parity tests. -5. Measure intermediate memory separately from requested response size. - -Tests: nested traversal handle, duplicate edges, ordering/slices, requested -columns, auth/generation ordering, and compact/full hashes. Require lower peak -memory or copied work and neutral/better runtime; otherwise disable/remove. - -## WP6 — Profile-driven Arango index audit - -**Owner:** index worker. **Owns:** `internal/ingest/backend.go`, Arango -explain/profile tests, index docs. No renderer edits. **Depends on:** WP0 and a -repeat after WP2--WP5 stabilize. - -1. Inventory installed indexes, field order, selectivity, and corpus usage. -2. Verify INBOUND `_to,project,dataset_generation,label,from_type` and OUTBOUND - `_from,project,dataset_generation,label,to_type` indexes. -3. Determine whether multi-type sharing uses compound or default edge indexes. -4. Test alternative orders only with disposable named indexes. -5. Compare equality-per-type and multi-type traversal. -6. Verify root scope plus `_key` sort avoids unrelated roots. -7. Record ingest time, index size, runtime, and scanned work. Add no speculative - index and remove none without corpus proof. - -Acceptance: checked-in shape/index matrix, no execution full scans, documented -tradeoffs, and `go test ./internal/ingest ./internal/store/arango -count=1`. - -## WP7 — Ingest-time relationship catalog - -**Owner:** catalog/ingest worker. **Owns:** catalog, ingest, loader command, and -related tests/docs. No physical compiler edits. May run with WP2--WP6. - -Create an ingest-owned relationship catalog keyed by project, generation, -auth path, from type, label, to type, and edge count. - -1. Bootstrap indexed builder lookup by project/generation/to-type and storage - lookup by project/generation/from-type, with auth where required. -2. Count successfully committed edges, not attempted rows. -3. Define legacy rebuild and immutable-generation behavior. -4. Read discovery from catalog; retain direct edge aggregation only as explicit - repair/backfill, never request fallback. -5. Add rebuild command for the existing 14.5-million-edge database. -6. Invalidate memory cache only after successful import/rebuild. -7. Preserve restricted authorization aggregation. - -Tests: empty data, two projects/generations, restricted/unrestricted auth, -idempotent rebuild, failed writes, builder orientation, and catalog/direct -parity. Gate: cold discovery performs no edge scan, GDC preparation below -250ms, and `go test ./internal/catalog ./internal/ingest -./cmd/arango-fhir-proto -count=1`. - -## WP8 — Durable parity/profile regression gates - -**Owner:** conformance worker. **Depends on:** WP0 and consumes WP2--WP7. - -1. Audit that every supplied bind is referenced and every AQL bind has a - value, correctly handling `@@collection` and prefix collisions. -2. Audit physical set/prepared variable definitions and lexical uses. -3. Compare canonical hashes across WP1 ablations. -4. Add opt-in live gates for indexes, `scannedFull == 0`, rows, and hashes. -5. Use generous timing ceilings; fail primarily on structural regressions. -6. Assert discovery uses the catalog, never direct aggregation. -7. Document exact 25/100/1,000 and profile commands. - -Acceptance: tests catch historical missing `child_set_1_prepared` and unused -`child_set_2_label`; corpus hashes match; `go test ./... -count=1` passes -offline; opt-in live suite passes. - -## WP9 — Integrate proven rules and publish baseline - -**Owner:** coordinator. **Depends on:** WP2--WP8 evidence. - -Review hashes, work counters, warm median, memory, and regressions. Classify -each rule as default, shape-cost-gated, experimental, or rejected. Delete -rejected prototype code. Run full unit/conformance/live suites and -25/100/1,000 plus cold discovery benchmarks. Publish hashes, AQL hashes, -profiles, and timings. - -Done: no normal execution/discovery full scans, cold preparation below 250ms, -all correctness contracts pass, and warm GDC median is below 6.34s. If it does -not improve, document the profile-proven irreducible fan-out and next physical -strategy rather than claiming success. - -## Parallel waves - -Wave 1, concurrent: Luna A WP0; Luna B WP6 investigation; Luna C WP7; -coordinator WP1. Merge WP0 contract before WP1 controls. WP7 is independent. - -Wave 2 after WP0/WP1, concurrent without shared-file edits: Luna D WP2; Luna E -WP3; Luna F WP5; Luna B repeat WP6. Workers deliver tests/reports/proposed -patches. Coordinator integrates one candidate, profiles, retains/removes, then -takes the next. - -Wave 3 after WP3 decision: Luna G WP4; Luna H WP8; Luna B final WP6; -coordinator sequential integration. - -Wave 4: coordinator executes WP9 alone. No new optimizer design during final -integration. - -## Copy-paste worker prompt - -```text -Execute in Loom. - -Read docs/LUNA_AQL_OPTIMIZATION_ROUND_2.md completely, then the package files -it lists. Own only . Do not edit physical_plan.go, -physical_optimize.go, physical_render.go, physical_cost.go, or -physical_diagnostics.go unless designated coordinator. - -Preserve every global contract. Use fhirschema and resolveStorageRoute; never -hard-code a FHIR type/route. Preserve unrelated dirty changes. Use apply_patch -and prefix shell commands with rtk. - -Run baseline tests, implement only this package, run named unit/live tests, -produce the required evidence artifact, and report changed files, hashes, -profile metrics, rejected experiments, and coordinator decisions needed. - -Stop rather than guess if an unowned IR change is required, hashes differ, -scope semantics change, profile benefit is absent, or an owned file changed -concurrently. -``` - -## Coordinator merge checklist - -For each candidate: reject resource-specific logic; run focused tests and -`go test ./... -count=1`; compile optimized/ablated AQL from the same request; -verify binds and lexical variables; compare hashes at 25/1,000 rows; confirm -indexes/no full scan; compare five warm runs and profiles; record median, work, -and memory; then enable, cost-gate, or remove. - diff --git a/docs/LUNA_AQL_RUNTIME_ROUND_4.md b/docs/LUNA_AQL_RUNTIME_ROUND_4.md deleted file mode 100644 index 08ae69a..0000000 --- a/docs/LUNA_AQL_RUNTIME_ROUND_4.md +++ /dev/null @@ -1,676 +0,0 @@ -# Luna multi-agent execution plan: AQL runtime round 4 - -## Mission - -Reduce the real GDC dataframe operation from its current roughly 5.7-second -Arango execution median to **1–3 seconds for 1,000 rows**, while preserving -generic FHIR semantics, authorization, generation isolation, deterministic -output, and bounded memory. - -This round is runtime-first. A memory reduction is valuable, but it does not -qualify as the principal result of a work package unless runtime also improves. -Compiler construction time, GraphQL input mapping, AQL planning, query -execution, row transfer, JSON materialization, and optional export are measured -separately so frontend turnaround can be predicted honestly. - -The target represents the first execution of a newly requested dataframe -shape. Do not use Arango's result cache to meet it. Repeated identical queries -may be reported as additional evidence, but cached results are not the product -SLO. - -Read these files completely before starting any package: - -- `docs/AQL_EXECUTION_IMPLEMENTATION_AUDIT.md` -- `docs/LUNA_AQL_EXECUTION_ROUND_3.md` -- `docs/benchmarks/round3/WP10_REPORT.md` -- `docs/benchmarks/round3/wp4/production.aql` -- `docs/benchmarks/round3/wp4/production.json` - -## Invariant request and current baseline - -Every promotion decision uses the actual frontend input path: - -- GraphQL document: `examples/meta_gdc_case_matrix.graphql` -- GraphQL variables: `examples/meta_gdc_case_matrix.variables.json` -- mapping: `graphqlapi/dataframe.BuilderFromInput` -- project: `ARANGODB_PROTO` -- database: `fhir_proto` -- root limit: 1,000 - -The compiler fixture `conformance/compiler/fixtures/gdc-case-matrix.json` is -useful for unit coverage but is not interchangeable with the real GraphQL -input and cannot provide promotion evidence. - -Current production facts: - -| Measure | Value | -|---|---:| -| result SHA-256 | `17faea7ac3ee7f308b37223f376530a0660f8068d5e015cc573cf99ccb4045ca` | -| production AQL SHA-256 | `4081527f4d893c7fc8b4957ad75ffbf51a975a8b646c315f01d09093444aad68` | -| five-run Arango executing median | approximately 5.67s | -| indexed items | 475,876 | -| full scans | 0 | -| peak memory | 194,117,632 bytes | -| native traversals | 4 | -| native traversal edge index | default `fhir_edge(_to)` | -| child-set materializations | 6 typed sets plus one broad shared set | -| child-set sorts | 7 plus three representative-slice sorts | -| repeated projected-set consumer loops | at least 7 | - -The root index and root limit are already effective. The remaining work is -dominated by traversal adjacency, correlated child materialization, selector -enumeration, deduplication, sorting, aggregate/pivot/slice consumers, and final -row construction. - -## Product SLO and promotion thresholds - -### Primary target - -- exact 1,000-row result; -- five alternating, non-result-cached candidate/control runs; -- candidate Arango `executing` median between 1 and 3 seconds; -- end-to-end GraphQL median below 4 seconds when the local API is available; -- peak Arango memory at or below 200 MB; -- zero full collection scans; and -- no authorization, generation, ordering, null, pivot, slice, or duplicate-edge - semantic drift. - -### Incremental package gate - -A package can merge before the final target only if it produces one of: - -1. at least 10% lower whole-query Arango median; or -2. at least 25% lower target-region indexed/items/calculation work and at least - 5% lower whole-query median; or -3. at least 15% lower end-to-end time for a previously dominant non-Arango - stage, without moving work out of the measured boundary. - -Memory must not regress by more than 10%. A candidate that improves runtime by -20% or more may use up to 225 MB temporarily, but it must carry an explicit -memory follow-up before default enablement. - -### Stop rule - -Reject a package when it changes only AQL text, estimated cost, or optimizer -diagnostics without removing measured runtime work. Do not retain alternate IR, -renderer branches, environment switches, or indexes for rejected candidates. - -## Benchmark protocol - -WP0 owns the protocol. Every worker consumes its artifacts unchanged. - -1. Record Arango version, edition, CPU allocation, container memory, database - document/edge counts, active index definitions, index cache state, and Loom - git/worktree hashes. -2. Disable query result caching for benchmark requests. Record whether plan - caching exists and whether the first execution populated it. -3. Alternate control and candidate: `C1, N1, C2, N2 ... C5, N5`. Do not run all - controls and then all candidates. -4. Use identical binds, limit, cursor batch size, database state, and output - consumption. Consume every result row. -5. Record both Arango `PROFILE` and ordinary query timings. `PROFILE` is not a - substitute for client wall time. -6. Record AQL/result hashes, response rows, uncompressed JSON bytes, compressed - bytes if relevant, and serialization throughput. If output transfer alone - exceeds the SLO, report that ceiling explicitly. -7. Record phase times: input mapping, semantic plan, physical plan, rendering, - Arango parsing/planning/executing/finalizing, cursor transfer, Go row - materialization, GraphQL result assembly, and optional NDJSON/Elasticsearch - export. -8. Record selected indexes, optimizer rules, scanned full/index, document - lookups, peak memory, calls/items/filtered/runtime for traversal, index, - calculation, list, collect, sort, limit, and return nodes. -9. Count rendered native traversals, explicit edge loops, `LET` child arrays, - `UNIQUE`, `COLLECT`, `SORT`, projected-set consumer loops, selector - subqueries, and retained payloads. -10. Preserve raw AQL and raw profile JSON under the package evidence directory. - -The profile comparator must not sum cumulative nested node runtimes. Use the -Arango executing phase and client wall clock for whole-query decisions. - -## Global semantic contracts - -Every candidate preserves: - -1. one row per root and exact ascending root `_key` order; -2. project, dataset-generation, authorization, and required root membership - before root `SORT/LIMIT`; -3. optional child shaping after the root window; -4. project, exact generation, and authorization checks on every edge and node; -5. routes exclusively from `resolveStorageRoute` and generated `fhirschema`; -6. inbound and proven outbound behavior, including - `ResearchSubject -> ResearchStudy`; -7. bind-backed user values and validated collection/index metadata; -8. duplicate-edge node identity semantics; -9. exact output columns, values, types, null/empty behavior, array ordering, - `SORTED_UNIQUE`, pivot collision selection, and slice sort-before-limit; -10. deterministic fallback when an index, statistic, server capability, or - specialized strategy is unavailable; and -11. no production branch on GDC, `Patient`, `child_set_N`, example aliases, or - example field names. - -## Shared-file ownership - -Only the coordinator may edit these shared production files: - -- `internal/dataframe/physical_plan.go` -- `internal/dataframe/generic_physical_plan.go` -- `internal/dataframe/physical_optimize.go` -- `internal/dataframe/physical_render.go` -- `internal/dataframe/physical_cost.go` -- `internal/dataframe/physical_diagnostics.go` -- `internal/dataframe/physical_helpers.go` -- `internal/dataframe/physical_execution.go` -- `internal/dataframe/compile.go` -- `internal/dataframe/storage_route.go` - -Experiment workers may add isolated `*_experiment_test.go` files and evidence -under `docs/benchmarks/round4//`. They stop and hand off a typed IR proposal -when production changes are required. - -WP0 alone may edit `cmd/dataframe-profile/`, `cmd/dataframe-query/`, and the -benchmark targets in `Makefile`. Index-definition changes are owned by the -index coordinator and require an explicit before/after index inventory; no -worker may create or remove indexes implicitly from a test. - -## Parallel execution graph - -```text -Wave 0, serialized: - WP0 benchmark integrity and capability lock - -Wave 1, four independent experiments (maximum three workers concurrently): - WP1 native traversal OPTIONS matrix - WP2 explicit endpoint full-query substitution - WP3 identity-first dedup-before-shaping - WP4 selector/expression lowering - -Wave 2, serialized coordinator production merges: - WP5 traversal strategy production integration (WP1/WP2 winners only) - WP6 identity-first set production integration (WP3 winner only) - WP7 expression lowering integration (WP4 winner only) - -Wave 3, three parallel architectural experiments against the new baseline: - WP8 leaf summary pushdown - WP9 batch-root/set-oriented execution - WP10 output materialization and export throughput - -Wave 4, serialized: - WP11 production integration and structural cost policy - WP12 combined 1–3 second gate, cleanup, and report -``` - -Wave 1 workers do not wait on each other. With four total agent slots, keep the -coordinator free and start WP1, WP2, and WP3 first; start WP4 when the first -worker slot becomes available. This is a scheduling constraint, not a data -dependency. Wave 2 is serialized because each merge changes the physical -baseline. Wave 3 starts only after all accepted Wave 2 changes are re-profiled -together. In Wave 3, WP8, WP9, and WP10 may occupy all three worker slots while -the coordinator protects shared production files. - -## Official Arango references - -Workers must verify syntax and version support against the server reported by -WP0. These are the primary references for this round: - -- query optimization and optimizer rules: - -- traversal execution options, including `parallelism`, `maxProjections`, - `indexHint`, and `useCache`: - -- profiling and execution-node statistics: - - -The optimizer is cost-based, but it cannot be credited with inventing Loom's -semantic batching, selector reuse, identity-first shaping, or consumer fusion. -Those transformations must be represented explicitly and proven by profiles. - -## WP0 — benchmark integrity and Arango capability lock - -**Owner:** coordinator. **May edit:** profiling commands, benchmark Makefile -targets, focused profiling tests, and `docs/benchmarks/round4/wp0/`. - -### Tasks - -1. Prove the benchmark command uses `BuilderFromInput` on the actual variables - file. Include the effective semantic/physical plan hash in the report. -2. Query and record the exact Arango server version. Mark support for traversal - `indexHint`, `parallelism`, `maxProjections`, `useCache`, collection index - hints, stored values, query plan cache, and result-cache controls. -3. Inventory all `fhir_edge` indexes with name, ID, fields, direction - applicability, selectivity, cache configuration, stored values, and size. -4. Verify inbound compound coverage begins with `_to` and outbound coverage - begins with `_from`. Record missing symmetric indexes without creating them. -5. Add alternating control/candidate execution and output-byte accounting to - the profile harness. -6. Add `-cache=false`, cursor batch size, ordinary-run count, and raw artifact - directory flags where the Arango API supports them. -7. Capture five alternating baseline pairs to quantify normal variance. -8. Measure compilation separately. If semantic+physical+rendering exceeds - 100ms, create a compiler-only follow-up; do not mix it into AQL execution. -9. Measure uncompressed result bytes and local cursor transfer throughput. State - whether 1–3 seconds is physically plausible for the current output size. - -### Acceptance - -- identical AQL/result hashes across unchanged runs; -- median pair variance below 10%, or a documented environment fix; -- exact Arango capability and index inventory; -- result cache proven disabled; and -- raw baseline artifacts in `docs/benchmarks/round4/wp0/`. - -## WP1 — native traversal OPTIONS matrix - -**Purpose:** determine whether Arango's native traversal can use existing -vertex-centric indexes and multiple cores without switching to explicit joins. - -**Owner:** traversal-options worker. **May edit:** isolated experiment tests -under `internal/dataframe/` or `internal/store/arango/` and -`docs/benchmarks/round4/wp1/`. No shared production files or indexes. - -### Candidate matrix - -Test one traversal region at a time, starting with the most expensive nested -region. Compare: - -1. current native traversal; -2. native plus compound vertex-centric `indexHint`; -3. native plus `parallelism` values 2, 4, and 8 bounded by available CPUs; -4. native plus index hint and each useful parallelism value; -5. useful candidates with `maxProjections` values 5, 8, and an explicit full - document threshold; and -6. `useCache` true/false only to diagnose cache pollution, not as the primary - speed mechanism. - -### Tasks - -1. Obtain edge collection, direction, route discriminator, and expected index - from validated route/index metadata. Hard-coded index names are allowed only - in isolated AQL probes and must be replaced by a typed metadata contract in - the handoff. -2. Test inbound and outbound index-hint syntax separately. Confirm the index is - eligible and actually selected by `EXPLAIN`; a hint is not assumed to be - forced. -3. Test the root shared multi-type traversal and each nested single-type route. - Multi-type `IN` and equality must have separate evidence. -4. Preserve all edge/node scope and deterministic post-traversal order. -5. Record CPU utilization and whether parallelism reduces wall time or merely - increases contention/memory. -6. Run isolated region tests and the full actual GDC query. Region-only wins do - not promote a production default. - -### Stop conditions - -- reject a hint if `EXPLAIN` still selects only the default edge index; -- reject parallelism if whole-query runtime or memory regresses; -- do not use `PRUNE` to change a depth-one result filter; -- do not force an index unsupported by the active server version; and -- stop if dynamic edge collection/index metadata cannot be represented without - a shared IR change. - -### Acceptance and handoff - -Pass only a generic structural strategy meeting the incremental gate on the -full query. Hand off traversal option fields, capability checks, index metadata -requirements, exact AQL, and default/fallback policy. - -## WP2 — explicit endpoint full-query substitution - -**Purpose:** determine whether explicit indexed edge equality beats native -traversal in the actual correlated dataframe plan. - -**Owner:** endpoint worker. **May edit:** isolated experiment tests and -`docs/benchmarks/round4/wp2/`. No shared production files or indexes. - -### Tasks - -1. Begin from the exact WP0 production AQL/binds. Replace exactly one nested - traversal region at a time with explicit endpoint equality. -2. For INBOUND, filter edge `_to == parent._id` plus project, generation, label, - and `from_type` equality before `DOCUMENT(edge._from)` or an indexed node - join. OUTBOUND uses `_from`, `to_type`, and `_to`. -3. Compare `DOCUMENT(endpoint)` with a primary-index collection join. Record - document lookups and memory for both. -4. Preserve auth on both edge and node, node type verification, duplicate-edge - identity, child filters, sorting, and compact projection. -5. Test the three actual nested GDC routes, then combinations of two and all - three. Region interactions must be measured; isolated percentages cannot be - added together. -6. Test shared explicit `IN` only as a control. Previous evidence shows it can - be fast while still missing the compound index. -7. Run five alternating full-query pairs for every promotable combination. - -### Acceptance and handoff - -Pass when endpoint equality selects the compound index, exact parity holds, -and the full query meets the incremental gate without unacceptable memory. -Hand off a typed native/explicit strategy proposal and supported route classes. - -## WP3 — identity-first deduplication before shaping - -**Purpose:** stop applying object-level `UNIQUE` to identity-plus-selector -objects containing arrays. - -**Owner:** identity worker. **May edit:** isolated experiment tests and -`docs/benchmarks/round4/wp3/`. No shared production files. - -### Candidate shapes - -Compare the current shape against: - -1. deduplicate scoped nodes by `_id` before selector extraction, then sort and - shape; -2. `COLLECT node_id = node._id INTO group` followed by deterministic node - selection and shaping; -3. `RETURN DISTINCT node._id` followed by primary lookup and shaping; and -4. identity-key object projection followed by selector projection. - -### Tasks - -1. Prove scope runs before identity deduplication. -2. Use duplicate-edge fixtures where one node appears through multiple edges. -3. Preserve one stable node document per `_id`; never deduplicate solely by - payload or shaped object equality. -4. Sort after any operation whose output order is unspecified. Do not rely on - traversal, `UNIQUE`, or `COLLECT` order. -5. Apply one region at a time and report removed object width, calculation - nodes, collect/unique work, memory, and whole-query runtime. -6. Include shared subsets, nested sets, empty sets, auth/generation, and - outbound routes. - -### Acceptance and handoff - -Pass only the identity operation that removes measured work and satisfies the -incremental gate. Hand off explicit identity/order properties and invalidation -rules; do not propose general sort removal. - -## WP4 — selector and expression lowering - -**Purpose:** reduce calculation/list-node work caused by generic singleton -selector subqueries and repeated selector enumeration. - -**Owner:** expression worker. **May edit:** isolated experiment tests and -`docs/benchmarks/round4/wp4/`. No shared production files. - -### Tasks - -1. Inventory every selector expression in the actual AQL and classify: - - direct scalar path; - - optional scalar path; - - fixed index; - - repeated array path; - - predicate-bearing selector; - - fallback chain; and - - derived/nested object expression. -2. Compare current `FOR __root IN [payload]` lowering against direct attribute - access for schema-proven scalar selectors. -3. Compare conditional array expansion against current nested subqueries for - schema-proven repeated paths. -4. Compute each selector union once per shaped child item and verify every - consumer reads the same field. Count remaining projected-set loops. -5. Test common-subexpression `LET` placement within the child loop versus outer - correlated expressions. -6. Preserve missing/null, array, fallback, filter quantifier, primitive type, - and FHIR choice-field behavior using `fhirschema`; no path heuristics. -7. Measure calculation/list nodes and whole-query time. Reduced AQL length is - not evidence. - -### Acceptance and handoff - -Pass only schema-proven lowering families meeting the incremental gate across -the protected selector corpus and actual query. Hand off typed selector -execution modes, never raw AQL fragments. - -## WP5 — production traversal strategy integration - -**Owner:** coordinator. **Depends on:** WP1 and/or WP2 passing. - -### Tasks - -1. Add typed traversal execution fields for native options and/or explicit - endpoint lookup. Store no raw AQL. -2. Validate direction, endpoint, discriminator, collection, index metadata, - server capability, and fallback strategy. -3. Render only experiment-approved route classes. -4. Add deterministic rule ablation and diagnostics showing selected strategy, - index expectation, parallelism, estimated/observed fan-out, and rejection - reason. -5. Preserve required matches and unsupported traversal forms on their existing - correct path. -6. Re-run actual full-query parity/profile after each accepted strategy rather - than merging all changes before measurement. - -### Acceptance - -The production execution path must reproduce the experiment's full-query win, -selected index, memory bound, and all semantic tests. - -## WP6 — production identity-first set integration - -**Owner:** coordinator. **Depends on:** WP3 passing. - -### Tasks - -1. Add typed identity/dedup/order requirements to `PhysicalSet`. -2. Apply scope before dedup, dedup before selector projection, and explicit sort - after any order-invalidating operation. -3. Render only the winning dedup shape. -4. Diagnose identity key, dedup strategy, order proof, shaped width avoided, - and retained fallback. -5. Add duplicate-edge, auth/generation, nested, outbound, and rich-shape parity - tests plus full-query ablation. - -### Acceptance - -Production must reproduce WP3's runtime improvement. Unknown identity/order -properties retain the current conservative behavior. - -## WP7 — production selector/expression integration - -**Owner:** coordinator. **Depends on:** WP4 passing. - -### Tasks - -1. Add typed selector execution modes derived from generated schema metadata. -2. Render direct scalar/array access only for proven-safe selector shapes. -3. Retain generic subquery lowering for predicates, fallbacks, unsupported - choices, and unknown cardinality. -4. Validate mode/path/cardinality consistency in physical IR. -5. Add diagnostics and ablation for each lowering family. -6. Run the generic selector conformance corpus and actual full-query profile. - -### Acceptance - -Each enabled family independently passes parity and the incremental gate. Do -not default-enable a combined family whose individual contribution is unknown. - -## WP8 — leaf summary pushdown - -**Purpose:** replace repeated aggregate, pivot, and slice scans over one shaped -leaf set with one summary-producing subquery. - -**Owner:** summary worker. **May edit:** isolated experiment tests and -`docs/benchmarks/round4/wp8/` until coordinator promotion. - -### Tasks - -1. Identify leaf sets with no navigated descendants and no unsupported escaping - consumer. -2. Deduplicate identity once, then compute named outputs in one correlated - summary contract: - - count; - - count distinct/distinct values/min/max/first/exists; - - bounded pivot pairs and collision reduction; and - - representative slice with exact predicate, sort, tie-break, limit, and - projection. -3. Compare one summary object against current independent loops. Do not create - a larger unbounded intermediate array. -4. Test each operation alone, compatible mixtures, incompatible predicates, - empty/high-fanout sets, duplicate edges, and auth/generation. -5. Apply to the actual diagnosis, sample, file, group-file, and observation - sets; report incremental wins per source. -6. Count eliminated child-set enumerations and calculation nodes. - -### Acceptance and handoff - -Require at least 10% additional whole-query improvement from the post-Wave-2 -baseline. Hand off a typed `PhysicalSetSummary` proposal with named outputs and -fallback reasons. - -## WP9 — batch-root/set-oriented execution - -**Purpose:** replace 1,000 correlated root-by-root child pipelines with batched -edge/node work over the complete root window. - -**Owner:** batch worker. **May edit:** isolated experiment tests and -`docs/benchmarks/round4/wp9/` until coordinator promotion. - -### Candidate shape - -1. materialize the scoped, sorted, limited root window once; -2. create a root identity set; -3. retrieve scoped edges for all root IDs using indexed endpoint access; -4. join scoped nodes and retain root identity; -5. deduplicate/shape/group by root identity; and -6. left-join summaries back to the root window in exact root order, preserving - roots with no optional children. - -### Tasks - -1. Compare per-root equality, batched `IN`, chunked root IDs, and grouped edge - scans. Record whether compound indexes remain selected. -2. Test root batch sizes 25, 100, 250, 500, and 1,000. Bound intermediate - cardinality and memory. -3. Start with one relationship and one output, then add nested paths. Attribute - each step. -4. Preserve optional-left-join semantics, root ordering, duplicate-edge - identity, auth/generation, and outbound direction. -5. Compare batch execution to the best accepted correlated plan, not Round 3. -6. Reject any shape that requires loading all project edges before the root - limit or loses the endpoint compound index. - -### Acceptance and handoff - -Require at least 20% additional whole-query improvement at 1,000 rows and no -more than 5% regression at 25/100 rows. Hand off typed batch/subplan/grouping -IR only after parity and memory pass. - -## WP10 — output materialization and export throughput - -**Purpose:** ensure the frontend-visible turnaround is not dominated by cursor -transfer, JSON assembly, or export after AQL reaches the target. - -**Owner:** runtime pipeline worker. **May edit:** isolated benchmark commands, -tests, and `docs/benchmarks/round4/wp10/`; no compiler semantics. - -### Tasks - -1. Measure AQL execution, cursor fetch, RawMessage decoding, GraphQL assembly, - response encoding, NDJSON/CSV encoding, and Elasticsearch bulk-body creation - separately for the exact 1,000 rows. -2. Record response bytes and rows/MB per second. -3. Compare cursor batch sizes without changing query results or memory bounds. -4. Test streaming rows directly into NDJSON/Elasticsearch bulk format instead - of retaining the full result in Go, if the existing API boundary permits it. -5. Do not hide AQL work in asynchronous background processing when measuring - "dataframe created". Report accepted/queued and fully-created latency - separately if a job API is proposed. -6. Do not use response compression to claim lower server computation time; - report transport benefit separately. - -### Acceptance - -The non-Arango pipeline should add less than one second for 1,000 rows on the -local development server, or produce a concrete throughput/output-size limit -that changes the product SLO. - -## WP11 — production integration and cost policy - -**Owner:** coordinator. **Depends on:** passing WP8 and/or WP9 plus accepted -Wave-2 production changes. - -### Tasks - -1. Add only experiment-proven summary/batch IR. -2. Integrate accepted strategies sequentially and re-profile after each. -3. Carry route cardinality, root limit, projected width, fan-out, server - capability, and available index metadata into deterministic structural - choices. -4. Statistics may choose only among semantically equivalent proven strategies. - Unknown statistics use the safest measured fallback. -5. Emit a decision trace suitable for frontend/admin diagnostics without - exposing authorization values. -6. Remove superseded prepared-array, rejected alternate renderers, stale rule - switches, and test-only production hooks. - -### Acceptance - -Combined production AQL reproduces individual wins, exact parity, and the -memory gate. If two individually useful rules regress together, keep the faster -combination and remove the loser. - -## WP12 — 1–3 second final gate and cleanup - -**Owner:** coordinator only. - -### Tasks - -1. Capture fresh alternating controls for the final production policy and every - accepted rule ablation at limits 25, 100, and 1,000. -2. Run the full Go suite, conformance/compiler suite, live Arango parity, - Explain/index, auth/generation, duplicate-edge, deep traversal, required - match, inbound, outbound, aggregate, pivot, slice, fallback, and derived - field cases. -3. Save final AQL, raw profiles, result hashes, response bytes, end-to-end - timings, selected indexes, CPU, and memory. -4. Delete rejected experiments from production code and update all stale - completion claims. -5. Report contribution by rewrite; do not attribute the combined win to all - packages equally. - -### Final decision - -The round succeeds when the actual 1,000-row request has: - -- five-run non-cached Arango median at or below 3.0 seconds; -- stretch median near 1.0–2.0 seconds; -- exact canonical result hash; -- zero full scans; -- peak memory at or below 200 MB; and -- end-to-end local API median below 4.0 seconds. - -If execution remains above three seconds, the final report identifies the -largest remaining node family and answers whether the limit is query shape, -edge/storage layout, output size, or available CPU. Do not close the round with -"more optimization may be possible." - -## Luna worker prompt template - -```text -Execute from docs/LUNA_AQL_RUNTIME_ROUND_4.md. - -Read the Round 4 plan, AQL implementation audit, Round 3 plan, Round 3 final -report, and every file named by this package completely. Own only . Do not edit shared compiler files unless designated coordinator. - -Before editing, record git status and SHA-256 hashes of owned existing files. -Preserve unrelated dirty changes. Use apply_patch and prefix shell commands -with rtk. Use the real examples/meta_gdc_case_matrix.variables.json through -BuilderFromInput for performance evidence; compiler fixtures are unit coverage -only. Use fhirschema and resolveStorageRoute and never hard-code a FHIR type, -route, child_set variable, example alias, or index name in production. - -Run WP0's alternating, cache-disabled baseline first. Implement only this -package. Preserve every global semantic contract. Run named unit/live tests and -write raw AQL/profile evidence under docs/benchmarks/round4//. - -Report changed files and hashes, exact commands, five raw alternating times, -medians, AQL/result hashes, response bytes, scanned items, document lookups, -peak memory, selected indexes, top profile nodes, structural work removed, -rejected candidates, and enable/cost-gate/reject decision. - -Stop rather than guess if an unowned IR change is required, an owned file -changes concurrently, the result hash differs, the intended index is not -selected, scope/order semantics change, server capability is absent, output is -not fully consumed, or the required runtime benefit is missing. -``` diff --git a/docs/benchmarks/AQL_PROFILE_CORPUS.md b/docs/benchmarks/AQL_PROFILE_CORPUS.md deleted file mode 100644 index 216550a..0000000 --- a/docs/benchmarks/AQL_PROFILE_CORPUS.md +++ /dev/null @@ -1,37 +0,0 @@ -# Generic AQL profile corpus - -`TestProfileCorpusAgainstArango` exercises the Arango adapter against five -schema-independent physical query shapes: - -| Shape | Physical work covered | -| --- | --- | -| `root` | scoped root scan, sort, limit, projection | -| `sibling` | three same-parent inbound traversals with typed targets | -| `deep` | two-hop nested traversal | -| `required` | traversal-backed root semi-join | -| `pivot` | repeated value extraction and `COLLECT` grouping | - -The test is read-only and opt-in. It uses the same local defaults as the -compiler integration suite and accepts these overrides: - -```bash -LOOM_COMPILER_ARANGO_INTEGRATION=1 \ -LOOM_ARANGO_URL=http://127.0.0.1:8529 \ -LOOM_ARANGO_DATABASE=fhir_proto \ -LOOM_ARANGO_PROJECT=ARANGODB_PROTO \ -GOCACHE="$(pwd)/.gocache" GOTOOLCHAIN=auto \ -go test ./internal/store/arango -run TestProfileCorpusAgainstArango -count=1 -v -``` - -For every shape the test performs both `EXPLAIN` and cursor `PROFILE` level 2 -using bind variables. The test requires a project index on the root shape and -an edge index on every traversal shape. It also requires per-node profile -statistics, then logs a stable summary containing result count, execution -runtime, full/index scan counts, and the slowest execution node. - -The profile adapter reports Arango's execution plan node IDs and joins them to -node types from `extra.plan`. This makes repeated traversal nodes and nested -subqueries comparable across compiler rewrites without matching generated AQL -variable names. Keep the corpus queries deliberately generic: new FHIR routes -with the same physical shape should be covered without changing this test. - diff --git a/go.mod b/go.mod index 7988e58..ea320b2 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.25.0 require ( github.com/99designs/gqlgen v0.17.66 + github.com/ClickHouse/clickhouse-go/v2 v2.47.0 github.com/arangodb/go-driver/v2 v2.3.1 github.com/bmeg/jsonschema/v6 v6.0.4 github.com/bmeg/jsonschemagraph v0.0.4-0.20250828230703-257ca9afd85a @@ -14,14 +15,18 @@ require ( ) require ( + github.com/ClickHouse/ch-go v0.73.0 // indirect github.com/agnivade/levenshtein v1.2.0 // indirect github.com/andybalholm/brotli v1.2.1 // indirect github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e // indirect github.com/bmeg/grip v0.0.0-20250915204302-93cb1e8117c8 // indirect github.com/bytedance/gopkg v0.1.3 // indirect github.com/bytedance/sonic/loader v0.5.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudwego/base64x v0.1.6 // indirect github.com/dchest/siphash v1.2.3 // indirect + github.com/go-faster/city v1.0.1 // indirect + github.com/go-faster/errors v0.7.1 // indirect github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/gofiber/schema v1.7.1 // indirect github.com/gofiber/utils/v2 v2.0.6 // indirect @@ -39,23 +44,30 @@ require ( github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.22 // indirect + github.com/paulmach/orb v0.13.0 // indirect github.com/philhofer/fwd v1.2.0 // indirect + github.com/pierrec/lz4/v4 v4.1.27 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rs/zerolog v1.34.0 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect + github.com/segmentio/asm v1.2.1 // indirect + github.com/shopspring/decimal v1.4.0 // indirect + github.com/sirupsen/logrus v1.9.4 // indirect github.com/sosodev/duration v1.3.1 // indirect github.com/tinylib/msgp v1.6.4 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.71.0 // indirect + go.opentelemetry.io/otel v1.44.0 // indirect + go.opentelemetry.io/otel/trace v1.44.0 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect - golang.org/x/crypto v0.51.0 // indirect - golang.org/x/net v0.54.0 // indirect - golang.org/x/sync v0.20.0 // indirect - golang.org/x/sys v0.44.0 // indirect - golang.org/x/term v0.43.0 // indirect - golang.org/x/text v0.37.0 // indirect + golang.org/x/crypto v0.53.0 // indirect + golang.org/x/net v0.56.0 // indirect + golang.org/x/sync v0.21.0 // indirect + golang.org/x/sys v0.46.0 // indirect + golang.org/x/term v0.44.0 // indirect + golang.org/x/text v0.38.0 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect google.golang.org/grpc v1.71.0 // indirect google.golang.org/protobuf v1.36.7 // indirect diff --git a/go.sum b/go.sum index c288e08..9a4123e 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT github.com/99designs/gqlgen v0.17.66 h1:2/SRc+h3115fCOZeTtsqrB5R5gTGm+8qCAwcrZa+CXA= github.com/99designs/gqlgen v0.17.66/go.mod h1:gucrb5jK5pgCKzAGuOMMVU9C8PnReecHEHd2UxLQwCg= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/ClickHouse/ch-go v0.73.0 h1:jsHiGRbQ3sz+gekvDFJF29LWDo5dzbJm5s1h8TWVP2M= +github.com/ClickHouse/ch-go v0.73.0/go.mod h1:wkFIxrqlXeRJ9cn3r5Fz5Qen9jl5aTMPuGZeuJpANNY= +github.com/ClickHouse/clickhouse-go/v2 v2.47.0 h1:ZDAzrnKSOPTIsm4tdUNfrii2yc8dk4SVRLC77BR7Z5Q= +github.com/ClickHouse/clickhouse-go/v2 v2.47.0/go.mod h1:sPj7C7UYQ2MWHcfX+4eGN6nwnCqwUKfgO6PcwKpd6K8= github.com/PuerkitoBio/goquery v1.9.3 h1:mpJr/ikUA9/GNJB/DBZcGeFDXUtosHRyRrwh7KGdTG0= github.com/PuerkitoBio/goquery v1.9.3/go.mod h1:1ndLHPdTz+DyQPICCWYlYQMPl0oXZj0G6D4LCYA6u4U= github.com/agnivade/levenshtein v1.2.0 h1:U9L4IOT0Y3i0TIlUIDJ7rVUziKi/zPbrJGaFrtYH3SY= @@ -21,6 +25,12 @@ github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdK github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/bmeg/grip v0.0.0-20250915204302-93cb1e8117c8 h1:UhgcpVbQuvqg8KJ0ioB4i/KaQw1Zel34oHKjSENPEIA= github.com/bmeg/grip v0.0.0-20250915204302-93cb1e8117c8/go.mod h1:mIN98ALRqqjqRHqopIuZ9iDJ97w4gAzXqdKE6Enuu7Y= +github.com/bmeg/jsonschema/v6 v6.0.4 h1:AXFAz7G05VZkKretSSU+uacMKF8+C16ONG6pzFzzA7E= +github.com/bmeg/jsonschema/v6 v6.0.4/go.mod h1:gTh32doM+BEZyi/TDPJEp8k3qXTckXY4ohptV2xExQY= +github.com/bmeg/jsonschemagraph v0.0.3 h1:n5c1p7VJKt3I4UVBmROLyHZ4NWDHR8unxBFwODHprAg= +github.com/bmeg/jsonschemagraph v0.0.3/go.mod h1:R3JJHOyGpYDGp9vaXSTPc55A+dt9+c8TUrwbiFujAAA= +github.com/bmeg/jsonschemagraph v0.0.4-0.20250828230703-257ca9afd85a h1:O0JcMLcazrwVzf8iC/RogUen4CG5UVErrBU76UkxhYQ= +github.com/bmeg/jsonschemagraph v0.0.4-0.20250828230703-257ca9afd85a/go.mod h1:rlek2WcKAhnynqE7NJi8U+RDbUkRFr8Kqpb2SDmcW94= github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M= github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM= github.com/bytedance/sonic v1.15.2 h1:90H+rcF/FwLXwfB1cudOLq/je83n683Utf4Cbp0xHCo= @@ -28,6 +38,8 @@ github.com/bytedance/sonic v1.15.2/go.mod h1:mT2NbXunuaEbnZ+mRIX/vYqKISmgEuHFDI4 github.com/bytedance/sonic/loader v0.5.1 h1:Ygpfa9zwRCCKSlrp5bBP/b/Xzc3VxsAW+5NIYXrOOpI= github.com/bytedance/sonic/loader v0.5.1/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= @@ -52,10 +64,14 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fxamacker/cbor/v2 v2.9.2 h1:X4Ksno9+x3cz0TZv69ec1hxP/+tymuR8PXQJyDwfh78= github.com/fxamacker/cbor/v2 v2.9.2/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= +github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw= +github.com/go-faster/city v1.0.1/go.mod h1:jKcUJId49qdW3L1qKHH/3wPeUstCVpVSXTM6vO3VcTw= +github.com/go-faster/errors v0.7.1 h1:MkJTnDoEdi9pDabt1dpWf7AA8/BaSYZqibYyhZ20AYg= +github.com/go-faster/errors v0.7.1/go.mod h1:5ySTjWFiphBs07IKuiL69nxdfd5+fzh1u7FPGZP2quo= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -120,8 +136,12 @@ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4= github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/paulmach/orb v0.13.0 h1:r7n7mQGGF+cj/CbcivEj9J3HGK+XR+yXnvzRdq9saIw= +github.com/paulmach/orb v0.13.0/go.mod h1:6scRWINywA2Jf05dcjOfLfxrUIMECvTSG2MVbRLxu/k= github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM= github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= +github.com/pierrec/lz4/v4 v4.1.27 h1:+PhzhWDrjRj89TH2sw43nE3+4+W8lSxIuQadEHZyjUk= +github.com/pierrec/lz4/v4 v4.1.27/go.mod h1:EoQMVJgeeEOMsCqCzqFm2O0cJvljX2nGZjcRIPL34O4= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -137,13 +157,17 @@ github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/segmentio/asm v1.2.1 h1:DTNbBqs57ioxAD4PrArqftgypG4/qNpXoJx8TVXxPR0= +github.com/segmentio/asm v1.2.1/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/shamaton/msgpack/v3 v3.1.2 h1:d5gWAIyMU4M0WgDjz6IFSCuXJUA2dFwRHBpDclE8CLw= github.com/shamaton/msgpack/v3 v3.1.2/go.mod h1:DcQG8jrdrQCIxr3HlMYkiXdMhK+KfN2CitkyzsQV4uc= +github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= +github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= +github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= github.com/sosodev/duration v1.3.1 h1:qtHBDMQ6lvMQsL15g4aopM4HEfOaYuhWBw3NPTtlqq4= github.com/sosodev/duration v1.3.1/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -182,29 +206,31 @@ github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZ github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= -go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= -go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= -go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= -go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= -go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= -go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= +go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= +go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= +go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= +go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= +go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= -go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= -go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= +go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= -golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= +golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto= +golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -212,8 +238,8 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= -golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= +golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4= +golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -222,34 +248,33 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w= -golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ= +golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= +golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= -golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= +golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= -golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= -golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= +golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= +golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc= +golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= -golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= +golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE= +golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -259,8 +284,8 @@ golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= -golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= +golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8= +golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -283,6 +308,8 @@ google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2 google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/graphqlapi/dataframe/service.go b/graphqlapi/dataframe/service.go index 9fda7db..5f5ba44 100644 --- a/graphqlapi/dataframe/service.go +++ b/graphqlapi/dataframe/service.go @@ -2,12 +2,14 @@ package dataframeapi import ( "context" + "fmt" "time" "github.com/calypr/loom/graphqlapi/model" "github.com/calypr/loom/internal/authscope" "github.com/calypr/loom/internal/catalog" "github.com/calypr/loom/internal/dataframe" + "github.com/calypr/loom/internal/dataframe/materialization" "github.com/calypr/loom/internal/dataset" arangostore "github.com/calypr/loom/internal/store/arango" ) @@ -21,6 +23,8 @@ type Service struct { activeManifestResolver dataset.ActiveManifestResolver discoverDatasets func(context.Context, catalog.DatasetSummaryOptions) ([]catalog.DatasetSummary, error) datasetProjectAllowlist []string + materializations *materialization.Service + materializationReader *materialization.Reader } type Config struct { @@ -38,6 +42,8 @@ type Config struct { // unrestricted catalog scan. DatasetProjectAllowlist []string DiscoverDatasets func(context.Context, catalog.DatasetSummaryOptions) ([]catalog.DatasetSummary, error) + Materializations *materialization.Service + MaterializationReader *materialization.Reader } func NewService(cfg Config) *Service { @@ -46,6 +52,8 @@ func NewService(cfg Config) *Service { scopeResolver: cfg.ScopeResolver, activeManifestResolver: cfg.ActiveManifestResolver, datasetProjectAllowlist: cloneStrings(cfg.DatasetProjectAllowlist), + materializations: cfg.Materializations, + materializationReader: cfg.MaterializationReader, } if cfg.DiscoverDatasets != nil { service.discoverDatasets = cfg.DiscoverDatasets @@ -108,3 +116,123 @@ func (s *Service) Run(ctx context.Context, input model.FhirDataframeInput, limit result.Diagnostics.Total = time.Since(started) return result, nil } + +func (s *Service) GetMaterialization(ctx context.Context, id string) (*materialization.Materialization, error) { + if s.materializationReader == nil { + return nil, fmt.Errorf("dataframe materialization reads are not configured") + } + value, err := s.materializationReader.Registry.Get(ctx, id) + if err != nil { + return nil, err + } + if err := s.authorizeMaterialization(ctx, value); err != nil { + return nil, err + } + return &value, nil +} + +func (s *Service) ReadMaterialization(ctx context.Context, input model.DataframeRowsInput) (materialization.Page, error) { + if s.materializationReader == nil { + return materialization.Page{}, fmt.Errorf("dataframe materialization reads are not configured") + } + materialized, err := s.materializationReader.Registry.Get(ctx, input.MaterializationID) + if err != nil { + return materialization.Page{}, err + } + if err := s.authorizeMaterialization(ctx, materialized); err != nil { + return materialization.Page{}, err + } + filters := make([]materialization.Filter, 0, len(input.Filters)) + for _, filter := range input.Filters { + if filter == nil { + continue + } + filters = append(filters, materialization.Filter{Column: filter.Column, Op: filter.Op, Value: filter.Value}) + } + var sortInput *materialization.Sort + if input.Sort != nil { + sortInput = &materialization.Sort{Column: input.Sort.Column, Desc: input.Sort.Desc != nil && *input.Sort.Desc} + } + first := 0 + if input.First != nil { + first = *input.First + } + return s.materializationReader.Page(ctx, materialization.PageRequest{MaterializationID: input.MaterializationID, Columns: input.Columns, Filters: filters, Sort: sortInput, First: first, After: derefString(input.After)}) +} + +func (s *Service) AggregateMaterialization(ctx context.Context, id string, groupBy []string, filters []*model.DataframeFilterInput, operation, column string) (materialization.AggregateResult, error) { + if s.materializationReader == nil { + return materialization.AggregateResult{}, fmt.Errorf("dataframe materialization reads are not configured") + } + value, err := s.materializationReader.Registry.Get(ctx, id) + if err != nil { + return materialization.AggregateResult{}, err + } + if err := s.authorizeMaterialization(ctx, value); err != nil { + return materialization.AggregateResult{}, err + } + converted := make([]materialization.Filter, 0, len(filters)) + for _, filter := range filters { + if filter == nil { + continue + } + converted = append(converted, materialization.Filter{Column: filter.Column, Op: filter.Op, Value: filter.Value}) + } + return s.materializationReader.Aggregate(ctx, materialization.AggregateRequest{MaterializationID: id, GroupBy: groupBy, Filters: converted, Operation: operation, Column: column}) +} + +func (s *Service) authorizeMaterialization(ctx context.Context, value materialization.Materialization) error { + principal, _ := authscope.PrincipalFromContext(ctx) + if principal != nil && len(principal.Projects) > 0 { + allowed := false + for _, project := range principal.Projects { + if project == value.Project { + allowed = true + break + } + } + if !allowed { + return fmt.Errorf("principal is not authorized for project %q", value.Project) + } + } + if value.AuthScopeMode == authscope.ReadScopeUnrestricted { + if s.scopeResolver != nil { + scope, err := s.scopeResolver.ResolveReadScopeForGeneration(ctx, principal, value.Project, value.DatasetGeneration, nil) + if err != nil { + return err + } + if !scope.Unrestricted() { + return fmt.Errorf("materialization %q requires unrestricted authorization", value.ID) + } + } else if principal != nil && len(principal.AuthResourcePaths) > 0 { + return fmt.Errorf("materialization %q requires unrestricted authorization", value.ID) + } + return nil + } + if s.scopeResolver != nil { + scope, err := s.scopeResolver.ResolveReadScopeForGeneration(ctx, principal, value.Project, value.DatasetGeneration, value.AuthResourcePaths) + if err != nil { + return err + } + if len(scope.AuthResourcePaths) != len(value.AuthResourcePaths) { + return fmt.Errorf("materialization %q is outside caller scope", value.ID) + } + return nil + } + if principal == nil { + return fmt.Errorf("materialization %q requires an authorized principal", value.ID) + } + for _, requested := range value.AuthResourcePaths { + found := false + for _, allowed := range principal.AuthResourcePaths { + if requested == allowed { + found = true + break + } + } + if !found { + return fmt.Errorf("materialization %q is outside caller scope", value.ID) + } + } + return nil +} diff --git a/graphqlapi/generated.go b/graphqlapi/generated.go index b9cf81b..c51413f 100644 --- a/graphqlapi/generated.go +++ b/graphqlapi/generated.go @@ -48,6 +48,12 @@ type DirectiveRoot struct { } type ComplexityRoot struct { + DataframeAggregateResult struct { + Columns func(childComplexity int) int + Materialization func(childComplexity int) int + Rows func(childComplexity int) int + } + DataframeBuilderIntrospection struct { AuthResourcePaths func(childComplexity int) int Fields func(childComplexity int) int @@ -59,6 +65,11 @@ type ComplexityRoot struct { Traversals func(childComplexity int) int } + DataframeColumn struct { + ClickhouseType func(childComplexity int) int + Name func(childComplexity int) int + } + DataframeCompilerPlanDiagnostics struct { OptimizationPolicy func(childComplexity int) int PotentialSharingOpportunityGroups func(childComplexity int) int @@ -102,6 +113,19 @@ type ComplexityRoot struct { Where func(childComplexity int) int } + DataframeMaterialization struct { + Columns func(childComplexity int) int + CreatedAt func(childComplexity int) int + DatasetGeneration func(childComplexity int) int + Error func(childComplexity int) int + ID func(childComplexity int) int + Name func(childComplexity int) int + Project func(childComplexity int) int + ReadyAt func(childComplexity int) int + RowCount func(childComplexity int) int + State func(childComplexity int) int + } + DataframeOptimizationDecision struct { CandidateSets func(childComplexity int) int Enabled func(childComplexity int) int @@ -119,6 +143,11 @@ type ComplexityRoot struct { Name func(childComplexity int) int } + DataframePageInfo struct { + EndCursor func(childComplexity int) int + HasNextPage func(childComplexity int) int + } + DataframeQueryDiagnostics struct { ArangoQueryMs func(childComplexity int) int CompilationMs func(childComplexity int) int @@ -151,6 +180,13 @@ type ComplexityRoot struct { TotalConsumers func(childComplexity int) int } + DataframeRowConnection struct { + Columns func(childComplexity int) int + Materialization func(childComplexity int) int + PageInfo func(childComplexity int) int + Rows func(childComplexity int) int + } + DataframeTraversalHint struct { EdgeCount func(childComplexity int) int FromType func(childComplexity int) int @@ -170,7 +206,10 @@ type ComplexityRoot struct { } Query struct { + DataframeAggregate func(childComplexity int, input model.DataframeAggregateInput) int DataframeBuilderIntrospection func(childComplexity int, input model.DataframeBuilderIntrospectionInput) int + DataframeMaterialization func(childComplexity int, id string) int + DataframeRows func(childComplexity int, input model.DataframeRowsInput) int } } @@ -179,6 +218,9 @@ type MutationResolver interface { } type QueryResolver interface { DataframeBuilderIntrospection(ctx context.Context, input model.DataframeBuilderIntrospectionInput) (*model.DataframeBuilderIntrospection, error) + DataframeMaterialization(ctx context.Context, id string) (*model.DataframeMaterialization, error) + DataframeRows(ctx context.Context, input model.DataframeRowsInput) (*model.DataframeRowConnection, error) + DataframeAggregate(ctx context.Context, input model.DataframeAggregateInput) (*model.DataframeAggregateResult, error) } type executableSchema struct { @@ -200,6 +242,27 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in _ = ec switch typeName + "." + field { + case "DataframeAggregateResult.columns": + if e.complexity.DataframeAggregateResult.Columns == nil { + break + } + + return e.complexity.DataframeAggregateResult.Columns(childComplexity), true + + case "DataframeAggregateResult.materialization": + if e.complexity.DataframeAggregateResult.Materialization == nil { + break + } + + return e.complexity.DataframeAggregateResult.Materialization(childComplexity), true + + case "DataframeAggregateResult.rows": + if e.complexity.DataframeAggregateResult.Rows == nil { + break + } + + return e.complexity.DataframeAggregateResult.Rows(childComplexity), true + case "DataframeBuilderIntrospection.authResourcePaths": if e.complexity.DataframeBuilderIntrospection.AuthResourcePaths == nil { break @@ -256,6 +319,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.DataframeBuilderIntrospection.Traversals(childComplexity), true + case "DataframeColumn.clickhouseType": + if e.complexity.DataframeColumn.ClickhouseType == nil { + break + } + + return e.complexity.DataframeColumn.ClickhouseType(childComplexity), true + + case "DataframeColumn.name": + if e.complexity.DataframeColumn.Name == nil { + break + } + + return e.complexity.DataframeColumn.Name(childComplexity), true + case "DataframeCompilerPlanDiagnostics.optimizationPolicy": if e.complexity.DataframeCompilerPlanDiagnostics.OptimizationPolicy == nil { break @@ -473,6 +550,76 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.DataframeFieldSelector.Where(childComplexity), true + case "DataframeMaterialization.columns": + if e.complexity.DataframeMaterialization.Columns == nil { + break + } + + return e.complexity.DataframeMaterialization.Columns(childComplexity), true + + case "DataframeMaterialization.createdAt": + if e.complexity.DataframeMaterialization.CreatedAt == nil { + break + } + + return e.complexity.DataframeMaterialization.CreatedAt(childComplexity), true + + case "DataframeMaterialization.datasetGeneration": + if e.complexity.DataframeMaterialization.DatasetGeneration == nil { + break + } + + return e.complexity.DataframeMaterialization.DatasetGeneration(childComplexity), true + + case "DataframeMaterialization.error": + if e.complexity.DataframeMaterialization.Error == nil { + break + } + + return e.complexity.DataframeMaterialization.Error(childComplexity), true + + case "DataframeMaterialization.id": + if e.complexity.DataframeMaterialization.ID == nil { + break + } + + return e.complexity.DataframeMaterialization.ID(childComplexity), true + + case "DataframeMaterialization.name": + if e.complexity.DataframeMaterialization.Name == nil { + break + } + + return e.complexity.DataframeMaterialization.Name(childComplexity), true + + case "DataframeMaterialization.project": + if e.complexity.DataframeMaterialization.Project == nil { + break + } + + return e.complexity.DataframeMaterialization.Project(childComplexity), true + + case "DataframeMaterialization.readyAt": + if e.complexity.DataframeMaterialization.ReadyAt == nil { + break + } + + return e.complexity.DataframeMaterialization.ReadyAt(childComplexity), true + + case "DataframeMaterialization.rowCount": + if e.complexity.DataframeMaterialization.RowCount == nil { + break + } + + return e.complexity.DataframeMaterialization.RowCount(childComplexity), true + + case "DataframeMaterialization.state": + if e.complexity.DataframeMaterialization.State == nil { + break + } + + return e.complexity.DataframeMaterialization.State(childComplexity), true + case "DataframeOptimizationDecision.candidateSets": if e.complexity.DataframeOptimizationDecision.CandidateSets == nil { break @@ -550,6 +697,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.DataframeOptimizationPolicy.Name(childComplexity), true + case "DataframePageInfo.endCursor": + if e.complexity.DataframePageInfo.EndCursor == nil { + break + } + + return e.complexity.DataframePageInfo.EndCursor(childComplexity), true + + case "DataframePageInfo.hasNextPage": + if e.complexity.DataframePageInfo.HasNextPage == nil { + break + } + + return e.complexity.DataframePageInfo.HasNextPage(childComplexity), true + case "DataframeQueryDiagnostics.arangoQueryMs": if e.complexity.DataframeQueryDiagnostics.ArangoQueryMs == nil { break @@ -690,6 +851,34 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.DataframeRichSourceReuse.TotalConsumers(childComplexity), true + case "DataframeRowConnection.columns": + if e.complexity.DataframeRowConnection.Columns == nil { + break + } + + return e.complexity.DataframeRowConnection.Columns(childComplexity), true + + case "DataframeRowConnection.materialization": + if e.complexity.DataframeRowConnection.Materialization == nil { + break + } + + return e.complexity.DataframeRowConnection.Materialization(childComplexity), true + + case "DataframeRowConnection.pageInfo": + if e.complexity.DataframeRowConnection.PageInfo == nil { + break + } + + return e.complexity.DataframeRowConnection.PageInfo(childComplexity), true + + case "DataframeRowConnection.rows": + if e.complexity.DataframeRowConnection.Rows == nil { + break + } + + return e.complexity.DataframeRowConnection.Rows(childComplexity), true + case "DataframeTraversalHint.edgeCount": if e.complexity.DataframeTraversalHint.EdgeCount == nil { break @@ -758,6 +947,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.RunFhirDataframe(childComplexity, args["input"].(model.FhirDataframeInput), args["limit"].(*int)), true + case "Query.dataframeAggregate": + if e.complexity.Query.DataframeAggregate == nil { + break + } + + args, err := ec.field_Query_dataframeAggregate_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.DataframeAggregate(childComplexity, args["input"].(model.DataframeAggregateInput)), true + case "Query.dataframeBuilderIntrospection": if e.complexity.Query.DataframeBuilderIntrospection == nil { break @@ -770,6 +971,30 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.DataframeBuilderIntrospection(childComplexity, args["input"].(model.DataframeBuilderIntrospectionInput)), true + case "Query.dataframeMaterialization": + if e.complexity.Query.DataframeMaterialization == nil { + break + } + + args, err := ec.field_Query_dataframeMaterialization_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.DataframeMaterialization(childComplexity, args["id"].(string)), true + + case "Query.dataframeRows": + if e.complexity.Query.DataframeRows == nil { + break + } + + args, err := ec.field_Query_dataframeRows_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.DataframeRows(childComplexity, args["input"].(model.DataframeRowsInput)), true + } return 0, false } @@ -778,7 +1003,11 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { opCtx := graphql.GetOperationContext(ctx) ec := executionContext{opCtx, e, 0, 0, make(chan graphql.DeferredResult)} inputUnmarshalMap := graphql.BuildUnmarshalerMap( + ec.unmarshalInputDataframeAggregateInput, ec.unmarshalInputDataframeBuilderIntrospectionInput, + ec.unmarshalInputDataframeFilterInput, + ec.unmarshalInputDataframeRowsInput, + ec.unmarshalInputDataframeSortInput, ec.unmarshalInputFhirAggregateInput, ec.unmarshalInputFhirDataframeInput, ec.unmarshalInputFhirFieldPredicateInput, @@ -982,6 +1211,34 @@ func (ec *executionContext) field_Query___type_argsName( return zeroVal, nil } +func (ec *executionContext) field_Query_dataframeAggregate_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := ec.field_Query_dataframeAggregate_argsInput(ctx, rawArgs) + if err != nil { + return nil, err + } + args["input"] = arg0 + return args, nil +} +func (ec *executionContext) field_Query_dataframeAggregate_argsInput( + ctx context.Context, + rawArgs map[string]any, +) (model.DataframeAggregateInput, error) { + if _, ok := rawArgs["input"]; !ok { + var zeroVal model.DataframeAggregateInput + return zeroVal, nil + } + + ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + if tmp, ok := rawArgs["input"]; ok { + return ec.unmarshalNDataframeAggregateInput2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeAggregateInput(ctx, tmp) + } + + var zeroVal model.DataframeAggregateInput + return zeroVal, nil +} + func (ec *executionContext) field_Query_dataframeBuilderIntrospection_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} @@ -1010,6 +1267,62 @@ func (ec *executionContext) field_Query_dataframeBuilderIntrospection_argsInput( return zeroVal, nil } +func (ec *executionContext) field_Query_dataframeMaterialization_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := ec.field_Query_dataframeMaterialization_argsID(ctx, rawArgs) + if err != nil { + return nil, err + } + args["id"] = arg0 + return args, nil +} +func (ec *executionContext) field_Query_dataframeMaterialization_argsID( + ctx context.Context, + rawArgs map[string]any, +) (string, error) { + if _, ok := rawArgs["id"]; !ok { + var zeroVal string + return zeroVal, nil + } + + ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + if tmp, ok := rawArgs["id"]; ok { + return ec.unmarshalNID2string(ctx, tmp) + } + + var zeroVal string + return zeroVal, nil +} + +func (ec *executionContext) field_Query_dataframeRows_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := ec.field_Query_dataframeRows_argsInput(ctx, rawArgs) + if err != nil { + return nil, err + } + args["input"] = arg0 + return args, nil +} +func (ec *executionContext) field_Query_dataframeRows_argsInput( + ctx context.Context, + rawArgs map[string]any, +) (model.DataframeRowsInput, error) { + if _, ok := rawArgs["input"]; !ok { + var zeroVal model.DataframeRowsInput + return zeroVal, nil + } + + ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + if tmp, ok := rawArgs["input"]; ok { + return ec.unmarshalNDataframeRowsInput2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeRowsInput(ctx, tmp) + } + + var zeroVal model.DataframeRowsInput + return zeroVal, nil +} + func (ec *executionContext) field___Directive_args_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} @@ -1130,8 +1443,8 @@ func (ec *executionContext) field___Type_fields_argsIncludeDeprecated( // region **************************** field.gotpl ***************************** -func (ec *executionContext) _DataframeBuilderIntrospection_project(ctx context.Context, field graphql.CollectedField, obj *model.DataframeBuilderIntrospection) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeBuilderIntrospection_project(ctx, field) +func (ec *executionContext) _DataframeAggregateResult_materialization(ctx context.Context, field graphql.CollectedField, obj *model.DataframeAggregateResult) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeAggregateResult_materialization(ctx, field) if err != nil { return graphql.Null } @@ -1144,7 +1457,7 @@ func (ec *executionContext) _DataframeBuilderIntrospection_project(ctx context.C }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.Project, nil + return obj.Materialization, nil }) if err != nil { ec.Error(ctx, err) @@ -1156,26 +1469,48 @@ func (ec *executionContext) _DataframeBuilderIntrospection_project(ctx context.C } return graphql.Null } - res := resTmp.(string) + res := resTmp.(*model.DataframeMaterialization) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNDataframeMaterialization2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeMaterialization(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeBuilderIntrospection_project(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeAggregateResult_materialization(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeBuilderIntrospection", + Object: "DataframeAggregateResult", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + switch field.Name { + case "id": + return ec.fieldContext_DataframeMaterialization_id(ctx, field) + case "name": + return ec.fieldContext_DataframeMaterialization_name(ctx, field) + case "project": + return ec.fieldContext_DataframeMaterialization_project(ctx, field) + case "datasetGeneration": + return ec.fieldContext_DataframeMaterialization_datasetGeneration(ctx, field) + case "state": + return ec.fieldContext_DataframeMaterialization_state(ctx, field) + case "columns": + return ec.fieldContext_DataframeMaterialization_columns(ctx, field) + case "rowCount": + return ec.fieldContext_DataframeMaterialization_rowCount(ctx, field) + case "createdAt": + return ec.fieldContext_DataframeMaterialization_createdAt(ctx, field) + case "readyAt": + return ec.fieldContext_DataframeMaterialization_readyAt(ctx, field) + case "error": + return ec.fieldContext_DataframeMaterialization_error(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DataframeMaterialization", field.Name) }, } return fc, nil } -func (ec *executionContext) _DataframeBuilderIntrospection_rootResourceType(ctx context.Context, field graphql.CollectedField, obj *model.DataframeBuilderIntrospection) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeBuilderIntrospection_rootResourceType(ctx, field) +func (ec *executionContext) _DataframeAggregateResult_columns(ctx context.Context, field graphql.CollectedField, obj *model.DataframeAggregateResult) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeAggregateResult_columns(ctx, field) if err != nil { return graphql.Null } @@ -1188,7 +1523,7 @@ func (ec *executionContext) _DataframeBuilderIntrospection_rootResourceType(ctx }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.RootResourceType, nil + return obj.Columns, nil }) if err != nil { ec.Error(ctx, err) @@ -1200,14 +1535,14 @@ func (ec *executionContext) _DataframeBuilderIntrospection_rootResourceType(ctx } return graphql.Null } - res := resTmp.(string) + res := resTmp.([]string) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNString2ᚕstringᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeBuilderIntrospection_rootResourceType(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeAggregateResult_columns(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeBuilderIntrospection", + Object: "DataframeAggregateResult", Field: field, IsMethod: false, IsResolver: false, @@ -1218,8 +1553,8 @@ func (ec *executionContext) fieldContext_DataframeBuilderIntrospection_rootResou return fc, nil } -func (ec *executionContext) _DataframeBuilderIntrospection_authResourcePaths(ctx context.Context, field graphql.CollectedField, obj *model.DataframeBuilderIntrospection) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeBuilderIntrospection_authResourcePaths(ctx, field) +func (ec *executionContext) _DataframeAggregateResult_rows(ctx context.Context, field graphql.CollectedField, obj *model.DataframeAggregateResult) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeAggregateResult_rows(ctx, field) if err != nil { return graphql.Null } @@ -1232,7 +1567,7 @@ func (ec *executionContext) _DataframeBuilderIntrospection_authResourcePaths(ctx }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.AuthResourcePaths, nil + return obj.Rows, nil }) if err != nil { ec.Error(ctx, err) @@ -1244,26 +1579,26 @@ func (ec *executionContext) _DataframeBuilderIntrospection_authResourcePaths(ctx } return graphql.Null } - res := resTmp.([]string) + res := resTmp.(json.RawMessage) fc.Result = res - return ec.marshalNString2ᚕstringᚄ(ctx, field.Selections, res) + return ec.marshalNJSON2encodingᚋjsonᚐRawMessage(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeBuilderIntrospection_authResourcePaths(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeAggregateResult_rows(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeBuilderIntrospection", + Object: "DataframeAggregateResult", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + return nil, errors.New("field of type JSON does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeBuilderIntrospection_root(ctx context.Context, field graphql.CollectedField, obj *model.DataframeBuilderIntrospection) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeBuilderIntrospection_root(ctx, field) +func (ec *executionContext) _DataframeBuilderIntrospection_project(ctx context.Context, field graphql.CollectedField, obj *model.DataframeBuilderIntrospection) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeBuilderIntrospection_project(ctx, field) if err != nil { return graphql.Null } @@ -1276,7 +1611,7 @@ func (ec *executionContext) _DataframeBuilderIntrospection_root(ctx context.Cont }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.Root, nil + return obj.Project, nil }) if err != nil { ec.Error(ctx, err) @@ -1288,36 +1623,26 @@ func (ec *executionContext) _DataframeBuilderIntrospection_root(ctx context.Cont } return graphql.Null } - res := resTmp.(*model.DataframeResourceHints) + res := resTmp.(string) fc.Result = res - return ec.marshalNDataframeResourceHints2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeResourceHints(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeBuilderIntrospection_root(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeBuilderIntrospection_project(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DataframeBuilderIntrospection", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "resourceType": - return ec.fieldContext_DataframeResourceHints_resourceType(ctx, field) - case "fields": - return ec.fieldContext_DataframeResourceHints_fields(ctx, field) - case "pivotFields": - return ec.fieldContext_DataframeResourceHints_pivotFields(ctx, field) - case "traversals": - return ec.fieldContext_DataframeResourceHints_traversals(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type DataframeResourceHints", field.Name) + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeBuilderIntrospection_relatedResources(ctx context.Context, field graphql.CollectedField, obj *model.DataframeBuilderIntrospection) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeBuilderIntrospection_relatedResources(ctx, field) +func (ec *executionContext) _DataframeBuilderIntrospection_rootResourceType(ctx context.Context, field graphql.CollectedField, obj *model.DataframeBuilderIntrospection) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeBuilderIntrospection_rootResourceType(ctx, field) if err != nil { return graphql.Null } @@ -1330,7 +1655,7 @@ func (ec *executionContext) _DataframeBuilderIntrospection_relatedResources(ctx }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.RelatedResources, nil + return obj.RootResourceType, nil }) if err != nil { ec.Error(ctx, err) @@ -1342,21 +1667,163 @@ func (ec *executionContext) _DataframeBuilderIntrospection_relatedResources(ctx } return graphql.Null } - res := resTmp.([]*model.DataframeRelatedResourceHints) + res := resTmp.(string) fc.Result = res - return ec.marshalNDataframeRelatedResourceHints2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeRelatedResourceHintsᚄ(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeBuilderIntrospection_relatedResources(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeBuilderIntrospection_rootResourceType(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DataframeBuilderIntrospection", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "viaLabel": - return ec.fieldContext_DataframeRelatedResourceHints_viaLabel(ctx, field) + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeBuilderIntrospection_authResourcePaths(ctx context.Context, field graphql.CollectedField, obj *model.DataframeBuilderIntrospection) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeBuilderIntrospection_authResourcePaths(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.AuthResourcePaths, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]string) + fc.Result = res + return ec.marshalNString2ᚕstringᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeBuilderIntrospection_authResourcePaths(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeBuilderIntrospection", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeBuilderIntrospection_root(ctx context.Context, field graphql.CollectedField, obj *model.DataframeBuilderIntrospection) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeBuilderIntrospection_root(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Root, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.DataframeResourceHints) + fc.Result = res + return ec.marshalNDataframeResourceHints2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeResourceHints(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeBuilderIntrospection_root(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeBuilderIntrospection", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "resourceType": + return ec.fieldContext_DataframeResourceHints_resourceType(ctx, field) + case "fields": + return ec.fieldContext_DataframeResourceHints_fields(ctx, field) + case "pivotFields": + return ec.fieldContext_DataframeResourceHints_pivotFields(ctx, field) + case "traversals": + return ec.fieldContext_DataframeResourceHints_traversals(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DataframeResourceHints", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeBuilderIntrospection_relatedResources(ctx context.Context, field graphql.CollectedField, obj *model.DataframeBuilderIntrospection) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeBuilderIntrospection_relatedResources(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.RelatedResources, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.DataframeRelatedResourceHints) + fc.Result = res + return ec.marshalNDataframeRelatedResourceHints2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeRelatedResourceHintsᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeBuilderIntrospection_relatedResources(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeBuilderIntrospection", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "viaLabel": + return ec.fieldContext_DataframeRelatedResourceHints_viaLabel(ctx, field) case "edgeCount": return ec.fieldContext_DataframeRelatedResourceHints_edgeCount(ctx, field) case "target": @@ -1578,6 +2045,94 @@ func (ec *executionContext) fieldContext_DataframeBuilderIntrospection_pivotFiel return fc, nil } +func (ec *executionContext) _DataframeColumn_name(ctx context.Context, field graphql.CollectedField, obj *model.DataframeColumn) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeColumn_name(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeColumn_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeColumn", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeColumn_clickhouseType(ctx context.Context, field graphql.CollectedField, obj *model.DataframeColumn) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeColumn_clickhouseType(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.ClickhouseType, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeColumn_clickhouseType(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeColumn", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _DataframeCompilerPlanDiagnostics_traversalSets(ctx context.Context, field graphql.CollectedField, obj *model.DataframeCompilerPlanDiagnostics) (ret graphql.Marshaler) { fc, err := ec.fieldContext_DataframeCompilerPlanDiagnostics_traversalSets(ctx, field) if err != nil { @@ -2978,8 +3533,8 @@ func (ec *executionContext) fieldContext_DataframeFieldSelector_valuePath(_ cont return fc, nil } -func (ec *executionContext) _DataframeOptimizationDecision_rule(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationDecision) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeOptimizationDecision_rule(ctx, field) +func (ec *executionContext) _DataframeMaterialization_id(ctx context.Context, field graphql.CollectedField, obj *model.DataframeMaterialization) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeMaterialization_id(ctx, field) if err != nil { return graphql.Null } @@ -2992,7 +3547,7 @@ func (ec *executionContext) _DataframeOptimizationDecision_rule(ctx context.Cont }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.Rule, nil + return obj.ID, nil }) if err != nil { ec.Error(ctx, err) @@ -3006,24 +3561,24 @@ func (ec *executionContext) _DataframeOptimizationDecision_rule(ctx context.Cont } res := resTmp.(string) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeOptimizationDecision_rule(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeMaterialization_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeOptimizationDecision", + Object: "DataframeMaterialization", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + return nil, errors.New("field of type ID does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeOptimizationDecision_enabled(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationDecision) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeOptimizationDecision_enabled(ctx, field) +func (ec *executionContext) _DataframeMaterialization_name(ctx context.Context, field graphql.CollectedField, obj *model.DataframeMaterialization) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeMaterialization_name(ctx, field) if err != nil { return graphql.Null } @@ -3036,7 +3591,7 @@ func (ec *executionContext) _DataframeOptimizationDecision_enabled(ctx context.C }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.Enabled, nil + return obj.Name, nil }) if err != nil { ec.Error(ctx, err) @@ -3048,26 +3603,26 @@ func (ec *executionContext) _DataframeOptimizationDecision_enabled(ctx context.C } return graphql.Null } - res := resTmp.(bool) + res := resTmp.(string) fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeOptimizationDecision_enabled(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeMaterialization_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeOptimizationDecision", + Object: "DataframeMaterialization", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Boolean does not have child fields") + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeOptimizationDecision_candidateSets(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationDecision) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeOptimizationDecision_candidateSets(ctx, field) +func (ec *executionContext) _DataframeMaterialization_project(ctx context.Context, field graphql.CollectedField, obj *model.DataframeMaterialization) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeMaterialization_project(ctx, field) if err != nil { return graphql.Null } @@ -3080,7 +3635,7 @@ func (ec *executionContext) _DataframeOptimizationDecision_candidateSets(ctx con }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.CandidateSets, nil + return obj.Project, nil }) if err != nil { ec.Error(ctx, err) @@ -3092,26 +3647,26 @@ func (ec *executionContext) _DataframeOptimizationDecision_candidateSets(ctx con } return graphql.Null } - res := resTmp.(int) + res := resTmp.(string) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeOptimizationDecision_candidateSets(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeMaterialization_project(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeOptimizationDecision", + Object: "DataframeMaterialization", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeOptimizationDecision_estimatedBaselineWork(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationDecision) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeOptimizationDecision_estimatedBaselineWork(ctx, field) +func (ec *executionContext) _DataframeMaterialization_datasetGeneration(ctx context.Context, field graphql.CollectedField, obj *model.DataframeMaterialization) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeMaterialization_datasetGeneration(ctx, field) if err != nil { return graphql.Null } @@ -3124,7 +3679,7 @@ func (ec *executionContext) _DataframeOptimizationDecision_estimatedBaselineWork }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.EstimatedBaselineWork, nil + return obj.DatasetGeneration, nil }) if err != nil { ec.Error(ctx, err) @@ -3136,26 +3691,26 @@ func (ec *executionContext) _DataframeOptimizationDecision_estimatedBaselineWork } return graphql.Null } - res := resTmp.(int) + res := resTmp.(string) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeOptimizationDecision_estimatedBaselineWork(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeMaterialization_datasetGeneration(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeOptimizationDecision", + Object: "DataframeMaterialization", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeOptimizationDecision_estimatedOptimizedWork(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationDecision) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeOptimizationDecision_estimatedOptimizedWork(ctx, field) +func (ec *executionContext) _DataframeMaterialization_state(ctx context.Context, field graphql.CollectedField, obj *model.DataframeMaterialization) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeMaterialization_state(ctx, field) if err != nil { return graphql.Null } @@ -3168,7 +3723,7 @@ func (ec *executionContext) _DataframeOptimizationDecision_estimatedOptimizedWor }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.EstimatedOptimizedWork, nil + return obj.State, nil }) if err != nil { ec.Error(ctx, err) @@ -3180,26 +3735,26 @@ func (ec *executionContext) _DataframeOptimizationDecision_estimatedOptimizedWor } return graphql.Null } - res := resTmp.(int) + res := resTmp.(model.DataframeMaterializationState) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNDataframeMaterializationState2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeMaterializationState(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeOptimizationDecision_estimatedOptimizedWork(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeMaterialization_state(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeOptimizationDecision", + Object: "DataframeMaterialization", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") + return nil, errors.New("field of type DataframeMaterializationState does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeOptimizationDecision_estimatedSavings(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationDecision) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeOptimizationDecision_estimatedSavings(ctx, field) +func (ec *executionContext) _DataframeMaterialization_columns(ctx context.Context, field graphql.CollectedField, obj *model.DataframeMaterialization) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeMaterialization_columns(ctx, field) if err != nil { return graphql.Null } @@ -3212,7 +3767,7 @@ func (ec *executionContext) _DataframeOptimizationDecision_estimatedSavings(ctx }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.EstimatedSavings, nil + return obj.Columns, nil }) if err != nil { ec.Error(ctx, err) @@ -3224,26 +3779,32 @@ func (ec *executionContext) _DataframeOptimizationDecision_estimatedSavings(ctx } return graphql.Null } - res := resTmp.(int) + res := resTmp.([]*model.DataframeColumn) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNDataframeColumn2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeColumnᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeOptimizationDecision_estimatedSavings(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeMaterialization_columns(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeOptimizationDecision", + Object: "DataframeMaterialization", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") + switch field.Name { + case "name": + return ec.fieldContext_DataframeColumn_name(ctx, field) + case "clickhouseType": + return ec.fieldContext_DataframeColumn_clickhouseType(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DataframeColumn", field.Name) }, } return fc, nil } -func (ec *executionContext) _DataframeOptimizationDecision_reason(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationDecision) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeOptimizationDecision_reason(ctx, field) +func (ec *executionContext) _DataframeMaterialization_rowCount(ctx context.Context, field graphql.CollectedField, obj *model.DataframeMaterialization) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeMaterialization_rowCount(ctx, field) if err != nil { return graphql.Null } @@ -3256,7 +3817,7 @@ func (ec *executionContext) _DataframeOptimizationDecision_reason(ctx context.Co }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.Reason, nil + return obj.RowCount, nil }) if err != nil { ec.Error(ctx, err) @@ -3268,26 +3829,26 @@ func (ec *executionContext) _DataframeOptimizationDecision_reason(ctx context.Co } return graphql.Null } - res := resTmp.(string) + res := resTmp.(int) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeOptimizationDecision_reason(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeMaterialization_rowCount(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeOptimizationDecision", + Object: "DataframeMaterialization", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + return nil, errors.New("field of type Int does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeOptimizationPolicy_name(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationPolicy) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeOptimizationPolicy_name(ctx, field) +func (ec *executionContext) _DataframeMaterialization_createdAt(ctx context.Context, field graphql.CollectedField, obj *model.DataframeMaterialization) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeMaterialization_createdAt(ctx, field) if err != nil { return graphql.Null } @@ -3300,7 +3861,7 @@ func (ec *executionContext) _DataframeOptimizationPolicy_name(ctx context.Contex }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.Name, nil + return obj.CreatedAt, nil }) if err != nil { ec.Error(ctx, err) @@ -3317,9 +3878,9 @@ func (ec *executionContext) _DataframeOptimizationPolicy_name(ctx context.Contex return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeOptimizationPolicy_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeMaterialization_createdAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeOptimizationPolicy", + Object: "DataframeMaterialization", Field: field, IsMethod: false, IsResolver: false, @@ -3330,8 +3891,8 @@ func (ec *executionContext) fieldContext_DataframeOptimizationPolicy_name(_ cont return fc, nil } -func (ec *executionContext) _DataframeOptimizationPolicy_enabled(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationPolicy) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeOptimizationPolicy_enabled(ctx, field) +func (ec *executionContext) _DataframeMaterialization_readyAt(ctx context.Context, field graphql.CollectedField, obj *model.DataframeMaterialization) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeMaterialization_readyAt(ctx, field) if err != nil { return graphql.Null } @@ -3344,38 +3905,35 @@ func (ec *executionContext) _DataframeOptimizationPolicy_enabled(ctx context.Con }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.Enabled, nil + return obj.ReadyAt, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(bool) + res := resTmp.(*string) fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeOptimizationPolicy_enabled(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeMaterialization_readyAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeOptimizationPolicy", + Object: "DataframeMaterialization", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Boolean does not have child fields") + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeOptimizationPolicy_minimumSavings(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationPolicy) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeOptimizationPolicy_minimumSavings(ctx, field) +func (ec *executionContext) _DataframeMaterialization_error(ctx context.Context, field graphql.CollectedField, obj *model.DataframeMaterialization) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeMaterialization_error(ctx, field) if err != nil { return graphql.Null } @@ -3388,38 +3946,35 @@ func (ec *executionContext) _DataframeOptimizationPolicy_minimumSavings(ctx cont }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.MinimumSavings, nil + return obj.Error, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(int) + res := resTmp.(*string) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeOptimizationPolicy_minimumSavings(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeMaterialization_error(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeOptimizationPolicy", + Object: "DataframeMaterialization", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeOptimizationPolicy_decisions(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationPolicy) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeOptimizationPolicy_decisions(ctx, field) +func (ec *executionContext) _DataframeOptimizationDecision_rule(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationDecision) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeOptimizationDecision_rule(ctx, field) if err != nil { return graphql.Null } @@ -3432,7 +3987,7 @@ func (ec *executionContext) _DataframeOptimizationPolicy_decisions(ctx context.C }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.Decisions, nil + return obj.Rule, nil }) if err != nil { ec.Error(ctx, err) @@ -3444,42 +3999,26 @@ func (ec *executionContext) _DataframeOptimizationPolicy_decisions(ctx context.C } return graphql.Null } - res := resTmp.([]*model.DataframeOptimizationDecision) + res := resTmp.(string) fc.Result = res - return ec.marshalNDataframeOptimizationDecision2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeOptimizationDecisionᚄ(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeOptimizationPolicy_decisions(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeOptimizationDecision_rule(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeOptimizationPolicy", + Object: "DataframeOptimizationDecision", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "rule": - return ec.fieldContext_DataframeOptimizationDecision_rule(ctx, field) - case "enabled": - return ec.fieldContext_DataframeOptimizationDecision_enabled(ctx, field) - case "candidateSets": - return ec.fieldContext_DataframeOptimizationDecision_candidateSets(ctx, field) - case "estimatedBaselineWork": - return ec.fieldContext_DataframeOptimizationDecision_estimatedBaselineWork(ctx, field) - case "estimatedOptimizedWork": - return ec.fieldContext_DataframeOptimizationDecision_estimatedOptimizedWork(ctx, field) - case "estimatedSavings": - return ec.fieldContext_DataframeOptimizationDecision_estimatedSavings(ctx, field) - case "reason": - return ec.fieldContext_DataframeOptimizationDecision_reason(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type DataframeOptimizationDecision", field.Name) + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeQueryDiagnostics_inputResolutionMs(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeQueryDiagnostics_inputResolutionMs(ctx, field) +func (ec *executionContext) _DataframeOptimizationDecision_enabled(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationDecision) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeOptimizationDecision_enabled(ctx, field) if err != nil { return graphql.Null } @@ -3492,7 +4031,7 @@ func (ec *executionContext) _DataframeQueryDiagnostics_inputResolutionMs(ctx con }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.InputResolutionMs, nil + return obj.Enabled, nil }) if err != nil { ec.Error(ctx, err) @@ -3504,26 +4043,26 @@ func (ec *executionContext) _DataframeQueryDiagnostics_inputResolutionMs(ctx con } return graphql.Null } - res := resTmp.(float64) + res := resTmp.(bool) fc.Result = res - return ec.marshalNFloat2float64(ctx, field.Selections, res) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_inputResolutionMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeOptimizationDecision_enabled(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeQueryDiagnostics", + Object: "DataframeOptimizationDecision", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Float does not have child fields") + return nil, errors.New("field of type Boolean does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeQueryDiagnostics_requestPreparationMs(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeQueryDiagnostics_requestPreparationMs(ctx, field) +func (ec *executionContext) _DataframeOptimizationDecision_candidateSets(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationDecision) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeOptimizationDecision_candidateSets(ctx, field) if err != nil { return graphql.Null } @@ -3536,7 +4075,7 @@ func (ec *executionContext) _DataframeQueryDiagnostics_requestPreparationMs(ctx }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.RequestPreparationMs, nil + return obj.CandidateSets, nil }) if err != nil { ec.Error(ctx, err) @@ -3548,26 +4087,26 @@ func (ec *executionContext) _DataframeQueryDiagnostics_requestPreparationMs(ctx } return graphql.Null } - res := resTmp.(float64) + res := resTmp.(int) fc.Result = res - return ec.marshalNFloat2float64(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_requestPreparationMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeOptimizationDecision_candidateSets(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeQueryDiagnostics", + Object: "DataframeOptimizationDecision", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Float does not have child fields") + return nil, errors.New("field of type Int does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeQueryDiagnostics_compilationMs(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeQueryDiagnostics_compilationMs(ctx, field) +func (ec *executionContext) _DataframeOptimizationDecision_estimatedBaselineWork(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationDecision) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeOptimizationDecision_estimatedBaselineWork(ctx, field) if err != nil { return graphql.Null } @@ -3580,7 +4119,7 @@ func (ec *executionContext) _DataframeQueryDiagnostics_compilationMs(ctx context }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.CompilationMs, nil + return obj.EstimatedBaselineWork, nil }) if err != nil { ec.Error(ctx, err) @@ -3592,26 +4131,26 @@ func (ec *executionContext) _DataframeQueryDiagnostics_compilationMs(ctx context } return graphql.Null } - res := resTmp.(float64) + res := resTmp.(int) fc.Result = res - return ec.marshalNFloat2float64(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_compilationMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeOptimizationDecision_estimatedBaselineWork(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeQueryDiagnostics", + Object: "DataframeOptimizationDecision", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Float does not have child fields") + return nil, errors.New("field of type Int does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeQueryDiagnostics_arangoQueryMs(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeQueryDiagnostics_arangoQueryMs(ctx, field) +func (ec *executionContext) _DataframeOptimizationDecision_estimatedOptimizedWork(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationDecision) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeOptimizationDecision_estimatedOptimizedWork(ctx, field) if err != nil { return graphql.Null } @@ -3624,7 +4163,7 @@ func (ec *executionContext) _DataframeQueryDiagnostics_arangoQueryMs(ctx context }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.ArangoQueryMs, nil + return obj.EstimatedOptimizedWork, nil }) if err != nil { ec.Error(ctx, err) @@ -3636,26 +4175,26 @@ func (ec *executionContext) _DataframeQueryDiagnostics_arangoQueryMs(ctx context } return graphql.Null } - res := resTmp.(float64) + res := resTmp.(int) fc.Result = res - return ec.marshalNFloat2float64(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_arangoQueryMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeOptimizationDecision_estimatedOptimizedWork(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeQueryDiagnostics", + Object: "DataframeOptimizationDecision", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Float does not have child fields") + return nil, errors.New("field of type Int does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeQueryDiagnostics_rowMaterializationMs(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeQueryDiagnostics_rowMaterializationMs(ctx, field) +func (ec *executionContext) _DataframeOptimizationDecision_estimatedSavings(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationDecision) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeOptimizationDecision_estimatedSavings(ctx, field) if err != nil { return graphql.Null } @@ -3668,7 +4207,7 @@ func (ec *executionContext) _DataframeQueryDiagnostics_rowMaterializationMs(ctx }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.RowMaterializationMs, nil + return obj.EstimatedSavings, nil }) if err != nil { ec.Error(ctx, err) @@ -3680,26 +4219,26 @@ func (ec *executionContext) _DataframeQueryDiagnostics_rowMaterializationMs(ctx } return graphql.Null } - res := resTmp.(float64) + res := resTmp.(int) fc.Result = res - return ec.marshalNFloat2float64(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_rowMaterializationMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeOptimizationDecision_estimatedSavings(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeQueryDiagnostics", + Object: "DataframeOptimizationDecision", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Float does not have child fields") + return nil, errors.New("field of type Int does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeQueryDiagnostics_resultAssemblyMs(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeQueryDiagnostics_resultAssemblyMs(ctx, field) +func (ec *executionContext) _DataframeOptimizationDecision_reason(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationDecision) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeOptimizationDecision_reason(ctx, field) if err != nil { return graphql.Null } @@ -3712,7 +4251,7 @@ func (ec *executionContext) _DataframeQueryDiagnostics_resultAssemblyMs(ctx cont }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.ResultAssemblyMs, nil + return obj.Reason, nil }) if err != nil { ec.Error(ctx, err) @@ -3724,26 +4263,26 @@ func (ec *executionContext) _DataframeQueryDiagnostics_resultAssemblyMs(ctx cont } return graphql.Null } - res := resTmp.(float64) + res := resTmp.(string) fc.Result = res - return ec.marshalNFloat2float64(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_resultAssemblyMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeOptimizationDecision_reason(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeQueryDiagnostics", + Object: "DataframeOptimizationDecision", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Float does not have child fields") + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeQueryDiagnostics_totalMs(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeQueryDiagnostics_totalMs(ctx, field) +func (ec *executionContext) _DataframeOptimizationPolicy_name(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationPolicy) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeOptimizationPolicy_name(ctx, field) if err != nil { return graphql.Null } @@ -3756,7 +4295,7 @@ func (ec *executionContext) _DataframeQueryDiagnostics_totalMs(ctx context.Conte }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.TotalMs, nil + return obj.Name, nil }) if err != nil { ec.Error(ctx, err) @@ -3768,26 +4307,26 @@ func (ec *executionContext) _DataframeQueryDiagnostics_totalMs(ctx context.Conte } return graphql.Null } - res := resTmp.(float64) + res := resTmp.(string) fc.Result = res - return ec.marshalNFloat2float64(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_totalMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeOptimizationPolicy_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeQueryDiagnostics", + Object: "DataframeOptimizationPolicy", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Float does not have child fields") + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeQueryDiagnostics_plan(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeQueryDiagnostics_plan(ctx, field) +func (ec *executionContext) _DataframeOptimizationPolicy_enabled(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationPolicy) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeOptimizationPolicy_enabled(ctx, field) if err != nil { return graphql.Null } @@ -3800,7 +4339,7 @@ func (ec *executionContext) _DataframeQueryDiagnostics_plan(ctx context.Context, }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.Plan, nil + return obj.Enabled, nil }) if err != nil { ec.Error(ctx, err) @@ -3812,45 +4351,586 @@ func (ec *executionContext) _DataframeQueryDiagnostics_plan(ctx context.Context, } return graphql.Null } - res := resTmp.(*model.DataframeCompilerPlanDiagnostics) + res := resTmp.(bool) fc.Result = res - return ec.marshalNDataframeCompilerPlanDiagnostics2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeCompilerPlanDiagnostics(ctx, field.Selections, res) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_plan(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeOptimizationPolicy_enabled(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeQueryDiagnostics", + Object: "DataframeOptimizationPolicy", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "traversalSets": - return ec.fieldContext_DataframeCompilerPlanDiagnostics_traversalSets(ctx, field) - case "sharedTraversalCount": - return ec.fieldContext_DataframeCompilerPlanDiagnostics_sharedTraversalCount(ctx, field) - case "requiredMatchReuseCount": - return ec.fieldContext_DataframeCompilerPlanDiagnostics_requiredMatchReuseCount(ctx, field) - case "scopedSharingCandidateGroups": - return ec.fieldContext_DataframeCompilerPlanDiagnostics_scopedSharingCandidateGroups(ctx, field) - case "scopedSharingCandidateSets": - return ec.fieldContext_DataframeCompilerPlanDiagnostics_scopedSharingCandidateSets(ctx, field) - case "potentialSharingOpportunityGroups": - return ec.fieldContext_DataframeCompilerPlanDiagnostics_potentialSharingOpportunityGroups(ctx, field) - case "potentialSharingOpportunitySets": - return ec.fieldContext_DataframeCompilerPlanDiagnostics_potentialSharingOpportunitySets(ctx, field) - case "optimizationPolicy": - return ec.fieldContext_DataframeCompilerPlanDiagnostics_optimizationPolicy(ctx, field) - case "richSourceReuse": - return ec.fieldContext_DataframeCompilerPlanDiagnostics_richSourceReuse(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type DataframeCompilerPlanDiagnostics", field.Name) + return nil, errors.New("field of type Boolean does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeRelatedResourceHints_viaLabel(ctx context.Context, field graphql.CollectedField, obj *model.DataframeRelatedResourceHints) (ret graphql.Marshaler) { +func (ec *executionContext) _DataframeOptimizationPolicy_minimumSavings(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationPolicy) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeOptimizationPolicy_minimumSavings(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.MinimumSavings, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeOptimizationPolicy_minimumSavings(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeOptimizationPolicy", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeOptimizationPolicy_decisions(ctx context.Context, field graphql.CollectedField, obj *model.DataframeOptimizationPolicy) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeOptimizationPolicy_decisions(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Decisions, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.DataframeOptimizationDecision) + fc.Result = res + return ec.marshalNDataframeOptimizationDecision2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeOptimizationDecisionᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeOptimizationPolicy_decisions(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeOptimizationPolicy", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "rule": + return ec.fieldContext_DataframeOptimizationDecision_rule(ctx, field) + case "enabled": + return ec.fieldContext_DataframeOptimizationDecision_enabled(ctx, field) + case "candidateSets": + return ec.fieldContext_DataframeOptimizationDecision_candidateSets(ctx, field) + case "estimatedBaselineWork": + return ec.fieldContext_DataframeOptimizationDecision_estimatedBaselineWork(ctx, field) + case "estimatedOptimizedWork": + return ec.fieldContext_DataframeOptimizationDecision_estimatedOptimizedWork(ctx, field) + case "estimatedSavings": + return ec.fieldContext_DataframeOptimizationDecision_estimatedSavings(ctx, field) + case "reason": + return ec.fieldContext_DataframeOptimizationDecision_reason(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DataframeOptimizationDecision", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframePageInfo_hasNextPage(ctx context.Context, field graphql.CollectedField, obj *model.DataframePageInfo) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframePageInfo_hasNextPage(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.HasNextPage, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframePageInfo_hasNextPage(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframePageInfo", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframePageInfo_endCursor(ctx context.Context, field graphql.CollectedField, obj *model.DataframePageInfo) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframePageInfo_endCursor(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.EndCursor, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframePageInfo_endCursor(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframePageInfo", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeQueryDiagnostics_inputResolutionMs(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeQueryDiagnostics_inputResolutionMs(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.InputResolutionMs, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(float64) + fc.Result = res + return ec.marshalNFloat2float64(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_inputResolutionMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeQueryDiagnostics", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Float does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeQueryDiagnostics_requestPreparationMs(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeQueryDiagnostics_requestPreparationMs(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.RequestPreparationMs, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(float64) + fc.Result = res + return ec.marshalNFloat2float64(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_requestPreparationMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeQueryDiagnostics", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Float does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeQueryDiagnostics_compilationMs(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeQueryDiagnostics_compilationMs(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.CompilationMs, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(float64) + fc.Result = res + return ec.marshalNFloat2float64(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_compilationMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeQueryDiagnostics", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Float does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeQueryDiagnostics_arangoQueryMs(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeQueryDiagnostics_arangoQueryMs(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.ArangoQueryMs, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(float64) + fc.Result = res + return ec.marshalNFloat2float64(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_arangoQueryMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeQueryDiagnostics", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Float does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeQueryDiagnostics_rowMaterializationMs(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeQueryDiagnostics_rowMaterializationMs(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.RowMaterializationMs, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(float64) + fc.Result = res + return ec.marshalNFloat2float64(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_rowMaterializationMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeQueryDiagnostics", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Float does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeQueryDiagnostics_resultAssemblyMs(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeQueryDiagnostics_resultAssemblyMs(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.ResultAssemblyMs, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(float64) + fc.Result = res + return ec.marshalNFloat2float64(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_resultAssemblyMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeQueryDiagnostics", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Float does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeQueryDiagnostics_totalMs(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeQueryDiagnostics_totalMs(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.TotalMs, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(float64) + fc.Result = res + return ec.marshalNFloat2float64(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_totalMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeQueryDiagnostics", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Float does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeQueryDiagnostics_plan(ctx context.Context, field graphql.CollectedField, obj *model.DataframeQueryDiagnostics) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeQueryDiagnostics_plan(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Plan, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.DataframeCompilerPlanDiagnostics) + fc.Result = res + return ec.marshalNDataframeCompilerPlanDiagnostics2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeCompilerPlanDiagnostics(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeQueryDiagnostics_plan(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeQueryDiagnostics", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "traversalSets": + return ec.fieldContext_DataframeCompilerPlanDiagnostics_traversalSets(ctx, field) + case "sharedTraversalCount": + return ec.fieldContext_DataframeCompilerPlanDiagnostics_sharedTraversalCount(ctx, field) + case "requiredMatchReuseCount": + return ec.fieldContext_DataframeCompilerPlanDiagnostics_requiredMatchReuseCount(ctx, field) + case "scopedSharingCandidateGroups": + return ec.fieldContext_DataframeCompilerPlanDiagnostics_scopedSharingCandidateGroups(ctx, field) + case "scopedSharingCandidateSets": + return ec.fieldContext_DataframeCompilerPlanDiagnostics_scopedSharingCandidateSets(ctx, field) + case "potentialSharingOpportunityGroups": + return ec.fieldContext_DataframeCompilerPlanDiagnostics_potentialSharingOpportunityGroups(ctx, field) + case "potentialSharingOpportunitySets": + return ec.fieldContext_DataframeCompilerPlanDiagnostics_potentialSharingOpportunitySets(ctx, field) + case "optimizationPolicy": + return ec.fieldContext_DataframeCompilerPlanDiagnostics_optimizationPolicy(ctx, field) + case "richSourceReuse": + return ec.fieldContext_DataframeCompilerPlanDiagnostics_richSourceReuse(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DataframeCompilerPlanDiagnostics", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeRelatedResourceHints_viaLabel(ctx context.Context, field graphql.CollectedField, obj *model.DataframeRelatedResourceHints) (ret graphql.Marshaler) { fc, err := ec.fieldContext_DataframeRelatedResourceHints_viaLabel(ctx, field) if err != nil { return graphql.Null @@ -4192,8 +5272,194 @@ func (ec *executionContext) fieldContext_DataframeResourceHints_pivotFields(_ co return fc, nil } -func (ec *executionContext) _DataframeResourceHints_traversals(ctx context.Context, field graphql.CollectedField, obj *model.DataframeResourceHints) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeResourceHints_traversals(ctx, field) +func (ec *executionContext) _DataframeResourceHints_traversals(ctx context.Context, field graphql.CollectedField, obj *model.DataframeResourceHints) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeResourceHints_traversals(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Traversals, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.DataframeTraversalHint) + fc.Result = res + return ec.marshalNDataframeTraversalHint2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeTraversalHintᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeResourceHints_traversals(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeResourceHints", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "fromType": + return ec.fieldContext_DataframeTraversalHint_fromType(ctx, field) + case "label": + return ec.fieldContext_DataframeTraversalHint_label(ctx, field) + case "toType": + return ec.fieldContext_DataframeTraversalHint_toType(ctx, field) + case "edgeCount": + return ec.fieldContext_DataframeTraversalHint_edgeCount(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DataframeTraversalHint", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeRichSourceReuse_sourceSet(ctx context.Context, field graphql.CollectedField, obj *model.DataframeRichSourceReuse) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeRichSourceReuse_sourceSet(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.SourceSet, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeRichSourceReuse_sourceSet(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeRichSourceReuse", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeRichSourceReuse_aggregateConsumers(ctx context.Context, field graphql.CollectedField, obj *model.DataframeRichSourceReuse) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeRichSourceReuse_aggregateConsumers(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.AggregateConsumers, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeRichSourceReuse_aggregateConsumers(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeRichSourceReuse", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeRichSourceReuse_pivotConsumers(ctx context.Context, field graphql.CollectedField, obj *model.DataframeRichSourceReuse) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeRichSourceReuse_pivotConsumers(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.PivotConsumers, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DataframeRichSourceReuse_pivotConsumers(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DataframeRichSourceReuse", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DataframeRichSourceReuse_sliceConsumers(ctx context.Context, field graphql.CollectedField, obj *model.DataframeRichSourceReuse) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeRichSourceReuse_sliceConsumers(ctx, field) if err != nil { return graphql.Null } @@ -4206,7 +5472,7 @@ func (ec *executionContext) _DataframeResourceHints_traversals(ctx context.Conte }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.Traversals, nil + return obj.SliceConsumers, nil }) if err != nil { ec.Error(ctx, err) @@ -4218,36 +5484,26 @@ func (ec *executionContext) _DataframeResourceHints_traversals(ctx context.Conte } return graphql.Null } - res := resTmp.([]*model.DataframeTraversalHint) + res := resTmp.(int) fc.Result = res - return ec.marshalNDataframeTraversalHint2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeTraversalHintᚄ(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeResourceHints_traversals(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeRichSourceReuse_sliceConsumers(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeResourceHints", + Object: "DataframeRichSourceReuse", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "fromType": - return ec.fieldContext_DataframeTraversalHint_fromType(ctx, field) - case "label": - return ec.fieldContext_DataframeTraversalHint_label(ctx, field) - case "toType": - return ec.fieldContext_DataframeTraversalHint_toType(ctx, field) - case "edgeCount": - return ec.fieldContext_DataframeTraversalHint_edgeCount(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type DataframeTraversalHint", field.Name) + return nil, errors.New("field of type Int does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeRichSourceReuse_sourceSet(ctx context.Context, field graphql.CollectedField, obj *model.DataframeRichSourceReuse) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeRichSourceReuse_sourceSet(ctx, field) +func (ec *executionContext) _DataframeRichSourceReuse_totalConsumers(ctx context.Context, field graphql.CollectedField, obj *model.DataframeRichSourceReuse) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeRichSourceReuse_totalConsumers(ctx, field) if err != nil { return graphql.Null } @@ -4260,7 +5516,7 @@ func (ec *executionContext) _DataframeRichSourceReuse_sourceSet(ctx context.Cont }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.SourceSet, nil + return obj.TotalConsumers, nil }) if err != nil { ec.Error(ctx, err) @@ -4272,26 +5528,26 @@ func (ec *executionContext) _DataframeRichSourceReuse_sourceSet(ctx context.Cont } return graphql.Null } - res := resTmp.(string) + res := resTmp.(int) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeRichSourceReuse_sourceSet(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeRichSourceReuse_totalConsumers(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DataframeRichSourceReuse", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + return nil, errors.New("field of type Int does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeRichSourceReuse_aggregateConsumers(ctx context.Context, field graphql.CollectedField, obj *model.DataframeRichSourceReuse) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeRichSourceReuse_aggregateConsumers(ctx, field) +func (ec *executionContext) _DataframeRowConnection_materialization(ctx context.Context, field graphql.CollectedField, obj *model.DataframeRowConnection) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeRowConnection_materialization(ctx, field) if err != nil { return graphql.Null } @@ -4304,7 +5560,7 @@ func (ec *executionContext) _DataframeRichSourceReuse_aggregateConsumers(ctx con }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.AggregateConsumers, nil + return obj.Materialization, nil }) if err != nil { ec.Error(ctx, err) @@ -4316,26 +5572,48 @@ func (ec *executionContext) _DataframeRichSourceReuse_aggregateConsumers(ctx con } return graphql.Null } - res := resTmp.(int) + res := resTmp.(*model.DataframeMaterialization) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNDataframeMaterialization2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeMaterialization(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeRichSourceReuse_aggregateConsumers(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeRowConnection_materialization(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeRichSourceReuse", + Object: "DataframeRowConnection", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") + switch field.Name { + case "id": + return ec.fieldContext_DataframeMaterialization_id(ctx, field) + case "name": + return ec.fieldContext_DataframeMaterialization_name(ctx, field) + case "project": + return ec.fieldContext_DataframeMaterialization_project(ctx, field) + case "datasetGeneration": + return ec.fieldContext_DataframeMaterialization_datasetGeneration(ctx, field) + case "state": + return ec.fieldContext_DataframeMaterialization_state(ctx, field) + case "columns": + return ec.fieldContext_DataframeMaterialization_columns(ctx, field) + case "rowCount": + return ec.fieldContext_DataframeMaterialization_rowCount(ctx, field) + case "createdAt": + return ec.fieldContext_DataframeMaterialization_createdAt(ctx, field) + case "readyAt": + return ec.fieldContext_DataframeMaterialization_readyAt(ctx, field) + case "error": + return ec.fieldContext_DataframeMaterialization_error(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DataframeMaterialization", field.Name) }, } return fc, nil } -func (ec *executionContext) _DataframeRichSourceReuse_pivotConsumers(ctx context.Context, field graphql.CollectedField, obj *model.DataframeRichSourceReuse) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeRichSourceReuse_pivotConsumers(ctx, field) +func (ec *executionContext) _DataframeRowConnection_columns(ctx context.Context, field graphql.CollectedField, obj *model.DataframeRowConnection) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeRowConnection_columns(ctx, field) if err != nil { return graphql.Null } @@ -4348,7 +5626,7 @@ func (ec *executionContext) _DataframeRichSourceReuse_pivotConsumers(ctx context }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.PivotConsumers, nil + return obj.Columns, nil }) if err != nil { ec.Error(ctx, err) @@ -4360,26 +5638,26 @@ func (ec *executionContext) _DataframeRichSourceReuse_pivotConsumers(ctx context } return graphql.Null } - res := resTmp.(int) + res := resTmp.([]string) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNString2ᚕstringᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeRichSourceReuse_pivotConsumers(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeRowConnection_columns(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeRichSourceReuse", + Object: "DataframeRowConnection", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeRichSourceReuse_sliceConsumers(ctx context.Context, field graphql.CollectedField, obj *model.DataframeRichSourceReuse) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeRichSourceReuse_sliceConsumers(ctx, field) +func (ec *executionContext) _DataframeRowConnection_rows(ctx context.Context, field graphql.CollectedField, obj *model.DataframeRowConnection) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeRowConnection_rows(ctx, field) if err != nil { return graphql.Null } @@ -4392,7 +5670,7 @@ func (ec *executionContext) _DataframeRichSourceReuse_sliceConsumers(ctx context }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.SliceConsumers, nil + return obj.Rows, nil }) if err != nil { ec.Error(ctx, err) @@ -4404,26 +5682,26 @@ func (ec *executionContext) _DataframeRichSourceReuse_sliceConsumers(ctx context } return graphql.Null } - res := resTmp.(int) + res := resTmp.(json.RawMessage) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNJSON2encodingᚋjsonᚐRawMessage(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeRichSourceReuse_sliceConsumers(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeRowConnection_rows(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeRichSourceReuse", + Object: "DataframeRowConnection", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") + return nil, errors.New("field of type JSON does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DataframeRichSourceReuse_totalConsumers(ctx context.Context, field graphql.CollectedField, obj *model.DataframeRichSourceReuse) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DataframeRichSourceReuse_totalConsumers(ctx, field) +func (ec *executionContext) _DataframeRowConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *model.DataframeRowConnection) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DataframeRowConnection_pageInfo(ctx, field) if err != nil { return graphql.Null } @@ -4436,7 +5714,7 @@ func (ec *executionContext) _DataframeRichSourceReuse_totalConsumers(ctx context }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.TotalConsumers, nil + return obj.PageInfo, nil }) if err != nil { ec.Error(ctx, err) @@ -4448,19 +5726,25 @@ func (ec *executionContext) _DataframeRichSourceReuse_totalConsumers(ctx context } return graphql.Null } - res := resTmp.(int) + res := resTmp.(*model.DataframePageInfo) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNDataframePageInfo2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframePageInfo(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DataframeRichSourceReuse_totalConsumers(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DataframeRowConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DataframeRichSourceReuse", + Object: "DataframeRowConnection", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") + switch field.Name { + case "hasNextPage": + return ec.fieldContext_DataframePageInfo_hasNextPage(ctx, field) + case "endCursor": + return ec.fieldContext_DataframePageInfo_endCursor(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DataframePageInfo", field.Name) }, } return fc, nil @@ -4730,8 +6014,179 @@ func (ec *executionContext) fieldContext_FhirDataframeResult_rows(_ context.Cont return fc, nil } -func (ec *executionContext) _FhirDataframeResult_rowCount(ctx context.Context, field graphql.CollectedField, obj *model.FhirDataframeResult) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_FhirDataframeResult_rowCount(ctx, field) +func (ec *executionContext) _FhirDataframeResult_rowCount(ctx context.Context, field graphql.CollectedField, obj *model.FhirDataframeResult) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_FhirDataframeResult_rowCount(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.RowCount, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_FhirDataframeResult_rowCount(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "FhirDataframeResult", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _FhirDataframeResult_diagnostics(ctx context.Context, field graphql.CollectedField, obj *model.FhirDataframeResult) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_FhirDataframeResult_diagnostics(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Diagnostics, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.DataframeQueryDiagnostics) + fc.Result = res + return ec.marshalNDataframeQueryDiagnostics2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeQueryDiagnostics(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_FhirDataframeResult_diagnostics(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "FhirDataframeResult", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "inputResolutionMs": + return ec.fieldContext_DataframeQueryDiagnostics_inputResolutionMs(ctx, field) + case "requestPreparationMs": + return ec.fieldContext_DataframeQueryDiagnostics_requestPreparationMs(ctx, field) + case "compilationMs": + return ec.fieldContext_DataframeQueryDiagnostics_compilationMs(ctx, field) + case "arangoQueryMs": + return ec.fieldContext_DataframeQueryDiagnostics_arangoQueryMs(ctx, field) + case "rowMaterializationMs": + return ec.fieldContext_DataframeQueryDiagnostics_rowMaterializationMs(ctx, field) + case "resultAssemblyMs": + return ec.fieldContext_DataframeQueryDiagnostics_resultAssemblyMs(ctx, field) + case "totalMs": + return ec.fieldContext_DataframeQueryDiagnostics_totalMs(ctx, field) + case "plan": + return ec.fieldContext_DataframeQueryDiagnostics_plan(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DataframeQueryDiagnostics", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _Mutation_runFhirDataframe(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_runFhirDataframe(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().RunFhirDataframe(rctx, fc.Args["input"].(model.FhirDataframeInput), fc.Args["limit"].(*int)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.FhirDataframeResult) + fc.Result = res + return ec.marshalNFhirDataframeResult2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirDataframeResult(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Mutation_runFhirDataframe(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "columns": + return ec.fieldContext_FhirDataframeResult_columns(ctx, field) + case "rows": + return ec.fieldContext_FhirDataframeResult_rows(ctx, field) + case "rowCount": + return ec.fieldContext_FhirDataframeResult_rowCount(ctx, field) + case "diagnostics": + return ec.fieldContext_FhirDataframeResult_diagnostics(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type FhirDataframeResult", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_runFhirDataframe_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_dataframeBuilderIntrospection(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_dataframeBuilderIntrospection(ctx, field) if err != nil { return graphql.Null } @@ -4744,7 +6199,7 @@ func (ec *executionContext) _FhirDataframeResult_rowCount(ctx context.Context, f }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.RowCount, nil + return ec.resolvers.Query().DataframeBuilderIntrospection(rctx, fc.Args["input"].(model.DataframeBuilderIntrospectionInput)) }) if err != nil { ec.Error(ctx, err) @@ -4756,26 +6211,55 @@ func (ec *executionContext) _FhirDataframeResult_rowCount(ctx context.Context, f } return graphql.Null } - res := resTmp.(int) + res := resTmp.(*model.DataframeBuilderIntrospection) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNDataframeBuilderIntrospection2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeBuilderIntrospection(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_FhirDataframeResult_rowCount(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_dataframeBuilderIntrospection(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "FhirDataframeResult", + Object: "Query", Field: field, - IsMethod: false, - IsResolver: false, + IsMethod: true, + IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") + switch field.Name { + case "project": + return ec.fieldContext_DataframeBuilderIntrospection_project(ctx, field) + case "rootResourceType": + return ec.fieldContext_DataframeBuilderIntrospection_rootResourceType(ctx, field) + case "authResourcePaths": + return ec.fieldContext_DataframeBuilderIntrospection_authResourcePaths(ctx, field) + case "root": + return ec.fieldContext_DataframeBuilderIntrospection_root(ctx, field) + case "relatedResources": + return ec.fieldContext_DataframeBuilderIntrospection_relatedResources(ctx, field) + case "traversals": + return ec.fieldContext_DataframeBuilderIntrospection_traversals(ctx, field) + case "fields": + return ec.fieldContext_DataframeBuilderIntrospection_fields(ctx, field) + case "pivotFields": + return ec.fieldContext_DataframeBuilderIntrospection_pivotFields(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DataframeBuilderIntrospection", field.Name) }, } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_dataframeBuilderIntrospection_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } return fc, nil } -func (ec *executionContext) _FhirDataframeResult_diagnostics(ctx context.Context, field graphql.CollectedField, obj *model.FhirDataframeResult) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_FhirDataframeResult_diagnostics(ctx, field) +func (ec *executionContext) _Query_dataframeMaterialization(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_dataframeMaterialization(ctx, field) if err != nil { return graphql.Null } @@ -4788,56 +6272,68 @@ func (ec *executionContext) _FhirDataframeResult_diagnostics(ctx context.Context }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.Diagnostics, nil + return ec.resolvers.Query().DataframeMaterialization(rctx, fc.Args["id"].(string)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(*model.DataframeQueryDiagnostics) + res := resTmp.(*model.DataframeMaterialization) fc.Result = res - return ec.marshalNDataframeQueryDiagnostics2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeQueryDiagnostics(ctx, field.Selections, res) + return ec.marshalODataframeMaterialization2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeMaterialization(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_FhirDataframeResult_diagnostics(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_dataframeMaterialization(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "FhirDataframeResult", + Object: "Query", Field: field, - IsMethod: false, - IsResolver: false, + IsMethod: true, + IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "inputResolutionMs": - return ec.fieldContext_DataframeQueryDiagnostics_inputResolutionMs(ctx, field) - case "requestPreparationMs": - return ec.fieldContext_DataframeQueryDiagnostics_requestPreparationMs(ctx, field) - case "compilationMs": - return ec.fieldContext_DataframeQueryDiagnostics_compilationMs(ctx, field) - case "arangoQueryMs": - return ec.fieldContext_DataframeQueryDiagnostics_arangoQueryMs(ctx, field) - case "rowMaterializationMs": - return ec.fieldContext_DataframeQueryDiagnostics_rowMaterializationMs(ctx, field) - case "resultAssemblyMs": - return ec.fieldContext_DataframeQueryDiagnostics_resultAssemblyMs(ctx, field) - case "totalMs": - return ec.fieldContext_DataframeQueryDiagnostics_totalMs(ctx, field) - case "plan": - return ec.fieldContext_DataframeQueryDiagnostics_plan(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type DataframeQueryDiagnostics", field.Name) + case "id": + return ec.fieldContext_DataframeMaterialization_id(ctx, field) + case "name": + return ec.fieldContext_DataframeMaterialization_name(ctx, field) + case "project": + return ec.fieldContext_DataframeMaterialization_project(ctx, field) + case "datasetGeneration": + return ec.fieldContext_DataframeMaterialization_datasetGeneration(ctx, field) + case "state": + return ec.fieldContext_DataframeMaterialization_state(ctx, field) + case "columns": + return ec.fieldContext_DataframeMaterialization_columns(ctx, field) + case "rowCount": + return ec.fieldContext_DataframeMaterialization_rowCount(ctx, field) + case "createdAt": + return ec.fieldContext_DataframeMaterialization_createdAt(ctx, field) + case "readyAt": + return ec.fieldContext_DataframeMaterialization_readyAt(ctx, field) + case "error": + return ec.fieldContext_DataframeMaterialization_error(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DataframeMaterialization", field.Name) }, } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_dataframeMaterialization_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } return fc, nil } -func (ec *executionContext) _Mutation_runFhirDataframe(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Mutation_runFhirDataframe(ctx, field) +func (ec *executionContext) _Query_dataframeRows(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_dataframeRows(ctx, field) if err != nil { return graphql.Null } @@ -4850,7 +6346,7 @@ func (ec *executionContext) _Mutation_runFhirDataframe(ctx context.Context, fiel }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Mutation().RunFhirDataframe(rctx, fc.Args["input"].(model.FhirDataframeInput), fc.Args["limit"].(*int)) + return ec.resolvers.Query().DataframeRows(rctx, fc.Args["input"].(model.DataframeRowsInput)) }) if err != nil { ec.Error(ctx, err) @@ -4862,29 +6358,29 @@ func (ec *executionContext) _Mutation_runFhirDataframe(ctx context.Context, fiel } return graphql.Null } - res := resTmp.(*model.FhirDataframeResult) + res := resTmp.(*model.DataframeRowConnection) fc.Result = res - return ec.marshalNFhirDataframeResult2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirDataframeResult(ctx, field.Selections, res) + return ec.marshalNDataframeRowConnection2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeRowConnection(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Mutation_runFhirDataframe(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_dataframeRows(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "Mutation", + Object: "Query", Field: field, IsMethod: true, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { + case "materialization": + return ec.fieldContext_DataframeRowConnection_materialization(ctx, field) case "columns": - return ec.fieldContext_FhirDataframeResult_columns(ctx, field) + return ec.fieldContext_DataframeRowConnection_columns(ctx, field) case "rows": - return ec.fieldContext_FhirDataframeResult_rows(ctx, field) - case "rowCount": - return ec.fieldContext_FhirDataframeResult_rowCount(ctx, field) - case "diagnostics": - return ec.fieldContext_FhirDataframeResult_diagnostics(ctx, field) + return ec.fieldContext_DataframeRowConnection_rows(ctx, field) + case "pageInfo": + return ec.fieldContext_DataframeRowConnection_pageInfo(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type FhirDataframeResult", field.Name) + return nil, fmt.Errorf("no field named %q was found under type DataframeRowConnection", field.Name) }, } defer func() { @@ -4894,15 +6390,15 @@ func (ec *executionContext) fieldContext_Mutation_runFhirDataframe(ctx context.C } }() ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Mutation_runFhirDataframe_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + if fc.Args, err = ec.field_Query_dataframeRows_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) return fc, err } return fc, nil } -func (ec *executionContext) _Query_dataframeBuilderIntrospection(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_dataframeBuilderIntrospection(ctx, field) +func (ec *executionContext) _Query_dataframeAggregate(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_dataframeAggregate(ctx, field) if err != nil { return graphql.Null } @@ -4915,7 +6411,7 @@ func (ec *executionContext) _Query_dataframeBuilderIntrospection(ctx context.Con }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().DataframeBuilderIntrospection(rctx, fc.Args["input"].(model.DataframeBuilderIntrospectionInput)) + return ec.resolvers.Query().DataframeAggregate(rctx, fc.Args["input"].(model.DataframeAggregateInput)) }) if err != nil { ec.Error(ctx, err) @@ -4927,12 +6423,12 @@ func (ec *executionContext) _Query_dataframeBuilderIntrospection(ctx context.Con } return graphql.Null } - res := resTmp.(*model.DataframeBuilderIntrospection) + res := resTmp.(*model.DataframeAggregateResult) fc.Result = res - return ec.marshalNDataframeBuilderIntrospection2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeBuilderIntrospection(ctx, field.Selections, res) + return ec.marshalNDataframeAggregateResult2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeAggregateResult(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_dataframeBuilderIntrospection(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_dataframeAggregate(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -4940,24 +6436,14 @@ func (ec *executionContext) fieldContext_Query_dataframeBuilderIntrospection(ctx IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "project": - return ec.fieldContext_DataframeBuilderIntrospection_project(ctx, field) - case "rootResourceType": - return ec.fieldContext_DataframeBuilderIntrospection_rootResourceType(ctx, field) - case "authResourcePaths": - return ec.fieldContext_DataframeBuilderIntrospection_authResourcePaths(ctx, field) - case "root": - return ec.fieldContext_DataframeBuilderIntrospection_root(ctx, field) - case "relatedResources": - return ec.fieldContext_DataframeBuilderIntrospection_relatedResources(ctx, field) - case "traversals": - return ec.fieldContext_DataframeBuilderIntrospection_traversals(ctx, field) - case "fields": - return ec.fieldContext_DataframeBuilderIntrospection_fields(ctx, field) - case "pivotFields": - return ec.fieldContext_DataframeBuilderIntrospection_pivotFields(ctx, field) + case "materialization": + return ec.fieldContext_DataframeAggregateResult_materialization(ctx, field) + case "columns": + return ec.fieldContext_DataframeAggregateResult_columns(ctx, field) + case "rows": + return ec.fieldContext_DataframeAggregateResult_rows(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type DataframeBuilderIntrospection", field.Name) + return nil, fmt.Errorf("no field named %q was found under type DataframeAggregateResult", field.Name) }, } defer func() { @@ -4967,7 +6453,7 @@ func (ec *executionContext) fieldContext_Query_dataframeBuilderIntrospection(ctx } }() ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_dataframeBuilderIntrospection_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + if fc.Args, err = ec.field_Query_dataframeAggregate_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) return fc, err } @@ -7039,69 +8525,269 @@ func (ec *executionContext) ___Type_isOneOf(ctx context.Context, field graphql.C return ec.marshalOBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Type_isOneOf(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "__Type", - Field: field, - IsMethod: true, - IsResolver: false, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Boolean does not have child fields") - }, +func (ec *executionContext) fieldContext___Type_isOneOf(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + +// endregion **************************** field.gotpl ***************************** + +// region **************************** input.gotpl ***************************** + +func (ec *executionContext) unmarshalInputDataframeAggregateInput(ctx context.Context, obj any) (model.DataframeAggregateInput, error) { + var it model.DataframeAggregateInput + asMap := map[string]any{} + for k, v := range obj.(map[string]any) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"materializationId", "groupBy", "filters", "operation", "column"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "materializationId": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("materializationId")) + data, err := ec.unmarshalNID2string(ctx, v) + if err != nil { + return it, err + } + it.MaterializationID = data + case "groupBy": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("groupBy")) + data, err := ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + it.GroupBy = data + case "filters": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filters")) + data, err := ec.unmarshalODataframeFilterInput2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeFilterInputᚄ(ctx, v) + if err != nil { + return it, err + } + it.Filters = data + case "operation": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("operation")) + data, err := ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + it.Operation = data + case "column": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("column")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.Column = data + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputDataframeBuilderIntrospectionInput(ctx context.Context, obj any) (model.DataframeBuilderIntrospectionInput, error) { + var it model.DataframeBuilderIntrospectionInput + asMap := map[string]any{} + for k, v := range obj.(map[string]any) { + asMap[k] = v + } + + if _, present := asMap["includePivotOnlyFields"]; !present { + asMap["includePivotOnlyFields"] = true + } + + fieldsInOrder := [...]string{"project", "rootResourceType", "authResourcePaths", "includePivotOnlyFields"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "project": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("project")) + data, err := ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + it.Project = data + case "rootResourceType": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("rootResourceType")) + data, err := ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + it.RootResourceType = data + case "authResourcePaths": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("authResourcePaths")) + data, err := ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + it.AuthResourcePaths = data + case "includePivotOnlyFields": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("includePivotOnlyFields")) + data, err := ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + it.IncludePivotOnlyFields = data + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputDataframeFilterInput(ctx context.Context, obj any) (model.DataframeFilterInput, error) { + var it model.DataframeFilterInput + asMap := map[string]any{} + for k, v := range obj.(map[string]any) { + asMap[k] = v } - return fc, nil -} -// endregion **************************** field.gotpl ***************************** + fieldsInOrder := [...]string{"column", "op", "value"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "column": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("column")) + data, err := ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + it.Column = data + case "op": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("op")) + data, err := ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + it.Op = data + case "value": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("value")) + data, err := ec.unmarshalNJSON2encodingᚋjsonᚐRawMessage(ctx, v) + if err != nil { + return it, err + } + it.Value = data + } + } -// region **************************** input.gotpl ***************************** + return it, nil +} -func (ec *executionContext) unmarshalInputDataframeBuilderIntrospectionInput(ctx context.Context, obj any) (model.DataframeBuilderIntrospectionInput, error) { - var it model.DataframeBuilderIntrospectionInput +func (ec *executionContext) unmarshalInputDataframeRowsInput(ctx context.Context, obj any) (model.DataframeRowsInput, error) { + var it model.DataframeRowsInput asMap := map[string]any{} for k, v := range obj.(map[string]any) { asMap[k] = v } - if _, present := asMap["includePivotOnlyFields"]; !present { - asMap["includePivotOnlyFields"] = true + if _, present := asMap["first"]; !present { + asMap["first"] = 100 } - fieldsInOrder := [...]string{"project", "rootResourceType", "authResourcePaths", "includePivotOnlyFields"} + fieldsInOrder := [...]string{"materializationId", "columns", "filters", "sort", "first", "after"} for _, k := range fieldsInOrder { v, ok := asMap[k] if !ok { continue } switch k { - case "project": - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("project")) - data, err := ec.unmarshalNString2string(ctx, v) + case "materializationId": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("materializationId")) + data, err := ec.unmarshalNID2string(ctx, v) if err != nil { return it, err } - it.Project = data - case "rootResourceType": - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("rootResourceType")) - data, err := ec.unmarshalNString2string(ctx, v) + it.MaterializationID = data + case "columns": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("columns")) + data, err := ec.unmarshalOString2ᚕstringᚄ(ctx, v) if err != nil { return it, err } - it.RootResourceType = data - case "authResourcePaths": - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("authResourcePaths")) - data, err := ec.unmarshalOString2ᚕstringᚄ(ctx, v) + it.Columns = data + case "filters": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filters")) + data, err := ec.unmarshalODataframeFilterInput2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeFilterInputᚄ(ctx, v) if err != nil { return it, err } - it.AuthResourcePaths = data - case "includePivotOnlyFields": - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("includePivotOnlyFields")) + it.Filters = data + case "sort": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("sort")) + data, err := ec.unmarshalODataframeSortInput2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeSortInput(ctx, v) + if err != nil { + return it, err + } + it.Sort = data + case "first": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("first")) + data, err := ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + it.First = data + case "after": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("after")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.After = data + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputDataframeSortInput(ctx context.Context, obj any) (model.DataframeSortInput, error) { + var it model.DataframeSortInput + asMap := map[string]any{} + for k, v := range obj.(map[string]any) { + asMap[k] = v + } + + if _, present := asMap["desc"]; !present { + asMap["desc"] = false + } + + fieldsInOrder := [...]string{"column", "desc"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "column": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("column")) + data, err := ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + it.Column = data + case "desc": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("desc")) data, err := ec.unmarshalOBoolean2ᚖbool(ctx, v) if err != nil { return it, err } - it.IncludePivotOnlyFields = data + it.Desc = data } } @@ -7675,6 +9361,55 @@ func (ec *executionContext) unmarshalInputFhirTraversalStepInput(ctx context.Con // region **************************** object.gotpl **************************** +var dataframeAggregateResultImplementors = []string{"DataframeAggregateResult"} + +func (ec *executionContext) _DataframeAggregateResult(ctx context.Context, sel ast.SelectionSet, obj *model.DataframeAggregateResult) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, dataframeAggregateResultImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("DataframeAggregateResult") + case "materialization": + out.Values[i] = ec._DataframeAggregateResult_materialization(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "columns": + out.Values[i] = ec._DataframeAggregateResult_columns(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "rows": + out.Values[i] = ec._DataframeAggregateResult_rows(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var dataframeBuilderIntrospectionImplementors = []string{"DataframeBuilderIntrospection"} func (ec *executionContext) _DataframeBuilderIntrospection(ctx context.Context, sel ast.SelectionSet, obj *model.DataframeBuilderIntrospection) graphql.Marshaler { @@ -7749,6 +9484,50 @@ func (ec *executionContext) _DataframeBuilderIntrospection(ctx context.Context, return out } +var dataframeColumnImplementors = []string{"DataframeColumn"} + +func (ec *executionContext) _DataframeColumn(ctx context.Context, sel ast.SelectionSet, obj *model.DataframeColumn) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, dataframeColumnImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("DataframeColumn") + case "name": + out.Values[i] = ec._DataframeColumn_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "clickhouseType": + out.Values[i] = ec._DataframeColumn_clickhouseType(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var dataframeCompilerPlanDiagnosticsImplementors = []string{"DataframeCompilerPlanDiagnostics"} func (ec *executionContext) _DataframeCompilerPlanDiagnostics(ctx context.Context, sel ast.SelectionSet, obj *model.DataframeCompilerPlanDiagnostics) graphql.Marshaler { @@ -8022,6 +9801,84 @@ func (ec *executionContext) _DataframeFieldSelector(ctx context.Context, sel ast return out } +var dataframeMaterializationImplementors = []string{"DataframeMaterialization"} + +func (ec *executionContext) _DataframeMaterialization(ctx context.Context, sel ast.SelectionSet, obj *model.DataframeMaterialization) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, dataframeMaterializationImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("DataframeMaterialization") + case "id": + out.Values[i] = ec._DataframeMaterialization_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "name": + out.Values[i] = ec._DataframeMaterialization_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "project": + out.Values[i] = ec._DataframeMaterialization_project(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "datasetGeneration": + out.Values[i] = ec._DataframeMaterialization_datasetGeneration(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "state": + out.Values[i] = ec._DataframeMaterialization_state(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "columns": + out.Values[i] = ec._DataframeMaterialization_columns(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "rowCount": + out.Values[i] = ec._DataframeMaterialization_rowCount(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "createdAt": + out.Values[i] = ec._DataframeMaterialization_createdAt(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "readyAt": + out.Values[i] = ec._DataframeMaterialization_readyAt(ctx, field, obj) + case "error": + out.Values[i] = ec._DataframeMaterialization_error(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var dataframeOptimizationDecisionImplementors = []string{"DataframeOptimizationDecision"} func (ec *executionContext) _DataframeOptimizationDecision(ctx context.Context, sel ast.SelectionSet, obj *model.DataframeOptimizationDecision) graphql.Marshaler { @@ -8145,6 +10002,47 @@ func (ec *executionContext) _DataframeOptimizationPolicy(ctx context.Context, se return out } +var dataframePageInfoImplementors = []string{"DataframePageInfo"} + +func (ec *executionContext) _DataframePageInfo(ctx context.Context, sel ast.SelectionSet, obj *model.DataframePageInfo) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, dataframePageInfoImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("DataframePageInfo") + case "hasNextPage": + out.Values[i] = ec._DataframePageInfo_hasNextPage(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "endCursor": + out.Values[i] = ec._DataframePageInfo_endCursor(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var dataframeQueryDiagnosticsImplementors = []string{"DataframeQueryDiagnostics"} func (ec *executionContext) _DataframeQueryDiagnostics(ctx context.Context, sel ast.SelectionSet, obj *model.DataframeQueryDiagnostics) graphql.Marshaler { @@ -8381,6 +10279,60 @@ func (ec *executionContext) _DataframeRichSourceReuse(ctx context.Context, sel a return out } +var dataframeRowConnectionImplementors = []string{"DataframeRowConnection"} + +func (ec *executionContext) _DataframeRowConnection(ctx context.Context, sel ast.SelectionSet, obj *model.DataframeRowConnection) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, dataframeRowConnectionImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("DataframeRowConnection") + case "materialization": + out.Values[i] = ec._DataframeRowConnection_materialization(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "columns": + out.Values[i] = ec._DataframeRowConnection_columns(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "rows": + out.Values[i] = ec._DataframeRowConnection_rows(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "pageInfo": + out.Values[i] = ec._DataframeRowConnection_pageInfo(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var dataframeTraversalHintImplementors = []string{"DataframeTraversalHint"} func (ec *executionContext) _DataframeTraversalHint(ctx context.Context, sel ast.SelectionSet, obj *model.DataframeTraversalHint) graphql.Marshaler { @@ -8578,6 +10530,69 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "dataframeMaterialization": + field := field + + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_dataframeMaterialization(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "dataframeRows": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_dataframeRows(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "dataframeAggregate": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_dataframeAggregate(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "__type": out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { @@ -8960,6 +10975,25 @@ func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.Se return res } +func (ec *executionContext) unmarshalNDataframeAggregateInput2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeAggregateInput(ctx context.Context, v any) (model.DataframeAggregateInput, error) { + res, err := ec.unmarshalInputDataframeAggregateInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNDataframeAggregateResult2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeAggregateResult(ctx context.Context, sel ast.SelectionSet, v model.DataframeAggregateResult) graphql.Marshaler { + return ec._DataframeAggregateResult(ctx, sel, &v) +} + +func (ec *executionContext) marshalNDataframeAggregateResult2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeAggregateResult(ctx context.Context, sel ast.SelectionSet, v *model.DataframeAggregateResult) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._DataframeAggregateResult(ctx, sel, v) +} + func (ec *executionContext) marshalNDataframeBuilderIntrospection2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeBuilderIntrospection(ctx context.Context, sel ast.SelectionSet, v model.DataframeBuilderIntrospection) graphql.Marshaler { return ec._DataframeBuilderIntrospection(ctx, sel, &v) } @@ -8979,6 +11013,60 @@ func (ec *executionContext) unmarshalNDataframeBuilderIntrospectionInput2github return res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) marshalNDataframeColumn2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeColumnᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.DataframeColumn) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNDataframeColumn2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeColumn(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNDataframeColumn2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeColumn(ctx context.Context, sel ast.SelectionSet, v *model.DataframeColumn) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._DataframeColumn(ctx, sel, v) +} + func (ec *executionContext) marshalNDataframeCompilerPlanDiagnostics2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeCompilerPlanDiagnostics(ctx context.Context, sel ast.SelectionSet, v *model.DataframeCompilerPlanDiagnostics) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { @@ -9053,6 +11141,31 @@ func (ec *executionContext) marshalNDataframeFieldSelector2ᚖgithubᚗcomᚋcal return ec._DataframeFieldSelector(ctx, sel, v) } +func (ec *executionContext) unmarshalNDataframeFilterInput2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeFilterInput(ctx context.Context, v any) (*model.DataframeFilterInput, error) { + res, err := ec.unmarshalInputDataframeFilterInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNDataframeMaterialization2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeMaterialization(ctx context.Context, sel ast.SelectionSet, v *model.DataframeMaterialization) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._DataframeMaterialization(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNDataframeMaterializationState2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeMaterializationState(ctx context.Context, v any) (model.DataframeMaterializationState, error) { + var res model.DataframeMaterializationState + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNDataframeMaterializationState2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeMaterializationState(ctx context.Context, sel ast.SelectionSet, v model.DataframeMaterializationState) graphql.Marshaler { + return v +} + func (ec *executionContext) marshalNDataframeOptimizationDecision2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeOptimizationDecisionᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.DataframeOptimizationDecision) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup @@ -9117,6 +11230,16 @@ func (ec *executionContext) marshalNDataframeOptimizationPolicy2ᚖgithubᚗcom return ec._DataframeOptimizationPolicy(ctx, sel, v) } +func (ec *executionContext) marshalNDataframePageInfo2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframePageInfo(ctx context.Context, sel ast.SelectionSet, v *model.DataframePageInfo) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._DataframePageInfo(ctx, sel, v) +} + func (ec *executionContext) marshalNDataframeQueryDiagnostics2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeQueryDiagnostics(ctx context.Context, sel ast.SelectionSet, v *model.DataframeQueryDiagnostics) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { @@ -9245,6 +11368,25 @@ func (ec *executionContext) marshalNDataframeRichSourceReuse2ᚖgithubᚗcomᚋc return ec._DataframeRichSourceReuse(ctx, sel, v) } +func (ec *executionContext) marshalNDataframeRowConnection2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeRowConnection(ctx context.Context, sel ast.SelectionSet, v model.DataframeRowConnection) graphql.Marshaler { + return ec._DataframeRowConnection(ctx, sel, &v) +} + +func (ec *executionContext) marshalNDataframeRowConnection2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeRowConnection(ctx context.Context, sel ast.SelectionSet, v *model.DataframeRowConnection) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._DataframeRowConnection(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNDataframeRowsInput2githubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeRowsInput(ctx context.Context, v any) (model.DataframeRowsInput, error) { + res, err := ec.unmarshalInputDataframeRowsInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) marshalNDataframeTraversalHint2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeTraversalHintᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.DataframeTraversalHint) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup @@ -9427,6 +11569,21 @@ func (ec *executionContext) marshalNFloat2float64(ctx context.Context, sel ast.S return graphql.WrapContextMarshaler(ctx, res) } +func (ec *executionContext) unmarshalNID2string(ctx context.Context, v any) (string, error) { + res, err := graphql.UnmarshalID(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNID2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + res := graphql.MarshalID(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + func (ec *executionContext) unmarshalNInt2int(ctx context.Context, v any) (int, error) { res, err := graphql.UnmarshalInt(v) return res, graphql.ErrorOnPath(ctx, err) @@ -9797,6 +11954,41 @@ func (ec *executionContext) marshalODataframeFieldSelector2ᚖgithubᚗcomᚋcal return ec._DataframeFieldSelector(ctx, sel, v) } +func (ec *executionContext) unmarshalODataframeFilterInput2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeFilterInputᚄ(ctx context.Context, v any) ([]*model.DataframeFilterInput, error) { + if v == nil { + return nil, nil + } + var vSlice []any + if v != nil { + vSlice = graphql.CoerceList(v) + } + var err error + res := make([]*model.DataframeFilterInput, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNDataframeFilterInput2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeFilterInput(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalODataframeMaterialization2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeMaterialization(ctx context.Context, sel ast.SelectionSet, v *model.DataframeMaterialization) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._DataframeMaterialization(ctx, sel, v) +} + +func (ec *executionContext) unmarshalODataframeSortInput2ᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐDataframeSortInput(ctx context.Context, v any) (*model.DataframeSortInput, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputDataframeSortInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalOFhirAggregateInput2ᚕᚖgithubᚗcomᚋcalyprᚋloomᚋgraphqlapiᚋmodelᚐFhirAggregateInputᚄ(ctx context.Context, v any) ([]*model.FhirAggregateInput, error) { if v == nil { return nil, nil diff --git a/graphqlapi/materialization_output.go b/graphqlapi/materialization_output.go new file mode 100644 index 0000000..5625cfc --- /dev/null +++ b/graphqlapi/materialization_output.go @@ -0,0 +1,37 @@ +package graphqlapi + +import ( + "encoding/json" + + "github.com/calypr/loom/graphqlapi/model" + "github.com/calypr/loom/internal/dataframe/materialization" +) + +func materializationModel(value materialization.Materialization) *model.DataframeMaterialization { + columns := make([]*model.DataframeColumn, 0, len(value.Columns)) + for _, column := range value.Columns { + columns = append(columns, &model.DataframeColumn{Name: column.Name, ClickhouseType: column.ClickHouse}) + } + var readyAt *string + if value.ReadyAt != nil { + formatted := value.ReadyAt.UTC().Format("2006-01-02T15:04:05.999Z07:00") + readyAt = &formatted + } + var failure *string + if value.Error != "" { + failure = &value.Error + } + return &model.DataframeMaterialization{ + ID: value.ID, Name: value.Name, Project: value.Project, + DatasetGeneration: value.DatasetGeneration, + State: model.DataframeMaterializationState(value.State), Columns: columns, + RowCount: int(value.RowCount), + CreatedAt: value.CreatedAt.UTC().Format("2006-01-02T15:04:05.999Z07:00"), + ReadyAt: readyAt, Error: failure, + } +} + +func aggregateRows(value []map[string]any) json.RawMessage { + data, _ := json.Marshal(value) + return data +} diff --git a/graphqlapi/model/models.go b/graphqlapi/model/models.go index 7e1950a..449faab 100644 --- a/graphqlapi/model/models.go +++ b/graphqlapi/model/models.go @@ -9,6 +9,20 @@ import ( "strconv" ) +type DataframeAggregateInput struct { + MaterializationID string `json:"materializationId"` + GroupBy []string `json:"groupBy,omitempty"` + Filters []*DataframeFilterInput `json:"filters,omitempty"` + Operation string `json:"operation"` + Column *string `json:"column,omitempty"` +} + +type DataframeAggregateResult struct { + Materialization *DataframeMaterialization `json:"materialization"` + Columns []string `json:"columns"` + Rows json.RawMessage `json:"rows"` +} + type DataframeBuilderIntrospection struct { Project string `json:"project"` RootResourceType string `json:"rootResourceType"` @@ -27,6 +41,11 @@ type DataframeBuilderIntrospectionInput struct { IncludePivotOnlyFields *bool `json:"includePivotOnlyFields,omitempty"` } +type DataframeColumn struct { + Name string `json:"name"` + ClickhouseType string `json:"clickhouseType"` +} + type DataframeCompilerPlanDiagnostics struct { TraversalSets int `json:"traversalSets"` SharedTraversalCount int `json:"sharedTraversalCount"` @@ -70,6 +89,25 @@ type DataframeFieldSelector struct { ValuePath string `json:"valuePath"` } +type DataframeFilterInput struct { + Column string `json:"column"` + Op string `json:"op"` + Value json.RawMessage `json:"value"` +} + +type DataframeMaterialization struct { + ID string `json:"id"` + Name string `json:"name"` + Project string `json:"project"` + DatasetGeneration string `json:"datasetGeneration"` + State DataframeMaterializationState `json:"state"` + Columns []*DataframeColumn `json:"columns"` + RowCount int `json:"rowCount"` + CreatedAt string `json:"createdAt"` + ReadyAt *string `json:"readyAt,omitempty"` + Error *string `json:"error,omitempty"` +} + type DataframeOptimizationDecision struct { Rule string `json:"rule"` Enabled bool `json:"enabled"` @@ -87,6 +125,11 @@ type DataframeOptimizationPolicy struct { Decisions []*DataframeOptimizationDecision `json:"decisions"` } +type DataframePageInfo struct { + HasNextPage bool `json:"hasNextPage"` + EndCursor *string `json:"endCursor,omitempty"` +} + type DataframeQueryDiagnostics struct { InputResolutionMs float64 `json:"inputResolutionMs"` RequestPreparationMs float64 `json:"requestPreparationMs"` @@ -119,6 +162,27 @@ type DataframeRichSourceReuse struct { TotalConsumers int `json:"totalConsumers"` } +type DataframeRowConnection struct { + Materialization *DataframeMaterialization `json:"materialization"` + Columns []string `json:"columns"` + Rows json.RawMessage `json:"rows"` + PageInfo *DataframePageInfo `json:"pageInfo"` +} + +type DataframeRowsInput struct { + MaterializationID string `json:"materializationId"` + Columns []string `json:"columns,omitempty"` + Filters []*DataframeFilterInput `json:"filters,omitempty"` + Sort *DataframeSortInput `json:"sort,omitempty"` + First *int `json:"first,omitempty"` + After *string `json:"after,omitempty"` +} + +type DataframeSortInput struct { + Column string `json:"column"` + Desc *bool `json:"desc,omitempty"` +} + type DataframeTraversalHint struct { FromType string `json:"fromType"` Label string `json:"label"` @@ -214,6 +278,51 @@ type Mutation struct { type Query struct { } +type DataframeMaterializationState string + +const ( + DataframeMaterializationStatePending DataframeMaterializationState = "PENDING" + DataframeMaterializationStateLoading DataframeMaterializationState = "LOADING" + DataframeMaterializationStateReady DataframeMaterializationState = "READY" + DataframeMaterializationStateFailed DataframeMaterializationState = "FAILED" +) + +var AllDataframeMaterializationState = []DataframeMaterializationState{ + DataframeMaterializationStatePending, + DataframeMaterializationStateLoading, + DataframeMaterializationStateReady, + DataframeMaterializationStateFailed, +} + +func (e DataframeMaterializationState) IsValid() bool { + switch e { + case DataframeMaterializationStatePending, DataframeMaterializationStateLoading, DataframeMaterializationStateReady, DataframeMaterializationStateFailed: + return true + } + return false +} + +func (e DataframeMaterializationState) String() string { + return string(e) +} + +func (e *DataframeMaterializationState) UnmarshalGQL(v any) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = DataframeMaterializationState(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid DataframeMaterializationState", str) + } + return nil +} + +func (e DataframeMaterializationState) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + type FhirAggregateOperation string const ( diff --git a/graphqlapi/schema.graphqls b/graphqlapi/schema.graphqls index 5d872da..2a5ffb9 100644 --- a/graphqlapi/schema.graphqls +++ b/graphqlapi/schema.graphqls @@ -2,6 +2,10 @@ type Query { dataframeBuilderIntrospection( input: DataframeBuilderIntrospectionInput! ): DataframeBuilderIntrospection! + + dataframeMaterialization(id: ID!): DataframeMaterialization + dataframeRows(input: DataframeRowsInput!): DataframeRowConnection! + dataframeAggregate(input: DataframeAggregateInput!): DataframeAggregateResult! } scalar JSON @@ -13,6 +17,77 @@ type Mutation { ): FhirDataframeResult! } +enum DataframeMaterializationState { + PENDING + LOADING + READY + FAILED +} + +type DataframeColumn { + name: String! + clickhouseType: String! +} + +type DataframeMaterialization { + id: ID! + name: String! + project: String! + datasetGeneration: String! + state: DataframeMaterializationState! + columns: [DataframeColumn!]! + rowCount: Int! + createdAt: String! + readyAt: String + error: String +} + +input DataframeFilterInput { + column: String! + op: String! + value: JSON! +} + +input DataframeSortInput { + column: String! + desc: Boolean = false +} + +input DataframeRowsInput { + materializationId: ID! + columns: [String!] + filters: [DataframeFilterInput!] + sort: DataframeSortInput + first: Int = 100 + after: String +} + +type DataframePageInfo { + hasNextPage: Boolean! + endCursor: String +} + +type DataframeRowConnection { + materialization: DataframeMaterialization! + columns: [String!]! + rows: JSON! + pageInfo: DataframePageInfo! +} + +input DataframeAggregateInput { + materializationId: ID! + groupBy: [String!] + filters: [DataframeFilterInput!] + operation: String! + column: String +} + +type DataframeAggregateResult { + materialization: DataframeMaterialization! + columns: [String!]! + rows: JSON! +} + input DataframeBuilderIntrospectionInput { project: String! rootResourceType: String! diff --git a/graphqlapi/schema.resolvers.go b/graphqlapi/schema.resolvers.go index d285211..1bc48b0 100644 --- a/graphqlapi/schema.resolvers.go +++ b/graphqlapi/schema.resolvers.go @@ -6,6 +6,7 @@ package graphqlapi import ( "context" + "encoding/json" dataframeapi "github.com/calypr/loom/graphqlapi/dataframe" "github.com/calypr/loom/graphqlapi/model" @@ -52,6 +53,50 @@ func (r *queryResolver) DataframeBuilderIntrospection(ctx context.Context, input }, nil } +// DataframeMaterialization is the resolver for the dataframeMaterialization field. +func (r *queryResolver) DataframeMaterialization(ctx context.Context, id string) (*model.DataframeMaterialization, error) { + value, err := r.service.GetMaterialization(ctx, id) + if err != nil { + return nil, err + } + return materializationModel(*value), nil +} + +// DataframeRows is the resolver for the dataframeRows field. +func (r *queryResolver) DataframeRows(ctx context.Context, input model.DataframeRowsInput) (*model.DataframeRowConnection, error) { + page, err := r.service.ReadMaterialization(ctx, input) + if err != nil { + return nil, err + } + rows, err := json.Marshal(page.Rows) + if err != nil { + return nil, err + } + var cursor *string + if page.NextCursor != "" { + cursor = &page.NextCursor + } + return &model.DataframeRowConnection{ + Materialization: materializationModel(page.Materialization), + Columns: append([]string(nil), page.Columns...), Rows: rows, + PageInfo: &model.DataframePageInfo{HasNextPage: page.HasNext, EndCursor: cursor}, + }, nil +} + +// DataframeAggregate is the resolver for the dataframeAggregate field. +func (r *queryResolver) DataframeAggregate(ctx context.Context, input model.DataframeAggregateInput) (*model.DataframeAggregateResult, error) { + groupBy := append([]string(nil), input.GroupBy...) + column := "" + if input.Column != nil { + column = *input.Column + } + result, err := r.service.AggregateMaterialization(ctx, input.MaterializationID, groupBy, input.Filters, input.Operation, column) + if err != nil { + return nil, err + } + return &model.DataframeAggregateResult{Materialization: materializationModel(result.Materialization), Columns: result.Columns, Rows: aggregateRows(result.Rows)}, nil +} + // Mutation returns MutationResolver implementation. func (r *Resolver) Mutation() MutationResolver { return &mutationResolver{r} } diff --git a/internal/dataframe/api.go b/internal/dataframe/api.go index 90d6252..acdd29c 100644 --- a/internal/dataframe/api.go +++ b/internal/dataframe/api.go @@ -1,239 +1,244 @@ -// Package dataframe is the compatibility façade for Loom's dataframe engine. +// Package dataframe is Loom's stable dataframe compatibility facade. // -// Runtime orchestration lives in ./runtime, pure compilation in ./compiler, -// and the stable error contract in ./errors. This package preserves the -// historical import path through aliases and forwarding functions. +// Runtime orchestration, compiler contracts, and user errors are re-exported +// from their canonical packages here so existing GraphQL, CLI, and +// conformance callers do not depend on implementation layout. package dataframe import ( + "github.com/calypr/loom/internal/dataframe/compiler" + dataframeerrors "github.com/calypr/loom/internal/dataframe/errors" "github.com/calypr/loom/internal/dataframe/runtime" ) type ( - Service = runtime.Service - ServiceConfig = runtime.ServiceConfig - ExecuteQueryOptions = runtime.ExecuteQueryOptions - ValidationWarning = runtime.ValidationWarning - ValidationResult = runtime.ValidationResult - ValidateRequest = runtime.ValidateRequest - Builder = runtime.Builder - TraversalStep = runtime.TraversalStep - RepresentativeSlice = runtime.RepresentativeSlice - FieldSelect = runtime.FieldSelect - PivotSelect = runtime.PivotSelect - AggregateSelect = runtime.AggregateSelect - RunRequest = runtime.RunRequest - Result = runtime.Result - QueryDiagnostics = runtime.QueryDiagnostics - StreamResult = runtime.StreamResult - CompiledQuery = runtime.CompiledQuery - SemanticPlan = runtime.SemanticPlan - SemanticNode = runtime.SemanticNode - SemanticField = runtime.SemanticField - SemanticPivot = runtime.SemanticPivot - SemanticAggregate = runtime.SemanticAggregate - SemanticSlice = runtime.SemanticSlice - SemanticPlanExplanation = runtime.SemanticPlanExplanation - SemanticNodeExplanation = runtime.SemanticNodeExplanation - SelectionSemanticSpec = runtime.SelectionSemanticSpec - RowGrain = runtime.RowGrain - ProjectionMode = runtime.ProjectionMode - Cardinality = runtime.Cardinality - RowIdentity = runtime.RowIdentity - TraversalMatchMode = runtime.TraversalMatchMode - FilterOperator = runtime.FilterOperator - FilterValueKind = runtime.FilterValueKind - ArrayQuantifier = runtime.ArrayQuantifier - CodeValue = runtime.CodeValue - FilterValue = runtime.FilterValue - TypedFilter = runtime.TypedFilter - Selector = runtime.Selector - SelectorStep = runtime.SelectorStep - ContainsFilter = runtime.ContainsFilter - PhysicalOptimizationPolicy = runtime.PhysicalOptimizationPolicy - PhysicalOptimizationRule = runtime.PhysicalOptimizationRule - PhysicalOptimizationDecision = runtime.PhysicalOptimizationDecision - PhysicalOptimizationReport = runtime.PhysicalOptimizationReport - PhysicalOptimizationRuleState = runtime.PhysicalOptimizationRuleState - CompilerPlanDiagnostics = runtime.CompilerPlanDiagnostics - PhysicalTraversalDecision = runtime.PhysicalTraversalDecision - RichSourceReuse = runtime.RichSourceReuse - RichConsumerGroup = runtime.RichConsumerGroup - RenderedPhysicalPlan = runtime.RenderedPhysicalPlan - PhysicalTraversalPrefix = runtime.PhysicalTraversalPrefix - PhysicalTraversalSubset = runtime.PhysicalTraversalSubset - PhysicalTraversalPrefixDecomposition = runtime.PhysicalTraversalPrefixDecomposition - PhysicalTraversalPrefixRejectionReason = runtime.PhysicalTraversalPrefixRejectionReason - PhysicalTraversalPrefixError = runtime.PhysicalTraversalPrefixError - PhysicalPlan = runtime.PhysicalPlan - PhysicalSource = runtime.PhysicalSource - PhysicalOperationKind = runtime.PhysicalOperationKind - PhysicalOperation = runtime.PhysicalOperation - PhysicalRootScan = runtime.PhysicalRootScan - PhysicalTraversalDirection = runtime.PhysicalTraversalDirection - PhysicalTraversalStrategy = runtime.PhysicalTraversalStrategy - PhysicalTraversal = runtime.PhysicalTraversal - PhysicalValue = runtime.PhysicalValue - PhysicalCardinality = runtime.PhysicalCardinality - PhysicalNullBehavior = runtime.PhysicalNullBehavior - PhysicalExpressionKind = runtime.PhysicalExpressionKind - PhysicalSelectorExecutionMode = runtime.PhysicalSelectorExecutionMode - PhysicalExpression = runtime.PhysicalExpression - PhysicalExtract = runtime.PhysicalExtract - PhysicalPreparedReference = runtime.PhysicalPreparedReference - PhysicalPreparedSet = runtime.PhysicalPreparedSet - PhysicalPreparedField = runtime.PhysicalPreparedField - PhysicalAggregateOperation = runtime.PhysicalAggregateOperation - PhysicalAggregate = runtime.PhysicalAggregate - PhysicalPivotMap = runtime.PhysicalPivotMap - PhysicalSlice = runtime.PhysicalSlice - PhysicalExpressionProjection = runtime.PhysicalExpressionProjection - PhysicalObject = runtime.PhysicalObject - PhysicalSet = runtime.PhysicalSet - PhysicalSetProjection = runtime.PhysicalSetProjection - PhysicalSetProjectionField = runtime.PhysicalSetProjectionField - PhysicalSetOutputField = runtime.PhysicalSetOutputField - PhysicalSetOutput = runtime.PhysicalSetOutput - PhysicalSubplan = runtime.PhysicalSubplan - PhysicalPredicate = runtime.PhysicalPredicate - PhysicalPredicateKind = runtime.PhysicalPredicateKind - PhysicalPredicateExpression = runtime.PhysicalPredicateExpression - PhysicalFilter = runtime.PhysicalFilter - PhysicalDerivedLet = runtime.PhysicalDerivedLet - PhysicalSort = runtime.PhysicalSort - PhysicalLimit = runtime.PhysicalLimit - PhysicalProjection = runtime.PhysicalProjection - PhysicalReturn = runtime.PhysicalReturn - StorageRoute = runtime.StorageRoute - ErrorCode = runtime.ErrorCode - UserError = runtime.UserError - Error = runtime.Error - ErrorOption = runtime.ErrorOption + Service = runtime.Service + ServiceConfig = runtime.ServiceConfig + ExecuteQueryOptions = runtime.ExecuteQueryOptions + ValidationWarning = runtime.ValidationWarning + ValidationResult = runtime.ValidationResult + ValidateRequest = runtime.ValidateRequest + RunRequest = runtime.RunRequest + Result = runtime.Result + QueryDiagnostics = runtime.QueryDiagnostics + StreamResult = runtime.StreamResult + + Builder = compiler.Builder + TraversalStep = compiler.TraversalStep + RepresentativeSlice = compiler.RepresentativeSlice + FieldSelect = compiler.FieldSelect + PivotSelect = compiler.PivotSelect + AggregateSelect = compiler.AggregateSelect + CompiledQuery = compiler.CompiledQuery + SemanticPlan = compiler.SemanticPlan + SemanticNode = compiler.SemanticNode + SemanticField = compiler.SemanticField + SemanticPivot = compiler.SemanticPivot + SemanticAggregate = compiler.SemanticAggregate + SemanticSlice = compiler.SemanticSlice + SemanticPlanExplanation = compiler.SemanticPlanExplanation + SemanticNodeExplanation = compiler.SemanticNodeExplanation + SelectionSemanticSpec = compiler.SelectionSemanticSpec + RowGrain = compiler.RowGrain + ProjectionMode = compiler.ProjectionMode + Cardinality = compiler.Cardinality + RowIdentity = compiler.RowIdentity + TraversalMatchMode = compiler.TraversalMatchMode + FilterOperator = compiler.FilterOperator + FilterValueKind = compiler.FilterValueKind + ArrayQuantifier = compiler.ArrayQuantifier + CodeValue = compiler.CodeValue + FilterValue = compiler.FilterValue + TypedFilter = compiler.TypedFilter + Selector = compiler.Selector + SelectorStep = compiler.SelectorStep + ContainsFilter = compiler.ContainsFilter + + PhysicalOptimizationPolicy = compiler.PhysicalOptimizationPolicy + PhysicalOptimizationRule = compiler.PhysicalOptimizationRule + PhysicalOptimizationDecision = compiler.PhysicalOptimizationDecision + PhysicalOptimizationReport = compiler.PhysicalOptimizationReport + PhysicalOptimizationRuleState = compiler.PhysicalOptimizationRuleState + CompilerPlanDiagnostics = compiler.CompilerPlanDiagnostics + PhysicalTraversalDecision = compiler.PhysicalTraversalDecision + RichSourceReuse = compiler.RichSourceReuse + RichConsumerGroup = compiler.RichConsumerGroup + RenderedPhysicalPlan = compiler.RenderedPhysicalPlan + PhysicalTraversalPrefix = compiler.PhysicalTraversalPrefix + PhysicalTraversalSubset = compiler.PhysicalTraversalSubset + PhysicalTraversalPrefixDecomposition = compiler.PhysicalTraversalPrefixDecomposition + PhysicalTraversalPrefixRejectionReason = compiler.PhysicalTraversalPrefixRejectionReason + PhysicalTraversalPrefixError = compiler.PhysicalTraversalPrefixError + PhysicalPlan = compiler.PhysicalPlan + PhysicalSource = compiler.PhysicalSource + PhysicalOperationKind = compiler.PhysicalOperationKind + PhysicalOperation = compiler.PhysicalOperation + PhysicalRootScan = compiler.PhysicalRootScan + PhysicalTraversalDirection = compiler.PhysicalTraversalDirection + PhysicalTraversalStrategy = compiler.PhysicalTraversalStrategy + PhysicalTraversal = compiler.PhysicalTraversal + PhysicalValue = compiler.PhysicalValue + PhysicalCardinality = compiler.PhysicalCardinality + PhysicalNullBehavior = compiler.PhysicalNullBehavior + PhysicalExpressionKind = compiler.PhysicalExpressionKind + PhysicalSelectorExecutionMode = compiler.PhysicalSelectorExecutionMode + PhysicalExpression = compiler.PhysicalExpression + PhysicalExtract = compiler.PhysicalExtract + PhysicalPreparedReference = compiler.PhysicalPreparedReference + PhysicalPreparedSet = compiler.PhysicalPreparedSet + PhysicalPreparedField = compiler.PhysicalPreparedField + PhysicalAggregateOperation = compiler.PhysicalAggregateOperation + PhysicalAggregate = compiler.PhysicalAggregate + PhysicalPivotMap = compiler.PhysicalPivotMap + PhysicalSlice = compiler.PhysicalSlice + PhysicalExpressionProjection = compiler.PhysicalExpressionProjection + PhysicalObject = compiler.PhysicalObject + PhysicalSet = compiler.PhysicalSet + PhysicalSetProjection = compiler.PhysicalSetProjection + PhysicalSetProjectionField = compiler.PhysicalSetProjectionField + PhysicalSetOutputField = compiler.PhysicalSetOutputField + PhysicalSetOutput = compiler.PhysicalSetOutput + PhysicalSubplan = compiler.PhysicalSubplan + PhysicalPredicate = compiler.PhysicalPredicate + PhysicalPredicateKind = compiler.PhysicalPredicateKind + PhysicalPredicateExpression = compiler.PhysicalPredicateExpression + PhysicalFilter = compiler.PhysicalFilter + PhysicalDerivedLet = compiler.PhysicalDerivedLet + PhysicalSort = compiler.PhysicalSort + PhysicalLimit = compiler.PhysicalLimit + PhysicalProjection = compiler.PhysicalProjection + PhysicalReturn = compiler.PhysicalReturn + StorageRoute = compiler.StorageRoute + + ErrorCode = dataframeerrors.ErrorCode + UserError = dataframeerrors.UserError + Error = dataframeerrors.Error + ErrorOption = dataframeerrors.ErrorOption ) const ( - MaxSemanticTraversalDepth = runtime.MaxSemanticTraversalDepth - RowGrainResource = runtime.RowGrainResource - RowGrainPatient = runtime.RowGrainPatient - RowGrainSpecimen = runtime.RowGrainSpecimen - RowGrainFile = runtime.RowGrainFile - RowGrainDiagnosis = runtime.RowGrainDiagnosis - RowGrainObservation = runtime.RowGrainObservation - RowGrainStudyEnrollment = runtime.RowGrainStudyEnrollment - ProjectionScalar = runtime.ProjectionScalar - ProjectionFirst = runtime.ProjectionFirst - ProjectionArray = runtime.ProjectionArray - ProjectionDistinctArray = runtime.ProjectionDistinctArray - ProjectionAggregate = runtime.ProjectionAggregate - ProjectionPivot = runtime.ProjectionPivot - ProjectionExplode = runtime.ProjectionExplode - CardinalityRequiredOne = runtime.CardinalityRequiredOne - CardinalityOptionalOne = runtime.CardinalityOptionalOne - CardinalityMany = runtime.CardinalityMany - CardinalityUnknownObservedMany = runtime.CardinalityUnknownObservedMany - TraversalMatchOptional = runtime.TraversalMatchOptional - TraversalMatchRequired = runtime.TraversalMatchRequired - FilterEquals = runtime.FilterEquals - FilterNotEquals = runtime.FilterNotEquals - FilterIn = runtime.FilterIn - FilterExists = runtime.FilterExists - FilterMissing = runtime.FilterMissing - FilterContains = runtime.FilterContains - FilterGreaterThan = runtime.FilterGreaterThan - FilterGreaterEq = runtime.FilterGreaterEq - FilterLessThan = runtime.FilterLessThan - FilterLessEq = runtime.FilterLessEq - FilterString = runtime.FilterString - FilterCode = runtime.FilterCode - FilterBoolean = runtime.FilterBoolean - FilterInteger = runtime.FilterInteger - FilterDecimal = runtime.FilterDecimal - FilterDate = runtime.FilterDate - FilterDateTime = runtime.FilterDateTime - QuantifierAny = runtime.QuantifierAny - QuantifierAll = runtime.QuantifierAll - QuantifierNone = runtime.QuantifierNone - PhysicalTraversalNative = runtime.PhysicalTraversalNative - PhysicalTraversalEndpointLookup = runtime.PhysicalTraversalEndpointLookup - PhysicalOutbound = runtime.PhysicalOutbound - PhysicalInbound = runtime.PhysicalInbound - PhysicalAny = runtime.PhysicalAny - PhysicalRootScanOp = runtime.PhysicalRootScanOp - PhysicalTraversalOp = runtime.PhysicalTraversalOp - PhysicalFilterOp = runtime.PhysicalFilterOp - PhysicalDerivedLetOp = runtime.PhysicalDerivedLetOp - PhysicalSetOp = runtime.PhysicalSetOp - PhysicalSortOp = runtime.PhysicalSortOp - PhysicalLimitOp = runtime.PhysicalLimitOp - PhysicalReturnOp = runtime.PhysicalReturnOp - PhysicalScalarCardinality = runtime.PhysicalScalarCardinality - PhysicalArrayCardinality = runtime.PhysicalArrayCardinality - PhysicalObjectCardinality = runtime.PhysicalObjectCardinality - PhysicalPreserveNull = runtime.PhysicalPreserveNull - PhysicalOmitNulls = runtime.PhysicalOmitNulls - PhysicalEmptyOnNull = runtime.PhysicalEmptyOnNull - PhysicalValueExpression = runtime.PhysicalValueExpression - PhysicalExtractExpression = runtime.PhysicalExtractExpression - PhysicalAggregateExpression = runtime.PhysicalAggregateExpression - PhysicalPivotExpression = runtime.PhysicalPivotExpression - PhysicalSliceExpression = runtime.PhysicalSliceExpression - PhysicalObjectExpression = runtime.PhysicalObjectExpression - PhysicalSelectorGeneric = runtime.PhysicalSelectorGeneric - PhysicalSelectorDirectScalar = runtime.PhysicalSelectorDirectScalar - PhysicalSelectorConditionalArray = runtime.PhysicalSelectorConditionalArray - PhysicalCountAggregate = runtime.PhysicalCountAggregate - PhysicalCountDistinctAggregate = runtime.PhysicalCountDistinctAggregate - PhysicalExistsAggregate = runtime.PhysicalExistsAggregate - PhysicalDistinctValuesAggregate = runtime.PhysicalDistinctValuesAggregate - PhysicalMinAggregate = runtime.PhysicalMinAggregate - PhysicalMaxAggregate = runtime.PhysicalMaxAggregate - PhysicalFirstAggregate = runtime.PhysicalFirstAggregate - PhysicalSetGraphIDField = runtime.PhysicalSetGraphIDField - PhysicalSetKeyField = runtime.PhysicalSetKeyField - PhysicalSetIDField = runtime.PhysicalSetIDField - PhysicalSetResourceTypeField = runtime.PhysicalSetResourceTypeField - PhysicalSetPayloadField = runtime.PhysicalSetPayloadField - PhysicalComparisonPredicate = runtime.PhysicalComparisonPredicate - PhysicalAllPredicate = runtime.PhysicalAllPredicate - PhysicalAnyPredicate = runtime.PhysicalAnyPredicate - PhysicalNotPredicate = runtime.PhysicalNotPredicate - PhysicalExistsPredicate = runtime.PhysicalExistsPredicate - PhysicalPrefixNotOptionalSet = runtime.PhysicalPrefixNotOptionalSet - PhysicalPrefixSharedSubset = runtime.PhysicalPrefixSharedSubset - PhysicalPrefixInvalidCapture = runtime.PhysicalPrefixInvalidCapture - PhysicalPrefixMissingTraversal = runtime.PhysicalPrefixMissingTraversal - PhysicalPrefixUnsupportedDirection = runtime.PhysicalPrefixUnsupportedDirection - PhysicalPrefixInvalidRoute = runtime.PhysicalPrefixInvalidRoute - PhysicalPrefixInvalidScope = runtime.PhysicalPrefixInvalidScope - PhysicalPrefixInvalidTarget = runtime.PhysicalPrefixInvalidTarget - PhysicalOptimizationRuleTraversalSharing = runtime.PhysicalOptimizationRuleTraversalSharing - PhysicalOptimizationRulePreparedSelectors = runtime.PhysicalOptimizationRulePreparedSelectors - PhysicalOptimizationRuleNestedSharing = runtime.PhysicalOptimizationRuleNestedSharing - PhysicalOptimizationRuleRichConsumerFusion = runtime.PhysicalOptimizationRuleRichConsumerFusion - PhysicalOptimizationRuleCompactProjection = runtime.PhysicalOptimizationRuleCompactProjection - PhysicalOptimizationRuleEndpointTraversal = runtime.PhysicalOptimizationRuleEndpointTraversal - OptimizerRuleFilterPushdown = runtime.OptimizerRuleFilterPushdown - OptimizerRuleTraversalSharing = runtime.OptimizerRuleTraversalSharing - OptimizerRuleRelationshipSemiJoin = runtime.OptimizerRuleRelationshipSemiJoin - CodeProjectRequired = runtime.CodeProjectRequired - CodeRootResourceTypeRequired = runtime.CodeRootResourceTypeRequired - CodeUnauthorizedProject = runtime.CodeUnauthorizedProject - CodeUnknownField = runtime.CodeUnknownField - CodeFieldNotPopulated = runtime.CodeFieldNotPopulated - CodeInvalidTraversal = runtime.CodeInvalidTraversal - CodeUnsafeTraversalRoute = runtime.CodeUnsafeTraversalRoute - CodeInvalidFilter = runtime.CodeInvalidFilter - CodeUnboundedPivot = runtime.CodeUnboundedPivot - CodeInvalidPivotColumn = runtime.CodeInvalidPivotColumn - CodeInvalidSlice = runtime.CodeInvalidSlice - CodePlanTooExpensive = runtime.CodePlanTooExpensive - CodeInvalidCursor = runtime.CodeInvalidCursor - CodeStaleCursor = runtime.CodeStaleCursor - CodeDatasetGenerationChanged = runtime.CodeDatasetGenerationChanged - CodeUnsupportedExportFormat = runtime.CodeUnsupportedExportFormat - CodeClientCanceled = runtime.CodeClientCanceled - CodeBackendUnavailable = runtime.CodeBackendUnavailable - CodeInternalError = runtime.CodeInternalError + MaxSemanticTraversalDepth = compiler.MaxSemanticTraversalDepth + RowGrainResource = compiler.RowGrainResource + RowGrainPatient = compiler.RowGrainPatient + RowGrainSpecimen = compiler.RowGrainSpecimen + RowGrainFile = compiler.RowGrainFile + RowGrainDiagnosis = compiler.RowGrainDiagnosis + RowGrainObservation = compiler.RowGrainObservation + RowGrainStudyEnrollment = compiler.RowGrainStudyEnrollment + ProjectionScalar = compiler.ProjectionScalar + ProjectionFirst = compiler.ProjectionFirst + ProjectionArray = compiler.ProjectionArray + ProjectionDistinctArray = compiler.ProjectionDistinctArray + ProjectionAggregate = compiler.ProjectionAggregate + ProjectionPivot = compiler.ProjectionPivot + ProjectionExplode = compiler.ProjectionExplode + CardinalityRequiredOne = compiler.CardinalityRequiredOne + CardinalityOptionalOne = compiler.CardinalityOptionalOne + CardinalityMany = compiler.CardinalityMany + CardinalityUnknownObservedMany = compiler.CardinalityUnknownObservedMany + TraversalMatchOptional = compiler.TraversalMatchOptional + TraversalMatchRequired = compiler.TraversalMatchRequired + FilterEquals = compiler.FilterEquals + FilterNotEquals = compiler.FilterNotEquals + FilterIn = compiler.FilterIn + FilterExists = compiler.FilterExists + FilterMissing = compiler.FilterMissing + FilterContains = compiler.FilterContains + FilterGreaterThan = compiler.FilterGreaterThan + FilterGreaterEq = compiler.FilterGreaterEq + FilterLessThan = compiler.FilterLessThan + FilterLessEq = compiler.FilterLessEq + FilterString = compiler.FilterString + FilterCode = compiler.FilterCode + FilterBoolean = compiler.FilterBoolean + FilterInteger = compiler.FilterInteger + FilterDecimal = compiler.FilterDecimal + FilterDate = compiler.FilterDate + FilterDateTime = compiler.FilterDateTime + QuantifierAny = compiler.QuantifierAny + QuantifierAll = compiler.QuantifierAll + QuantifierNone = compiler.QuantifierNone + PhysicalTraversalNative = compiler.PhysicalTraversalNative + PhysicalTraversalEndpointLookup = compiler.PhysicalTraversalEndpointLookup + PhysicalOutbound = compiler.PhysicalOutbound + PhysicalInbound = compiler.PhysicalInbound + PhysicalAny = compiler.PhysicalAny + PhysicalRootScanOp = compiler.PhysicalRootScanOp + PhysicalTraversalOp = compiler.PhysicalTraversalOp + PhysicalFilterOp = compiler.PhysicalFilterOp + PhysicalDerivedLetOp = compiler.PhysicalDerivedLetOp + PhysicalSetOp = compiler.PhysicalSetOp + PhysicalSortOp = compiler.PhysicalSortOp + PhysicalLimitOp = compiler.PhysicalLimitOp + PhysicalReturnOp = compiler.PhysicalReturnOp + PhysicalScalarCardinality = compiler.PhysicalScalarCardinality + PhysicalArrayCardinality = compiler.PhysicalArrayCardinality + PhysicalObjectCardinality = compiler.PhysicalObjectCardinality + PhysicalPreserveNull = compiler.PhysicalPreserveNull + PhysicalOmitNulls = compiler.PhysicalOmitNulls + PhysicalEmptyOnNull = compiler.PhysicalEmptyOnNull + PhysicalValueExpression = compiler.PhysicalValueExpression + PhysicalExtractExpression = compiler.PhysicalExtractExpression + PhysicalAggregateExpression = compiler.PhysicalAggregateExpression + PhysicalPivotExpression = compiler.PhysicalPivotExpression + PhysicalSliceExpression = compiler.PhysicalSliceExpression + PhysicalObjectExpression = compiler.PhysicalObjectExpression + PhysicalSelectorGeneric = compiler.PhysicalSelectorGeneric + PhysicalSelectorDirectScalar = compiler.PhysicalSelectorDirectScalar + PhysicalSelectorConditionalArray = compiler.PhysicalSelectorConditionalArray + PhysicalCountAggregate = compiler.PhysicalCountAggregate + PhysicalCountDistinctAggregate = compiler.PhysicalCountDistinctAggregate + PhysicalExistsAggregate = compiler.PhysicalExistsAggregate + PhysicalDistinctValuesAggregate = compiler.PhysicalDistinctValuesAggregate + PhysicalMinAggregate = compiler.PhysicalMinAggregate + PhysicalMaxAggregate = compiler.PhysicalMaxAggregate + PhysicalFirstAggregate = compiler.PhysicalFirstAggregate + PhysicalSetGraphIDField = compiler.PhysicalSetGraphIDField + PhysicalSetKeyField = compiler.PhysicalSetKeyField + PhysicalSetIDField = compiler.PhysicalSetIDField + PhysicalSetResourceTypeField = compiler.PhysicalSetResourceTypeField + PhysicalSetPayloadField = compiler.PhysicalSetPayloadField + PhysicalComparisonPredicate = compiler.PhysicalComparisonPredicate + PhysicalAllPredicate = compiler.PhysicalAllPredicate + PhysicalAnyPredicate = compiler.PhysicalAnyPredicate + PhysicalNotPredicate = compiler.PhysicalNotPredicate + PhysicalExistsPredicate = compiler.PhysicalExistsPredicate + PhysicalPrefixNotOptionalSet = compiler.PhysicalPrefixNotOptionalSet + PhysicalPrefixSharedSubset = compiler.PhysicalPrefixSharedSubset + PhysicalPrefixInvalidCapture = compiler.PhysicalPrefixInvalidCapture + PhysicalPrefixMissingTraversal = compiler.PhysicalPrefixMissingTraversal + PhysicalPrefixUnsupportedDirection = compiler.PhysicalPrefixUnsupportedDirection + PhysicalPrefixInvalidRoute = compiler.PhysicalPrefixInvalidRoute + PhysicalPrefixInvalidScope = compiler.PhysicalPrefixInvalidScope + PhysicalPrefixInvalidTarget = compiler.PhysicalPrefixInvalidTarget + PhysicalOptimizationRuleTraversalSharing = compiler.PhysicalOptimizationRuleTraversalSharing + PhysicalOptimizationRulePreparedSelectors = compiler.PhysicalOptimizationRulePreparedSelectors + PhysicalOptimizationRuleNestedSharing = compiler.PhysicalOptimizationRuleNestedSharing + PhysicalOptimizationRuleRichConsumerFusion = compiler.PhysicalOptimizationRuleRichConsumerFusion + PhysicalOptimizationRuleCompactProjection = compiler.PhysicalOptimizationRuleCompactProjection + PhysicalOptimizationRuleEndpointTraversal = compiler.PhysicalOptimizationRuleEndpointTraversal + OptimizerRuleFilterPushdown = compiler.OptimizerRuleFilterPushdown + OptimizerRuleTraversalSharing = compiler.OptimizerRuleTraversalSharing + OptimizerRuleRelationshipSemiJoin = compiler.OptimizerRuleRelationshipSemiJoin + CodeProjectRequired = dataframeerrors.CodeProjectRequired + CodeRootResourceTypeRequired = dataframeerrors.CodeRootResourceTypeRequired + CodeUnauthorizedProject = dataframeerrors.CodeUnauthorizedProject + CodeUnknownField = dataframeerrors.CodeUnknownField + CodeFieldNotPopulated = dataframeerrors.CodeFieldNotPopulated + CodeInvalidTraversal = dataframeerrors.CodeInvalidTraversal + CodeUnsafeTraversalRoute = dataframeerrors.CodeUnsafeTraversalRoute + CodeInvalidFilter = dataframeerrors.CodeInvalidFilter + CodeUnboundedPivot = dataframeerrors.CodeUnboundedPivot + CodeInvalidPivotColumn = dataframeerrors.CodeInvalidPivotColumn + CodeInvalidSlice = dataframeerrors.CodeInvalidSlice + CodePlanTooExpensive = dataframeerrors.CodePlanTooExpensive + CodeInvalidCursor = dataframeerrors.CodeInvalidCursor + CodeStaleCursor = dataframeerrors.CodeStaleCursor + CodeDatasetGenerationChanged = dataframeerrors.CodeDatasetGenerationChanged + CodeUnsupportedExportFormat = dataframeerrors.CodeUnsupportedExportFormat + CodeClientCanceled = dataframeerrors.CodeClientCanceled + CodeBackendUnavailable = dataframeerrors.CodeBackendUnavailable + CodeInternalError = dataframeerrors.CodeInternalError ) var ( @@ -241,48 +246,45 @@ var ( ExecuteQueryRows = runtime.ExecuteQueryRows ExplainCompiledQuery = runtime.ExplainCompiledQuery ProfileCompiledQuery = runtime.ProfileCompiledQuery - DefaultPhysicalOptimizationPolicy = runtime.DefaultPhysicalOptimizationPolicy - CompileRequest = runtime.CompileRequest - CompileRequestWithPolicy = runtime.CompileRequestWithPolicy - BuildSemanticPlan = runtime.BuildSemanticPlan - ValidateSemanticGraph = runtime.ValidateSemanticGraph - BuildPhysicalPlan = runtime.BuildPhysicalPlan - BuildPhysicalPlanWithPolicy = runtime.BuildPhysicalPlanWithPolicy - BuildGenericPhysicalPlan = runtime.BuildGenericPhysicalPlan - BuildGenericPhysicalPlanWithPolicy = runtime.BuildGenericPhysicalPlanWithPolicy - OptimizePhysicalPlan = runtime.OptimizePhysicalPlan - OptimizePhysicalPlanWithPolicy = runtime.OptimizePhysicalPlanWithPolicy - RenderPhysicalPlan = runtime.RenderPhysicalPlan - ParseSelector = runtime.ParseSelector - ValidateTypedFilterForResource = runtime.ValidateTypedFilterForResource - NormalizeSelectionPlan = runtime.NormalizeSelectionPlan - ResolveSemanticField = runtime.ResolveSemanticField - InferRowGrain = runtime.InferRowGrain - RootResourceForGrain = runtime.RootResourceForGrain - ValidateRootGrain = runtime.ValidateRootGrain - DefaultRowIdentity = runtime.DefaultRowIdentity - ValidateProjection = runtime.ValidateProjection - OperatorSupportsKind = runtime.OperatorSupportsKind - ValidateGenericPhysicalPlanScope = runtime.ValidateGenericPhysicalPlanScope - DecomposePhysicalTraversalPrefix = runtime.DecomposePhysicalTraversalPrefix - ResolveStorageRoute = runtime.ResolveStorageRoute - AsUserError = runtime.AsUserError - Normalize = runtime.Normalize - PublicMessage = runtime.PublicMessage - NewError = runtime.NewError - Wrap = runtime.Wrap - WithFieldPath = runtime.WithFieldPath - WithDetails = runtime.WithDetails - WithRetryable = runtime.WithRetryable - WithCause = runtime.WithCause - IsUserCorrectable = runtime.IsUserCorrectable - IsRetryableCode = runtime.IsRetryableCode - IsOperatorFailure = runtime.IsOperatorFailure - Errorf = runtime.Errorf -) - -var ( - AllErrorCodes = runtime.AllErrorCodes - ErrBackendUnavailable = runtime.ErrBackendUnavailable - ErrClientCanceled = runtime.ErrClientCanceled + DefaultPhysicalOptimizationPolicy = compiler.DefaultPhysicalOptimizationPolicy + CompileRequest = compiler.CompileRequest + CompileRequestWithPolicy = compiler.CompileRequestWithPolicy + BuildSemanticPlan = compiler.BuildSemanticPlan + ValidateSemanticGraph = compiler.ValidateSemanticGraph + BuildPhysicalPlan = compiler.BuildPhysicalPlan + BuildPhysicalPlanWithPolicy = compiler.BuildPhysicalPlanWithPolicy + BuildGenericPhysicalPlan = compiler.BuildGenericPhysicalPlan + BuildGenericPhysicalPlanWithPolicy = compiler.BuildGenericPhysicalPlanWithPolicy + OptimizePhysicalPlan = compiler.OptimizePhysicalPlan + OptimizePhysicalPlanWithPolicy = compiler.OptimizePhysicalPlanWithPolicy + RenderPhysicalPlan = compiler.RenderPhysicalPlan + ParseSelector = compiler.ParseSelector + ValidateTypedFilterForResource = compiler.ValidateTypedFilterForResource + NormalizeSelectionPlan = compiler.NormalizeSelectionPlan + ResolveSemanticField = compiler.ResolveSemanticField + InferRowGrain = compiler.InferRowGrain + RootResourceForGrain = compiler.RootResourceForGrain + ValidateRootGrain = compiler.ValidateRootGrain + DefaultRowIdentity = compiler.DefaultRowIdentity + ValidateProjection = compiler.ValidateProjection + OperatorSupportsKind = compiler.OperatorSupportsKind + ValidateGenericPhysicalPlanScope = compiler.ValidateGenericPhysicalPlanScope + DecomposePhysicalTraversalPrefix = compiler.DecomposePhysicalTraversalPrefix + ResolveStorageRoute = compiler.ResolveStorageRoute + AsUserError = dataframeerrors.AsUserError + Normalize = dataframeerrors.Normalize + PublicMessage = dataframeerrors.PublicMessage + NewError = dataframeerrors.NewError + Wrap = dataframeerrors.Wrap + WithFieldPath = dataframeerrors.WithFieldPath + WithDetails = dataframeerrors.WithDetails + WithRetryable = dataframeerrors.WithRetryable + WithCause = dataframeerrors.WithCause + IsUserCorrectable = dataframeerrors.IsUserCorrectable + IsRetryableCode = dataframeerrors.IsRetryableCode + IsOperatorFailure = dataframeerrors.IsOperatorFailure + Errorf = dataframeerrors.Errorf + AllErrorCodes = dataframeerrors.AllErrorCodes + ErrBackendUnavailable = dataframeerrors.ErrBackendUnavailable + ErrClientCanceled = dataframeerrors.ErrClientCanceled ) diff --git a/internal/dataframe/compact_batch_tournament_test.go b/internal/dataframe/compact_batch_tournament_test.go deleted file mode 100644 index e04ebb6..0000000 --- a/internal/dataframe/compact_batch_tournament_test.go +++ /dev/null @@ -1,205 +0,0 @@ -package dataframe_test - -// Tournament F is an isolated compact batch experiment. It freezes the -// endpoint-first plus typed-selector incumbent and batches the child_set_3 -// edge lookup per root. Only identity, scope fields, and selector projections -// are retained in the grouped result; no FHIR payload is carried through the -// batch. No production compiler or index files are changed. - -import ( - "context" - "encoding/json" - "fmt" - "os" - "path/filepath" - "runtime" - "strings" - "testing" - "time" - - dataframe "github.com/calypr/loom/internal/dataframe" - arangostore "github.com/calypr/loom/internal/store/arango" -) - -func TestCompactBatchTournamentCandidateBuilds(t *testing.T) { - compiled := compileActualGDC(t, 1000) - candidate, err := compactBatchChildSet3(compiled.Query) - if err != nil { - t.Fatal(err) - } - for _, fragment := range []string{ - "LET child_set_3_by_parent = (", - "FILTER child_set_3_edge._to IN child_set_2[*]._id", - "COLLECT __loom_child_set_3_parent_id = child_set_3_edge._to", - "LET __loom_compact_child_set_3 = {", - "nodes: __loom_child_set_3_rows[*].__loom_compact_child_set_3", - "LET child_set_3 = UNIQUE((", - } { - if !strings.Contains(candidate, fragment) { - t.Fatalf("compact batch candidate missing %q", fragment) - } - } - if strings.Contains(candidate, "FOR __loom_physical_parent_set_4 IN child_set_2\n FOR child_set_3_edge") { - t.Fatal("candidate retained the per-parent edge loop") - } - if strings.Contains(candidate, "payload: child_set_3") || strings.Contains(candidate, "RETURN child_set_3_node") { - t.Fatal("candidate appears to retain a full child payload") - } -} - -func TestCompactBatchTournamentProfilesActualGDC(t *testing.T) { - if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { - t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run compact batch tournament against Arango") - } - compiled := compileActualGDC(t, 1000) - candidate, err := compactBatchChildSet3(compiled.Query) - if err != nil { - t.Fatal(err) - } - url, database, _ := compilerArangoTarget() - client, err := arangostore.Open(context.Background(), url, database) - if err != nil { - t.Fatal(err) - } - defer client.Close(context.Background()) - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) - defer cancel() - controlTimes := make([]float64, 0, 5) - candidateTimes := make([]float64, 0, 5) - controlBytes := make([]int, 0, 5) - candidateBytes := make([]int, 0, 5) - var controlHash, candidateHash string - for run := 0; run < 5; run++ { - controlQuery, controlBinds := cacheBust(compiled.Query, compiled.BindVars, 51000+run) - candidateQuery, candidateBinds := cacheBust(candidate, compiled.BindVars, 52000+run) - controlDuration, bytes, hash, err := executeOrdinary(ctx, client, controlQuery, controlBinds) - if err != nil { - t.Fatalf("control run %d: %v", run+1, err) - } - candidateDuration, candidateSize, candidateResultHash, err := executeOrdinary(ctx, client, candidateQuery, candidateBinds) - if err != nil { - t.Fatalf("candidate run %d: %v", run+1, err) - } - controlTimes = append(controlTimes, controlDuration) - candidateTimes = append(candidateTimes, candidateDuration) - controlBytes = append(controlBytes, bytes) - candidateBytes = append(candidateBytes, candidateSize) - controlHash, candidateHash = hash, candidateResultHash - } - if controlHash != candidateHash { - t.Fatalf("result parity mismatch control=%s candidate=%s", controlHash, candidateHash) - } - controlProfileQuery, controlProfileBinds := cacheBust(compiled.Query, compiled.BindVars, 51999) - candidateProfileQuery, candidateProfileBinds := cacheBust(candidate, compiled.BindVars, 52999) - controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: controlProfileQuery, BindVars: controlProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - t.Fatalf("control PROFILE: %v", err) - } - candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidateProfileQuery, BindVars: candidateProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - t.Fatalf("candidate PROFILE: %v", err) - } - if hashRawRows(controlProfile.Result) != hashRawRows(candidateProfile.Result) { - t.Fatalf("PROFILE result parity mismatch control=%s candidate=%s", hashRawRows(controlProfile.Result), hashRawRows(candidateProfile.Result)) - } - controlExplain, err := client.Explain(ctx, arangostore.ExplainRequest{Query: controlProfileQuery, BindVars: controlProfileBinds}) - if err != nil { - t.Fatalf("control EXPLAIN: %v", err) - } - candidateExplain, err := client.Explain(ctx, arangostore.ExplainRequest{Query: candidateProfileQuery, BindVars: candidateProfileBinds}) - if err != nil { - t.Fatalf("candidate EXPLAIN: %v", err) - } - controlSummary := arangostore.SummarizeProfile(controlProfile) - candidateSummary := arangostore.SummarizeProfile(candidateProfile) - t.Logf("compact batch control median=%.6f candidate median=%.6f control profile=%+v candidate profile=%+v bytes=%v/%v", median(controlTimes), median(candidateTimes), controlSummary, candidateSummary, controlBytes, candidateBytes) - writeCompactBatchEvidence(t, compiled, candidate, controlTimes, candidateTimes, controlBytes, candidateBytes, controlHash, candidateHash, controlProfile, candidateProfile, controlExplain, candidateExplain) - if median(candidateTimes) > median(controlTimes)*1.05 || candidateSummary.PeakMemory > 225*1024*1024 { - t.Logf("compact batch candidate rejected by hard runtime/memory gate") - } -} - -func compactBatchChildSet3(query string) (string, error) { - start := strings.Index(query, " LET child_set_3 = UNIQUE((") - end := strings.Index(query, " LET child_set_4 = UNIQUE((") - if start < 0 || end < 0 || end <= start { - return "", fmt.Errorf("child_set_3/child_set_4 markers not found") - } - block := query[start:end] - returnIndex := strings.Index(block, " RETURN {") - if returnIndex < 0 { - return "", fmt.Errorf("child_set_3 projection return not found") - } - projection := block[returnIndex+len(" RETURN "):] - if closeIndex := strings.Index(projection, "\n ))"); closeIndex >= 0 { - projection = projection[:closeIndex] - } - prefix := block[:returnIndex] - edgeIndex := strings.Index(prefix, "FOR child_set_3_edge IN @@child_set_3_edge_collection") - if edgeIndex < 0 { - return "", fmt.Errorf("child_set_3 edge loop not found") - } - edgePrefix := prefix[edgeIndex:] - if strings.Contains(edgePrefix, "FOR __loom_physical_parent_set_4 IN child_set_2") { - return "", fmt.Errorf("parent loop unexpectedly inside edge prefix") - } - edgePrefix = strings.Replace(edgePrefix, "FILTER child_set_3_edge._to == __loom_physical_parent_set_4._id", "FILTER child_set_3_edge._to IN child_set_2[*]._id", 1) - edgePrefix = strings.Replace(edgePrefix, " SORT child_set_3_node._key\n", "", 1) - if !strings.Contains(edgePrefix, "FILTER child_set_3_edge._to IN child_set_2[*]._id") { - return "", fmt.Errorf("child_set_3 endpoint filter was not replaced") - } - // Strip the final edge-loop indentation only for readability; AQL ignores - // whitespace. The projection object is compact and contains no payload key. - batch := " LET child_set_3_by_parent = (\n " + strings.ReplaceAll(edgePrefix, "\n", "\n ") + - " LET __loom_compact_child_set_3 = " + projection + "\n" + - " COLLECT __loom_child_set_3_parent_id = child_set_3_edge._to INTO __loom_child_set_3_rows\n" + - " RETURN {root_id: root._id, parent_id: __loom_child_set_3_parent_id, nodes: __loom_child_set_3_rows[*].__loom_compact_child_set_3}\n" + - " )\n" + - " LET child_set_3 = UNIQUE((\n" + - " FOR __loom_physical_parent_set_4 IN child_set_2\n" + - " LET __loom_child_set_3_group = FIRST((\n" + - " FOR __loom_group IN child_set_3_by_parent\n" + - " FILTER __loom_group.root_id == root._id AND __loom_group.parent_id == __loom_physical_parent_set_4._id\n" + - " RETURN __loom_group\n" + - " ))\n" + - " FOR child_set_3_item IN (__loom_child_set_3_group ? __loom_child_set_3_group.nodes : [])\n" + - " SORT child_set_3_item._key\n" + - " RETURN child_set_3_item\n" + - " ))\n" - return query[:start] + batch + query[end:], nil -} - -func writeCompactBatchEvidence(t *testing.T, compiled dataframe.CompiledQuery, candidate string, controlTimes, candidateTimes []float64, controlBytes, candidateBytes []int, controlHash, candidateHash string, controlProfile, candidateProfile arangostore.ProfileResult, controlExplain, candidateExplain arangostore.ExplainResult) { - _, source, _, _ := runtime.Caller(0) - directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "tournament_compact_batch") - if err := os.MkdirAll(directory, 0o755); err != nil { - t.Fatalf("create compact batch evidence directory: %v", err) - } - writeJSON := func(name string, value any) { - data, err := json.MarshalIndent(value, "", " ") - if err != nil { - t.Fatalf("encode %s: %v", name, err) - } - if err := os.WriteFile(filepath.Join(directory, name), append(data, '\n'), 0o644); err != nil { - t.Fatalf("write %s: %v", name, err) - } - } - if err := os.WriteFile(filepath.Join(directory, "control.aql"), []byte(compiled.Query+"\n"), 0o644); err != nil { - t.Fatalf("write control AQL: %v", err) - } - if err := os.WriteFile(filepath.Join(directory, "candidate.aql"), []byte(candidate+"\n"), 0o644); err != nil { - t.Fatalf("write candidate AQL: %v", err) - } - writeJSON("control.profile.json", controlProfile) - writeJSON("candidate.profile.json", candidateProfile) - writeJSON("evidence.json", map[string]any{ - "fixture": "examples/meta_gdc_case_matrix.variables.json", "limit": 1000, - "control_aql_sha256": sha256Hex(compiled.Query), "candidate_aql_sha256": sha256Hex(candidate), - "control_result_sha256": controlHash, "candidate_result_sha256": candidateHash, - "control_seconds": controlTimes, "candidate_seconds": candidateTimes, - "control_bytes": controlBytes, "candidate_bytes": candidateBytes, - "control_profile": arangostore.SummarizeProfile(controlProfile), "candidate_profile": arangostore.SummarizeProfile(candidateProfile), - "control_explain": arangostore.AssessExplainResult(controlExplain), "candidate_explain": arangostore.AssessExplainResult(candidateExplain), - "decision": "pending-threshold-review", - }) -} diff --git a/internal/dataframe/compact_summary_experiment_test.go b/internal/dataframe/compact_summary_experiment_test.go deleted file mode 100644 index 9900937..0000000 --- a/internal/dataframe/compact_summary_experiment_test.go +++ /dev/null @@ -1,325 +0,0 @@ -package dataframe_test - -// Read-only candidate E tournament. The incumbent is the frozen current -// root-endpoint plus selector-lowering AQL. The candidate adds one compact -// summary for a structurally selected leaf set with two distinct-value -// consumers and a representative slice. No production compiler files are -// touched. - -import ( - "context" - "encoding/json" - "fmt" - "os" - "path/filepath" - "regexp" - "runtime" - "sort" - "strings" - "testing" - "time" - - arangostore "github.com/calypr/loom/internal/store/arango" -) - -const compactSummaryIncumbentSHA = "2c5c598d96f161ac74129b532d2d05d8933a348d3032666d5b5262b7a654704d" - -type compactSummaryRun struct { - Name string `json:"name"` - QuerySHA256 string `json:"query_sha256"` - ResultSHA256 string `json:"result_sha256"` - Rows int `json:"rows"` - Bytes []int `json:"bytes"` - WarmSeconds []float64 `json:"warm_seconds"` - MedianSeconds float64 `json:"median_seconds"` - MinSeconds float64 `json:"min_seconds"` - Explain arangostore.ExplainAssessment `json:"explain"` - Profile compactSummaryProfile `json:"profile"` - RawProfile arangostore.ProfileResult `json:"-"` -} - -type compactSummaryProfile struct { - ScannedFull int `json:"scanned_full"` - ScannedIndex int `json:"scanned_index"` - PeakMemoryBytes uint64 `json:"peak_memory_bytes"` - Phases arangostore.ProfilePhases `json:"phases"` - TopNodes []arangostore.ProfileNodeSummary `json:"top_nodes"` -} - -type compactSummaryRewrite struct { - SetVariable string `json:"set_variable"` - Fields []string `json:"fields"` - BeforeLoops int `json:"before_loops"` - AfterLoops int `json:"after_loops"` -} - -func TestCompactSummaryCandidateStructure(t *testing.T) { - incumbent, _ := loadCompactSummaryIncumbent(t) - candidate, rewrite, err := buildCompactSummaryCandidate(incumbent) - if err != nil { - t.Fatal(err) - } - if len(rewrite.Fields) < 2 || rewrite.BeforeLoops < 2 || rewrite.AfterLoops >= rewrite.BeforeLoops { - t.Fatalf("summary did not select a rich leaf or remove consumers: %+v", rewrite) - } - if !strings.Contains(candidate, "COLLECT AGGREGATE") { - t.Fatalf("candidate omitted typed summary aggregation") - } - if !strings.Contains(candidate, "representative_files_limit") && !strings.Contains(candidate, "representative_samples_limit") && !strings.Contains(candidate, "representative_diagnoses_limit") { - t.Fatalf("candidate removed representative slice") - } - t.Logf("summary candidate bindings:\n%s", compactSummaryLines(candidate)) - t.Logf("compact summary structure: %+v", rewrite) -} - -func compactSummaryLines(query string) string { - lines := strings.Split(query, "\n") - selected := make([]string, 0, 20) - for _, line := range lines { - if strings.Contains(line, "__loom_summary") || strings.Contains(line, "__loom_physical_projection_10_name") || strings.Contains(line, "__loom_physical_projection_11_name") || strings.Contains(line, "__loom_physical_projection_12_name") { - selected = append(selected, line) - } - } - return strings.Join(selected, "\n") -} - -func TestCompactSummaryProfilesAgainstCurrentIncumbent(t *testing.T) { - if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { - t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run compact summary tournament against Arango") - } - incumbent, binds := loadCompactSummaryIncumbent(t) - candidate, rewrite, err := buildCompactSummaryCandidate(incumbent) - if err != nil { - t.Fatal(err) - } - url, database, _ := compilerArangoTarget() - client, err := arangostore.Open(context.Background(), url, database) - if err != nil { - t.Fatal(err) - } - defer client.Close(context.Background()) - ctx, cancel := context.WithTimeout(context.Background(), 20*time.Minute) - defer cancel() - control, candidateRun, err := runCompactSummaryAlternating(ctx, client, incumbent, candidate, binds) - if err != nil { - t.Fatal(err) - } - if control.ResultSHA256 != candidateRun.ResultSHA256 { - t.Fatalf("summary result parity mismatch control=%s candidate=%s", control.ResultSHA256, candidateRun.ResultSHA256) - } - if candidateRun.Profile.PeakMemoryBytes > 225000000 { - t.Fatalf("summary candidate exceeds 225 MB gate: %d", candidateRun.Profile.PeakMemoryBytes) - } - if candidateRun.MedianSeconds >= control.MedianSeconds*0.95 { - t.Logf("compact summary rejected: control=%.6fs candidate=%.6fs improvement=%.2f%% rewrite=%+v", control.MedianSeconds, candidateRun.MedianSeconds, 100*(control.MedianSeconds-candidateRun.MedianSeconds)/control.MedianSeconds, rewrite) - } else { - t.Logf("compact summary passes runtime gate: control=%.6fs candidate=%.6fs improvement=%.2f%% rewrite=%+v", control.MedianSeconds, candidateRun.MedianSeconds, 100*(control.MedianSeconds-candidateRun.MedianSeconds)/control.MedianSeconds, rewrite) - } - writeCompactSummaryArtifacts(t, incumbent, candidate, binds, rewrite, control, candidateRun) -} - -func loadCompactSummaryIncumbent(t *testing.T) (string, map[string]any) { - _, source, _, _ := runtime.Caller(0) - root := filepath.Join(filepath.Dir(source), "..", "..") - queryBytes, err := os.ReadFile(filepath.Join(root, "docs", "benchmarks", "round4", "tournament_root_endpoint", "candidate.aql")) - if err != nil { - t.Fatalf("read compact-summary incumbent: %v", err) - } - query := strings.TrimSuffix(strings.TrimSuffix(string(queryBytes), "\n"), "\r") - if sha256Hex(query) != compactSummaryIncumbentSHA { - t.Fatalf("compact-summary incumbent hash changed: got %s want %s", sha256Hex(query), compactSummaryIncumbentSHA) - } - reportBytes, err := os.ReadFile(filepath.Join(root, "docs", "benchmarks", "round4", "wp2", "integrated.json")) - if err != nil { - t.Fatalf("read compact-summary bind report: %v", err) - } - var report struct { - BindVars map[string]any `json:"bind_vars"` - } - if err := json.Unmarshal(reportBytes, &report); err != nil { - t.Fatalf("decode compact-summary bind report: %v", err) - } - return query, report.BindVars -} - -var compactSetRE = regexp.MustCompile(`(?ms)^ LET ([A-Za-z0-9_]+) = UNIQUE\(\(.*?^ {2,}\)\)\n`) -var compactConsumerRE = regexp.MustCompile(`SORTED_UNIQUE\(FLATTEN\(\(FOR __loom_prepared_value IN ([A-Za-z0-9_]+) RETURN __loom_prepared_value\.([A-Za-z0-9_]+)\)\)\)`) - -func buildCompactSummaryCandidate(control string) (string, compactSummaryRewrite, error) { - blocks := compactSetRE.FindAllStringSubmatchIndex(control, -1) - if len(blocks) == 0 { - return "", compactSummaryRewrite{}, fmt.Errorf("no child-set materializations found") - } - returnStart := strings.LastIndex(control, "\nRETURN ") - if returnStart < 0 { - return "", compactSummaryRewrite{}, fmt.Errorf("no root RETURN found") - } - returnText := control[returnStart:] - chosenSet := "" - fieldSet := map[string]bool{} - for _, block := range blocks { - setVariable := control[block[2]:block[3]] - for _, match := range compactConsumerRE.FindAllStringSubmatch(returnText, -1) { - if match[1] == setVariable { - fieldSet[match[2]] = true - } - } - if len(fieldSet) >= 2 { - chosenSet = setVariable - break - } - fieldSet = map[string]bool{} - } - if chosenSet == "" { - return "", compactSummaryRewrite{}, fmt.Errorf("no leaf set has two distinct-value consumers") - } - fields := make([]string, 0, len(fieldSet)) - for field := range fieldSet { - fields = append(fields, field) - } - sort.Strings(fields) - parts := make([]string, 0, len(fields)) - outputs := make([]string, 0, len(fields)) - defaults := make([]string, 0, len(fields)) - for index, field := range fields { - parts = append(parts, fmt.Sprintf(" __loom_summary_%d = UNIQUE(__loom_summary_item.%s)", index, field)) - outputs = append(outputs, fmt.Sprintf("values_%d: SORTED_UNIQUE(FLATTEN(__loom_summary_%d))", index, index)) - defaults = append(defaults, fmt.Sprintf("values_%d: []", index)) - } - summaryVariable := "__loom_summary_" + chosenSet - summary := fmt.Sprintf(" LET %s = FIRST((\n FOR __loom_summary_item IN %s\n COLLECT AGGREGATE\n __loom_summary_count = COUNT(),\n%s\n RETURN { count: __loom_summary_count, %s }\n )) || { count: 0, %s }\n", summaryVariable, chosenSet, strings.Join(parts, ",\n"), strings.Join(outputs, ", "), strings.Join(defaults, ", ")) - chosenBlock := -1 - for index, block := range blocks { - if control[block[2]:block[3]] == chosenSet { - chosenBlock = index - break - } - } - if chosenBlock < 0 { - return "", compactSummaryRewrite{}, fmt.Errorf("selected set block disappeared") - } - insertAt := blocks[chosenBlock][1] - candidate := control[:insertAt] + summary + control[insertAt:] - candidateReturnStart := strings.LastIndex(candidate, "\nRETURN ") - candidateReturn := candidate[candidateReturnStart:] - candidateReturn = strings.ReplaceAll(candidateReturn, "LENGTH("+chosenSet+")", summaryVariable+".count") - for index, field := range fields { - old := "SORTED_UNIQUE(FLATTEN((FOR __loom_prepared_value IN " + chosenSet + " RETURN __loom_prepared_value." + field + ")))" - candidateReturn = strings.ReplaceAll(candidateReturn, old, fmt.Sprintf("%s.values_%d", summaryVariable, index)) - } - candidate = candidate[:candidateReturnStart] + candidateReturn - return candidate, compactSummaryRewrite{SetVariable: chosenSet, Fields: fields, BeforeLoops: strings.Count(returnText, "FOR __loom_prepared_value IN "+chosenSet), AfterLoops: strings.Count(candidateReturn, "FOR __loom_prepared_value IN "+chosenSet)}, nil -} - -func runCompactSummaryAlternating(ctx context.Context, client *arangostore.Client, control, candidate string, baseBinds map[string]any) (compactSummaryRun, compactSummaryRun, error) { - controlRun := compactSummaryRun{Name: "endpoint_selector_incumbent", QuerySHA256: sha256Hex(control)} - candidateRun := compactSummaryRun{Name: "compact_leaf_summary", QuerySHA256: sha256Hex(candidate)} - for i := 0; i < 5; i++ { - controlQuery, controlBinds := cacheBust(control, baseBinds, 15000+i) - candidateQuery, candidateBinds := cacheBust(candidate, baseBinds, 16000+i) - controlSeconds, controlBytes, controlHash, err := executeOrdinary(ctx, client, controlQuery, controlBinds) - if err != nil { - return controlRun, candidateRun, fmt.Errorf("control run %d: %w", i+1, err) - } - candidateSeconds, candidateBytes, candidateHash, err := executeOrdinary(ctx, client, candidateQuery, candidateBinds) - if err != nil { - return controlRun, candidateRun, fmt.Errorf("candidate run %d: %w", i+1, err) - } - controlRun.WarmSeconds = append(controlRun.WarmSeconds, controlSeconds) - controlRun.Bytes = append(controlRun.Bytes, controlBytes) - controlRun.ResultSHA256 = controlHash - controlRun.Rows = 1000 - candidateRun.WarmSeconds = append(candidateRun.WarmSeconds, candidateSeconds) - candidateRun.Bytes = append(candidateRun.Bytes, candidateBytes) - candidateRun.ResultSHA256 = candidateHash - candidateRun.Rows = 1000 - } - controlRun.MedianSeconds, controlRun.MinSeconds = median(controlRun.WarmSeconds), minCompact(controlRun.WarmSeconds) - candidateRun.MedianSeconds, candidateRun.MinSeconds = median(candidateRun.WarmSeconds), minCompact(candidateRun.WarmSeconds) - controlProfileQuery, controlProfileBinds := cacheBust(control, baseBinds, 17001) - candidateProfileQuery, candidateProfileBinds := cacheBust(candidate, baseBinds, 17002) - controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: controlProfileQuery, BindVars: controlProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - return controlRun, candidateRun, err - } - candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidateProfileQuery, BindVars: candidateProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - return controlRun, candidateRun, err - } - controlRun.Explain, err = explainCompact(ctx, client, control, baseBinds) - if err != nil { - return controlRun, candidateRun, err - } - candidateRun.Explain, err = explainCompact(ctx, client, candidate, baseBinds) - if err != nil { - return controlRun, candidateRun, err - } - controlRun.RawProfile, candidateRun.RawProfile = controlProfile, candidateProfile - controlRun.Profile, candidateRun.Profile = summarizeCompact(controlProfile), summarizeCompact(candidateProfile) - return controlRun, candidateRun, nil -} - -func explainCompact(ctx context.Context, client *arangostore.Client, query string, binds map[string]any) (arangostore.ExplainAssessment, error) { - explain, err := client.Explain(ctx, arangostore.ExplainRequest{Query: query, BindVars: binds}) - if err != nil { - return arangostore.ExplainAssessment{}, err - } - assessment := arangostore.AssessExplainResult(explain) - if len(assessment.FullCollectionScans) != 0 { - return assessment, fmt.Errorf("summary candidate introduced full scans: %#v", assessment.FullCollectionScans) - } - return assessment, nil -} - -func summarizeCompact(profile arangostore.ProfileResult) compactSummaryProfile { - summary := arangostore.SummarizeProfile(profile) - nodes := append([]arangostore.ProfileNodeSummary(nil), summary.Nodes...) - if len(nodes) > 20 { - nodes = nodes[:20] - } - return compactSummaryProfile{ScannedFull: summary.ScannedFull, ScannedIndex: summary.ScannedIndex, PeakMemoryBytes: summary.PeakMemory, Phases: profile.Extra.Profile, TopNodes: nodes} -} - -func minCompact(values []float64) float64 { - if len(values) == 0 { - return 0 - } - minimum := values[0] - for _, value := range values[1:] { - if value < minimum { - minimum = value - } - } - return minimum -} - -func writeCompactSummaryArtifacts(t *testing.T, incumbent, candidate string, binds map[string]any, rewrite compactSummaryRewrite, control, candidateRun compactSummaryRun) { - _, source, _, _ := runtime.Caller(0) - root := filepath.Join(filepath.Dir(source), "..", "..") - directory := filepath.Join(root, "docs", "benchmarks", "round4", "tournament_summaries") - if err := os.MkdirAll(directory, 0o755); err != nil { - t.Fatal(err) - } - for name, query := range map[string]string{"incumbent.aql": incumbent, "candidate.aql": candidate} { - if err := os.WriteFile(filepath.Join(directory, name), []byte(query+"\n"), 0o644); err != nil { - t.Fatal(err) - } - } - for name, profile := range map[string]arangostore.ProfileResult{"incumbent.profile.json": control.RawProfile, "candidate.profile.json": candidateRun.RawProfile} { - encoded, err := json.MarshalIndent(profile, "", " ") - if err != nil { - t.Fatal(err) - } - if err := os.WriteFile(filepath.Join(directory, name), append(encoded, '\n'), 0o644); err != nil { - t.Fatal(err) - } - } - payload := map[string]any{"incumbent": control, "candidate": candidateRun, "bind_vars": binds, "rewrite": rewrite} - encoded, err := json.MarshalIndent(payload, "", " ") - if err != nil { - t.Fatal(err) - } - if err := os.WriteFile(filepath.Join(directory, "RESULTS.json"), append(encoded, '\n'), 0o644); err != nil { - t.Fatal(err) - } -} diff --git a/internal/dataframe/compat_test_helpers_test.go b/internal/dataframe/compat_test_helpers_test.go index 8a47f41..abfade3 100644 --- a/internal/dataframe/compat_test_helpers_test.go +++ b/internal/dataframe/compat_test_helpers_test.go @@ -1,7 +1,7 @@ package dataframe -// These aliases keep legacy experiment tests in the root compatibility -// package while their implementations live in compiler/runtime packages. +// These aliases keep package-local compiler tests readable while their +// implementations live in the canonical compiler/runtime packages. type storageRoute = StorageRoute func resolveStorageRoute(fromType, label, toType string) (storageRoute, error) { diff --git a/internal/dataframe/compiler/api.go b/internal/dataframe/compiler/api.go new file mode 100644 index 0000000..273e9fa --- /dev/null +++ b/internal/dataframe/compiler/api.go @@ -0,0 +1,6 @@ +// Package compiler is the stable dataframe compiler facade. +// +// Compilation proceeds through spec, semantic, ir, lower, optimize, and +// render/aql. The facade keeps the historical public symbols available while +// each implementation layer remains independently navigable and testable. +package compiler diff --git a/internal/dataframe/compiler/arango_test_helpers_test.go b/internal/dataframe/compiler/arango_test_helpers_test.go deleted file mode 100644 index a277c64..0000000 --- a/internal/dataframe/compiler/arango_test_helpers_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package compiler - -import "os" - -func compilerArangoTarget() (string, string, string) { - url := os.Getenv("LOOM_ARANGO_URL") - if url == "" { - url = "http://127.0.0.1:8529" - } - database := os.Getenv("LOOM_ARANGO_DATABASE") - if database == "" { - database = "fhir_proto" - } - project := os.Getenv("LOOM_ARANGO_PROJECT") - if project == "" { - project = "ARANGODB_PROTO" - } - return url, database, project -} diff --git a/internal/dataframe/compiler/clone_helpers.go b/internal/dataframe/compiler/clone_helpers.go new file mode 100644 index 0000000..76ab92a --- /dev/null +++ b/internal/dataframe/compiler/clone_helpers.go @@ -0,0 +1,17 @@ +package compiler + +func cloneStrings(in []string) []string { + if in == nil { + return nil + } + return append([]string(nil), in...) +} + +func cloneRowIdentity(identity *RowIdentity) *RowIdentity { + if identity == nil { + return nil + } + copy := *identity + copy.Fields = cloneStrings(identity.Fields) + return © +} diff --git a/internal/dataframe/compiler/physical_helpers.go b/internal/dataframe/compiler/ir/clone.go similarity index 88% rename from internal/dataframe/compiler/physical_helpers.go rename to internal/dataframe/compiler/ir/clone.go index 9592213..7ad717f 100644 --- a/internal/dataframe/compiler/physical_helpers.go +++ b/internal/dataframe/compiler/ir/clone.go @@ -1,19 +1,4 @@ -package compiler - -// genericPhysicalPlanUnavailableReason reports whether a semantic node needs -// an operation the navigation-only physical plan does not yet represent. -func genericPhysicalPlanUnavailableReason(node SemanticNode) string { - return genericPhysicalNodeUnavailableReason(node, true) -} - -func genericPhysicalNodeUnavailableReason(node SemanticNode, root bool) string { - for _, child := range node.Children { - if reason := genericPhysicalNodeUnavailableReason(child, false); reason != "" { - return reason - } - } - return "" -} +package ir func clonePhysicalPlan(plan PhysicalPlan) PhysicalPlan { copy := plan @@ -26,6 +11,26 @@ func clonePhysicalPlan(plan PhysicalPlan) PhysicalPlan { return copy } +func ClonePhysicalPlan(plan PhysicalPlan) PhysicalPlan { return clonePhysicalPlan(plan) } +func ClonePhysicalOperation(operation PhysicalOperation) PhysicalOperation { + return clonePhysicalOperation(operation) +} +func ClonePhysicalOperations(operations []PhysicalOperation) []PhysicalOperation { + return clonePhysicalOperations(operations) +} +func ClonePhysicalPredicate(predicate PhysicalPredicate) PhysicalPredicate { + return clonePhysicalPredicate(predicate) +} +func ClonePhysicalPredicateExpression(predicate PhysicalPredicateExpression) PhysicalPredicateExpression { + return clonePhysicalPredicateExpression(predicate) +} +func ClonePhysicalExpression(expression PhysicalExpression) PhysicalExpression { + return clonePhysicalExpression(expression) +} +func ClonePhysicalSubplan(subplan PhysicalSubplan) PhysicalSubplan { + return clonePhysicalSubplan(subplan) +} + func clonePhysicalBindVars(bindVars map[string]any) map[string]any { if bindVars == nil { return nil diff --git a/internal/dataframe/compiler/ir/clone_values.go b/internal/dataframe/compiler/ir/clone_values.go new file mode 100644 index 0000000..d19a7c6 --- /dev/null +++ b/internal/dataframe/compiler/ir/clone_values.go @@ -0,0 +1,29 @@ +package ir + +func cloneStrings(in []string) []string { + if in == nil { + return nil + } + return append([]string(nil), in...) +} + +func clonePhysicalBindValue(value any) any { + switch value := value.(type) { + case []any: + out := make([]any, len(value)) + for i, item := range value { + out[i] = clonePhysicalBindValue(item) + } + return out + case []string: + return append([]string(nil), value...) + case map[string]any: + out := make(map[string]any, len(value)) + for key, item := range value { + out[key] = clonePhysicalBindValue(item) + } + return out + default: + return value + } +} diff --git a/internal/dataframe/compiler/dataset_generation.go b/internal/dataframe/compiler/ir/dataset_generation.go similarity index 74% rename from internal/dataframe/compiler/dataset_generation.go rename to internal/dataframe/compiler/ir/dataset_generation.go index 4e6bf84..f5ddff7 100644 --- a/internal/dataframe/compiler/dataset_generation.go +++ b/internal/dataframe/compiler/ir/dataset_generation.go @@ -1,4 +1,4 @@ -package compiler +package ir import "strings" @@ -22,3 +22,8 @@ func datasetGenerationBindValue(generation string) any { } return generation } + +func NormalizeDatasetGeneration(generation string) string { + return normalizeDatasetGeneration(generation) +} +func DatasetGenerationBindValue(generation string) any { return datasetGenerationBindValue(generation) } diff --git a/internal/dataframe/compiler/physical_diagnostics.go b/internal/dataframe/compiler/ir/diagnostics.go similarity index 98% rename from internal/dataframe/compiler/physical_diagnostics.go rename to internal/dataframe/compiler/ir/diagnostics.go index faf575c..9ff2bc9 100644 --- a/internal/dataframe/compiler/physical_diagnostics.go +++ b/internal/dataframe/compiler/ir/diagnostics.go @@ -1,4 +1,4 @@ -package compiler +package ir import ( "encoding/json" @@ -192,6 +192,10 @@ func physicalPlanDiagnostics(plan PhysicalPlan) CompilerPlanDiagnostics { return diagnostics } +func PhysicalPlanDiagnostics(plan PhysicalPlan) CompilerPlanDiagnostics { + return physicalPlanDiagnostics(plan) +} + func collectRichConsumerGroups(expression *PhysicalExpression, groups map[string]*RichConsumerGroup) { if expression == nil { return diff --git a/internal/dataframe/compiler/ir/doc.go b/internal/dataframe/compiler/ir/doc.go new file mode 100644 index 0000000..f44bc53 --- /dev/null +++ b/internal/dataframe/compiler/ir/doc.go @@ -0,0 +1,3 @@ +// Package ir contains the typed physical operation graph and its scope, +// variable, bind, and optimization-diagnostic invariants. +package ir diff --git a/internal/dataframe/compiler/ir/navigation.go b/internal/dataframe/compiler/ir/navigation.go new file mode 100644 index 0000000..ae91801 --- /dev/null +++ b/internal/dataframe/compiler/ir/navigation.go @@ -0,0 +1,121 @@ +package ir + +import ( + "fmt" + "strings" +) + +const genericPhysicalExecutionLimitBind = "limit" + +func validateGenericNavigationTraversal(plan PhysicalPlan, traversal PhysicalTraversal) error { + if traversal.Direction != PhysicalInbound && traversal.Direction != PhysicalOutbound { + return fmt.Errorf("generic navigation traversal direction must be INBOUND or OUTBOUND, got %q", traversal.Direction) + } + wantEdgeTypeField := "from_type" + if traversal.Direction == PhysicalOutbound { + wantEdgeTypeField = "to_type" + } + if traversal.EdgeTargetTypeField != wantEdgeTypeField { + return fmt.Errorf("generic navigation traversal %s must constrain edge.%s, got %q", traversal.Direction, wantEdgeTypeField, traversal.EdgeTargetTypeField) + } + if traversal.EdgeVariable == "" || traversal.EdgeLabelBindKey == "" || traversal.TargetTypeBindKey == "" { + return fmt.Errorf("generic navigation traversal requires edge variable, edge label bind, and target type bind") + } + collection, ok := plan.BindVars[traversal.EdgeCollectionBindKey].(string) + if !ok || collection != "fhir_edge" { + return fmt.Errorf("generic navigation traversal must use fhir_edge through its collection bind") + } + strategy := traversal.Strategy + if strategy == "" { + strategy = PhysicalTraversalNative + } + if strategy != PhysicalTraversalNative && strategy != PhysicalTraversalEndpointLookup { + return fmt.Errorf("unsupported generic navigation traversal strategy %q", strategy) + } + if strategy == PhysicalTraversalEndpointLookup { + wantEndpoint, wantJoin := "_to", "_from" + wantIndexType := "from_type" + if traversal.Direction == PhysicalOutbound { + wantEndpoint, wantJoin, wantIndexType = "_from", "_to", "to_type" + } + if traversal.EndpointField != wantEndpoint || traversal.EndpointJoinField != wantJoin { + return fmt.Errorf("endpoint lookup %s requires %s -> %s, got %s -> %s", traversal.Direction, wantEndpoint, wantJoin, traversal.EndpointField, traversal.EndpointJoinField) + } + wantIndex := []string{wantEndpoint, "project", "dataset_generation", "label", wantIndexType} + if len(traversal.EndpointIndexFields) != len(wantIndex) { + return fmt.Errorf("endpoint lookup requires compound index fields %#v", wantIndex) + } + for index := range wantIndex { + if traversal.EndpointIndexFields[index] != wantIndex[index] { + return fmt.Errorf("endpoint lookup index field %d = %q, want %q", index, traversal.EndpointIndexFields[index], wantIndex[index]) + } + } + } + return nil +} + +func sameRenderPhysicalValue(left, right PhysicalValue) bool { + if left.Variable != right.Variable || left.BindKey != right.BindKey || len(left.Path) != len(right.Path) { + return false + } + for index := range left.Path { + if left.Path[index] != right.Path[index] { + return false + } + } + return true +} + +func matchesPhysicalEquality(predicate PhysicalPredicate, left, right PhysicalValue) bool { + return strings.EqualFold(strings.TrimSpace(predicate.Operator), "EQUALS") && predicate.Right != nil && sameRenderPhysicalValue(predicate.Left, left) && sameRenderPhysicalValue(*predicate.Right, right) +} + +func validateGenericNavigationScopeBlock(operations []PhysicalOperation, resourceVariable, edgeVariable, targetVariable string) (string, error) { + expectedProjectVariables := []string{resourceVariable} + expectedGenerationVariables := []string{resourceVariable} + if edgeVariable != "" { + expectedProjectVariables = []string{edgeVariable, targetVariable} + expectedGenerationVariables = []string{edgeVariable, targetVariable} + } + expectedLength := len(expectedProjectVariables) + len(expectedGenerationVariables) + 2 + if len(operations) != expectedLength || operations[0].Kind != PhysicalFilterOp { + return "", fmt.Errorf("requires project filters for every graph document, dataset_generation filters, LET AUTH_RESOURCE_PATH_ALLOWED, FILTER scope_allowed in order") + } + for index, variable := range expectedProjectVariables { + operation := operations[index] + if operation.Kind != PhysicalFilterOp || !matchesPhysicalEquality(operation.Filter.Predicate, PhysicalValue{Variable: variable, Path: []string{"project"}}, PhysicalValue{BindKey: "project"}) { + return "", fmt.Errorf("project scope must be %s.project == @project", variable) + } + } + for index, variable := range expectedGenerationVariables { + operation := operations[len(expectedProjectVariables)+index] + if operation.Kind != PhysicalFilterOp || !matchesPhysicalEquality(operation.Filter.Predicate, PhysicalValue{Variable: variable, Path: []string{"dataset_generation"}}, PhysicalValue{BindKey: "dataset_generation"}) { + return "", fmt.Errorf("dataset generation scope must be %s.dataset_generation == @dataset_generation", variable) + } + } + authLetIndex := len(expectedProjectVariables) + len(expectedGenerationVariables) + if operations[authLetIndex].Kind != PhysicalDerivedLetOp || operations[authLetIndex].DerivedLet == nil { + return "", fmt.Errorf("scope block requires AUTH_RESOURCE_PATH_ALLOWED LET after dataset generation scope") + } + derived := operations[authLetIndex].DerivedLet + if strings.ToUpper(strings.TrimSpace(derived.Operator)) != "AUTH_RESOURCE_PATH_ALLOWED" { + return "", fmt.Errorf("scope LET must use AUTH_RESOURCE_PATH_ALLOWED") + } + expectedInputs := []PhysicalValue{{Variable: resourceVariable, Path: []string{"auth_resource_path"}}} + if edgeVariable != "" { + expectedInputs = []PhysicalValue{{Variable: edgeVariable, Path: []string{"auth_resource_path"}}, {Variable: targetVariable, Path: []string{"auth_resource_path"}}} + } + expectedInputs = append(expectedInputs, PhysicalValue{BindKey: "auth_resource_paths"}, PhysicalValue{BindKey: "auth_resource_paths_unrestricted"}) + if len(derived.Inputs) != len(expectedInputs) { + return "", fmt.Errorf("AUTH_RESOURCE_PATH_ALLOWED requires the exact generic auth scope inputs") + } + for index := range expectedInputs { + if !sameRenderPhysicalValue(derived.Inputs[index], expectedInputs[index]) { + return "", fmt.Errorf("AUTH_RESOURCE_PATH_ALLOWED input %d is not the required generic scope value", index) + } + } + if len(operations) <= authLetIndex+1 || operations[authLetIndex+1].Kind != PhysicalFilterOp || !matchesPhysicalEquality(operations[authLetIndex+1].Filter.Predicate, PhysicalValue{Variable: derived.Variable}, PhysicalValue{BindKey: "scope_allowed"}) { + return "", fmt.Errorf("auth scope must be %s == @scope_allowed", derived.Variable) + } + return derived.Variable, nil +} diff --git a/internal/dataframe/compiler/physical_plan.go b/internal/dataframe/compiler/ir/plan.go similarity index 99% rename from internal/dataframe/compiler/physical_plan.go rename to internal/dataframe/compiler/ir/plan.go index 3d7b945..7f39a4f 100644 --- a/internal/dataframe/compiler/physical_plan.go +++ b/internal/dataframe/compiler/ir/plan.go @@ -1,7 +1,9 @@ -package compiler +package ir import ( "fmt" + + "github.com/calypr/loom/internal/dataframe/spec" "regexp" "strings" @@ -1064,7 +1066,7 @@ func validatePhysicalSelector(resourceType string, selector Selector) error { if len(selector.Steps) == 0 { return fmt.Errorf("selector is required") } - if _, _, err := selectorCardinality(resourceType, selector); err != nil { + if _, _, err := spec.SelectorCardinality(resourceType, selector); err != nil { return err } return nil diff --git a/internal/dataframe/compiler/physical_cost.go b/internal/dataframe/compiler/ir/policy.go similarity index 93% rename from internal/dataframe/compiler/physical_cost.go rename to internal/dataframe/compiler/ir/policy.go index 6f71f1b..e2f711b 100644 --- a/internal/dataframe/compiler/physical_cost.go +++ b/internal/dataframe/compiler/ir/policy.go @@ -1,4 +1,4 @@ -package compiler +package ir import ( "os" @@ -198,6 +198,10 @@ func (report *PhysicalOptimizationReport) addDecision(decision PhysicalOptimizat report.Decisions = append(report.Decisions, decision) } +func (report *PhysicalOptimizationReport) AddDecision(decision PhysicalOptimizationDecision) { + report.addDecision(decision) +} + // estimateTraversalSharingWork models the prefix and subset operations that // the rewrite actually changes. Every original set pays for its traversal and // scope prefix. The shared plan pays for one prefix plus one typed subset per @@ -241,3 +245,19 @@ func clonePhysicalOptimizationReport(report PhysicalOptimizationReport) Physical copy.Decisions = append([]PhysicalOptimizationDecision(nil), report.Decisions...) return copy } + +func NewPhysicalOptimizationReport(policy PhysicalOptimizationPolicy) PhysicalOptimizationReport { + return newPhysicalOptimizationReport(policy) +} + +func ClonePhysicalOptimizationReport(report PhysicalOptimizationReport) PhysicalOptimizationReport { + return clonePhysicalOptimizationReport(report) +} + +func EstimateTraversalSharingWork(prefix PhysicalTraversalPrefixDecomposition, candidateSets int) (int, int, int) { + return estimateTraversalSharingWork(prefix, candidateSets) +} + +func EstimatePreparedSelectorWork(selectorUseCount int) (int, int, int) { + return estimatePreparedSelectorWork(selectorUseCount) +} diff --git a/internal/dataframe/compiler/physical_prefix.go b/internal/dataframe/compiler/ir/prefix.go similarity index 99% rename from internal/dataframe/compiler/physical_prefix.go rename to internal/dataframe/compiler/ir/prefix.go index 6f791e7..c2575ca 100644 --- a/internal/dataframe/compiler/physical_prefix.go +++ b/internal/dataframe/compiler/ir/prefix.go @@ -1,4 +1,4 @@ -package compiler +package ir import ( "encoding/json" diff --git a/internal/dataframe/compiler/physical_scope.go b/internal/dataframe/compiler/ir/scope.go similarity index 98% rename from internal/dataframe/compiler/physical_scope.go rename to internal/dataframe/compiler/ir/scope.go index da649b8..1701739 100644 --- a/internal/dataframe/compiler/physical_scope.go +++ b/internal/dataframe/compiler/ir/scope.go @@ -1,4 +1,4 @@ -package compiler +package ir import "fmt" @@ -89,6 +89,10 @@ func physicalScopeWindowEnd(operations []PhysicalOperation, start int) int { return len(operations) } +func PhysicalScopeWindowEnd(operations []PhysicalOperation, start int) int { + return physicalScopeWindowEnd(operations, start) +} + func validatePhysicalScopeWindow(operations []PhysicalOperation, resourceIndex, windowEnd int, resource physicalScopeResource) error { projectIndex, err := findProjectScopeFilters(operations, resourceIndex+1, windowEnd, resource) if err != nil { diff --git a/internal/dataframe/compiler/ir/selector_helpers.go b/internal/dataframe/compiler/ir/selector_helpers.go new file mode 100644 index 0000000..cffd9b8 --- /dev/null +++ b/internal/dataframe/compiler/ir/selector_helpers.go @@ -0,0 +1,19 @@ +package ir + +func selectorHasNoArrays(sel Selector) bool { + for _, step := range sel.Steps { + if step.Iterate || step.Index != nil { + return false + } + } + return true +} + +func selectorHasIteratedArray(sel Selector) bool { + for _, step := range sel.Steps { + if step.Iterate { + return true + } + } + return false +} diff --git a/internal/dataframe/compiler/ir/spec_aliases.go b/internal/dataframe/compiler/ir/spec_aliases.go new file mode 100644 index 0000000..9444ea8 --- /dev/null +++ b/internal/dataframe/compiler/ir/spec_aliases.go @@ -0,0 +1,12 @@ +package ir + +import "github.com/calypr/loom/internal/dataframe/spec" + +type ( + Selector = spec.Selector + SelectorStep = spec.SelectorStep + ContainsFilter = spec.ContainsFilter + TypedFilter = spec.TypedFilter + ArrayQuantifier = spec.ArrayQuantifier + FilterValueKind = spec.FilterValueKind +) diff --git a/internal/dataframe/compiler/ir/value.go b/internal/dataframe/compiler/ir/value.go new file mode 100644 index 0000000..b477937 --- /dev/null +++ b/internal/dataframe/compiler/ir/value.go @@ -0,0 +1,7 @@ +package ir + +import "fmt" + +func valueString(value any) string { + return fmt.Sprint(value) +} diff --git a/internal/dataframe/compiler/ir_helpers.go b/internal/dataframe/compiler/ir_helpers.go new file mode 100644 index 0000000..4d0f33b --- /dev/null +++ b/internal/dataframe/compiler/ir_helpers.go @@ -0,0 +1,28 @@ +package compiler + +import "github.com/calypr/loom/internal/dataframe/compiler/ir" + +func datasetGenerationBindValue(generation string) any { + return ir.DatasetGenerationBindValue(generation) +} +func normalizeDatasetGeneration(generation string) string { + return ir.NormalizeDatasetGeneration(generation) +} +func physicalScopeWindowEnd(operations []PhysicalOperation, start int) int { + return ir.PhysicalScopeWindowEnd(operations, start) +} +func physicalPlanDiagnostics(plan PhysicalPlan) CompilerPlanDiagnostics { + return ir.PhysicalPlanDiagnostics(plan) +} +func newPhysicalOptimizationReport(policy PhysicalOptimizationPolicy) PhysicalOptimizationReport { + return ir.NewPhysicalOptimizationReport(policy) +} +func clonePhysicalOptimizationReport(report PhysicalOptimizationReport) PhysicalOptimizationReport { + return ir.ClonePhysicalOptimizationReport(report) +} +func estimateTraversalSharingWork(prefix PhysicalTraversalPrefixDecomposition, candidateSets int) (int, int, int) { + return ir.EstimateTraversalSharingWork(prefix, candidateSets) +} +func estimatePreparedSelectorWork(selectorUseCount int) (int, int, int) { + return ir.EstimatePreparedSelectorWork(selectorUseCount) +} diff --git a/internal/dataframe/compiler/lower/aliases.go b/internal/dataframe/compiler/lower/aliases.go new file mode 100644 index 0000000..830af80 --- /dev/null +++ b/internal/dataframe/compiler/lower/aliases.go @@ -0,0 +1,133 @@ +package lower + +import ( + "github.com/calypr/loom/internal/dataframe/compiler/ir" + "github.com/calypr/loom/internal/dataframe/semantic" + "github.com/calypr/loom/internal/dataframe/spec" +) + +type ( + SemanticPlan = semantic.SemanticPlan + SemanticNode = semantic.SemanticNode + SemanticField = semantic.SemanticField + SemanticPivot = semantic.SemanticPivot + SemanticAggregate = semantic.SemanticAggregate + SemanticSlice = semantic.SemanticSlice + SelectionSemanticSpec = semantic.SelectionSemanticSpec + Builder = spec.Builder + FieldSelect = spec.FieldSelect + TypedFilter = spec.TypedFilter + Selector = spec.Selector + FilterValue = spec.FilterValue + PhysicalPlan = ir.PhysicalPlan + PhysicalSource = ir.PhysicalSource + PhysicalOperation = ir.PhysicalOperation + PhysicalOperationKind = ir.PhysicalOperationKind + PhysicalRootScan = ir.PhysicalRootScan + PhysicalTraversal = ir.PhysicalTraversal + PhysicalTraversalDirection = ir.PhysicalTraversalDirection + PhysicalTraversalStrategy = ir.PhysicalTraversalStrategy + PhysicalValue = ir.PhysicalValue + PhysicalCardinality = ir.PhysicalCardinality + PhysicalNullBehavior = ir.PhysicalNullBehavior + PhysicalExpression = ir.PhysicalExpression + PhysicalExtract = ir.PhysicalExtract + PhysicalPreparedSet = ir.PhysicalPreparedSet + PhysicalPreparedField = ir.PhysicalPreparedField + PhysicalPreparedReference = ir.PhysicalPreparedReference + PhysicalAggregate = ir.PhysicalAggregate + PhysicalPivotMap = ir.PhysicalPivotMap + PhysicalSlice = ir.PhysicalSlice + PhysicalExpressionProjection = ir.PhysicalExpressionProjection + PhysicalObject = ir.PhysicalObject + PhysicalSet = ir.PhysicalSet + PhysicalSetProjection = ir.PhysicalSetProjection + PhysicalSetProjectionField = ir.PhysicalSetProjectionField + PhysicalSetOutput = ir.PhysicalSetOutput + PhysicalSetOutputField = ir.PhysicalSetOutputField + PhysicalSubplan = ir.PhysicalSubplan + PhysicalPredicate = ir.PhysicalPredicate + PhysicalPredicateExpression = ir.PhysicalPredicateExpression + PhysicalFilter = ir.PhysicalFilter + PhysicalDerivedLet = ir.PhysicalDerivedLet + PhysicalProjection = ir.PhysicalProjection + PhysicalReturn = ir.PhysicalReturn + PhysicalPredicateKind = ir.PhysicalPredicateKind + PhysicalAggregateOperation = ir.PhysicalAggregateOperation + PhysicalSelectorExecutionMode = ir.PhysicalSelectorExecutionMode + PhysicalOptimizationPolicy = ir.PhysicalOptimizationPolicy +) + +const ( + PhysicalRootScanOp = ir.PhysicalRootScanOp + PhysicalTraversalOp = ir.PhysicalTraversalOp + PhysicalFilterOp = ir.PhysicalFilterOp + PhysicalDerivedLetOp = ir.PhysicalDerivedLetOp + PhysicalSetOp = ir.PhysicalSetOp + PhysicalScalarCardinality = ir.PhysicalScalarCardinality + PhysicalArrayCardinality = ir.PhysicalArrayCardinality + PhysicalObjectCardinality = ir.PhysicalObjectCardinality + PhysicalPreserveNull = ir.PhysicalPreserveNull + PhysicalOmitNulls = ir.PhysicalOmitNulls + PhysicalEmptyOnNull = ir.PhysicalEmptyOnNull + PhysicalValueExpression = ir.PhysicalValueExpression + PhysicalExtractExpression = ir.PhysicalExtractExpression + PhysicalAggregateExpression = ir.PhysicalAggregateExpression + PhysicalPivotExpression = ir.PhysicalPivotExpression + PhysicalSliceExpression = ir.PhysicalSliceExpression + PhysicalObjectExpression = ir.PhysicalObjectExpression + PhysicalSelectorGeneric = ir.PhysicalSelectorGeneric + PhysicalSelectorDirectScalar = ir.PhysicalSelectorDirectScalar + PhysicalSelectorConditionalArray = ir.PhysicalSelectorConditionalArray + PhysicalInbound = ir.PhysicalInbound + PhysicalOutbound = ir.PhysicalOutbound + PhysicalTraversalNative = ir.PhysicalTraversalNative + PhysicalTraversalEndpointLookup = ir.PhysicalTraversalEndpointLookup + PhysicalCountAggregate = ir.PhysicalCountAggregate + PhysicalCountDistinctAggregate = ir.PhysicalCountDistinctAggregate + PhysicalExistsAggregate = ir.PhysicalExistsAggregate + PhysicalDistinctValuesAggregate = ir.PhysicalDistinctValuesAggregate + PhysicalMinAggregate = ir.PhysicalMinAggregate + PhysicalMaxAggregate = ir.PhysicalMaxAggregate + PhysicalFirstAggregate = ir.PhysicalFirstAggregate + PhysicalSetGraphIDField = ir.PhysicalSetGraphIDField + PhysicalSetKeyField = ir.PhysicalSetKeyField + PhysicalSetIDField = ir.PhysicalSetIDField + PhysicalSetResourceTypeField = ir.PhysicalSetResourceTypeField + PhysicalSetPayloadField = ir.PhysicalSetPayloadField + PhysicalReturnOp = ir.PhysicalReturnOp + PhysicalComparisonPredicate = ir.PhysicalComparisonPredicate + PhysicalExistsPredicate = ir.PhysicalExistsPredicate + PhysicalOptimizationRuleCompactProjection = ir.PhysicalOptimizationRuleCompactProjection + PhysicalOptimizationRuleEndpointTraversal = ir.PhysicalOptimizationRuleEndpointTraversal + PhysicalOptimizationRulePreparedSelectors = ir.PhysicalOptimizationRulePreparedSelectors + ProjectionArray = spec.ProjectionArray + ProjectionScalar = spec.ProjectionScalar + ProjectionFirst = spec.ProjectionFirst + FilterEquals = spec.FilterEquals + FilterIn = spec.FilterIn + FilterExists = spec.FilterExists + FilterMissing = spec.FilterMissing + ProjectionDistinctArray = spec.ProjectionDistinctArray + FilterString = spec.FilterString + FilterCode = spec.FilterCode + FilterBoolean = spec.FilterBoolean + FilterInteger = spec.FilterInteger + FilterDecimal = spec.FilterDecimal + FilterDate = spec.FilterDate + FilterDateTime = spec.FilterDateTime +) + +var ( + ValidateSemanticGraph = semantic.ValidateSemanticGraph + NormalizeSelectionPlan = semantic.NormalizeSelectionPlan + ResolveSemanticField = semantic.ResolveSemanticField + ValidateTypedFilterForResource = spec.ValidateTypedFilterForResource + ParseSelector = spec.ParseSelector + ValidateGenericPhysicalPlanScope = ir.ValidateGenericPhysicalPlanScope + DefaultPhysicalOptimizationPolicy = ir.DefaultPhysicalOptimizationPolicy +) + +func estimatePreparedSelectorWork(selectorUseCount int) (int, int, int) { + return ir.EstimatePreparedSelectorWork(selectorUseCount) +} diff --git a/internal/dataframe/compiler/auth_scope.go b/internal/dataframe/compiler/lower/auth_scope.go similarity index 98% rename from internal/dataframe/compiler/auth_scope.go rename to internal/dataframe/compiler/lower/auth_scope.go index c94df73..6d67582 100644 --- a/internal/dataframe/compiler/auth_scope.go +++ b/internal/dataframe/compiler/lower/auth_scope.go @@ -1,4 +1,4 @@ -package compiler +package lower import "github.com/calypr/loom/internal/authscope" diff --git a/internal/dataframe/compiler/lower/doc.go b/internal/dataframe/compiler/lower/doc.go new file mode 100644 index 0000000..7c5e821 --- /dev/null +++ b/internal/dataframe/compiler/lower/doc.go @@ -0,0 +1,4 @@ +// Package lower lowers logical FHIR dataframe plans into typed physical IR. +// It is the only compiler layer allowed to resolve stored graph routes and +// endpoint-versus-native traversal strategies. +package lower diff --git a/internal/dataframe/compiler/lower/filter_literal.go b/internal/dataframe/compiler/lower/filter_literal.go new file mode 100644 index 0000000..eb23afa --- /dev/null +++ b/internal/dataframe/compiler/lower/filter_literal.go @@ -0,0 +1,31 @@ +package lower + +import ( + "fmt" + + "github.com/calypr/loom/internal/dataframe/spec" +) + +func filterLiteral(value FilterValue) (any, error) { + if err := value.Validate(); err != nil { + return nil, err + } + switch value.Kind { + case spec.FilterString: + return *value.String, nil + case spec.FilterCode: + return value.Code.Code, nil + case spec.FilterBoolean: + return *value.Boolean, nil + case spec.FilterInteger: + return *value.Integer, nil + case spec.FilterDecimal: + return *value.Decimal, nil + case spec.FilterDate: + return *value.Date, nil + case spec.FilterDateTime: + return *value.DateTime, nil + default: + return nil, fmt.Errorf("unsupported filter literal kind %q", value.Kind) + } +} diff --git a/internal/dataframe/compiler/generic_physical_plan.go b/internal/dataframe/compiler/lower/generic_plan.go similarity index 99% rename from internal/dataframe/compiler/generic_physical_plan.go rename to internal/dataframe/compiler/lower/generic_plan.go index e7d8d78..b3ff76b 100644 --- a/internal/dataframe/compiler/generic_physical_plan.go +++ b/internal/dataframe/compiler/lower/generic_plan.go @@ -1,4 +1,4 @@ -package compiler +package lower import ( "fmt" @@ -68,7 +68,7 @@ func BuildGenericPhysicalPlanWithPolicy(semantic SemanticPlan, policy PhysicalOp var walk func(parent SemanticNode, parentVariable, projectionPrefix string) error walk = func(parent SemanticNode, parentVariable, projectionPrefix string) error { for _, child := range parent.Children { - if child.MatchMode.required() { + if child.MatchMode.Required() { // Required routes are represented by the root semi-join emitted // above for membership, but they may still need a materialized // child set for selected fields or nested shaping. The second @@ -174,7 +174,7 @@ func physicalNodeNeedsMaterializedSet(node SemanticNode) bool { return true } for _, child := range node.Children { - if child.MatchMode.required() || physicalNodeNeedsMaterializedSet(child) { + if child.MatchMode.Required() || physicalNodeNeedsMaterializedSet(child) { return true } } diff --git a/internal/dataframe/compiler/lower/helpers.go b/internal/dataframe/compiler/lower/helpers.go new file mode 100644 index 0000000..ecda0c3 --- /dev/null +++ b/internal/dataframe/compiler/lower/helpers.go @@ -0,0 +1,69 @@ +package lower + +import ( + "os" + "strings" + + "github.com/calypr/loom/fhirschema" + "github.com/calypr/loom/internal/dataframe/compiler/ir" +) + +const ( + datasetGenerationBindKey = "dataset_generation" + datasetGenerationField = "dataset_generation" +) + +func datasetGenerationBindValue(generation string) any { + return ir.DatasetGenerationBindValue(generation) +} + +func sanitizeColumnName(in string) string { + var b strings.Builder + for _, r := range in { + if r >= 'a' && r <= 'z' || r >= 'A' && r <= 'Z' || r >= '0' && r <= '9' { + b.WriteRune(r) + } else { + b.WriteRune('_') + } + } + return b.String() +} + +func selectorHasNoArrays(sel Selector) bool { + for _, step := range sel.Steps { + if step.Iterate || step.Index != nil { + return false + } + } + return true +} + +func selectorHasIteratedArray(sel Selector) bool { + for _, step := range sel.Steps { + if step.Iterate { + return true + } + } + return false +} + +func selectorExecutionMode(resourceType string, selector Selector, fallbacks ...Selector) PhysicalSelectorExecutionMode { + switch strings.ToLower(strings.TrimSpace(os.Getenv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS"))) { + case "off", "0", "false", "disabled": + return PhysicalSelectorGeneric + } + if len(fallbacks) != 0 || selector.Filter != nil { + return PhysicalSelectorGeneric + } + metadata, ok := fhirschema.ResolveTerminalScalarMetadata(resourceType, selector.CanonicalPath()) + if !ok { + return PhysicalSelectorGeneric + } + if selectorHasNoArrays(selector) && !metadata.Repeated { + return PhysicalSelectorDirectScalar + } + if selectorHasIteratedArray(selector) && metadata.Repeated { + return PhysicalSelectorConditionalArray + } + return PhysicalSelectorGeneric +} diff --git a/internal/dataframe/compiler/physical_lowering.go b/internal/dataframe/compiler/lower/lowering.go similarity index 98% rename from internal/dataframe/compiler/physical_lowering.go rename to internal/dataframe/compiler/lower/lowering.go index 243d9a0..c67e189 100644 --- a/internal/dataframe/compiler/physical_lowering.go +++ b/internal/dataframe/compiler/lower/lowering.go @@ -1,4 +1,4 @@ -package compiler +package lower import "fmt" diff --git a/internal/dataframe/compiler/physical_required_match.go b/internal/dataframe/compiler/lower/required_match.go similarity index 99% rename from internal/dataframe/compiler/physical_required_match.go rename to internal/dataframe/compiler/lower/required_match.go index cdc37e6..f1b1646 100644 --- a/internal/dataframe/compiler/physical_required_match.go +++ b/internal/dataframe/compiler/lower/required_match.go @@ -1,4 +1,4 @@ -package compiler +package lower import ( "encoding/json" @@ -16,7 +16,7 @@ func appendRequiredTraversalMatchFilters(physical *PhysicalPlan, root SemanticNo walk = func(parent SemanticNode, route []SemanticNode) error { for _, child := range parent.Children { next := append(append([]SemanticNode(nil), route...), child) - if child.MatchMode.required() { + if child.MatchMode.Required() { // Two required children with the same physical route and typed // predicates are the same root semi-join even when their aliases // differ. Deduplicating this exact proof is safe: it does not diff --git a/internal/dataframe/compiler/lower/shape.go b/internal/dataframe/compiler/lower/shape.go new file mode 100644 index 0000000..9a0738d --- /dev/null +++ b/internal/dataframe/compiler/lower/shape.go @@ -0,0 +1,14 @@ +package lower + +func genericPhysicalPlanUnavailableReason(node SemanticNode) string { + return genericPhysicalNodeUnavailableReason(node) +} + +func genericPhysicalNodeUnavailableReason(node SemanticNode) string { + for _, child := range node.Children { + if reason := genericPhysicalNodeUnavailableReason(child); reason != "" { + return reason + } + } + return "" +} diff --git a/internal/dataframe/compiler/storage_route.go b/internal/dataframe/compiler/lower/storage_route.go similarity index 99% rename from internal/dataframe/compiler/storage_route.go rename to internal/dataframe/compiler/lower/storage_route.go index 3a19f90..45621f9 100644 --- a/internal/dataframe/compiler/storage_route.go +++ b/internal/dataframe/compiler/lower/storage_route.go @@ -1,4 +1,4 @@ -package compiler +package lower import ( "errors" diff --git a/internal/dataframe/compiler/lower_aliases.go b/internal/dataframe/compiler/lower_aliases.go new file mode 100644 index 0000000..dea757e --- /dev/null +++ b/internal/dataframe/compiler/lower_aliases.go @@ -0,0 +1,14 @@ +package compiler + +import "github.com/calypr/loom/internal/dataframe/compiler/lower" + +type StorageRoute = lower.StorageRoute + +var ( + BuildPhysicalPlan = lower.BuildPhysicalPlan + BuildPhysicalPlanWithPolicy = lower.BuildPhysicalPlanWithPolicy + BuildGenericPhysicalPlan = lower.BuildGenericPhysicalPlan + BuildGenericPhysicalPlanWithPolicy = lower.BuildGenericPhysicalPlanWithPolicy + ResolveStorageRoute = lower.ResolveStorageRoute + ErrUnsupportedStorageRoute = lower.ErrUnsupportedStorageRoute +) diff --git a/internal/dataframe/compiler/lowering_helpers.go b/internal/dataframe/compiler/lowering_helpers.go new file mode 100644 index 0000000..38d0bf9 --- /dev/null +++ b/internal/dataframe/compiler/lowering_helpers.go @@ -0,0 +1,16 @@ +package compiler + +// genericPhysicalPlanUnavailableReason is semantic-shape validation that +// remains in the compiler facade until the lowerer is extracted. +func genericPhysicalPlanUnavailableReason(node SemanticNode) string { + return genericPhysicalNodeUnavailableReason(node, true) +} + +func genericPhysicalNodeUnavailableReason(node SemanticNode, root bool) string { + for _, child := range node.Children { + if reason := genericPhysicalNodeUnavailableReason(child, false); reason != "" { + return reason + } + } + return "" +} diff --git a/internal/dataframe/compiler/optimization_helpers.go b/internal/dataframe/compiler/optimization_helpers.go new file mode 100644 index 0000000..c72bce8 --- /dev/null +++ b/internal/dataframe/compiler/optimization_helpers.go @@ -0,0 +1,10 @@ +package compiler + +func appendUniqueRule(rules []string, rule string) []string { + for _, existing := range rules { + if existing == rule { + return rules + } + } + return append(rules, rule) +} diff --git a/internal/dataframe/compiler/optimize/aliases.go b/internal/dataframe/compiler/optimize/aliases.go new file mode 100644 index 0000000..5ad8de6 --- /dev/null +++ b/internal/dataframe/compiler/optimize/aliases.go @@ -0,0 +1,100 @@ +package optimize + +import ( + "github.com/calypr/loom/internal/dataframe/compiler/ir" + "github.com/calypr/loom/internal/dataframe/spec" +) + +type ( + PhysicalPlan = ir.PhysicalPlan + PhysicalOperation = ir.PhysicalOperation + PhysicalOperationKind = ir.PhysicalOperationKind + PhysicalFilter = ir.PhysicalFilter + PhysicalDerivedLet = ir.PhysicalDerivedLet + PhysicalProjection = ir.PhysicalProjection + PhysicalReturn = ir.PhysicalReturn + PhysicalAggregate = ir.PhysicalAggregate + PhysicalPivotMap = ir.PhysicalPivotMap + PhysicalSlice = ir.PhysicalSlice + PhysicalSet = ir.PhysicalSet + PhysicalSetProjection = ir.PhysicalSetProjection + PhysicalSetProjectionField = ir.PhysicalSetProjectionField + PhysicalExpressionProjection = ir.PhysicalExpressionProjection + PhysicalPreparedReference = ir.PhysicalPreparedReference + PhysicalTraversal = ir.PhysicalTraversal + PhysicalTraversalPrefixDecomposition = ir.PhysicalTraversalPrefixDecomposition + PhysicalValue = ir.PhysicalValue + PhysicalExpression = ir.PhysicalExpression + PhysicalPredicateExpression = ir.PhysicalPredicateExpression + PhysicalPredicate = ir.PhysicalPredicate + PhysicalSubplan = ir.PhysicalSubplan + PhysicalOptimizationPolicy = ir.PhysicalOptimizationPolicy + PhysicalOptimizationRule = ir.PhysicalOptimizationRule + PhysicalOptimizationDecision = ir.PhysicalOptimizationDecision + Selector = spec.Selector +) + +const ( + PhysicalSetOp = ir.PhysicalSetOp + PhysicalFilterOp = ir.PhysicalFilterOp + PhysicalTraversalOp = ir.PhysicalTraversalOp + PhysicalOptimizationRuleTraversalSharing = ir.PhysicalOptimizationRuleTraversalSharing + PhysicalOptimizationRuleEndpointTraversal = ir.PhysicalOptimizationRuleEndpointTraversal + PhysicalTraversalEndpointLookup = ir.PhysicalTraversalEndpointLookup + PhysicalValueExpression = ir.PhysicalValueExpression + PhysicalObjectCardinality = ir.PhysicalObjectCardinality + PhysicalPreserveNull = ir.PhysicalPreserveNull + OptimizerRuleTraversalSharing = "share_identical_traversals" +) + +var ( + DefaultPhysicalOptimizationPolicy = ir.DefaultPhysicalOptimizationPolicy + DecomposePhysicalTraversalPrefix = ir.DecomposePhysicalTraversalPrefix +) + +func clonePhysicalPlan(plan PhysicalPlan) PhysicalPlan { return ir.ClonePhysicalPlan(plan) } +func clonePhysicalOperation(operation PhysicalOperation) PhysicalOperation { + return ir.ClonePhysicalOperation(operation) +} +func clonePhysicalOperations(operations []PhysicalOperation) []PhysicalOperation { + return ir.ClonePhysicalOperations(operations) +} +func clonePhysicalPredicateExpression(predicate PhysicalPredicateExpression) PhysicalPredicateExpression { + return ir.ClonePhysicalPredicateExpression(predicate) +} +func clonePhysicalSubplan(subplan PhysicalSubplan) PhysicalSubplan { + return ir.ClonePhysicalSubplan(subplan) +} + +func newPhysicalOptimizationReport(policy PhysicalOptimizationPolicy) ir.PhysicalOptimizationReport { + return ir.NewPhysicalOptimizationReport(policy) +} + +func estimateTraversalSharingWork(prefix PhysicalTraversalPrefixDecomposition, candidateSets int) (int, int, int) { + return ir.EstimateTraversalSharingWork(prefix, candidateSets) +} + +func sanitizeColumnName(in string) string { + var out []rune + for _, r := range in { + if r >= 'a' && r <= 'z' || r >= 'A' && r <= 'Z' || r >= '0' && r <= '9' { + out = append(out, r) + } else { + out = append(out, '_') + } + } + return string(out) +} + +type storageRoute struct{ Direction ir.PhysicalTraversalDirection } + +func (route storageRoute) endpointLookupFields() (string, string, []string, bool) { + switch route.Direction { + case ir.PhysicalInbound: + return "_to", "_from", []string{"_to", "project", "dataset_generation", "label", "from_type"}, true + case ir.PhysicalOutbound: + return "_from", "_to", []string{"_from", "project", "dataset_generation", "label", "to_type"}, true + default: + return "", "", nil, false + } +} diff --git a/internal/dataframe/compiler/optimize/doc.go b/internal/dataframe/compiler/optimize/doc.go new file mode 100644 index 0000000..4b760ba --- /dev/null +++ b/internal/dataframe/compiler/optimize/doc.go @@ -0,0 +1,3 @@ +// Package optimize applies explainable, semantics-preserving rewrites to +// typed physical IR. It never parses or edits rendered AQL. +package optimize diff --git a/internal/dataframe/compiler/physical_optimize.go b/internal/dataframe/compiler/optimize/optimize.go similarity index 98% rename from internal/dataframe/compiler/physical_optimize.go rename to internal/dataframe/compiler/optimize/optimize.go index 7d86b26..9c8c000 100644 --- a/internal/dataframe/compiler/physical_optimize.go +++ b/internal/dataframe/compiler/optimize/optimize.go @@ -1,4 +1,4 @@ -package compiler +package optimize import ( "fmt" @@ -61,7 +61,7 @@ func OptimizePhysicalPlanWithPolicy(plan PhysicalPlan, policy PhysicalOptimizati } if len(types) < 2 { decision.Reason = "candidate group has fewer than two target resource types" - out.OptimizationPolicy.addDecision(decision) + out.OptimizationPolicy.AddDecision(decision) continue } baseline, optimized, savings := estimateTraversalSharingWork(decompositions[indices[0]], len(indices)) @@ -74,22 +74,22 @@ func OptimizePhysicalPlanWithPolicy(plan PhysicalPlan, policy PhysicalOptimizati } else { decision.Reason = "traversal sharing rule disabled" } - out.OptimizationPolicy.addDecision(decision) + out.OptimizationPolicy.AddDecision(decision) continue } if savings < policy.MinimumSavings { decision.Reason = fmt.Sprintf("estimated savings %d is below policy minimum %d", savings, policy.MinimumSavings) - out.OptimizationPolicy.addDecision(decision) + out.OptimizationPolicy.AddDecision(decision) continue } if err := sharePhysicalSetGroup(&out, indices, types, decompositions, policy); err != nil { decision.Reason = "rewrite rejected: " + err.Error() - out.OptimizationPolicy.addDecision(decision) + out.OptimizationPolicy.AddDecision(decision) continue } decision.Enabled = true decision.Reason = "estimated prefix work reduction exceeds policy minimum" - out.OptimizationPolicy.addDecision(decision) + out.OptimizationPolicy.AddDecision(decision) } if err := out.Validate(); err != nil { return PhysicalPlan{}, fmt.Errorf("validate optimized physical plan: %w", err) diff --git a/internal/dataframe/compiler/optimize_aliases.go b/internal/dataframe/compiler/optimize_aliases.go new file mode 100644 index 0000000..5e95030 --- /dev/null +++ b/internal/dataframe/compiler/optimize_aliases.go @@ -0,0 +1,16 @@ +package compiler + +import ( + "fmt" + + "github.com/calypr/loom/internal/dataframe/compiler/optimize" +) + +var ( + OptimizePhysicalPlan = optimize.OptimizePhysicalPlan + OptimizePhysicalPlanWithPolicy = optimize.OptimizePhysicalPlanWithPolicy +) + +func valueString(value any) string { + return fmt.Sprint(value) +} diff --git a/internal/dataframe/compiler/physical_execution.go b/internal/dataframe/compiler/output.go similarity index 99% rename from internal/dataframe/compiler/physical_execution.go rename to internal/dataframe/compiler/output.go index 6919a37..fa47991 100644 --- a/internal/dataframe/compiler/physical_execution.go +++ b/internal/dataframe/compiler/output.go @@ -44,7 +44,7 @@ func physicalOptimizationRules(node SemanticNode) []string { rules = append(rules, OptimizerRuleFilterPushdown) } for _, child := range node.Children { - if child.MatchMode.required() { + if child.MatchMode.Required() { rules = appendUniqueRule(rules, OptimizerRuleRelationshipSemiJoin) } for _, rule := range physicalOptimizationRules(child) { diff --git a/internal/dataframe/compiler/physical_aliases.go b/internal/dataframe/compiler/physical_aliases.go new file mode 100644 index 0000000..f120bde --- /dev/null +++ b/internal/dataframe/compiler/physical_aliases.go @@ -0,0 +1,135 @@ +package compiler + +import "github.com/calypr/loom/internal/dataframe/compiler/ir" + +type ( + PhysicalPlan = ir.PhysicalPlan + PhysicalSource = ir.PhysicalSource + PhysicalOperationKind = ir.PhysicalOperationKind + PhysicalOperation = ir.PhysicalOperation + PhysicalRootScan = ir.PhysicalRootScan + PhysicalTraversalDirection = ir.PhysicalTraversalDirection + PhysicalTraversalStrategy = ir.PhysicalTraversalStrategy + PhysicalTraversal = ir.PhysicalTraversal + PhysicalValue = ir.PhysicalValue + PhysicalCardinality = ir.PhysicalCardinality + PhysicalNullBehavior = ir.PhysicalNullBehavior + PhysicalExpressionKind = ir.PhysicalExpressionKind + PhysicalSelectorExecutionMode = ir.PhysicalSelectorExecutionMode + PhysicalExpression = ir.PhysicalExpression + PhysicalExtract = ir.PhysicalExtract + PhysicalPreparedReference = ir.PhysicalPreparedReference + PhysicalPreparedSet = ir.PhysicalPreparedSet + PhysicalPreparedField = ir.PhysicalPreparedField + PhysicalAggregateOperation = ir.PhysicalAggregateOperation + PhysicalAggregate = ir.PhysicalAggregate + PhysicalPivotMap = ir.PhysicalPivotMap + PhysicalSlice = ir.PhysicalSlice + PhysicalExpressionProjection = ir.PhysicalExpressionProjection + PhysicalObject = ir.PhysicalObject + PhysicalSet = ir.PhysicalSet + PhysicalSetProjection = ir.PhysicalSetProjection + PhysicalSetProjectionField = ir.PhysicalSetProjectionField + PhysicalSetOutputField = ir.PhysicalSetOutputField + PhysicalSetOutput = ir.PhysicalSetOutput + PhysicalSubplan = ir.PhysicalSubplan + PhysicalPredicate = ir.PhysicalPredicate + PhysicalPredicateKind = ir.PhysicalPredicateKind + PhysicalPredicateExpression = ir.PhysicalPredicateExpression + PhysicalFilter = ir.PhysicalFilter + PhysicalDerivedLet = ir.PhysicalDerivedLet + PhysicalSort = ir.PhysicalSort + PhysicalLimit = ir.PhysicalLimit + PhysicalProjection = ir.PhysicalProjection + PhysicalReturn = ir.PhysicalReturn + PhysicalTraversalPrefix = ir.PhysicalTraversalPrefix + PhysicalTraversalSubset = ir.PhysicalTraversalSubset + PhysicalTraversalPrefixDecomposition = ir.PhysicalTraversalPrefixDecomposition + PhysicalTraversalPrefixRejectionReason = ir.PhysicalTraversalPrefixRejectionReason + PhysicalTraversalPrefixError = ir.PhysicalTraversalPrefixError + PhysicalOptimizationPolicy = ir.PhysicalOptimizationPolicy + PhysicalOptimizationRule = ir.PhysicalOptimizationRule + PhysicalOptimizationDecision = ir.PhysicalOptimizationDecision + PhysicalOptimizationReport = ir.PhysicalOptimizationReport + PhysicalOptimizationRuleState = ir.PhysicalOptimizationRuleState + CompilerPlanDiagnostics = ir.CompilerPlanDiagnostics + PhysicalTraversalDecision = ir.PhysicalTraversalDecision + RichSourceReuse = ir.RichSourceReuse + RichConsumerGroup = ir.RichConsumerGroup +) + +const ( + PhysicalRootScanOp = ir.PhysicalRootScanOp + PhysicalTraversalOp = ir.PhysicalTraversalOp + PhysicalFilterOp = ir.PhysicalFilterOp + PhysicalDerivedLetOp = ir.PhysicalDerivedLetOp + PhysicalSetOp = ir.PhysicalSetOp + PhysicalSortOp = ir.PhysicalSortOp + PhysicalLimitOp = ir.PhysicalLimitOp + PhysicalReturnOp = ir.PhysicalReturnOp + PhysicalInbound = ir.PhysicalInbound + PhysicalOutbound = ir.PhysicalOutbound + PhysicalAny = ir.PhysicalAny + PhysicalTraversalNative = ir.PhysicalTraversalNative + PhysicalTraversalEndpointLookup = ir.PhysicalTraversalEndpointLookup + PhysicalScalarCardinality = ir.PhysicalScalarCardinality + PhysicalArrayCardinality = ir.PhysicalArrayCardinality + PhysicalObjectCardinality = ir.PhysicalObjectCardinality + PhysicalPreserveNull = ir.PhysicalPreserveNull + PhysicalOmitNulls = ir.PhysicalOmitNulls + PhysicalEmptyOnNull = ir.PhysicalEmptyOnNull + PhysicalValueExpression = ir.PhysicalValueExpression + PhysicalExtractExpression = ir.PhysicalExtractExpression + PhysicalAggregateExpression = ir.PhysicalAggregateExpression + PhysicalPivotExpression = ir.PhysicalPivotExpression + PhysicalSliceExpression = ir.PhysicalSliceExpression + PhysicalObjectExpression = ir.PhysicalObjectExpression + PhysicalSelectorGeneric = ir.PhysicalSelectorGeneric + PhysicalSelectorDirectScalar = ir.PhysicalSelectorDirectScalar + PhysicalSelectorConditionalArray = ir.PhysicalSelectorConditionalArray + PhysicalCountAggregate = ir.PhysicalCountAggregate + PhysicalCountDistinctAggregate = ir.PhysicalCountDistinctAggregate + PhysicalExistsAggregate = ir.PhysicalExistsAggregate + PhysicalDistinctValuesAggregate = ir.PhysicalDistinctValuesAggregate + PhysicalMinAggregate = ir.PhysicalMinAggregate + PhysicalMaxAggregate = ir.PhysicalMaxAggregate + PhysicalFirstAggregate = ir.PhysicalFirstAggregate + PhysicalSetGraphIDField = ir.PhysicalSetGraphIDField + PhysicalSetKeyField = ir.PhysicalSetKeyField + PhysicalSetIDField = ir.PhysicalSetIDField + PhysicalSetResourceTypeField = ir.PhysicalSetResourceTypeField + PhysicalSetPayloadField = ir.PhysicalSetPayloadField + PhysicalComparisonPredicate = ir.PhysicalComparisonPredicate + PhysicalAllPredicate = ir.PhysicalAllPredicate + PhysicalAnyPredicate = ir.PhysicalAnyPredicate + PhysicalNotPredicate = ir.PhysicalNotPredicate + PhysicalExistsPredicate = ir.PhysicalExistsPredicate + PhysicalPrefixNotOptionalSet = ir.PhysicalPrefixNotOptionalSet + PhysicalPrefixSharedSubset = ir.PhysicalPrefixSharedSubset + PhysicalPrefixInvalidCapture = ir.PhysicalPrefixInvalidCapture + PhysicalPrefixMissingTraversal = ir.PhysicalPrefixMissingTraversal + PhysicalPrefixUnsupportedDirection = ir.PhysicalPrefixUnsupportedDirection + PhysicalPrefixInvalidRoute = ir.PhysicalPrefixInvalidRoute + PhysicalPrefixInvalidScope = ir.PhysicalPrefixInvalidScope + PhysicalPrefixInvalidTarget = ir.PhysicalPrefixInvalidTarget + PhysicalOptimizationRuleTraversalSharing = ir.PhysicalOptimizationRuleTraversalSharing + PhysicalOptimizationRulePreparedSelectors = ir.PhysicalOptimizationRulePreparedSelectors + PhysicalOptimizationRuleNestedSharing = ir.PhysicalOptimizationRuleNestedSharing + PhysicalOptimizationRuleRichConsumerFusion = ir.PhysicalOptimizationRuleRichConsumerFusion + PhysicalOptimizationRuleCompactProjection = ir.PhysicalOptimizationRuleCompactProjection + PhysicalOptimizationRuleEndpointTraversal = ir.PhysicalOptimizationRuleEndpointTraversal +) + +var ( + ValidateGenericPhysicalPlanScope = ir.ValidateGenericPhysicalPlanScope + DecomposePhysicalTraversalPrefix = ir.DecomposePhysicalTraversalPrefix + DefaultPhysicalOptimizationPolicy = ir.DefaultPhysicalOptimizationPolicy + NewPhysicalOptimizationReport = ir.NewPhysicalOptimizationReport + ClonePhysicalOptimizationReport = ir.ClonePhysicalOptimizationReport + EstimateTraversalSharingWork = ir.EstimateTraversalSharingWork + EstimatePreparedSelectorWork = ir.EstimatePreparedSelectorWork + NormalizeDatasetGeneration = ir.NormalizeDatasetGeneration + DatasetGenerationBindValue = ir.DatasetGenerationBindValue + PhysicalScopeWindowEnd = ir.PhysicalScopeWindowEnd + PhysicalPlanDiagnostics = ir.PhysicalPlanDiagnostics +) diff --git a/internal/dataframe/compiler/physical_clone_aliases.go b/internal/dataframe/compiler/physical_clone_aliases.go new file mode 100644 index 0000000..d9a6cd7 --- /dev/null +++ b/internal/dataframe/compiler/physical_clone_aliases.go @@ -0,0 +1,23 @@ +package compiler + +import "github.com/calypr/loom/internal/dataframe/compiler/ir" + +func clonePhysicalPlan(plan PhysicalPlan) PhysicalPlan { return ir.ClonePhysicalPlan(plan) } +func clonePhysicalOperation(operation PhysicalOperation) PhysicalOperation { + return ir.ClonePhysicalOperation(operation) +} +func clonePhysicalOperations(operations []PhysicalOperation) []PhysicalOperation { + return ir.ClonePhysicalOperations(operations) +} +func clonePhysicalPredicate(predicate PhysicalPredicate) PhysicalPredicate { + return ir.ClonePhysicalPredicate(predicate) +} +func clonePhysicalPredicateExpression(predicate PhysicalPredicateExpression) PhysicalPredicateExpression { + return ir.ClonePhysicalPredicateExpression(predicate) +} +func clonePhysicalExpression(expression PhysicalExpression) PhysicalExpression { + return ir.ClonePhysicalExpression(expression) +} +func clonePhysicalSubplan(subplan PhysicalSubplan) PhysicalSubplan { + return ir.ClonePhysicalSubplan(subplan) +} diff --git a/internal/dataframe/compiler/physical_scope_compat.go b/internal/dataframe/compiler/physical_scope_compat.go new file mode 100644 index 0000000..5187526 --- /dev/null +++ b/internal/dataframe/compiler/physical_scope_compat.go @@ -0,0 +1,23 @@ +package compiler + +// These small test-facing predicates preserve the historical same-package +// test vocabulary while scope validation now lives in compiler/ir. +func physicalPathEquals(left, right []string) bool { + if len(left) != len(right) { + return false + } + for i := range left { + if left[i] != right[i] { + return false + } + } + return true +} + +func isProjectScopePredicate(predicate PhysicalPredicate, variable string) bool { + return predicate.Operator == "EQUALS" && predicate.Left.Variable == variable && physicalPathEquals(predicate.Left.Path, []string{"project"}) && predicate.Right != nil && predicate.Right.BindKey == "project" +} + +func isScopeAllowedPredicate(predicate PhysicalPredicate, variable string) bool { + return predicate.Operator == "EQUALS" && predicate.Left.Variable == variable && predicate.Right != nil && predicate.Right.BindKey == "scope_allowed" +} diff --git a/internal/dataframe/compiler/physical_scope_constants.go b/internal/dataframe/compiler/physical_scope_constants.go new file mode 100644 index 0000000..a7266b9 --- /dev/null +++ b/internal/dataframe/compiler/physical_scope_constants.go @@ -0,0 +1,14 @@ +package compiler + +const ( + datasetGenerationBindKey = "dataset_generation" + datasetGenerationField = "dataset_generation" + physicalScopeProjectBind = "project" + physicalScopeAllowedBind = "scope_allowed" + physicalScopeAuthPathsBind = "auth_resource_paths" + physicalScopeAuthPathsUnrestrictedBind = "auth_resource_paths_unrestricted" + physicalScopeAuthPathField = "auth_resource_path" + physicalScopeProjectField = "project" + physicalScopeDatasetGenerationBind = datasetGenerationBindKey + physicalScopeDatasetGenerationField = datasetGenerationField +) diff --git a/internal/dataframe/compiler/render/aql/aliases.go b/internal/dataframe/compiler/render/aql/aliases.go new file mode 100644 index 0000000..138c4ae --- /dev/null +++ b/internal/dataframe/compiler/render/aql/aliases.go @@ -0,0 +1,120 @@ +package aql + +import ( + "github.com/calypr/loom/internal/dataframe/compiler/ir" + "github.com/calypr/loom/internal/dataframe/spec" +) + +type ( + PhysicalPlan = ir.PhysicalPlan + PhysicalSource = ir.PhysicalSource + PhysicalOperationKind = ir.PhysicalOperationKind + PhysicalOperation = ir.PhysicalOperation + PhysicalRootScan = ir.PhysicalRootScan + PhysicalTraversalDirection = ir.PhysicalTraversalDirection + PhysicalTraversalStrategy = ir.PhysicalTraversalStrategy + PhysicalTraversal = ir.PhysicalTraversal + PhysicalValue = ir.PhysicalValue + PhysicalCardinality = ir.PhysicalCardinality + PhysicalNullBehavior = ir.PhysicalNullBehavior + PhysicalExpressionKind = ir.PhysicalExpressionKind + PhysicalSelectorExecutionMode = ir.PhysicalSelectorExecutionMode + PhysicalExpression = ir.PhysicalExpression + PhysicalExtract = ir.PhysicalExtract + PhysicalPreparedReference = ir.PhysicalPreparedReference + PhysicalPreparedSet = ir.PhysicalPreparedSet + PhysicalPreparedField = ir.PhysicalPreparedField + PhysicalAggregateOperation = ir.PhysicalAggregateOperation + PhysicalAggregate = ir.PhysicalAggregate + PhysicalPivotMap = ir.PhysicalPivotMap + PhysicalSlice = ir.PhysicalSlice + PhysicalExpressionProjection = ir.PhysicalExpressionProjection + PhysicalObject = ir.PhysicalObject + PhysicalSet = ir.PhysicalSet + PhysicalSetProjection = ir.PhysicalSetProjection + PhysicalSetProjectionField = ir.PhysicalSetProjectionField + PhysicalSetOutputField = ir.PhysicalSetOutputField + PhysicalSetOutput = ir.PhysicalSetOutput + PhysicalSubplan = ir.PhysicalSubplan + PhysicalPredicate = ir.PhysicalPredicate + PhysicalPredicateKind = ir.PhysicalPredicateKind + PhysicalPredicateExpression = ir.PhysicalPredicateExpression + PhysicalFilter = ir.PhysicalFilter + PhysicalDerivedLet = ir.PhysicalDerivedLet + PhysicalSort = ir.PhysicalSort + PhysicalLimit = ir.PhysicalLimit + PhysicalProjection = ir.PhysicalProjection + PhysicalReturn = ir.PhysicalReturn + Selector = spec.Selector + SelectorStep = spec.SelectorStep + FilterValue = spec.FilterValue + FilterValueKind = spec.FilterValueKind +) + +const ( + FilterString = spec.FilterString + FilterCode = spec.FilterCode + FilterBoolean = spec.FilterBoolean + FilterInteger = spec.FilterInteger + FilterDecimal = spec.FilterDecimal + FilterDate = spec.FilterDate + FilterDateTime = spec.FilterDateTime + QuantifierAny = spec.QuantifierAny + QuantifierAll = spec.QuantifierAll + QuantifierNone = spec.QuantifierNone +) + +const ( + PhysicalRootScanOp = ir.PhysicalRootScanOp + PhysicalTraversalOp = ir.PhysicalTraversalOp + PhysicalFilterOp = ir.PhysicalFilterOp + PhysicalDerivedLetOp = ir.PhysicalDerivedLetOp + PhysicalSetOp = ir.PhysicalSetOp + PhysicalSortOp = ir.PhysicalSortOp + PhysicalLimitOp = ir.PhysicalLimitOp + PhysicalReturnOp = ir.PhysicalReturnOp + PhysicalInbound = ir.PhysicalInbound + PhysicalOutbound = ir.PhysicalOutbound + PhysicalTraversalNative = ir.PhysicalTraversalNative + PhysicalTraversalEndpointLookup = ir.PhysicalTraversalEndpointLookup + PhysicalScalarCardinality = ir.PhysicalScalarCardinality + PhysicalArrayCardinality = ir.PhysicalArrayCardinality + PhysicalObjectCardinality = ir.PhysicalObjectCardinality + PhysicalPreserveNull = ir.PhysicalPreserveNull + PhysicalOmitNulls = ir.PhysicalOmitNulls + PhysicalEmptyOnNull = ir.PhysicalEmptyOnNull + PhysicalValueExpression = ir.PhysicalValueExpression + PhysicalExtractExpression = ir.PhysicalExtractExpression + PhysicalAggregateExpression = ir.PhysicalAggregateExpression + PhysicalPivotExpression = ir.PhysicalPivotExpression + PhysicalSliceExpression = ir.PhysicalSliceExpression + PhysicalObjectExpression = ir.PhysicalObjectExpression + PhysicalSelectorGeneric = ir.PhysicalSelectorGeneric + PhysicalSelectorDirectScalar = ir.PhysicalSelectorDirectScalar + PhysicalSelectorConditionalArray = ir.PhysicalSelectorConditionalArray + PhysicalCountAggregate = ir.PhysicalCountAggregate + PhysicalCountDistinctAggregate = ir.PhysicalCountDistinctAggregate + PhysicalExistsAggregate = ir.PhysicalExistsAggregate + PhysicalDistinctValuesAggregate = ir.PhysicalDistinctValuesAggregate + PhysicalMinAggregate = ir.PhysicalMinAggregate + PhysicalMaxAggregate = ir.PhysicalMaxAggregate + PhysicalFirstAggregate = ir.PhysicalFirstAggregate + PhysicalSetGraphIDField = ir.PhysicalSetGraphIDField + PhysicalSetKeyField = ir.PhysicalSetKeyField + PhysicalSetIDField = ir.PhysicalSetIDField + PhysicalSetResourceTypeField = ir.PhysicalSetResourceTypeField + PhysicalSetPayloadField = ir.PhysicalSetPayloadField + PhysicalComparisonPredicate = ir.PhysicalComparisonPredicate + PhysicalAllPredicate = ir.PhysicalAllPredicate + PhysicalAnyPredicate = ir.PhysicalAnyPredicate + PhysicalNotPredicate = ir.PhysicalNotPredicate + PhysicalExistsPredicate = ir.PhysicalExistsPredicate +) + +const ( + genericPhysicalExecutionLimitBind = "limit" + datasetGenerationBindKey = "dataset_generation" + datasetGenerationField = "dataset_generation" +) + +var ValidateGenericPhysicalPlanScope = ir.ValidateGenericPhysicalPlanScope diff --git a/internal/dataframe/compiler/render/aql/doc.go b/internal/dataframe/compiler/render/aql/doc.go new file mode 100644 index 0000000..3235f06 --- /dev/null +++ b/internal/dataframe/compiler/render/aql/doc.go @@ -0,0 +1,3 @@ +// Package aql renders validated physical IR as deterministic, parameterized +// Arango AQL. It does not select FHIR routes or optimizer rules. +package aql diff --git a/internal/dataframe/compiler/filter_literal.go b/internal/dataframe/compiler/render/aql/filter_literal.go similarity index 98% rename from internal/dataframe/compiler/filter_literal.go rename to internal/dataframe/compiler/render/aql/filter_literal.go index e770bf0..fcf5b6b 100644 --- a/internal/dataframe/compiler/filter_literal.go +++ b/internal/dataframe/compiler/render/aql/filter_literal.go @@ -1,4 +1,4 @@ -package compiler +package aql import "fmt" diff --git a/internal/dataframe/compiler/physical_render.go b/internal/dataframe/compiler/render/aql/render.go similarity index 99% rename from internal/dataframe/compiler/physical_render.go rename to internal/dataframe/compiler/render/aql/render.go index 2297822..75a3df9 100644 --- a/internal/dataframe/compiler/physical_render.go +++ b/internal/dataframe/compiler/render/aql/render.go @@ -1,4 +1,4 @@ -package compiler +package aql import ( "fmt" @@ -116,6 +116,10 @@ func pruneUnusedRuntimeBindVars(bindVars map[string]any, query string) map[strin return pruned } +func PruneUnusedRuntimeBindVars(bindVars map[string]any, query string) map[string]any { + return pruneUnusedRuntimeBindVars(bindVars, query) +} + func (r *physicalPlanRenderer) renderRootWindowOperation(operation PhysicalOperation, indent string) ([]string, error) { switch operation.Kind { case PhysicalSortOp: diff --git a/internal/dataframe/compiler/selector_render.go b/internal/dataframe/compiler/render/aql/selector.go similarity index 83% rename from internal/dataframe/compiler/selector_render.go rename to internal/dataframe/compiler/render/aql/selector.go index b732ba1..6e67bcc 100644 --- a/internal/dataframe/compiler/selector_render.go +++ b/internal/dataframe/compiler/render/aql/selector.go @@ -1,9 +1,20 @@ -package compiler +package aql import ( "fmt" ) +func selectorStepText(step SelectorStep) string { + switch { + case step.Iterate: + return step.Field + "[]" + case step.Index != nil: + return fmt.Sprintf("%s[%d]", step.Field, *step.Index) + default: + return step.Field + } +} + // selectorHasNoArrays and the helpers below are shared by the physical // renderer and typed-filter compiler. They deliberately render only validated // Selector values and do not know anything about storage-plan representation. diff --git a/internal/dataframe/compiler/render_aliases.go b/internal/dataframe/compiler/render_aliases.go new file mode 100644 index 0000000..25ba87b --- /dev/null +++ b/internal/dataframe/compiler/render_aliases.go @@ -0,0 +1,7 @@ +package compiler + +import aql "github.com/calypr/loom/internal/dataframe/compiler/render/aql" + +type RenderedPhysicalPlan = aql.RenderedPhysicalPlan + +var RenderPhysicalPlan = aql.RenderPhysicalPlan diff --git a/internal/dataframe/compiler/render_test_compat.go b/internal/dataframe/compiler/render_test_compat.go new file mode 100644 index 0000000..082362e --- /dev/null +++ b/internal/dataframe/compiler/render_test_compat.go @@ -0,0 +1,7 @@ +package compiler + +import aql "github.com/calypr/loom/internal/dataframe/compiler/render/aql" + +func pruneUnusedRuntimeBindVars(bindVars map[string]any, query string) map[string]any { + return aql.PruneUnusedRuntimeBindVars(bindVars, query) +} diff --git a/internal/dataframe/compiler/selector_helpers.go b/internal/dataframe/compiler/selector_helpers.go index 9533844..4a68398 100644 --- a/internal/dataframe/compiler/selector_helpers.go +++ b/internal/dataframe/compiler/selector_helpers.go @@ -1,11 +1,36 @@ package compiler import ( + "fmt" "strings" "github.com/calypr/loom/fhirschema" ) +func selectorStepText(step SelectorStep) string { + switch { + case step.Iterate: + return step.Field + "[]" + case step.Index != nil: + return fmt.Sprintf("%s[%d]", step.Field, *step.Index) + default: + return step.Field + } +} + +func sanitizeColumnName(in string) string { + var b strings.Builder + for _, r := range in { + switch { + case r >= 'a' && r <= 'z', r >= 'A' && r <= 'Z', r >= '0' && r <= '9': + b.WriteRune(r) + default: + b.WriteRune('_') + } + } + return b.String() +} + func selectorSpecFromSelector(sel Selector) fhirschema.FieldSelectorSpec { sourcePath := "" valuePath := "" diff --git a/internal/dataframe/compiler/selector_identity_compat.go b/internal/dataframe/compiler/selector_identity_compat.go new file mode 100644 index 0000000..dca043a --- /dev/null +++ b/internal/dataframe/compiler/selector_identity_compat.go @@ -0,0 +1,24 @@ +package compiler + +import ( + "fmt" + "strings" +) + +func physicalSelectorIdentity(selector Selector) string { + var b strings.Builder + for _, step := range selector.Steps { + b.WriteString(step.Field) + if step.Iterate { + b.WriteString("[]") + } + if step.Index != nil { + fmt.Fprintf(&b, "[%d]", *step.Index) + } + b.WriteByte('.') + } + if selector.Filter != nil { + b.WriteString("?" + selector.Filter.Field + "=" + selector.Filter.Needle) + } + return b.String() +} diff --git a/internal/dataframe/compiler/selector_mode.go b/internal/dataframe/compiler/selector_mode.go new file mode 100644 index 0000000..a926a83 --- /dev/null +++ b/internal/dataframe/compiler/selector_mode.go @@ -0,0 +1,50 @@ +package compiler + +import ( + "os" + "strings" + + "github.com/calypr/loom/fhirschema" +) + +func selectorHasNoArrays(sel Selector) bool { + for _, step := range sel.Steps { + if step.Iterate || step.Index != nil { + return false + } + } + return true +} + +func selectorHasIteratedArray(sel Selector) bool { + for _, step := range sel.Steps { + if step.Iterate { + return true + } + } + return false +} + +// selectorExecutionMode is a physical lowering choice. Keeping it in the +// compiler facade during migration prevents semantic planning from depending +// on physical IR types; it will move with the lowerer in the next extraction. +func selectorExecutionMode(resourceType string, selector Selector, fallbacks ...Selector) PhysicalSelectorExecutionMode { + switch strings.ToLower(strings.TrimSpace(os.Getenv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS"))) { + case "off", "0", "false", "disabled": + return PhysicalSelectorGeneric + } + if len(fallbacks) != 0 || selector.Filter != nil { + return PhysicalSelectorGeneric + } + metadata, ok := fhirschema.ResolveTerminalScalarMetadata(resourceType, selector.CanonicalPath()) + if !ok { + return PhysicalSelectorGeneric + } + if selectorHasNoArrays(selector) && !metadata.Repeated { + return PhysicalSelectorDirectScalar + } + if selectorHasIteratedArray(selector) && metadata.Repeated { + return PhysicalSelectorConditionalArray + } + return PhysicalSelectorGeneric +} diff --git a/internal/dataframe/compiler/semantic_aliases.go b/internal/dataframe/compiler/semantic_aliases.go new file mode 100644 index 0000000..069cecb --- /dev/null +++ b/internal/dataframe/compiler/semantic_aliases.go @@ -0,0 +1,24 @@ +package compiler + +import "github.com/calypr/loom/internal/dataframe/semantic" + +type ( + SemanticPlan = semantic.SemanticPlan + SemanticNode = semantic.SemanticNode + SemanticField = semantic.SemanticField + SemanticPivot = semantic.SemanticPivot + SemanticAggregate = semantic.SemanticAggregate + SemanticSlice = semantic.SemanticSlice + SemanticPlanExplanation = semantic.SemanticPlanExplanation + SemanticNodeExplanation = semantic.SemanticNodeExplanation + SelectionSemanticSpec = semantic.SelectionSemanticSpec +) + +const MaxSemanticTraversalDepth = semantic.MaxSemanticTraversalDepth + +var ( + BuildSemanticPlan = semantic.BuildSemanticPlan + ValidateSemanticGraph = semantic.ValidateSemanticGraph + NormalizeSelectionPlan = semantic.NormalizeSelectionPlan + ResolveSemanticField = semantic.ResolveSemanticField +) diff --git a/internal/dataframe/compiler/spec_aliases.go b/internal/dataframe/compiler/spec_aliases.go new file mode 100644 index 0000000..fa6529d --- /dev/null +++ b/internal/dataframe/compiler/spec_aliases.go @@ -0,0 +1,83 @@ +package compiler + +// The compiler facade keeps the historical compiler symbols available while +// request contracts live in the independent spec package. These aliases are +// intentionally mechanical: the compiler does not own request semantics. +import "github.com/calypr/loom/internal/dataframe/spec" + +type ( + Builder = spec.Builder + TraversalStep = spec.TraversalStep + RepresentativeSlice = spec.RepresentativeSlice + FieldSelect = spec.FieldSelect + PivotSelect = spec.PivotSelect + AggregateSelect = spec.AggregateSelect + RowGrain = spec.RowGrain + ProjectionMode = spec.ProjectionMode + Cardinality = spec.Cardinality + RowIdentity = spec.RowIdentity + TraversalMatchMode = spec.TraversalMatchMode + FilterOperator = spec.FilterOperator + FilterValueKind = spec.FilterValueKind + ArrayQuantifier = spec.ArrayQuantifier + CodeValue = spec.CodeValue + FilterValue = spec.FilterValue + TypedFilter = spec.TypedFilter + Selector = spec.Selector + SelectorStep = spec.SelectorStep + ContainsFilter = spec.ContainsFilter +) + +const ( + RowGrainResource = spec.RowGrainResource + RowGrainPatient = spec.RowGrainPatient + RowGrainSpecimen = spec.RowGrainSpecimen + RowGrainFile = spec.RowGrainFile + RowGrainDiagnosis = spec.RowGrainDiagnosis + RowGrainObservation = spec.RowGrainObservation + RowGrainStudyEnrollment = spec.RowGrainStudyEnrollment + ProjectionScalar = spec.ProjectionScalar + ProjectionFirst = spec.ProjectionFirst + ProjectionArray = spec.ProjectionArray + ProjectionDistinctArray = spec.ProjectionDistinctArray + ProjectionAggregate = spec.ProjectionAggregate + ProjectionPivot = spec.ProjectionPivot + ProjectionExplode = spec.ProjectionExplode + CardinalityRequiredOne = spec.CardinalityRequiredOne + CardinalityOptionalOne = spec.CardinalityOptionalOne + CardinalityMany = spec.CardinalityMany + CardinalityUnknownObservedMany = spec.CardinalityUnknownObservedMany + TraversalMatchOptional = spec.TraversalMatchOptional + TraversalMatchRequired = spec.TraversalMatchRequired + FilterEquals = spec.FilterEquals + FilterNotEquals = spec.FilterNotEquals + FilterIn = spec.FilterIn + FilterExists = spec.FilterExists + FilterMissing = spec.FilterMissing + FilterContains = spec.FilterContains + FilterGreaterThan = spec.FilterGreaterThan + FilterGreaterEq = spec.FilterGreaterEq + FilterLessThan = spec.FilterLessThan + FilterLessEq = spec.FilterLessEq + FilterString = spec.FilterString + FilterCode = spec.FilterCode + FilterBoolean = spec.FilterBoolean + FilterInteger = spec.FilterInteger + FilterDecimal = spec.FilterDecimal + FilterDate = spec.FilterDate + FilterDateTime = spec.FilterDateTime + QuantifierAny = spec.QuantifierAny + QuantifierAll = spec.QuantifierAll + QuantifierNone = spec.QuantifierNone +) + +var ( + ParseSelector = spec.ParseSelector + ValidateTypedFilterForResource = spec.ValidateTypedFilterForResource + OperatorSupportsKind = spec.OperatorSupportsKind + InferRowGrain = spec.InferRowGrain + RootResourceForGrain = spec.RootResourceForGrain + ValidateRootGrain = spec.ValidateRootGrain + DefaultRowIdentity = spec.DefaultRowIdentity + ValidateProjection = spec.ValidateProjection +) diff --git a/internal/dataframe/compiler/traversal_projection_experiment_test.go b/internal/dataframe/compiler/traversal_projection_experiment_test.go deleted file mode 100644 index f70dea6..0000000 --- a/internal/dataframe/compiler/traversal_projection_experiment_test.go +++ /dev/null @@ -1,629 +0,0 @@ -package compiler - -// This file is deliberately an experiment. It models traversal-time shaping -// entirely in the test package by using the existing typed physical renderer: -// a relationship set returns one identity-plus-selector object and rich -// consumers read those selector fields directly. It does not change the -// production physical IR or renderer. - -import ( - "context" - "crypto/sha256" - "encoding/hex" - "encoding/json" - "fmt" - "os" - "path/filepath" - "runtime" - "sort" - "strings" - "testing" - "time" - - arangostore "github.com/calypr/loom/internal/store/arango" -) - -type traversalProjectionExperimentReport struct { - Sets int - EligibleSets int - ProjectedFields int - PayloadSets int - BaselinePayloads int - CandidatePayloads int - BaselineAQLHash string - CandidateAQLHash string -} - -// TestTraversalProjectionExperimentBuildsSingleShapedSets proves the -// candidate's structural contract against the real GDC compiler fixture. It -// intentionally does not enable a production policy switch: promotion is a -// coordinator decision after live parity/profile evidence. -func TestTraversalProjectionExperimentBuildsSingleShapedSets(t *testing.T) { - builder := loadTraversalProjectionGDCBuilder(t) - baseline, err := compileExperimentPhysicalPlan(builder) - if err != nil { - t.Fatal(err) - } - candidate, report, err := buildTraversalProjectionExperiment(baseline) - if err != nil { - t.Fatal(err) - } - renderedBaseline, err := RenderPhysicalPlan(baseline) - if err != nil { - t.Fatal(err) - } - renderedCandidate, err := RenderPhysicalPlan(candidate) - if err != nil { - t.Fatal(err) - } - report.BaselineAQLHash = sha256Hex(renderedBaseline.Query) - report.CandidateAQLHash = sha256Hex(renderedCandidate.Query) - t.Logf("WP3 traversal projection report: %+v", report) - t.Logf("baseline AQL:\n%s", renderedBaseline.Query) - t.Logf("candidate AQL:\n%s", renderedCandidate.Query) - - if report.Sets == 0 || report.EligibleSets == 0 || report.ProjectedFields == 0 { - t.Fatalf("experiment did not find eligible selector-bearing sets: %+v", report) - } - if report.CandidatePayloads >= report.BaselinePayloads { - t.Fatalf("candidate did not remove payload-bearing set returns: %+v", report) - } - if strings.Contains(renderedCandidate.Query, "_prepared = (") || strings.Contains(renderedCandidate.Query, "__loom_prepared_node") { - t.Fatalf("candidate introduced the rejected second prepared array:\n%s", renderedCandidate.Query) - } - if !strings.Contains(renderedCandidate.Query, "__loom_projection_") { - t.Fatalf("candidate did not render selector projection fields:\n%s", renderedCandidate.Query) - } - if strings.Contains(renderedCandidate.Query, "payload: ") { - t.Fatalf("eligible candidate still retains payload in a set return:\n%s", renderedCandidate.Query) - } - if err := candidate.Validate(); err != nil { - t.Fatalf("candidate physical plan does not validate: %v", err) - } -} - -// TestTraversalProjectionExperimentPreservesFallbackPayload is the required -// mixed-consumer safety case. A fallback selector cannot be represented by a -// single projected field, so the experiment leaves that set on the existing -// payload path and records it as an explicit rejection. -func TestTraversalProjectionExperimentPreservesFallbackPayload(t *testing.T) { - primary := Selector{Steps: []SelectorStep{{Field: "id"}}} - fallback := Selector{Steps: []SelectorStep{{Field: "code"}}} - plan, err := BuildPhysicalPlan(SemanticPlan{ - Version: 1, Project: "p", - Root: SemanticNode{Alias: "root", ResourceType: "Patient", Children: []SemanticNode{{ - Alias: "condition", ResourceType: "Condition", EdgeLabel: "subject_Patient", - Fields: []SemanticField{{Name: "status", Selector: primary, Fallbacks: []Selector{fallback}}}, - }}}, - }) - if err != nil { - t.Fatal(err) - } - candidate, report, err := buildTraversalProjectionExperiment(plan) - if err != nil { - t.Fatal(err) - } - if report.EligibleSets != 0 || report.PayloadSets != 1 { - t.Fatalf("fallback set was incorrectly projected: report=%+v", report) - } - rendered, err := RenderPhysicalPlan(candidate) - if err != nil { - t.Fatal(err) - } - if !strings.Contains(rendered.Query, "payload: ") { - t.Fatalf("fallback set lost payload retention:\n%s", rendered.Query) - } -} - -// TestTraversalProjectionExperimentProfilesGDC is opt-in because it reads the -// local META Arango fixture. It records parity, Explain/profile statistics, and -// five warm client timings for the exact 1,000-row GDC request. Set -// LOOM_WP3_WRITE_ARTIFACTS=1 to write the raw evidence directory. -func TestTraversalProjectionExperimentProfilesGDC(t *testing.T) { - if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { - t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run WP3 against Arango") - } - builder := loadTraversalProjectionGDCBuilder(t) - semantic, err := BuildSemanticPlan(builder) - if err != nil { - t.Fatal(err) - } - baselinePlan, err := BuildPhysicalPlan(semantic) - if err != nil { - t.Fatal(err) - } - baselinePlan, err = OptimizePhysicalPlan(baselinePlan) - if err != nil { - t.Fatal(err) - } - candidatePlan, report, err := buildTraversalProjectionExperiment(baselinePlan) - if err != nil { - t.Fatal(err) - } - baseline, err := compilePhysicalExecution(baselinePlan, semantic, 1000) - if err != nil { - t.Fatal(err) - } - candidate, err := compilePhysicalExecution(candidatePlan, semantic, 1000) - if err != nil { - t.Fatal(err) - } - url, database, _ := compilerArangoTarget() - client, err := arangostore.Open(context.Background(), url, database) - if err != nil { - t.Fatal(err) - } - defer client.Close(context.Background()) - ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute) - defer cancel() - baselineProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: baseline.Query, BindVars: baseline.BindVars, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - t.Fatalf("baseline PROFILE: %v", err) - } - candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidate.Query, BindVars: candidate.BindVars, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - t.Fatalf("candidate PROFILE: %v", err) - } - baselineHash := hashRawRows(baselineProfile.Result) - candidateHash := hashRawRows(candidateProfile.Result) - if baselineHash != candidateHash { - t.Logf("first result difference: %s", firstRawDifference(baselineProfile.Result, candidateProfile.Result)) - if os.Getenv("LOOM_WP3_WRITE_ARTIFACTS") != "" { - writeTraversalProjectionArtifacts(t, report, baseline, candidate, baselineHash, baselineProfile, candidateProfile, nil, nil) - } - t.Fatalf("result parity mismatch: baseline=%s candidate=%s", baselineHash, candidateHash) - } - baselineWarm := profileWarmQuery(ctx, client, baseline) - candidateWarm := profileWarmQuery(ctx, client, candidate) - baselineSummary := arangostore.SummarizeProfile(baselineProfile) - candidateSummary := arangostore.SummarizeProfile(candidateProfile) - report.BaselineAQLHash = sha256Hex(baseline.Query) - report.CandidateAQLHash = sha256Hex(candidate.Query) - t.Logf("WP3 live report: report=%+v baseline_hash=%s candidate_hash=%s baseline_profile=%+v candidate_profile=%+v baseline_warm=%v candidate_warm=%v", report, baselineHash, candidateHash, baselineSummary, candidateSummary, baselineWarm, candidateWarm) - if os.Getenv("LOOM_WP3_WRITE_ARTIFACTS") != "" { - writeTraversalProjectionArtifacts(t, report, baseline, candidate, baselineHash, baselineProfile, candidateProfile, baselineWarm, candidateWarm) - } -} - -func profileWarmQuery(ctx context.Context, client *arangostore.Client, compiled CompiledQuery) []float64 { - times := make([]float64, 0, 5) - for run := 0; run < 5; run++ { - started := time.Now() - _ = client.QueryRows(ctx, compiled.Query, 10000, compiled.BindVars, func(map[string]any) error { return nil }) - times = append(times, time.Since(started).Seconds()) - } - return times -} - -func hashRawRows(rows []json.RawMessage) string { - hash := sha256.New() - for _, row := range rows { - var value any - if json.Unmarshal(row, &value) != nil { - continue - } - canonical, err := json.Marshal(value) - if err != nil { - continue - } - _, _ = hash.Write(canonical) - _, _ = hash.Write([]byte{'\n'}) - } - return hex.EncodeToString(hash.Sum(nil)) -} - -func firstRawDifference(left, right []json.RawMessage) string { - if len(left) != len(right) { - return fmt.Sprintf("row count baseline=%d candidate=%d", len(left), len(right)) - } - for index := range left { - var leftValue, rightValue any - if json.Unmarshal(left[index], &leftValue) != nil || json.Unmarshal(right[index], &rightValue) != nil { - continue - } - leftJSON, _ := json.Marshal(leftValue) - rightJSON, _ := json.Marshal(rightValue) - if string(leftJSON) != string(rightJSON) { - return fmt.Sprintf("row=%d baseline=%s candidate=%s", index, leftJSON, rightJSON) - } - } - return "hash-only difference (JSON rows compare equal)" -} - -func writeTraversalProjectionArtifacts(t *testing.T, report traversalProjectionExperimentReport, baseline, candidate CompiledQuery, resultHash string, baselineProfile, candidateProfile arangostore.ProfileResult, baselineWarm, candidateWarm []float64) { - _, source, _, _ := runtime.Caller(0) - directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round3", "wp3") - if err := os.MkdirAll(directory, 0o755); err != nil { - t.Fatalf("create WP3 artifact directory: %v", err) - } - if err := os.WriteFile(filepath.Join(directory, "baseline.aql"), []byte(baseline.Query), 0o644); err != nil { - t.Fatalf("write baseline AQL: %v", err) - } - if err := os.WriteFile(filepath.Join(directory, "candidate.aql"), []byte(candidate.Query), 0o644); err != nil { - t.Fatalf("write candidate AQL: %v", err) - } - payload := map[string]any{ - "report": report, "result_hash": resultHash, - "baseline_profile": baselineProfile, "candidate_profile": candidateProfile, - "baseline_warm_seconds": baselineWarm, "candidate_warm_seconds": candidateWarm, - "decision": "pending coordinator live gate", - } - data, err := json.MarshalIndent(payload, "", " ") - if err != nil { - t.Fatalf("encode WP3 artifact: %v", err) - } - if err := os.WriteFile(filepath.Join(directory, "evidence.json"), append(data, '\n'), 0o644); err != nil { - t.Fatalf("write WP3 evidence: %v", err) - } -} - -func compileExperimentPhysicalPlan(builder Builder) (PhysicalPlan, error) { - semantic, err := BuildSemanticPlan(builder) - if err != nil { - return PhysicalPlan{}, err - } - physical, err := BuildPhysicalPlan(semantic) - if err != nil { - return PhysicalPlan{}, err - } - return OptimizePhysicalPlan(physical) -} - -type experimentSelector struct { - key string - selector Selector - field string -} - -// buildTraversalProjectionExperiment rewrites only the cloned plan. It uses -// PreparedReference as a test-only field reference; unlike PhysicalPreparedSet -// it points back to the owning set itself, so no second array is rendered. -func buildTraversalProjectionExperiment(plan PhysicalPlan) (PhysicalPlan, traversalProjectionExperimentReport, error) { - candidate := clonePhysicalPlan(plan) - // clonePhysicalPlan intentionally predates object-bearing return trees and - // keeps PhysicalProjection.Expression pointers shared. Detach them here so - // the experiment cannot mutate the baseline plan while annotating candidate - // consumers with projected-field references. - for index := range candidate.Operations { - operation := &candidate.Operations[index] - if operation.Kind != PhysicalReturnOp || operation.Return == nil { - continue - } - for projectionIndex := range operation.Return.Projections { - if operation.Return.Projections[projectionIndex].Expression == nil { - continue - } - expression := cloneExperimentExpression(*operation.Return.Projections[projectionIndex].Expression) - operation.Return.Projections[projectionIndex].Expression = &expression - } - } - report := traversalProjectionExperimentReport{} - for index := range candidate.Operations { - op := &candidate.Operations[index] - if op.Kind != PhysicalSetOp || op.Set == nil { - continue - } - report.Sets++ - set := op.Set - selectors, fallback := collectSetSelectors(candidate, set.Variable) - if fallback { - continue - } - if len(selectors) == 0 { - continue - } - report.EligibleSets++ - target := setTargetVariable(*set) - if target == "" { - return PhysicalPlan{}, report, fmt.Errorf("set %q has no target variable", set.Variable) - } - fields := make([]PhysicalExpressionProjection, 0, len(selectors)+4) - resourceType := op.Source.ResourceType - if resourceType == "" { - resourceType = setResourceType(candidate, *set) - } - if resourceType == "" { - return PhysicalPlan{}, report, fmt.Errorf("set %q has no resource type", set.Variable) - } - for _, name := range []string{"_id", "_key", "id", "resourceType"} { - fields = append(fields, PhysicalExpressionProjection{ - Name: name, - Expression: PhysicalExpression{Kind: PhysicalValueExpression, Cardinality: PhysicalScalarCardinality, NullBehavior: PhysicalPreserveNull, Value: &PhysicalValue{Variable: target, Path: []string{name}}}, - }) - } - for selectorIndex := range selectors { - selector := &selectors[selectorIndex] - field := fmt.Sprintf("__loom_projection_%d", report.ProjectedFields) - selector.field = field - fields = append(fields, PhysicalExpressionProjection{ - Name: field, - Expression: PhysicalExpression{Kind: PhysicalExtractExpression, Cardinality: PhysicalArrayCardinality, NullBehavior: PhysicalEmptyOnNull, Extract: &PhysicalExtract{ - Source: PhysicalValue{Variable: target, Path: []string{"payload"}}, ResourceType: resourceType, Selector: selector.selector, - }}, - }) - report.ProjectedFields++ - } - set.Subplan.Return = PhysicalExpression{Kind: PhysicalObjectExpression, Cardinality: PhysicalObjectCardinality, NullBehavior: PhysicalPreserveNull, Object: &PhysicalObject{Fields: fields}} - set.Output = nil - set.Prepared = nil - for projectionIndex := range candidate.Operations { - operation := &candidate.Operations[projectionIndex] - if operation.Kind != PhysicalReturnOp || operation.Return == nil { - continue - } - for expressionIndex := range operation.Return.Projections { - expression := operation.Return.Projections[expressionIndex].Expression - rewriteProjectionExpression(expression, set.Variable, selectors) - } - } - } - // The baseline payload count is measured from the original plan's compact - // output, not the rewritten candidate. - for _, operation := range plan.Operations { - if operation.Kind == PhysicalSetOp && operation.Set != nil { - if operation.Set.Output == nil { - report.BaselinePayloads++ - continue - } - for _, field := range operation.Set.Output.Fields { - if field == PhysicalSetPayloadField { - report.BaselinePayloads++ - break - } - } - } - } - for _, operation := range candidate.Operations { - if operation.Kind != PhysicalSetOp || operation.Set == nil { - continue - } - if operation.Set.Output != nil { - for _, field := range operation.Set.Output.Fields { - if field == PhysicalSetPayloadField { - report.CandidatePayloads++ - break - } - } - } - if operation.Set.Subplan.Return.Object != nil { - for _, field := range operation.Set.Subplan.Return.Object.Fields { - if field.Name == string(PhysicalSetPayloadField) { - report.CandidatePayloads++ - break - } - } - } - } - report.PayloadSets = report.BaselinePayloads - return candidate, report, candidate.Validate() -} - -// cloneExperimentExpression fills the deep-copy gaps in the production clone -// helper for nested rich expressions. The experiment must not annotate the -// baseline's Slice.Predicate or Slice.Projections while preparing a candidate. -func cloneExperimentExpression(expression PhysicalExpression) PhysicalExpression { - copy := clonePhysicalExpression(expression) - if expression.Aggregate != nil { - aggregate := *copy.Aggregate - if expression.Aggregate.Value != nil { - value := cloneExperimentExpression(*expression.Aggregate.Value) - aggregate.Value = &value - } - if expression.Aggregate.Predicate != nil { - predicate := cloneExperimentPredicateExpression(*expression.Aggregate.Predicate) - aggregate.Predicate = &predicate - } - copy.Aggregate = &aggregate - } - if expression.Slice != nil { - slice := *copy.Slice - if expression.Slice.Predicate != nil { - predicate := cloneExperimentPredicateExpression(*expression.Slice.Predicate) - slice.Predicate = &predicate - } - slice.Projections = make([]PhysicalExpressionProjection, len(expression.Slice.Projections)) - for index, projection := range expression.Slice.Projections { - slice.Projections[index] = projection - slice.Projections[index].Expression = cloneExperimentExpression(projection.Expression) - } - copy.Slice = &slice - } - if expression.Object != nil { - object := *copy.Object - object.Fields = make([]PhysicalExpressionProjection, len(expression.Object.Fields)) - for index, field := range expression.Object.Fields { - object.Fields[index] = field - object.Fields[index].Expression = cloneExperimentExpression(field.Expression) - } - copy.Object = &object - } - return copy -} - -func cloneExperimentPredicateExpression(predicate PhysicalPredicateExpression) PhysicalPredicateExpression { - copy := predicate - if predicate.Comparison != nil { - comparison := clonePhysicalPredicate(*predicate.Comparison) - if predicate.Comparison.LeftExpression != nil { - left := cloneExperimentExpression(*predicate.Comparison.LeftExpression) - comparison.LeftExpression = &left - } - copy.Comparison = &comparison - } - if predicate.Exists != nil { - exists := clonePhysicalSubplan(*predicate.Exists) - copy.Exists = &exists - } - copy.Children = make([]PhysicalPredicateExpression, len(predicate.Children)) - for index, child := range predicate.Children { - copy.Children[index] = cloneExperimentPredicateExpression(child) - } - return copy -} - -func setTargetVariable(set PhysicalSet) string { - if set.SourceSetVariable != "" { - return set.ItemVariable - } - if len(set.Subplan.Operations) == 0 || set.Subplan.Operations[0].Traversal == nil { - return "" - } - return set.Subplan.Operations[0].Traversal.TargetVariable -} - -func setResourceType(plan PhysicalPlan, set PhysicalSet) string { - if len(set.Subplan.Operations) > 0 && set.Subplan.Operations[0].Traversal != nil { - traversal := set.Subplan.Operations[0].Traversal - if value, ok := plan.BindVars[traversal.TargetTypeBindKey].(string); ok { - return value - } - if values, ok := plan.BindVars[traversal.TargetTypeBindKey].([]string); ok && len(values) == 1 { - return values[0] - } - } - return "" -} - -func collectSetSelectors(plan PhysicalPlan, setVariable string) ([]experimentSelector, bool) { - byKey := map[string]Selector{} - fallback := false - var collect func(*PhysicalExpression) - collect = func(expression *PhysicalExpression) { - if expression == nil { - return - } - switch expression.Kind { - case PhysicalExtractExpression: - if expression.Extract != nil && expression.Extract.Source.Variable == setVariable { - if len(expression.Extract.Fallbacks) > 0 { - fallback = true - } else { - byKey[physicalSelectorIdentity(expression.Extract.Selector)] = expression.Extract.Selector - } - } - case PhysicalAggregateExpression: - if expression.Aggregate != nil { - collect(expression.Aggregate.Value) - if expression.Aggregate.Predicate != nil && expression.Aggregate.Predicate.Comparison != nil { - collect(expression.Aggregate.Predicate.Comparison.LeftExpression) - } - } - case PhysicalPivotExpression: - if expression.Pivot != nil && expression.Pivot.Source.Variable == setVariable { - byKey[physicalSelectorIdentity(expression.Pivot.KeySelector)] = expression.Pivot.KeySelector - byKey[physicalSelectorIdentity(expression.Pivot.ValueSelector)] = expression.Pivot.ValueSelector - } - case PhysicalSliceExpression: - if expression.Slice != nil { - collect(expression.Slice.Sort) - if expression.Slice.Predicate != nil && expression.Slice.Predicate.Comparison != nil { - collect(expression.Slice.Predicate.Comparison.LeftExpression) - } - for index := range expression.Slice.Projections { - collect(&expression.Slice.Projections[index].Expression) - } - } - case PhysicalObjectExpression: - if expression.Object != nil { - for index := range expression.Object.Fields { - collect(&expression.Object.Fields[index].Expression) - } - } - } - } - for index := range plan.Operations { - operation := &plan.Operations[index] - if operation.Kind != PhysicalReturnOp || operation.Return == nil { - continue - } - for projectionIndex := range operation.Return.Projections { - collect(operation.Return.Projections[projectionIndex].Expression) - } - } - keys := make([]string, 0, len(byKey)) - for key := range byKey { - keys = append(keys, key) - } - sort.Strings(keys) - selectors := make([]experimentSelector, 0, len(keys)) - for _, key := range keys { - selectors = append(selectors, experimentSelector{key: key, selector: byKey[key]}) - } - return selectors, fallback -} - -func rewriteProjectionExpression(expression *PhysicalExpression, setVariable string, selectors []experimentSelector) { - if expression == nil { - return - } - fieldFor := func(selector Selector) string { - key := physicalSelectorIdentity(selector) - for _, candidate := range selectors { - if candidate.key == key { - return candidate.field - } - } - return "" - } - switch expression.Kind { - case PhysicalExtractExpression: - if expression.Extract != nil && expression.Extract.Source.Variable == setVariable && len(expression.Extract.Fallbacks) == 0 { - if field := fieldFor(expression.Extract.Selector); field != "" { - expression.Extract.Prepared = &PhysicalPreparedReference{SetVariable: setVariable, Field: field} - } - } - case PhysicalAggregateExpression: - if expression.Aggregate != nil { - rewriteProjectionExpression(expression.Aggregate.Value, setVariable, selectors) - if expression.Aggregate.Predicate != nil && expression.Aggregate.Predicate.Comparison != nil { - rewriteProjectionExpression(expression.Aggregate.Predicate.Comparison.LeftExpression, setVariable, selectors) - } - } - case PhysicalPivotExpression: - if expression.Pivot != nil && expression.Pivot.Source.Variable == setVariable { - if field := fieldFor(expression.Pivot.KeySelector); field != "" { - expression.Pivot.PreparedKey = &PhysicalPreparedReference{SetVariable: setVariable, Field: field} - } - if field := fieldFor(expression.Pivot.ValueSelector); field != "" { - expression.Pivot.PreparedValue = &PhysicalPreparedReference{SetVariable: setVariable, Field: field} - } - } - case PhysicalSliceExpression: - if expression.Slice != nil { - rewriteProjectionExpression(expression.Slice.Sort, setVariable, selectors) - if expression.Slice.Predicate != nil && expression.Slice.Predicate.Comparison != nil { - rewriteProjectionExpression(expression.Slice.Predicate.Comparison.LeftExpression, setVariable, selectors) - } - for index := range expression.Slice.Projections { - rewriteProjectionExpression(&expression.Slice.Projections[index].Expression, setVariable, selectors) - } - } - case PhysicalObjectExpression: - if expression.Object != nil { - for index := range expression.Object.Fields { - rewriteProjectionExpression(&expression.Object.Fields[index].Expression, setVariable, selectors) - } - } - } -} - -func loadTraversalProjectionGDCBuilder(t *testing.T) Builder { - _, source, _, _ := runtime.Caller(0) - path := filepath.Join(filepath.Dir(source), "..", "..", "..", "conformance", "compiler", "fixtures", "gdc-case-matrix.json") - data, err := os.ReadFile(path) - if err != nil { - t.Fatalf("read GDC fixture %q: %v", path, err) - } - var fixture struct { - Builder Builder `json:"builder"` - } - if err := json.Unmarshal(data, &fixture); err != nil { - t.Fatalf("decode GDC fixture: %v", err) - } - return fixture.Builder -} - -func sha256Hex(value string) string { - hash := sha256.Sum256([]byte(value)) - return hex.EncodeToString(hash[:]) -} diff --git a/internal/dataframe/doc.go b/internal/dataframe/doc.go new file mode 100644 index 0000000..677d878 --- /dev/null +++ b/internal/dataframe/doc.go @@ -0,0 +1,7 @@ +// Package dataframe is Loom's stable dataframe facade. +// +// Request contracts live in spec, schema-backed planning in semantic, physical +// planning in compiler, and catalog-aware execution in runtime. This package +// intentionally contains aliases and small compatibility entrypoints only; +// new implementation code belongs in the owning subpackage. +package dataframe diff --git a/internal/dataframe/endpoint_selector_combo_experiment_test.go b/internal/dataframe/endpoint_selector_combo_experiment_test.go deleted file mode 100644 index b30d5b2..0000000 --- a/internal/dataframe/endpoint_selector_combo_experiment_test.go +++ /dev/null @@ -1,376 +0,0 @@ -package dataframe_test - -// This is a read-only, opt-in tournament harness. It composes the two -// previously measured test-only rewrites (WP2 endpoint equality and WP4 -// selector lowering) after compiling the real GraphQL input through -// BuilderFromInput. It does not alter compiler IR or production rendering. - -import ( - "context" - "encoding/json" - "fmt" - "os" - "path/filepath" - "regexp" - "runtime" - "strings" - "testing" - "time" - - dataframe "github.com/calypr/loom/internal/dataframe" - arangostore "github.com/calypr/loom/internal/store/arango" -) - -type endpointSelectorComboRun struct { - Name string `json:"name"` - QuerySHA256 string `json:"query_sha256"` - ResultSHA256 string `json:"result_sha256"` - Rows int `json:"rows"` - Bytes []int `json:"bytes"` - WarmSeconds []float64 `json:"warm_seconds"` - MedianSeconds float64 `json:"median_seconds"` - MinSeconds float64 `json:"min_seconds"` - Explain arangostore.ExplainAssessment `json:"explain"` - Profile endpointSelectorProfileSummary `json:"profile"` -} - -type endpointSelectorProfileSummary struct { - ScannedFull int `json:"scanned_full"` - ScannedIndex int `json:"scanned_index"` - PeakMemoryBytes uint64 `json:"peak_memory_bytes"` - Phases arangostore.ProfilePhases `json:"phases"` - TopNodes []arangostore.ProfileNodeSummary `json:"top_nodes"` -} - -// TestEndpointSelectorComboRendersActualGDC is compile-safe and does not need -// Arango. It proves the composition starts with BuilderFromInput, rewrites all -// three eligible nested routes, and retains bind-backed AQL. -func TestEndpointSelectorComboRendersActualGDC(t *testing.T) { - compiled := compileActualGDC(t, 1000) - compiled = pinComboControlIfCompilerMoved(t, compiled) - endpointOnly, routes, err := prepareEndpointSelectorBase(compiled.Query) - if err != nil { - t.Fatal(err) - } - if len(routes) != 3 { - t.Fatalf("rewrote %d nested routes, want 3: %#v", len(routes), routes) - } - combo, lowering, err := lowerRenderedSelectorExpressions(endpointOnly) - if err != nil { - t.Fatalf("lower selectors after endpoint rewrite: %v", err) - } - if lowering.LoweredSubqueries == 0 { - t.Fatalf("combined candidate lowered no selectors: %+v", lowering) - } - if strings.Contains(combo, "IN 1..1 INBOUND __loom_physical_parent_set") || strings.Contains(combo, "IN 1..1 OUTBOUND __loom_physical_parent_set") { - t.Fatalf("combined candidate retained a nested native traversal:\n%s", combo) - } - if !strings.Contains(combo, "FILTER child_set_3_edge._to == __loom_physical_parent_set_4._id") || - !strings.Contains(combo, "FILTER child_set_4_edge._to == __loom_physical_parent_set_5._id") || - !strings.Contains(combo, "FILTER child_set_5_edge._to == __loom_physical_parent_set_6._id") { - t.Fatalf("combined candidate omitted one endpoint equality routes=%#v has3=%t has4=%t has5=%t\n%s", routes, strings.Contains(combo, "FILTER child_set_3_edge._to == __loom_physical_parent_set_4._id"), strings.Contains(combo, "FILTER child_set_4_edge._to == __loom_physical_parent_set_5._id"), strings.Contains(combo, "FILTER child_set_5_edge._to == __loom_physical_parent_set_6._id"), combo[:minComboLen(len(combo), 7000)]) - } - if !strings.Contains(combo, "@@child_set_3_edge_collection") || !strings.Contains(combo, "@project") { - t.Fatalf("combined candidate lost collection or value binds") - } -} - -func minComboLen(length, maximum int) int { - if length < maximum { - return length - } - return maximum -} - -// pinComboControlIfCompilerMoved protects this experiment from concurrent -// production renderer work. BuilderFromInput is still executed first; when -// its AQL no longer matches the locked WP2 control, the exact previously -// profiled AQL and bind variables are used so the comparison does not mix -// compiler baselines. -func pinComboControlIfCompilerMoved(t *testing.T, compiled dataframe.CompiledQuery) dataframe.CompiledQuery { - const expectedAQLSHA = "4081527f4d893c7fc8b4957ad75ffbf51a975a8b646c315f01d09093444aad68" - const integratedAQLSHA = "988775e708a0f836ed34de0815e74cdbf38172e75c12a80149a9ce6096b48925" - if sha256Hex(compiled.Query) == expectedAQLSHA || sha256Hex(compiled.Query) == integratedAQLSHA { - return compiled - } - t.Logf("BuilderFromInput control AQL changed during concurrent integration (got %s); pinning WP2 control %s", sha256Hex(compiled.Query), expectedAQLSHA) - _, source, _, _ := runtime.Caller(0) - root := filepath.Join(filepath.Dir(source), "..", "..") - queryPath := filepath.Join(root, "docs", "benchmarks", "round4", "wp2", "production.aql") - reportPath := filepath.Join(root, "docs", "benchmarks", "round4", "wp2", "production.json") - queryBytes, err := os.ReadFile(queryPath) - if err != nil { - t.Fatalf("read pinned control AQL: %v", err) - } - query := strings.TrimSuffix(strings.TrimSuffix(string(queryBytes), "\n"), "\r") - if sha256Hex(query) != expectedAQLSHA { - t.Fatalf("pinned control AQL hash changed: got %s want %s", sha256Hex(query), expectedAQLSHA) - } - reportBytes, err := os.ReadFile(reportPath) - if err != nil { - t.Fatalf("read pinned control bind vars: %v", err) - } - var report struct { - BindVars map[string]any `json:"bind_vars"` - } - if err := json.Unmarshal(reportBytes, &report); err != nil { - t.Fatalf("decode pinned control bind vars: %v", err) - } - return dataframe.CompiledQuery{Query: query, BindVars: report.BindVars, Limit: 1000} -} - -// TestEndpointSelectorComboProfilesActualGDC is deliberately opt-in. It -// alternates unchanged production control and the composed candidate, consumes -// every row, then captures Explain/Profile and raw artifacts. The endpoint-only -// median is run separately to answer whether selector lowering compounds the -// proven WP2 4.211s result. -func TestEndpointSelectorComboProfilesActualGDC(t *testing.T) { - if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { - t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run endpoint/selector combo against Arango") - } - compiled := compileActualGDC(t, 1000) - compiled = pinComboControlIfCompilerMoved(t, compiled) - endpointOnly, routes, err := prepareEndpointSelectorBase(compiled.Query) - if err != nil { - t.Fatal(err) - } - if len(routes) != 3 { - t.Fatalf("rewrote %d nested routes, want 3: %#v", len(routes), routes) - } - combo, lowering, err := lowerRenderedSelectorExpressions(endpointOnly) - if err != nil { - t.Fatal(err) - } - url, database, _ := compilerArangoTarget() - client, err := arangostore.Open(context.Background(), url, database) - if err != nil { - t.Fatal(err) - } - defer client.Close(context.Background()) - ctx, cancel := context.WithTimeout(context.Background(), 20*time.Minute) - defer cancel() - - control, candidate, err := runAlternatingCombo(ctx, client, compiled.Query, combo, compiled.BindVars, "control", "endpoint_selector_combo") - if err != nil { - t.Fatal(err) - } - endpoint, err := runShapeFive(ctx, client, endpointOnly, compiled.BindVars, "endpoint_only") - if err != nil { - t.Fatal(err) - } - if control.ResultSHA256 != candidate.ResultSHA256 || control.ResultSHA256 != endpoint.ResultSHA256 { - t.Fatalf("result parity mismatch control=%s endpoint=%s combo=%s", control.ResultSHA256, endpoint.ResultSHA256, candidate.ResultSHA256) - } - if candidate.MedianSeconds >= endpoint.MedianSeconds { - t.Logf("combined selector lowering did not beat endpoint-only: endpoint=%.6fs combo=%.6fs", endpoint.MedianSeconds, candidate.MedianSeconds) - } - if candidate.MedianSeconds >= control.MedianSeconds { - t.Fatalf("combined candidate regressed control: control=%.6fs combo=%.6fs", control.MedianSeconds, candidate.MedianSeconds) - } - - writeEndpointSelectorComboArtifacts(t, compiled, endpointOnly, combo, routes, lowering, control, endpoint, candidate) - t.Logf("WP2+WP4 control=%.6fs endpoint_only=%.6fs combo=%.6fs improvement_vs_control=%.2f%% improvement_vs_endpoint=%.2f%% control_profile=%.6fs combo_profile=%.6fs", control.MedianSeconds, endpoint.MedianSeconds, candidate.MedianSeconds, 100*(control.MedianSeconds-candidate.MedianSeconds)/control.MedianSeconds, 100*(endpoint.MedianSeconds-candidate.MedianSeconds)/endpoint.MedianSeconds, control.Profile.Phases.Executing, candidate.Profile.Phases.Executing) -} - -func runAlternatingCombo(ctx context.Context, client *arangostore.Client, controlQuery, candidateQuery string, baseBinds map[string]any, controlName, candidateName string) (endpointSelectorComboRun, endpointSelectorComboRun, error) { - control := endpointSelectorComboRun{Name: controlName, QuerySHA256: sha256Hex(controlQuery)} - candidate := endpointSelectorComboRun{Name: candidateName, QuerySHA256: sha256Hex(candidateQuery)} - for i := 0; i < 5; i++ { - controlQueryRun, controlBinds := cacheBust(controlQuery, baseBinds, 7000+i) - candidateQueryRun, candidateBinds := cacheBust(candidateQuery, baseBinds, 8000+i) - controlSeconds, controlBytes, controlHash, err := executeOrdinary(ctx, client, controlQueryRun, controlBinds) - if err != nil { - return control, candidate, fmt.Errorf("control run %d: %w", i+1, err) - } - candidateSeconds, candidateBytes, candidateHash, err := executeOrdinary(ctx, client, candidateQueryRun, candidateBinds) - if err != nil { - return control, candidate, fmt.Errorf("candidate run %d: %w", i+1, err) - } - control.WarmSeconds = append(control.WarmSeconds, controlSeconds) - control.Bytes = append(control.Bytes, controlBytes) - control.Rows = 1000 - control.ResultSHA256 = controlHash - candidate.WarmSeconds = append(candidate.WarmSeconds, candidateSeconds) - candidate.Bytes = append(candidate.Bytes, candidateBytes) - candidate.Rows = 1000 - candidate.ResultSHA256 = candidateHash - } - control.MedianSeconds, control.MinSeconds = median(control.WarmSeconds), minFloat(control.WarmSeconds) - candidate.MedianSeconds, candidate.MinSeconds = median(candidate.WarmSeconds), minFloat(candidate.WarmSeconds) - controlProfileQuery, controlProfileBinds := cacheBust(controlQuery, baseBinds, 9001) - candidateProfileQuery, candidateProfileBinds := cacheBust(candidateQuery, baseBinds, 9002) - controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: controlProfileQuery, BindVars: controlProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - return control, candidate, fmt.Errorf("control PROFILE: %w", err) - } - candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidateProfileQuery, BindVars: candidateProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - return control, candidate, fmt.Errorf("candidate PROFILE: %w", err) - } - control.Explain, err = explainShape(ctx, client, controlQuery, baseBinds) - if err != nil { - return control, candidate, err - } - candidate.Explain, err = explainShape(ctx, client, candidateQuery, baseBinds) - if err != nil { - return control, candidate, err - } - control.Profile = summarizeComboProfile(controlProfile) - candidate.Profile = summarizeComboProfile(candidateProfile) - return control, candidate, nil -} - -func runShapeFive(ctx context.Context, client *arangostore.Client, query string, baseBinds map[string]any, name string) (endpointSelectorComboRun, error) { - run := endpointSelectorComboRun{Name: name, QuerySHA256: sha256Hex(query)} - for i := 0; i < 5; i++ { - queryRun, binds := cacheBust(query, baseBinds, 10000+i) - seconds, bytes, hash, err := executeOrdinary(ctx, client, queryRun, binds) - if err != nil { - return run, fmt.Errorf("%s run %d: %w", name, i+1, err) - } - run.WarmSeconds = append(run.WarmSeconds, seconds) - run.Bytes = append(run.Bytes, bytes) - run.Rows = 1000 - run.ResultSHA256 = hash - } - run.MedianSeconds, run.MinSeconds = median(run.WarmSeconds), minFloat(run.WarmSeconds) - profileQuery, profileBinds := cacheBust(query, baseBinds, 11001) - profile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: profileQuery, BindVars: profileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - return run, fmt.Errorf("%s PROFILE: %w", name, err) - } - run.Explain, err = explainShape(ctx, client, query, baseBinds) - if err != nil { - return run, err - } - run.Profile = summarizeComboProfile(profile) - return run, nil -} - -func explainShape(ctx context.Context, client *arangostore.Client, query string, binds map[string]any) (arangostore.ExplainAssessment, error) { - explain, err := client.Explain(ctx, arangostore.ExplainRequest{Query: query, BindVars: binds}) - if err != nil { - return arangostore.ExplainAssessment{}, err - } - assessment := arangostore.AssessExplainResult(explain) - if len(assessment.FullCollectionScans) != 0 { - return assessment, fmt.Errorf("candidate introduced full collection scans: %#v", assessment.FullCollectionScans) - } - return assessment, nil -} - -func summarizeComboProfile(profile arangostore.ProfileResult) endpointSelectorProfileSummary { - summary := arangostore.SummarizeProfile(profile) - nodes := append([]arangostore.ProfileNodeSummary(nil), summary.Nodes...) - if len(nodes) > 20 { - nodes = nodes[:20] - } - return endpointSelectorProfileSummary{ScannedFull: summary.ScannedFull, ScannedIndex: summary.ScannedIndex, PeakMemoryBytes: summary.PeakMemory, Phases: profile.Extra.Profile, TopNodes: nodes} -} - -func minFloat(values []float64) float64 { - if len(values) == 0 { - return 0 - } - minimum := values[0] - for _, value := range values[1:] { - if value < minimum { - minimum = value - } - } - return minimum -} - -type endpointSelectorRouteRewrite struct { - Node string `json:"node"` - Edge string `json:"edge"` - Parent string `json:"parent"` - Direction string `json:"direction"` - Collection string `json:"collection"` -} - -var nestedEndpointHeaderRE = regexp.MustCompile(`(?m)^(\s*)FOR ([A-Za-z_][A-Za-z0-9_]*)_node, ([A-Za-z_][A-Za-z0-9_]*)_edge IN 1\.\.1 (INBOUND|OUTBOUND) ([A-Za-z_][A-Za-z0-9_]*) (@@[A-Za-z_][A-Za-z0-9_]*_edge_collection)\n`) - -func rewriteNestedEndpointTraversals(query string) (string, []endpointSelectorRouteRewrite, error) { - matches := nestedEndpointHeaderRE.FindAllStringSubmatchIndex(query, -1) - var builder strings.Builder - last := 0 - routes := make([]endpointSelectorRouteRewrite, 0, len(matches)) - for _, match := range matches { - node := query[match[4]:match[5]] + "_node" - edge := query[match[6]:match[7]] + "_edge" - direction := query[match[8]:match[9]] - parent := query[match[10]:match[11]] - collection := query[match[12]:match[13]] - if !strings.HasPrefix(parent, "__loom_physical_parent_set_") { - continue - } - endpoint, target := "_to", "_from" - if direction == "OUTBOUND" { - endpoint, target = "_from", "_to" - } - builder.WriteString(query[last:match[0]]) - builder.WriteString("FOR " + edge + " IN " + collection + "\n") - builder.WriteString(" FILTER " + edge + "." + endpoint + " == " + parent + "._id\n") - builder.WriteString(" LET " + node + " = DOCUMENT(" + edge + "." + target + ")\n") - last = match[1] - routes = append(routes, endpointSelectorRouteRewrite{Node: node, Edge: edge, Parent: parent, Direction: direction, Collection: collection}) - } - if len(routes) == 0 { - return query, nil, fmt.Errorf("no nested physical traversal headers found") - } - builder.WriteString(query[last:]) - return builder.String(), routes, nil -} - -var explicitEndpointHeaderRE = regexp.MustCompile(`(?m)^\s*FOR ([A-Za-z_][A-Za-z0-9_]*)_edge IN (@@[A-Za-z_][A-Za-z0-9_]*_edge_collection)\n\s+FILTER ([A-Za-z_][A-Za-z0-9_]*)_edge\.(\w+) == ([A-Za-z_][A-Za-z0-9_]*)\._id`) - -// prepareEndpointSelectorBase uses the test-only WP2 rewrite for the pinned -// native control. If the coordinator has already enabled WP2 in production, -// the current integrated AQL is itself the endpoint-only control and is used -// unchanged. This keeps the selector comparison meaningful while the shared -// compiler is moving. -func prepareEndpointSelectorBase(query string) (string, []endpointSelectorRouteRewrite, error) { - endpointOnly, routes, err := rewriteNestedEndpointTraversals(query) - if err == nil { - return endpointOnly, routes, nil - } - if sha256Hex(query) != "988775e708a0f836ed34de0815e74cdbf38172e75c12a80149a9ce6096b48925" { - return query, nil, err - } - matches := explicitEndpointHeaderRE.FindAllStringSubmatch(query, -1) - if len(matches) != 3 { - return query, nil, fmt.Errorf("integrated endpoint control has %d explicit nested routes, want 3", len(matches)) - } - routes = make([]endpointSelectorRouteRewrite, 0, len(matches)) - for _, match := range matches { - direction := "INBOUND" - if match[4] == "_from" { - direction = "OUTBOUND" - } - routes = append(routes, endpointSelectorRouteRewrite{Node: match[1] + "_node", Edge: match[1] + "_edge", Parent: match[5], Direction: direction, Collection: match[2]}) - } - return query, routes, nil -} - -func writeEndpointSelectorComboArtifacts(t *testing.T, compiled dataframe.CompiledQuery, endpointOnly, combo string, routes []endpointSelectorRouteRewrite, lowering selectorLoweringReport, control, endpoint, candidate endpointSelectorComboRun) { - _, source, _, _ := runtime.Caller(0) - root := filepath.Join(filepath.Dir(source), "..", "..") - directory := filepath.Join(root, "docs", "benchmarks", "round4", "wp2_selector_combo") - if err := os.MkdirAll(directory, 0o755); err != nil { - t.Fatal(err) - } - for name, query := range map[string]string{"production.aql": compiled.Query, "endpoint_only.aql": endpointOnly, "candidate.aql": combo} { - if err := os.WriteFile(filepath.Join(directory, name), []byte(query+"\n"), 0o644); err != nil { - t.Fatal(err) - } - } - payload := map[string]any{"control": control, "endpoint_only": endpoint, "candidate": candidate, "routes": routes, "selector_lowering": lowering, "compiled_columns": compiled.Columns} - encoded, err := json.MarshalIndent(payload, "", " ") - if err != nil { - t.Fatal(err) - } - if err := os.WriteFile(filepath.Join(directory, "RESULTS.json"), append(encoded, '\n'), 0o644); err != nil { - t.Fatal(err) - } -} diff --git a/internal/dataframe/endpoint_strategy_experiment_test.go b/internal/dataframe/endpoint_strategy_experiment_test.go deleted file mode 100644 index 77acc93..0000000 --- a/internal/dataframe/endpoint_strategy_experiment_test.go +++ /dev/null @@ -1,642 +0,0 @@ -package dataframe - -// This file is an opt-in experiment harness, not a production lowering. It -// discovers routes from fhir_edge, resolves them through generated schema -// metadata, and compares four generic AQL shapes without touching compiler IR. - -import ( - "context" - "crypto/sha256" - "encoding/hex" - "encoding/json" - "fmt" - "os" - "path/filepath" - "sort" - "strings" - "testing" - "time" - - "github.com/calypr/loom/fhirschema" - arangostore "github.com/calypr/loom/internal/store/arango" -) - -type endpointExperimentMode string - -const ( - endpointNativeShared endpointExperimentMode = "native_shared" - endpointNativeIndependent endpointExperimentMode = "native_independent" - endpointExplicitShared endpointExperimentMode = "explicit_shared" - endpointExplicitIndependent endpointExperimentMode = "explicit_independent" -) - -type endpointExperimentRoute struct { - ParentType string `json:"parent_type"` - Label string `json:"label"` - TargetType string `json:"target_type"` - EdgeCount int `json:"edge_count"` - Route storageRoute -} - -type endpointExperimentGroup struct { - ParentType string - Label string - Direction PhysicalTraversalDirection - Routes []endpointExperimentRoute -} - -type endpointRouteRow struct { - FromType string `json:"from_type"` - ToType string `json:"to_type"` - Label string `json:"label"` - Count int `json:"edge_count"` -} - -type endpointExperimentRun struct { - Mode endpointExperimentMode `json:"mode"` - QueryHash string `json:"query_hash"` - ResultHash string `json:"result_hash"` - Rows int `json:"rows"` - Bytes int `json:"bytes"` - WarmSeconds []float64 `json:"warm_seconds"` - MedianSeconds float64 `json:"median_seconds"` - MinSeconds float64 `json:"min_seconds"` - Explain arangoExplainExperiment `json:"explain"` - Profile arangoProfileExperiment `json:"profile"` -} - -type arangoExplainExperiment struct { - FullScans []arangostore.ExplainCollectionScan `json:"full_scans"` - Indexes []arangostore.ExplainIndexSummary `json:"indexes"` - Plans []arangostore.ExplainPlanEstimate `json:"plans"` -} - -type arangoProfileExperiment struct { - ScannedFull int `json:"scanned_full"` - ScannedIndex int `json:"scanned_index"` - PeakMemory uint64 `json:"peak_memory"` - Runtime float64 `json:"profile_runtime_seconds"` - TopNodes []arangostore.ProfileNodeSummary `json:"top_nodes"` - TopItemNodes []arangostore.ProfileNodeSummary `json:"top_item_nodes"` -} - -func TestRenderEndpointExperimentQueryShapes(t *testing.T) { - group := endpointExperimentGroup{ - ParentType: "RootCollection", - Label: "generated_label", - Direction: PhysicalInbound, - Routes: []endpointExperimentRoute{ - {ParentType: "RootCollection", Label: "generated_label", TargetType: "TargetA"}, - {ParentType: "RootCollection", Label: "generated_label", TargetType: "TargetB"}, - }, - } - for _, mode := range []endpointExperimentMode{endpointNativeShared, endpointNativeIndependent, endpointExplicitShared, endpointExplicitIndependent} { - query, bindVars, err := renderEndpointExperimentQuery(group, "project", 1000, mode) - if err != nil { - t.Fatalf("render %s: %v", mode, err) - } - if !strings.Contains(query, "@@root_collection") || !strings.Contains(query, "@@edge_collection") { - t.Fatalf("render %s omitted collection binds:\n%s", mode, query) - } - if strings.Contains(query, "TargetA") || strings.Contains(query, "TargetB") { - t.Fatalf("render %s interpolated a target type:\n%s", mode, query) - } - if mode == endpointNativeShared || mode == endpointExplicitShared { - if !strings.Contains(query, "IN @target_types") { - t.Fatalf("render %s omitted shared type predicate:\n%s", mode, query) - } - } else if !strings.Contains(query, "== @target_type_0") || !strings.Contains(query, "== @target_type_1") { - t.Fatalf("render %s omitted independent type predicates:\n%s", mode, query) - } - if mode == endpointNativeShared || mode == endpointExplicitShared { - if _, ok := bindVars["target_types"]; !ok { - t.Fatalf("render %s omitted target_types bind", mode) - } - } else if _, ok := bindVars["target_types"]; ok { - t.Fatalf("render %s retained unused target_types bind", mode) - } - } -} - -// TestEndpointStrategyMatrixAgainstArango is opt-in because it reads the -// provisioned META database. It never creates indexes or mutates documents. -func TestEndpointStrategyMatrixAgainstArango(t *testing.T) { - if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { - t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run endpoint strategy experiment") - } - url, database, project := compilerArangoTarget() - client, err := arangostore.Open(context.Background(), url, database) - if err != nil { - t.Fatalf("open Arango: %v", err) - } - defer client.Close(context.Background()) - - ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute) - defer cancel() - routes, err := discoverEndpointExperimentRoutes(ctx, client, project) - if err != nil { - t.Fatalf("discover endpoint experiment routes: %v", err) - } - groups := groupEndpointExperimentRoutes(routes) - if len(groups) == 0 { - t.Skip("loaded database has no generated route group with multiple target types") - } - sort.SliceStable(groups, func(i, j int) bool { return groupEdgeCount(groups[i]) > groupEdgeCount(groups[j]) }) - if len(groups) > 4 { - groups = groups[:4] - } - limit := experimentLimit() - for index, group := range groups { - group := group - t.Run(fmt.Sprintf("group_%02d_%s_%s", index, group.ParentType, group.Label), func(t *testing.T) { - runs, err := runEndpointExperimentGroup(ctx, client, project, limit, group) - if err != nil { - t.Fatalf("run endpoint strategy matrix: %v", err) - } - for _, run := range runs { - t.Logf("mode=%s query_hash=%s result_hash=%s median=%0.6fs min=%0.6fs rows=%d scanned_index=%d peak_memory=%d indexes=%#v", run.Mode, run.QueryHash, run.ResultHash, run.MedianSeconds, run.MinSeconds, run.Rows, run.Profile.ScannedIndex, run.Profile.PeakMemory, run.Explain.Indexes) - if len(run.Explain.FullScans) != 0 { - t.Errorf("mode=%s used full collection scan: %#v", run.Mode, run.Explain.FullScans) - } - } - if err := writeEndpointExperimentEvidence(project, limit, index, group, runs); err != nil { - t.Fatalf("write endpoint experiment evidence: %v", err) - } - }) - } -} - -// TestEndpointSingletonStrategyMatrixAgainstArango isolates the nested -// single-target paths that a sibling-union benchmark cannot expose. It uses -// the same generated route discovery, but runs one parent collection at a -// time, comparing native traversal with explicit endpoint equality. This is -// intentionally a route-region benchmark: it does not pretend to reproduce -// the parent-set correlation of the complete GDC dataframe. -func TestEndpointSingletonStrategyMatrixAgainstArango(t *testing.T) { - if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { - t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run singleton endpoint experiment") - } - url, database, project := compilerArangoTarget() - client, err := arangostore.Open(context.Background(), url, database) - if err != nil { - t.Fatalf("open Arango: %v", err) - } - defer client.Close(context.Background()) - ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute) - defer cancel() - routes, err := discoverEndpointExperimentRoutes(ctx, client, project) - if err != nil { - t.Fatalf("discover endpoint experiment routes: %v", err) - } - groups := singletonEndpointExperimentGroups(routes) - if len(groups) == 0 { - t.Skip("loaded database has no generated singleton route") - } - limit := experimentLimit() - for index, group := range groups { - group := group - t.Run(fmt.Sprintf("route_%02d_%s_%s_%s", index, group.ParentType, group.Label, group.Routes[0].TargetType), func(t *testing.T) { - runs, err := runEndpointExperimentModes(ctx, client, project, limit, group, []endpointExperimentMode{endpointNativeIndependent, endpointExplicitIndependent}) - if err != nil { - t.Fatalf("run singleton endpoint strategy matrix: %v", err) - } - for _, run := range runs { - t.Logf("mode=%s query_hash=%s result_hash=%s median=%0.6fs min=%0.6fs rows=%d scanned_index=%d peak_memory=%d indexes=%#v", run.Mode, run.QueryHash, run.ResultHash, run.MedianSeconds, run.MinSeconds, run.Rows, run.Profile.ScannedIndex, run.Profile.PeakMemory, run.Explain.Indexes) - if len(run.Explain.FullScans) != 0 { - t.Errorf("mode=%s used full collection scan: %#v", run.Mode, run.Explain.FullScans) - } - } - if err := writeEndpointExperimentEvidenceNamed(project, limit, "singleton", index, group, runs); err != nil { - t.Fatalf("write singleton endpoint experiment evidence: %v", err) - } - }) - } -} - -func singletonEndpointExperimentGroups(routes []endpointExperimentRoute) []endpointExperimentGroup { - if len(routes) == 0 { - return nil - } - // A parent that is itself a target of another generated route is a nested - // parent in the loaded graph. Prefer those regions, then fall back to the - // highest fan-out routes when the fixture has no deeper chain. - targetTypes := map[string]bool{} - for _, route := range routes { - targetTypes[route.TargetType] = true - } - preferred := make([]endpointExperimentRoute, 0, len(routes)) - for _, route := range routes { - if targetTypes[route.ParentType] { - preferred = append(preferred, route) - } - } - if len(preferred) == 0 { - preferred = append(preferred, routes...) - } - sort.SliceStable(preferred, func(i, j int) bool { - if preferred[i].EdgeCount != preferred[j].EdgeCount { - return preferred[i].EdgeCount > preferred[j].EdgeCount - } - if preferred[i].ParentType != preferred[j].ParentType { - return preferred[i].ParentType < preferred[j].ParentType - } - if preferred[i].Label != preferred[j].Label { - return preferred[i].Label < preferred[j].Label - } - return preferred[i].TargetType < preferred[j].TargetType - }) - seen := map[string]bool{} - seenParents := map[string]bool{} - groups := make([]endpointExperimentGroup, 0, 4) - // First cover distinct nested parent collections so a high-fanout resource - // cannot crowd out deeper regions such as Group -> DocumentReference. - for _, route := range preferred { - if seenParents[route.ParentType] { - continue - } - seenParents[route.ParentType] = true - key := fmt.Sprintf("%s\x00%s\x00%s", route.ParentType, route.Label, route.TargetType) - seen[key] = true - groups = append(groups, endpointExperimentGroup{ParentType: route.ParentType, Label: route.Label, Direction: route.Route.Direction, Routes: []endpointExperimentRoute{route}}) - if len(groups) == 4 { - return groups - } - } - for _, route := range preferred { - key := fmt.Sprintf("%s\x00%s\x00%s", route.ParentType, route.Label, route.TargetType) - if seen[key] { - continue - } - seen[key] = true - groups = append(groups, endpointExperimentGroup{ParentType: route.ParentType, Label: route.Label, Direction: route.Route.Direction, Routes: []endpointExperimentRoute{route}}) - if len(groups) == 4 { - break - } - } - return groups -} - -func experimentLimit() int { - if value := strings.TrimSpace(os.Getenv("DATAFRAME_PROFILE_LIMIT")); value != "" { - var limit int - if _, err := fmt.Sscanf(value, "%d", &limit); err == nil && limit > 0 { - return limit - } - } - return 1000 -} - -func discoverEndpointExperimentRoutes(ctx context.Context, client *arangostore.Client, project string) ([]endpointExperimentRoute, error) { - query := `FOR edge IN fhir_edge - FILTER edge.project == @project - COLLECT from_type = edge.from_type, to_type = edge.to_type, label = edge.label WITH COUNT INTO edge_count - RETURN {from_type, to_type, label, edge_count}` - rows := make([]endpointRouteRow, 0) - if err := client.QueryRows(ctx, query, 1000, map[string]any{"project": project}, func(row map[string]any) error { - encoded, err := json.Marshal(row) - if err != nil { - return err - } - var decoded endpointRouteRow - if err := json.Unmarshal(encoded, &decoded); err != nil { - return err - } - rows = append(rows, decoded) - return nil - }); err != nil { - return nil, err - } - - seen := map[string]bool{} - out := make([]endpointExperimentRoute, 0, len(rows)) - for _, edge := range rows { - if !fhirschema.HasResource(edge.FromType) || !fhirschema.HasResource(edge.ToType) || strings.TrimSpace(edge.Label) == "" { - continue - } - // Normal FHIR references are stored child _from -> parent _to. Try the - // generated parent->child tuple first, then the proven forward tuple. - candidates := [][2]string{{edge.ToType, edge.FromType}, {edge.FromType, edge.ToType}} - for _, candidate := range candidates { - route, err := resolveStorageRoute(candidate[0], edge.Label, candidate[1]) - if err != nil { - continue - } - key := fmt.Sprintf("%s\x00%s\x00%s\x00%s", candidate[0], edge.Label, candidate[1], route.Direction) - if seen[key] { - continue - } - seen[key] = true - out = append(out, endpointExperimentRoute{ParentType: candidate[0], Label: edge.Label, TargetType: candidate[1], EdgeCount: edge.Count, Route: route}) - } - } - sort.Slice(out, func(i, j int) bool { - if out[i].ParentType != out[j].ParentType { - return out[i].ParentType < out[j].ParentType - } - if out[i].Label != out[j].Label { - return out[i].Label < out[j].Label - } - return out[i].TargetType < out[j].TargetType - }) - return out, nil -} - -func groupEndpointExperimentRoutes(routes []endpointExperimentRoute) []endpointExperimentGroup { - groups := map[string]endpointExperimentGroup{} - for _, route := range routes { - key := fmt.Sprintf("%s\x00%s\x00%s", route.ParentType, route.Label, route.Route.Direction) - group := groups[key] - group.ParentType = route.ParentType - group.Label = route.Label - group.Direction = route.Route.Direction - group.Routes = append(group.Routes, route) - groups[key] = group - } - out := make([]endpointExperimentGroup, 0, len(groups)) - for _, group := range groups { - seen := map[string]bool{} - unique := group.Routes[:0] - for _, route := range group.Routes { - if seen[route.TargetType] { - continue - } - seen[route.TargetType] = true - unique = append(unique, route) - } - group.Routes = unique - if len(group.Routes) >= 2 { - out = append(out, group) - } - } - sort.Slice(out, func(i, j int) bool { - if out[i].ParentType != out[j].ParentType { - return out[i].ParentType < out[j].ParentType - } - return out[i].Label < out[j].Label - }) - return out -} - -func groupEdgeCount(group endpointExperimentGroup) int { - total := 0 - for _, route := range group.Routes { - total += route.EdgeCount - } - return total -} - -func runEndpointExperimentGroup(ctx context.Context, client *arangostore.Client, project string, limit int, group endpointExperimentGroup) ([]endpointExperimentRun, error) { - modes := []endpointExperimentMode{endpointNativeShared, endpointNativeIndependent, endpointExplicitShared, endpointExplicitIndependent} - return runEndpointExperimentModes(ctx, client, project, limit, group, modes) -} - -func runEndpointExperimentModes(ctx context.Context, client *arangostore.Client, project string, limit int, group endpointExperimentGroup, modes []endpointExperimentMode) ([]endpointExperimentRun, error) { - runs := make([]endpointExperimentRun, 0, len(modes)) - for _, mode := range modes { - query, bindVars, err := renderEndpointExperimentQuery(group, project, limit, mode) - if err != nil { - return nil, err - } - explain, err := client.Explain(ctx, arangostore.ExplainRequest{Query: query, BindVars: bindVars}) - if err != nil { - return nil, fmt.Errorf("explain %s: %w\nAQL:\n%s", mode, err, query) - } - assessment := arangostore.AssessExplainResult(explain) - resultHashes := make([]string, 0, 5) - warm := make([]float64, 0, 5) - rowsCount, bytesCount := 0, 0 - for run := 0; run < 5; run++ { - started := time.Now() - rows := make([]map[string]any, 0, limit) - if err := client.QueryRows(ctx, query, 1000, bindVars, func(row map[string]any) error { - rows = append(rows, row) - return nil - }); err != nil { - return nil, fmt.Errorf("execute %s run %d: %w", mode, run+1, err) - } - warm = append(warm, time.Since(started).Seconds()) - encoded, err := json.Marshal(rows) - if err != nil { - return nil, err - } - resultHashes = append(resultHashes, hashBytes(encoded)) - if run == 0 { - rowsCount, bytesCount = len(rows), len(encoded) - } - } - for _, hash := range resultHashes[1:] { - if hash != resultHashes[0] { - return nil, fmt.Errorf("mode %s changed result hash between warm runs: %v", mode, resultHashes) - } - } - profile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: query, BindVars: bindVars, BatchSize: 1000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - return nil, fmt.Errorf("profile %s: %w", mode, err) - } - profileSummary := arangostore.SummarizeProfile(profile) - sort.Float64s(warm) - runs = append(runs, endpointExperimentRun{ - Mode: mode, QueryHash: hashBytes([]byte(query)), ResultHash: resultHashes[0], Rows: rowsCount, Bytes: bytesCount, - WarmSeconds: warm, MedianSeconds: warm[len(warm)/2], MinSeconds: warm[0], - Explain: arangoExplainExperiment{FullScans: assessment.FullCollectionScans, Indexes: assessment.Indexes, Plans: assessment.Plans}, - Profile: arangoProfileExperiment{ScannedFull: profileSummary.ScannedFull, ScannedIndex: profileSummary.ScannedIndex, PeakMemory: profileSummary.PeakMemory, Runtime: profileSummary.RuntimeSeconds, TopNodes: topProfileNodesByRuntime(profileSummary.Nodes, 10), TopItemNodes: topProfileNodesByItems(profileSummary.Nodes, 10)}, - }) - } - return runs, nil -} - -func renderEndpointExperimentQuery(group endpointExperimentGroup, project string, limit int, mode endpointExperimentMode) (string, map[string]any, error) { - if len(group.Routes) == 0 { - return "", nil, fmt.Errorf("endpoint experiment group requires at least one target route") - } - if (mode == endpointNativeShared || mode == endpointExplicitShared) && len(group.Routes) < 2 { - return "", nil, fmt.Errorf("shared endpoint experiment requires at least two target routes") - } - endpoint, targetEndpoint, discriminator, direction := endpointFields(group.Direction) - types := make([]string, 0, len(group.Routes)) - for _, route := range group.Routes { - types = append(types, route.TargetType) - } - bindVars := map[string]any{ - "@root_collection": group.ParentType, - "@edge_collection": "fhir_edge", - "project": project, - "dataset_generation": "", - "auth_resource_paths_unrestricted": true, - "auth_resource_paths": []string{}, - "limit": limit, - "label": group.Label, - } - var childExpr string - if mode == endpointNativeShared { - bindVars["target_types"] = types - childExpr = fmt.Sprintf(`FOR node, edge IN 1..1 %s root @@edge_collection - FILTER edge.project == @project - FILTER @dataset_generation == "" OR edge.dataset_generation == @dataset_generation - FILTER @auth_resource_paths_unrestricted == true OR edge.auth_resource_path IN @auth_resource_paths - FILTER edge.label == @label - FILTER edge.%s IN @target_types - FILTER node.project == @project - FILTER @dataset_generation == "" OR node.dataset_generation == @dataset_generation - FILTER @auth_resource_paths_unrestricted == true OR node.auth_resource_path IN @auth_resource_paths - FILTER node.resourceType IN @target_types - SORT node._key - RETURN node._key`, direction, discriminator) - } else if mode == endpointExplicitShared { - bindVars["target_types"] = types - childExpr = fmt.Sprintf(`FOR edge IN @@edge_collection - FILTER edge.%s == root._id - FILTER edge.project == @project - FILTER @dataset_generation == "" OR edge.dataset_generation == @dataset_generation - FILTER @auth_resource_paths_unrestricted == true OR edge.auth_resource_path IN @auth_resource_paths - FILTER edge.label == @label - FILTER edge.%s IN @target_types - LET node = DOCUMENT(edge.%s) - FILTER node != null - FILTER node.project == @project - FILTER @dataset_generation == "" OR node.dataset_generation == @dataset_generation - FILTER @auth_resource_paths_unrestricted == true OR node.auth_resource_path IN @auth_resource_paths - FILTER node.resourceType IN @target_types - SORT node._key - RETURN node._key`, endpoint, discriminator, targetEndpoint) - } else { - children := make([]string, 0, len(group.Routes)) - for index, route := range group.Routes { - bindKey := fmt.Sprintf("target_type_%d", index) - bindVars[bindKey] = route.TargetType - if mode == endpointNativeIndependent { - children = append(children, fmt.Sprintf(`FOR node, edge IN 1..1 %s root @@edge_collection - FILTER edge.project == @project - FILTER @dataset_generation == "" OR edge.dataset_generation == @dataset_generation - FILTER @auth_resource_paths_unrestricted == true OR edge.auth_resource_path IN @auth_resource_paths - FILTER edge.label == @label - FILTER edge.%s == @%s - FILTER node.project == @project - FILTER @dataset_generation == "" OR node.dataset_generation == @dataset_generation - FILTER @auth_resource_paths_unrestricted == true OR node.auth_resource_path IN @auth_resource_paths - FILTER node.resourceType == @%s - SORT node._key - RETURN node._key`, direction, discriminator, bindKey, bindKey)) - } else { - children = append(children, fmt.Sprintf(`FOR edge IN @@edge_collection - FILTER edge.%s == root._id - FILTER edge.project == @project - FILTER @dataset_generation == "" OR edge.dataset_generation == @dataset_generation - FILTER @auth_resource_paths_unrestricted == true OR edge.auth_resource_path IN @auth_resource_paths - FILTER edge.label == @label - FILTER edge.%s == @%s - LET node = DOCUMENT(edge.%s) - FILTER node != null - FILTER node.project == @project - FILTER @dataset_generation == "" OR node.dataset_generation == @dataset_generation - FILTER @auth_resource_paths_unrestricted == true OR node.auth_resource_path IN @auth_resource_paths - FILTER node.resourceType == @%s - SORT node._key - RETURN node._key`, endpoint, discriminator, bindKey, targetEndpoint, bindKey)) - } - } - wrapped := make([]string, 0, len(children)) - for _, child := range children { - wrapped = append(wrapped, "("+child+")") - } - combined := wrapped[0] - for _, child := range wrapped[1:] { - // APPEND accepts one array at a time. Nesting it keeps this - // experiment valid for groups with more than two sibling types. - combined = fmt.Sprintf("APPEND(%s, %s, true)", combined, child) - } - childExpr = "SORTED_UNIQUE(" + combined + ")" - } - query := fmt.Sprintf(`FOR root IN @@root_collection - FILTER root.project == @project - FILTER @dataset_generation == "" OR root.dataset_generation == @dataset_generation - FILTER @auth_resource_paths_unrestricted == true OR root.auth_resource_path IN @auth_resource_paths - SORT root._key - LIMIT @limit - LET children = (%s) - RETURN {"_key": root._key, "children": children}`, childExpr) - return query, bindVars, nil -} - -func endpointFields(direction PhysicalTraversalDirection) (endpoint, targetEndpoint, discriminator, aqlDirection string) { - if direction == PhysicalOutbound { - return "_from", "_to", "to_type", "OUTBOUND" - } - return "_to", "_from", "from_type", "INBOUND" -} - -func topProfileNodesByRuntime(nodes []arangostore.ProfileNodeSummary, limit int) []arangostore.ProfileNodeSummary { - ordered := append([]arangostore.ProfileNodeSummary(nil), nodes...) - sort.SliceStable(ordered, func(i, j int) bool { - if ordered[i].Runtime != ordered[j].Runtime { - return ordered[i].Runtime > ordered[j].Runtime - } - return ordered[i].ID < ordered[j].ID - }) - if len(ordered) > limit { - ordered = ordered[:limit] - } - return ordered -} - -func topProfileNodesByItems(nodes []arangostore.ProfileNodeSummary, limit int) []arangostore.ProfileNodeSummary { - ordered := append([]arangostore.ProfileNodeSummary(nil), nodes...) - sort.SliceStable(ordered, func(i, j int) bool { - if ordered[i].Items != ordered[j].Items { - return ordered[i].Items > ordered[j].Items - } - return ordered[i].ID < ordered[j].ID - }) - if len(nodes) > limit { - ordered = ordered[:limit] - } - return ordered -} - -func writeEndpointExperimentEvidence(project string, limit, index int, group endpointExperimentGroup, runs []endpointExperimentRun) error { - return writeEndpointExperimentEvidenceNamed(project, limit, "group", index, group, runs) -} - -func writeEndpointExperimentEvidenceNamed(project string, limit int, prefix string, index int, group endpointExperimentGroup, runs []endpointExperimentRun) error { - directory := filepath.Join(round3BenchmarkRoot(), "docs", "benchmarks", "round3", "wp1") - if err := os.MkdirAll(directory, 0o755); err != nil { - return err - } - name := fmt.Sprintf("%s_%02d_%s_%s", prefix, index, group.ParentType, group.Label) - name = strings.NewReplacer("/", "_", "\\", "_", " ", "_").Replace(name) - payload := map[string]any{"generated_at": time.Now().UTC().Format(time.RFC3339Nano), "git_sha": gitSHAForEvidence(), "project": project, "limit": limit, "group": group, "runs": runs} - encoded, err := json.MarshalIndent(payload, "", " ") - if err != nil { - return err - } - return os.WriteFile(filepath.Join(directory, name+".json"), append(encoded, '\n'), 0o644) -} - -func round3BenchmarkRoot() string { - directory, err := os.Getwd() - if err != nil { - return "." - } - for { - if _, err := os.Stat(filepath.Join(directory, "go.mod")); err == nil { - return directory - } - parent := filepath.Dir(directory) - if parent == directory { - return "." - } - directory = parent - } -} - -func gitSHAForEvidence() string { - if value := strings.TrimSpace(os.Getenv("GIT_COMMIT")); value != "" { - return value - } - return "unknown" -} - -func hashBytes(value []byte) string { - sum := sha256.Sum256(value) - return hex.EncodeToString(sum[:]) -} diff --git a/internal/dataframe/endpoint_strategy_integration_test.go b/internal/dataframe/endpoint_strategy_integration_test.go deleted file mode 100644 index 12a81b2..0000000 --- a/internal/dataframe/endpoint_strategy_integration_test.go +++ /dev/null @@ -1,172 +0,0 @@ -package dataframe_test - -import ( - "context" - "encoding/json" - "os" - "path/filepath" - "runtime" - "strings" - "testing" - "time" - - dataframe "github.com/calypr/loom/internal/dataframe" - arangostore "github.com/calypr/loom/internal/store/arango" -) - -func TestEndpointStrategyUsesTypedLookupForNestedGDCAndFallsBack(t *testing.T) { - compiled := compileActualGDC(t, 1000) - if !strings.Contains(compiled.Query, "FOR child_set_3_edge IN @@child_set_3_edge_collection") { - t.Fatalf("default generic plan did not render endpoint lookup for nested route:\n%s", compiled.Query) - } - if !strings.Contains(compiled.Query, "FILTER child_set_3_edge._to == __loom_physical_parent_set_4._id") || !strings.Contains(compiled.Query, "DOCUMENT(child_set_3_edge._from)") { - t.Fatalf("endpoint lookup lost inbound endpoint/join fields:\n%s", compiled.Query) - } - - nativePolicy := dataframe.DefaultPhysicalOptimizationPolicy().WithRule(dataframe.PhysicalOptimizationRuleEndpointTraversal, false) - native, err := dataframe.CompileRequestWithPolicy(dataframe.Builder{ - Project: "ARANGODB_PROTO", RootResourceType: "Patient", - Traversals: []dataframe.TraversalStep{{Label: "subject_Patient", ToResourceType: "Specimen", Alias: "specimen", Traversals: []dataframe.TraversalStep{{Label: "subject_Specimen", ToResourceType: "DocumentReference", Alias: "file"}}}}, - }, 25, nativePolicy) - if err != nil { - t.Fatal(err) - } - if !strings.Contains(native.Query, "INBOUND __loom_physical_parent_2 @@traversal_2_edge_collection") { - t.Fatalf("disabled endpoint policy did not retain native traversal:\n%s", native.Query) - } -} - -func TestEndpointStrategySupportsProvenResearchSubjectStudyOutbound(t *testing.T) { - builder := dataframe.Builder{ - Project: "ARANGODB_PROTO", RootResourceType: "ResearchSubject", - Traversals: []dataframe.TraversalStep{{Label: "study", ToResourceType: "ResearchStudy", Alias: "study"}}, - } - semantic, err := dataframe.BuildSemanticPlan(builder) - if err != nil { - t.Fatal(err) - } - physical, err := dataframe.BuildPhysicalPlanWithPolicy(semantic, dataframe.DefaultPhysicalOptimizationPolicy()) - if err != nil { - t.Fatal(err) - } - for _, operation := range physical.Operations { - if operation.Traversal != nil { - t.Logf("outbound physical strategy=%q endpoint=%q join=%q index=%#v", operation.Traversal.Strategy, operation.Traversal.EndpointField, operation.Traversal.EndpointJoinField, operation.Traversal.EndpointIndexFields) - } - } - compiled, err := dataframe.CompileRequestWithPolicy(builder, 25, dataframe.DefaultPhysicalOptimizationPolicy()) - if err != nil { - t.Fatal(err) - } - if !strings.Contains(compiled.Query, "FOR edge_1 IN @@traversal_1_edge_collection") { - t.Fatalf("outbound route did not use typed endpoint lookup:\n%s", compiled.Query) - } - for _, want := range []string{ - "FILTER edge_1._from == root._id", - "FILTER edge_1.to_type == @traversal_1_target_type", - "LET node_1 = DOCUMENT(edge_1._to)", - "FILTER node_1.resourceType == @traversal_1_target_type", - } { - if !strings.Contains(compiled.Query, want) { - t.Fatalf("outbound endpoint lookup missing %q:\n%s", want, compiled.Query) - } - } -} - -func TestEndpointStrategyProfilesActualGDCAgainstArango(t *testing.T) { - if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { - t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run endpoint strategy live gate") - } - native := compileActualGDCWithEndpointRule(t, false) - candidate := compileActualGDCWithEndpointRule(t, true) - url, database, _ := compilerArangoTarget() - client, err := arangostore.Open(context.Background(), url, database) - if err != nil { - t.Fatalf("open Arango: %v", err) - } - defer client.Close(context.Background()) - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) - defer cancel() - controlTimes, candidateTimes := make([]float64, 0, 5), make([]float64, 0, 5) - var controlHash, candidateHash string - for run := 0; run < 5; run++ { - controlQuery, controlBinds := cacheBust(native.Query, native.BindVars, 51000+run) - candidateQuery, candidateBinds := cacheBust(candidate.Query, candidate.BindVars, 52000+run) - seconds, _, hash, err := executeOrdinary(ctx, client, controlQuery, controlBinds) - if err != nil { - t.Fatalf("native control run %d: %v", run+1, err) - } - controlTimes = append(controlTimes, seconds) - controlHash = hash - seconds, _, hash, err = executeOrdinary(ctx, client, candidateQuery, candidateBinds) - if err != nil { - t.Fatalf("endpoint candidate run %d: %v", run+1, err) - } - candidateTimes = append(candidateTimes, seconds) - candidateHash = hash - } - if controlHash != candidateHash { - t.Fatalf("endpoint result parity mismatch control=%s candidate=%s", controlHash, candidateHash) - } - controlExplain, err := client.Explain(ctx, arangostore.ExplainRequest{Query: native.Query, BindVars: native.BindVars}) - if err != nil { - t.Fatalf("native Explain: %v", err) - } - candidateExplain, err := client.Explain(ctx, arangostore.ExplainRequest{Query: candidate.Query, BindVars: candidate.BindVars}) - if err != nil { - t.Fatalf("endpoint Explain: %v", err) - } - controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: native.Query, BindVars: native.BindVars, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - t.Fatalf("native PROFILE: %v", err) - } - candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidate.Query, BindVars: candidate.BindVars, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - t.Fatalf("endpoint PROFILE: %v", err) - } - t.Logf("endpoint live control_hash=%s candidate_hash=%s control_median=%.6f candidate_median=%.6f control_explain=%+v candidate_explain=%+v control_profile=%+v candidate_profile=%+v", controlHash, candidateHash, median(controlTimes), median(candidateTimes), arangostore.AssessExplainResult(controlExplain), arangostore.AssessExplainResult(candidateExplain), arangostore.SummarizeProfile(controlProfile), arangostore.SummarizeProfile(candidateProfile)) - writeEndpointIntegrationEvidence(t, native, candidate, controlHash, candidateHash, controlTimes, candidateTimes, controlExplain, candidateExplain, controlProfile, candidateProfile) -} - -func compileActualGDCWithEndpointRule(t *testing.T, enabled bool) dataframe.CompiledQuery { - old, present := os.LookupEnv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL") - if enabled { - _ = os.Unsetenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL") - } else { - _ = os.Setenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL", "off") - } - defer func() { - if present { - _ = os.Setenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL", old) - } else { - _ = os.Unsetenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL") - } - }() - return compileActualGDC(t, 1000) -} - -func writeEndpointIntegrationEvidence(t *testing.T, control, candidate dataframe.CompiledQuery, controlHash, candidateHash string, controlTimes, candidateTimes []float64, controlExplain, candidateExplain arangostore.ExplainResult, controlProfile, candidateProfile arangostore.ProfileResult) { - _, source, _, _ := runtime.Caller(0) - directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "wp2") - if err := os.WriteFile(filepath.Join(directory, "integration-control.aql"), []byte(control.Query+"\n"), 0o644); err != nil { - t.Fatalf("write endpoint control AQL: %v", err) - } - if err := os.WriteFile(filepath.Join(directory, "integration-candidate.aql"), []byte(candidate.Query+"\n"), 0o644); err != nil { - t.Fatalf("write endpoint candidate AQL: %v", err) - } - payload := map[string]any{ - "control_aql_sha256": sha256Hex(control.Query), "candidate_aql_sha256": sha256Hex(candidate.Query), - "control_result_sha256": controlHash, "candidate_result_sha256": candidateHash, - "control_seconds": controlTimes, "candidate_seconds": candidateTimes, - "control_explain": controlExplain, "candidate_explain": candidateExplain, - "control_profile": controlProfile, "candidate_profile": candidateProfile, - "decision": "pending-coordinator-threshold-review", - } - data, err := json.MarshalIndent(payload, "", " ") - if err != nil { - t.Fatalf("encode endpoint integration evidence: %v", err) - } - if err := os.WriteFile(filepath.Join(directory, "integration-evidence.json"), append(data, '\n'), 0o644); err != nil { - t.Fatalf("write endpoint integration evidence: %v", err) - } -} diff --git a/internal/dataframe/full_batch_tournament_test.go b/internal/dataframe/full_batch_tournament_test.go deleted file mode 100644 index 7819255..0000000 --- a/internal/dataframe/full_batch_tournament_test.go +++ /dev/null @@ -1,265 +0,0 @@ -package dataframe_test - -// This file is an isolated, test-only WP9 experiment. It hand-edits the -// production AQL emitted by BuilderFromInput; it intentionally does not add a -// compiler strategy or renderer branch. Promotion requires exact output -// parity and a whole-query runtime win on the complete GDC request. - -import ( - "context" - "encoding/json" - "fmt" - "os" - "path/filepath" - "runtime" - "strconv" - "strings" - "testing" - "time" - - dataframe "github.com/calypr/loom/internal/dataframe" - arangostore "github.com/calypr/loom/internal/store/arango" -) - -// TestFullBatchTournamentCandidateBuilds verifies that the candidate is -// generated from the real frontend input and remains parameterized. It does -// not require Arango and therefore protects the experiment when the live -// database is unavailable. -func TestFullBatchTournamentCandidateBuilds(t *testing.T) { - compiled := compileActualGDC(t, 1000) - candidate, err := batchRootChildSet1Query(compiled.Query) - if err != nil { - t.Fatal(err) - } - for _, fragment := range []string{ - "LET root_window = (", - "LET batch_child_set_1_grouped = (", - "FILTER edge._to IN SLICE(root_window[*]._id", - "COLLECT __batch_root_id = edge._to", - "FOR child_set_1_item IN (__batch_child_set_1_group ?", - "DOCUMENT(edge._from)", - } { - if !strings.Contains(candidate, fragment) { - t.Fatalf("batch candidate missing %q", fragment) - } - } - if strings.Contains(candidate, "FOR __batch_child_set_1 IN shared_root_subject_Patient_neighbors") { - t.Fatal("candidate still consumes child_set_1 from the correlated shared traversal") - } - if !strings.Contains(candidate, "@@child_set_1_edge_collection") || !strings.Contains(candidate, "@project") { - t.Fatal("candidate lost collection or scope binds") - } - if strings.Contains(candidate, "ARANGODB_PROTO") || strings.Contains(candidate, "Patient") == false { - t.Fatal("candidate unexpectedly lost the generic root shape") - } -} - -// TestFullBatchTournamentProfilesActualGDC is opt-in because it executes the -// complete 1,000-row request against the local Arango instance. The control -// and every candidate run alternate, consume all output, and add a harmless -// bind-backed predicate so Arango's result cache cannot satisfy the request. -func TestFullBatchTournamentProfilesActualGDC(t *testing.T) { - if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { - t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run WP9 against Arango") - } - compiled := compileActualGDC(t, 1000) - candidate, err := batchRootChildSet1Query(compiled.Query) - if err != nil { - t.Fatal(err) - } - url, database, _ := compilerArangoTarget() - client, err := arangostore.Open(context.Background(), url, database) - if err != nil { - t.Fatal(err) - } - defer client.Close(context.Background()) - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) - defer cancel() - - batchSizes := []int{25, 100, 250, 500, 1000} - if raw := os.Getenv("LOOM_WP9_BATCH_SIZES"); raw != "" { - batchSizes = nil - for _, value := range strings.Split(raw, ",") { - size, parseErr := strconv.Atoi(strings.TrimSpace(value)) - if parseErr != nil || size <= 0 { - t.Fatalf("invalid LOOM_WP9_BATCH_SIZES value %q", value) - } - batchSizes = append(batchSizes, size) - } - } - runs := 5 - if raw := os.Getenv("LOOM_WP9_RUNS"); raw != "" { - parsed, parseErr := strconv.Atoi(raw) - if parseErr != nil || parsed <= 0 { - t.Fatalf("invalid LOOM_WP9_RUNS value %q", raw) - } - runs = parsed - } - results := make([]batchTournamentResult, 0, len(batchSizes)) - for _, batchSize := range batchSizes { - candidateSized := strings.ReplaceAll(candidate, "@__loom_batch_size", fmt.Sprintf("%d", batchSize)) - controlTimes := make([]float64, 0, 5) - candidateTimes := make([]float64, 0, 5) - controlBytes := make([]int, 0, 5) - candidateBytes := make([]int, 0, 5) - var controlHash, candidateHash string - for run := 0; run < runs; run++ { - controlQuery, controlBinds := cacheBust(compiled.Query, compiled.BindVars, 21000+batchSize*10+run) - candidateQuery, candidateBinds := cacheBust(candidateSized, compiled.BindVars, 22000+batchSize*10+run) - started := time.Now() - controlDuration, bytes, hash, err := executeOrdinary(ctx, client, controlQuery, controlBinds) - if err != nil { - t.Fatalf("batch size %d control run %d: %v", batchSize, run+1, err) - } - _ = started - controlTimes = append(controlTimes, controlDuration) - controlBytes = append(controlBytes, bytes) - controlHash = hash - candidateDuration, bytes, hash, err := executeOrdinary(ctx, client, candidateQuery, candidateBinds) - if err != nil { - t.Fatalf("batch size %d candidate run %d: %v", batchSize, run+1, err) - } - candidateTimes = append(candidateTimes, candidateDuration) - candidateBytes = append(candidateBytes, bytes) - candidateHash = hash - } - if controlHash != candidateHash { - t.Fatalf("batch size %d result parity mismatch control=%s candidate=%s", batchSize, controlHash, candidateHash) - } - controlProfileQuery, controlProfileBinds := cacheBust(compiled.Query, compiled.BindVars, 31000+batchSize) - candidateProfileQuery, candidateProfileBinds := cacheBust(candidateSized, compiled.BindVars, 32000+batchSize) - controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{ - Query: controlProfileQuery, BindVars: controlProfileBinds, BatchSize: 10000, Count: true, - Options: arangostore.ProfileOptions{Profile: 2}, - }) - if err != nil { - t.Fatalf("batch size %d control PROFILE: %v", batchSize, err) - } - candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{ - Query: candidateProfileQuery, BindVars: candidateProfileBinds, BatchSize: 10000, Count: true, - Options: arangostore.ProfileOptions{Profile: 2}, - }) - if err != nil { - t.Fatalf("batch size %d candidate PROFILE: %v", batchSize, err) - } - if hashRawRows(controlProfile.Result) != hashRawRows(candidateProfile.Result) { - t.Fatalf("batch size %d PROFILE result parity mismatch", batchSize) - } - controlSummary := arangostore.SummarizeProfile(controlProfile) - candidateSummary := arangostore.SummarizeProfile(candidateProfile) - results = append(results, batchTournamentResult{ - BatchSize: batchSize, ControlSeconds: controlTimes, CandidateSeconds: candidateTimes, - ControlBytes: controlBytes, CandidateBytes: candidateBytes, ControlHash: controlHash, - CandidateHash: candidateHash, ControlProfile: controlSummary, CandidateProfile: candidateSummary, - }) - t.Logf("WP9 batch size=%d control_median=%.6f candidate_median=%.6f control_profile=%+v candidate_profile=%+v bytes=%v/%v", batchSize, median(controlTimes), median(candidateTimes), controlSummary, candidateSummary, controlBytes, candidateBytes) - } - writeBatchTournamentEvidence(t, compiled, candidate, results) -} - -type batchTournamentResult struct { - BatchSize int `json:"batch_size"` - ControlSeconds []float64 `json:"control_seconds"` - CandidateSeconds []float64 `json:"candidate_seconds"` - ControlBytes []int `json:"control_bytes"` - CandidateBytes []int `json:"candidate_bytes"` - ControlHash string `json:"control_result_sha256"` - CandidateHash string `json:"candidate_result_sha256"` - ControlProfile arangostore.ProfileSummary `json:"control_profile"` - CandidateProfile arangostore.ProfileSummary `json:"candidate_profile"` -} - -// batchRootChildSet1Query converts only the Condition relationship to a -// batched endpoint lookup. The existing shared root traversal is still used -// by Specimen and Observation, but Condition nodes are excluded from it so the -// candidate does not pay for the same relationship twice. -func batchRootChildSet1Query(query string) (string, error) { - rootStart := strings.Index(query, "FOR root IN @@root_collection") - sharedStart := strings.Index(query, " LET shared_root_subject_Patient_neighbors =") - child1Start := strings.Index(query, " LET child_set_1 = UNIQUE((") - child2Start := strings.Index(query, " LET child_set_2 = UNIQUE((") - if rootStart < 0 || sharedStart < 0 || child1Start < 0 || child2Start < 0 || !(rootStart < sharedStart && sharedStart < child1Start && child1Start < child2Start) { - return "", fmt.Errorf("production AQL markers for root/child_set_1 not found") - } - rootPrefix := strings.TrimSpace(query[rootStart:sharedStart]) - rootWindow := "LET root_window = (\n" + batchIndent(rootPrefix, 2) + "\n RETURN root\n)\n" - - shared := query[sharedStart:child1Start] - nodeFilter := " FILTER POSITION(@shared_root_subject_Patient_neighbors_target_types, child_set_1_node.resourceType)\n" - if !strings.Contains(shared, nodeFilter) { - return "", fmt.Errorf("shared traversal node type filter not found") - } - shared = strings.Replace(shared, nodeFilter, nodeFilter+" FILTER child_set_1_node.resourceType != @child_set_1_target_type\n", 1) - - child1 := query[child1Start:child2Start] - oldConsumer := "FOR child_set_1_item IN shared_root_subject_Patient_neighbors" - newConsumer := "LET __batch_child_set_1_group = FIRST((\n FOR __batch_group IN batch_child_set_1_grouped\n FILTER __batch_group.root_id == root._id\n RETURN __batch_group\n ))\n LET child_set_1 = UNIQUE((\n FOR child_set_1_item IN (__batch_child_set_1_group ? __batch_child_set_1_group.nodes : [])" - if !strings.Contains(child1, oldConsumer) { - return "", fmt.Errorf("child_set_1 shared consumer not found") - } - child1 = strings.Replace(child1, " LET child_set_1 = UNIQUE((\n FOR "+oldConsumer[len("FOR "):], newConsumer, 1) - // The replacement above intentionally retains the original projection and - // closes; it changes only the input collection and inserts the left join. - if strings.Contains(child1, oldConsumer) { - return "", fmt.Errorf("child_set_1 consumer replacement incomplete") - } - - batch := `LET batch_child_set_1_grouped = ( - FOR __batch_offset IN RANGE(0, LENGTH(root_window), @__loom_batch_size) - FOR edge IN @@child_set_1_edge_collection - FILTER edge._to IN SLICE(root_window[*]._id, __batch_offset, @__loom_batch_size) - FILTER edge.label == @child_set_1_label - FILTER edge.project == @project - FILTER edge.dataset_generation == @dataset_generation - FILTER @auth_resource_paths_unrestricted == true OR edge.auth_resource_path IN @auth_resource_paths - LET node = DOCUMENT(edge._from) - FILTER node != null - FILTER node.resourceType == @child_set_1_target_type - FILTER node.project == @project - FILTER node.dataset_generation == @dataset_generation - FILTER @auth_resource_paths_unrestricted == true OR node.auth_resource_path IN @auth_resource_paths - COLLECT __batch_root_id = edge._to INTO __batch_rows - RETURN {root_id: __batch_root_id, nodes: __batch_rows[*].node} -) -FOR root IN root_window -` - return rootWindow + batch + shared + child1 + query[child2Start:], nil -} - -func batchIndent(value string, spaces int) string { - prefix := strings.Repeat(" ", spaces) - lines := strings.Split(strings.TrimSpace(value), "\n") - for i := range lines { - lines[i] = prefix + lines[i] - } - return strings.Join(lines, "\n") -} - -func writeBatchTournamentEvidence(t *testing.T, compiled dataframe.CompiledQuery, candidate string, results []batchTournamentResult) { - _, source, _, _ := runtime.Caller(0) - directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "wp9") - if err := os.MkdirAll(directory, 0o755); err != nil { - t.Fatalf("create WP9 evidence directory: %v", err) - } - if err := os.WriteFile(filepath.Join(directory, "control.aql"), []byte(compiled.Query+"\n"), 0o644); err != nil { - t.Fatalf("write WP9 control AQL: %v", err) - } - if err := os.WriteFile(filepath.Join(directory, "candidate.aql"), []byte(candidate+"\n"), 0o644); err != nil { - t.Fatalf("write WP9 candidate AQL: %v", err) - } - payload := map[string]any{ - "input": "examples/meta_gdc_case_matrix.variables.json", - "limit": 1000, - "control_aql_sha256": sha256Hex(compiled.Query), - "candidate_aql_sha256": sha256Hex(candidate), - "results": results, - "decision": "pending-live-evidence", - } - data, err := json.MarshalIndent(payload, "", " ") - if err != nil { - t.Fatalf("encode WP9 evidence: %v", err) - } - if err := os.WriteFile(filepath.Join(directory, "evidence.json"), append(data, '\n'), 0o644); err != nil { - t.Fatalf("write WP9 evidence: %v", err) - } -} diff --git a/internal/dataframe/full_identity_tournament_test.go b/internal/dataframe/full_identity_tournament_test.go deleted file mode 100644 index 837c7b7..0000000 --- a/internal/dataframe/full_identity_tournament_test.go +++ /dev/null @@ -1,266 +0,0 @@ -package dataframe_test - -// WP3 Round 4 is an experiment-only, full-query identity-deduplication -// tournament. It starts with the AQL produced by compileActualGDC (the real -// graphqlapi/dataframe.BuilderFromInput path) and edits only the rendered -// child-set expressions. No production compiler or renderer code is changed. - -import ( - "context" - "encoding/json" - "fmt" - "os" - "path/filepath" - "regexp" - "runtime" - "strings" - "testing" - "time" - - dataframe "github.com/calypr/loom/internal/dataframe" - arangostore "github.com/calypr/loom/internal/store/arango" -) - -type identityDedupReport struct { - Input string `json:"input"` - Limit int `json:"limit"` - ChildSets int `json:"child_sets"` - TransformedSets int `json:"transformed_sets"` - ControlObjectUnique int `json:"control_object_unique"` - CandidateObjectUnique int `json:"candidate_object_unique"` - CandidateIdentityCollects int `json:"candidate_identity_collects"` - ControlAQLSHA256 string `json:"control_aql_sha256"` - CandidateAQLSHA256 string `json:"candidate_aql_sha256"` - ControlResultSHA256 string `json:"control_result_sha256,omitempty"` - CandidateResultSHA256 string `json:"candidate_result_sha256,omitempty"` - ControlRows int `json:"control_rows,omitempty"` - CandidateRows int `json:"candidate_rows,omitempty"` - ControlBytes []int `json:"control_bytes,omitempty"` - CandidateBytes []int `json:"candidate_bytes,omitempty"` - ControlSeconds []float64 `json:"control_seconds,omitempty"` - CandidateSeconds []float64 `json:"candidate_seconds,omitempty"` - ControlProfile any `json:"control_profile,omitempty"` - CandidateProfile any `json:"candidate_profile,omitempty"` - Decision string `json:"decision"` - Blocker string `json:"blocker,omitempty"` -} - -// TestIdentityDedupCandidateBuildsActualGDC proves that the candidate is -// generated from the actual frontend request and keeps all user values bound. -func TestIdentityDedupCandidateBuildsActualGDC(t *testing.T) { - if os.Getenv("LOOM_WP3_IDENTITY_EXPERIMENT") == "" { - t.Skip("set LOOM_WP3_IDENTITY_EXPERIMENT=1 to run the identity-dedup experiment") - } - compiled := compileActualGDC(t, 1000) - candidate, report, err := buildIdentityDedupCandidate(compiled.Query) - if err != nil { - t.Fatal(err) - } - if report.ChildSets == 0 || report.TransformedSets == 0 { - t.Fatalf("no child sets transformed: %+v", report) - } - // Shared child sets may remain on the conservative object-shaping path; - // only independently materialized sets are eligible for identity-first - // grouping in this experiment. - if report.TransformedSets > report.ChildSets { - t.Fatalf("candidate transformed more sets than exist: %+v", report) - } - if report.CandidateObjectUnique >= report.ControlObjectUnique { - t.Fatalf("candidate did not remove child-set object UNIQUE wrappers: %+v", report) - } - if report.CandidateIdentityCollects != report.TransformedSets { - t.Fatalf("candidate identity collect count = %d, want eligible transformed set count %d", report.CandidateIdentityCollects, report.TransformedSets) - } - if !strings.Contains(candidate, "COLLECT __loom_identity_key_") { - t.Fatalf("candidate has no identity grouping:\n%s", candidate) - } - if strings.Contains(candidate, "LET child_set_1 = UNIQUE((") { - t.Fatal("candidate retained object-level child_set_1 UNIQUE") - } - if !strings.Contains(candidate, "@@child_set_1_edge_collection") || !strings.Contains(candidate, "@dataset_generation") { - t.Fatal("candidate lost route or scope binds") - } - t.Logf("WP3 identity candidate report: %+v", report) -} - -// TestIdentityDedupProfilesActualGDC is opt-in because it executes the full -// 1,000-row request against the local Arango instance. It alternates control -// and candidate with a bind-backed harmless predicate, consumes every row, -// captures PROFILE/Explain-derived node statistics, and always writes the -// decision artifact when live execution is available. -func TestIdentityDedupProfilesActualGDC(t *testing.T) { - if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { - t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run WP3 identity tournament") - } - compiled := compileActualGDC(t, 1000) - candidate, report, err := buildIdentityDedupCandidate(compiled.Query) - if err != nil { - t.Fatal(err) - } - url, database, _ := compilerArangoTarget() - client, err := arangostore.Open(context.Background(), url, database) - if err != nil { - t.Fatalf("open Arango: %v", err) - } - defer client.Close(context.Background()) - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) - defer cancel() - - controlSeconds := make([]float64, 0, 5) - candidateSeconds := make([]float64, 0, 5) - controlBytes := make([]int, 0, 5) - candidateBytes := make([]int, 0, 5) - var controlHash, candidateHash string - var controlRows, candidateRows int - for run := 0; run < 5; run++ { - controlQuery, controlBinds := cacheBust(compiled.Query, compiled.BindVars, 41000+run) - candidateQuery, candidateBinds := cacheBust(candidate, compiled.BindVars, 42000+run) - seconds, bytes, hash, err := executeOrdinary(ctx, client, controlQuery, controlBinds) - if err != nil { - t.Fatalf("control run %d: %v", run+1, err) - } - controlSeconds = append(controlSeconds, seconds) - controlBytes = append(controlBytes, bytes) - controlHash = hash - if run == 0 { - controlRows = 1000 - } - seconds, bytes, hash, err = executeOrdinary(ctx, client, candidateQuery, candidateBinds) - if err != nil { - t.Fatalf("candidate run %d: %v", run+1, err) - } - candidateSeconds = append(candidateSeconds, seconds) - candidateBytes = append(candidateBytes, bytes) - candidateHash = hash - if run == 0 { - candidateRows = 1000 - } - } - report.ControlResultSHA256 = controlHash - report.CandidateResultSHA256 = candidateHash - report.ControlRows = controlRows - report.CandidateRows = candidateRows - report.ControlBytes = controlBytes - report.CandidateBytes = candidateBytes - report.ControlSeconds = controlSeconds - report.CandidateSeconds = candidateSeconds - - controlProfileQuery, controlProfileBinds := cacheBust(compiled.Query, compiled.BindVars, 43001) - candidateProfileQuery, candidateProfileBinds := cacheBust(candidate, compiled.BindVars, 43002) - controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: controlProfileQuery, BindVars: controlProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - t.Fatalf("control PROFILE: %v", err) - } - candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidateProfileQuery, BindVars: candidateProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - t.Fatalf("candidate PROFILE: %v", err) - } - controlSummary := arangostore.SummarizeProfile(controlProfile) - candidateSummary := arangostore.SummarizeProfile(candidateProfile) - report.ControlProfile = controlSummary - report.CandidateProfile = candidateSummary - report.ControlAQLSHA256 = sha256Hex(compiled.Query) - report.CandidateAQLSHA256 = sha256Hex(candidate) - if controlHash != candidateHash || hashRawRows(controlProfile.Result) != hashRawRows(candidateProfile.Result) { - report.Decision = "reject-parity" - writeIdentityEvidence(t, compiled, candidate, report) - t.Fatalf("identity candidate result parity mismatch control=%s candidate=%s", controlHash, candidateHash) - } - controlMedian := median(controlSeconds) - candidateMedian := median(candidateSeconds) - if candidateMedian < controlMedian*0.90 { - report.Decision = "pass-10-percent-gate" - } else { - report.Decision = "reject-under-10-percent-gate" - } - writeIdentityEvidence(t, compiled, candidate, report) - t.Logf("WP3 identity tournament control_median=%.6fs candidate_median=%.6fs control_profile=%+v candidate_profile=%+v report=%+v", controlMedian, candidateMedian, controlSummary, candidateSummary, report) -} - -// buildIdentityDedupCandidate inserts identity grouping before the existing -// child projection. It intentionally retains the original scope filters and -// sorts, then sorts the deduplicated node stream again because COLLECT does -// not provide a documented order guarantee. The outer object projection is -// unchanged except that it reads the grouped node variable. -func buildIdentityDedupCandidate(control string) (string, identityDedupReport, error) { - report := identityDedupReport{ - Input: "examples/meta_gdc_case_matrix.variables.json", - Limit: 1000, - ControlObjectUnique: strings.Count(control, "UNIQUE(("), - } - startRE := regexp.MustCompile(`(?m)^ LET (child_set_[0-9]+) = UNIQUE\(\(\n`) - matches := startRE.FindAllStringSubmatchIndex(control, -1) - if len(matches) == 0 { - return "", report, fmt.Errorf("no typed child-set materializations in actual production AQL") - } - report.ChildSets = len(matches) - candidate := control - for index := len(matches) - 1; index >= 0; index-- { - match := matches[index] - name := control[match[2]:match[3]] - start := match[0] - bodyStart := match[1] - closeRel := strings.Index(control[bodyStart:], "\n ))") - if closeRel < 0 { - return "", report, fmt.Errorf("child set %s has no closing wrapper", name) - } - closeStart := bodyStart + closeRel - closeEnd := closeStart + len("\n ))") - block := control[start:closeEnd] - loopRE := regexp.MustCompile(`(?m)^ FOR ([A-Za-z0-9_]+) IN `) - loop := loopRE.FindStringSubmatch(block) - if len(loop) != 2 { - return "", report, fmt.Errorf("child set %s has no source loop", name) - } - loopVar := loop[1] - returnAt := strings.Index(block, "\n RETURN ") - if returnAt < 0 { - return "", report, fmt.Errorf("child set %s has no projection return", name) - } - identityKey := fmt.Sprintf("__loom_identity_key_%d", index) - identityRows := fmt.Sprintf("__loom_identity_rows_%d", index) - identityItem := fmt.Sprintf("__loom_identity_item_%d", index) - insert := fmt.Sprintf("\n COLLECT %s = %s._id INTO %s\n LET %s = FIRST(%s).%s\n SORT %s._key", identityKey, loopVar, identityRows, identityItem, identityRows, loopVar, identityItem) - block = block[:returnAt] + insert + block[returnAt:] - projectionStart := strings.Index(block, "\n RETURN ") + len("\n RETURN ") - projectionEnd := strings.LastIndex(block, "\n ))") - if projectionEnd < 0 { - return "", report, fmt.Errorf("child set %s projection boundary not found", name) - } - projection := strings.ReplaceAll(block[projectionStart:projectionEnd], loopVar+".", identityItem+".") - block = block[:projectionStart] + projection + block[projectionEnd:] - block = strings.Replace(block, " = UNIQUE((\n", " = (\n", 1) - block = strings.Replace(block, "\n ))", "\n )", 1) - candidate = candidate[:start] + block + candidate[closeEnd:] - report.TransformedSets++ - } - report.CandidateObjectUnique = strings.Count(candidate, "UNIQUE((") - report.CandidateIdentityCollects = strings.Count(candidate, "COLLECT __loom_identity_key_") - // Count the materialized identity groups that survived the textual rewrite; - // shared/nested blocks may be conservatively left unchanged. - report.TransformedSets = report.CandidateIdentityCollects - report.ControlAQLSHA256 = sha256Hex(control) - report.CandidateAQLSHA256 = sha256Hex(candidate) - return candidate, report, nil -} - -func writeIdentityEvidence(t *testing.T, compiled dataframe.CompiledQuery, candidate string, report identityDedupReport) { - _, source, _, _ := runtime.Caller(0) - directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "wp3") - if err := os.MkdirAll(directory, 0o755); err != nil { - t.Fatalf("create WP3 evidence directory: %v", err) - } - if err := os.WriteFile(filepath.Join(directory, "control.aql"), []byte(compiled.Query+"\n"), 0o644); err != nil { - t.Fatalf("write WP3 control AQL: %v", err) - } - if err := os.WriteFile(filepath.Join(directory, "candidate.aql"), []byte(candidate+"\n"), 0o644); err != nil { - t.Fatalf("write WP3 candidate AQL: %v", err) - } - data, err := json.MarshalIndent(report, "", " ") - if err != nil { - t.Fatalf("encode WP3 evidence: %v", err) - } - if err := os.WriteFile(filepath.Join(directory, "evidence.json"), append(data, '\n'), 0o644); err != nil { - t.Fatalf("write WP3 evidence: %v", err) - } -} diff --git a/internal/dataframe/identity_order_experiment_test.go b/internal/dataframe/identity_order_experiment_test.go deleted file mode 100644 index c3ec5d0..0000000 --- a/internal/dataframe/identity_order_experiment_test.go +++ /dev/null @@ -1,308 +0,0 @@ -package dataframe - -import ( - "crypto/sha256" - "encoding/hex" - "fmt" - "os" - "path/filepath" - "regexp" - "runtime" - "strings" - "testing" -) - -// WP6 is intentionally an experiment-only proof packet. These helpers model -// physical properties without changing the production IR. Unknown is always -// the safe answer; a coordinator may promote a rule only after the same proof -// is represented by typed production properties and its live profile passes. -type wp6Properties struct { - identityUnique bool - order []string - retained map[string]bool -} - -func wp6UnknownProperties() wp6Properties { - return wp6Properties{retained: map[string]bool{}} -} - -func wp6TransferProperties(in wp6Properties, operation string, keys ...string) wp6Properties { - out := wp6UnknownProperties() - switch operation { - case "filter": - // Filtering removes rows but does not reorder or duplicate them. - out.identityUnique = in.identityUnique - out.order = append([]string(nil), in.order...) - out.retained = cloneWP6Set(in.retained) - case "projection": - // Identity and order survive only when their proof keys remain in the - // projected item. A payload-only projection cannot inherit either. - out.identityUnique = in.identityUnique && in.retained["_id"] && in.retained["_key"] && containsWP6(keys, "_id") && containsWP6(keys, "_key") - for _, key := range in.order { - if !containsWP6(keys, key) { - out.order = nil - break - } - out.order = append(out.order, key) - } - for _, key := range keys { - out.retained[key] = true - } - case "identity_dedup": - // Arango UNIQUE does not provide a compiler contract that its output - // order is stable. Dedup proves identity uniqueness, but invalidates - // order until a physical SORT establishes it again. - out.identityUnique = true - out.retained = cloneWP6Set(in.retained) - case "sort": - out.identityUnique = in.identityUnique - out.order = append([]string(nil), keys...) - out.retained = cloneWP6Set(in.retained) - case "traversal": - // A traversal may repeat a node through duplicate edges; a union/group - // can reorder or multiply rows. No property transfers implicitly. - out = wp6UnknownProperties() - // The target document still exposes whatever graph identity fields the - // source contract explicitly retained; uniqueness/order remain unknown. - out.retained = cloneWP6Set(in.retained) - case "union", "group": - out = wp6UnknownProperties() - default: - panic("unknown WP6 property operation: " + operation) - } - return out -} - -func cloneWP6Set(in map[string]bool) map[string]bool { - out := map[string]bool{} - for key, value := range in { - out[key] = value - } - return out -} - -func containsWP6(values []string, want string) bool { - for _, value := range values { - if value == want { - return true - } - } - return false -} - -func TestWP6RenderedBaselineInventory(t *testing.T) { - aql := wp6ReadRepoFile(t, "docs/benchmarks/round3/wp0/baseline.aql") - exactUnique := regexp.MustCompile(`(?m)\bUNIQUE\(`).FindAllStringIndex(aql, -1) - if got := len(exactUnique); got != 8 { - t.Fatalf("baseline UNIQUE inventory = %d, want 8; SORTED_UNIQUE must not be counted", got) - } - sorts := regexp.MustCompile(`(?m)^\s+SORT `).FindAllStringIndex(aql, -1) - if got := len(sorts); got != 11 { - t.Fatalf("baseline SORT inventory = %d, want 11", got) - } - if got := strings.Count(aql, " INBOUND "); got != 4 { - t.Fatalf("baseline inbound traversal inventory = %d, want 4", got) - } - if got := len(regexp.MustCompile(`(?m)^\s+LET child_set_[0-9]+ = UNIQUE`).FindAllStringIndex(aql, -1)); got != 6 { - t.Fatalf("payload child-set materializations = %d, want 6", got) - } - if got := len(regexp.MustCompile(`FOR __item IN child_set_[0-9]+`).FindAllStringIndex(aql, -1)); got != 7 { - t.Fatalf("post-materialization aggregate child-set loops = %d, want 7", got) - } - if got := strings.Count(aql, "payload: "); got != 6 { - t.Fatalf("payload-retaining child sets = %d, want 6", got) - } - if got := len(regexp.MustCompile(`SORT [^\n]+\._key ASC, [^\n]+\._key ASC`).FindAllStringIndex(aql, -1)); got != 3 { - t.Fatalf("duplicate slice sort keys = %d, want 3", got) - } -} - -func TestWP6IdentityDedupRequiresScopeBeforeDedup(t *testing.T) { - type row struct { - id string - project string - generation string - auth string - } - rows := []row{ - {id: "n1", project: "p", generation: "g2", auth: "denied"}, - {id: "n1", project: "p", generation: "g1", auth: "allowed"}, - {id: "n2", project: "p", generation: "g1", auth: "allowed"}, - } - // Scope is evaluated on edge and node before identity dedup. Deduping - // first would let an inaccessible duplicate hide the accessible row. - scoped := make([]row, 0, len(rows)) - for _, candidate := range rows { - if candidate.project == "p" && candidate.generation == "g1" && candidate.auth == "allowed" { - scoped = append(scoped, candidate) - } - } - got := wp6DedupRowsByKey(scoped, func(candidate row) string { return candidate.id }) - if len(got) != 2 || got[0].id != "n1" || got[1].id != "n2" { - t.Fatalf("scope-before-dedup rows = %#v, want n1,n2", got) - } - // This intentionally demonstrates why a property rule may not move scope - // after dedup, even when the identity key is stable. - preScope := wp6DedupRowsByKey(rows, func(candidate row) string { return candidate.id }) - if len(preScope) != 2 || preScope[0].generation != "g2" { - t.Fatalf("fixture did not retain inaccessible first duplicate for unsafe order proof: %#v", preScope) - } -} - -func TestWP6DuplicateEdgesUseNodeIdentityNotObjectEquality(t *testing.T) { - type row struct { - id string - key string - payload string - } - rows := []row{ - {id: "Patient/n1", key: "n1", payload: "same"}, - {id: "Patient/n1", key: "n1", payload: "same"}, // duplicate edge - {id: "Patient/n2", key: "n2", payload: "different"}, - } - got := wp6DedupRowsByKey(rows, func(candidate row) string { return candidate.id }) - if len(got) != 2 || got[0].id != "Patient/n1" || got[1].id != "Patient/n2" { - t.Fatalf("identity dedup = %#v, want one row per node", got) - } - // A candidate that dedups only after projecting arbitrary payload fields - // is not equivalent to node identity. Keep this assertion explicit so a - // future property implementation cannot silently use object equality. - if got[0].id == "" || got[0].key == "" { - t.Fatal("identity proof lost stable node keys") - } -} - -func TestWP6PropertyTransferRejectsUndocumentedTraversalOrder(t *testing.T) { - initial := wp6UnknownProperties() - initial.retained["_id"] = true - initial.retained["_key"] = true - traversed := wp6TransferProperties(initial, "traversal") - if traversed.identityUnique || len(traversed.order) != 0 { - t.Fatalf("traversal unexpectedly inherited identity/order: %#v", traversed) - } - filtered := wp6TransferProperties(traversed, "filter") - if filtered.identityUnique || len(filtered.order) != 0 { - t.Fatalf("filter manufactured identity/order proof: %#v", filtered) - } - deduped := wp6TransferProperties(filtered, "identity_dedup") - if !deduped.identityUnique || len(deduped.order) != 0 { - t.Fatalf("identity dedup properties = %#v, want unique and unknown order", deduped) - } - sorted := wp6TransferProperties(deduped, "sort", "_key") - if !sorted.identityUnique || fmt.Sprint(sorted.order) != "[_key]" { - t.Fatalf("explicit sort properties = %#v, want unique and [_key] order", sorted) - } - projected := wp6TransferProperties(sorted, "projection", "_id", "_key") - if !projected.identityUnique || fmt.Sprint(projected.order) != "[_key]" { - t.Fatalf("identity projection properties = %#v, want proof retained", projected) - } - withoutKey := wp6TransferProperties(sorted, "projection", "_id") - if withoutKey.identityUnique || len(withoutKey.order) != 0 { - t.Fatalf("projection without _key retained unsafe properties: %#v", withoutKey) - } - union := wp6TransferProperties(sorted, "union") - if union.identityUnique || len(union.order) != 0 { - t.Fatalf("union retained unsafe properties: %#v", union) - } -} - -func TestWP6SliceTieBreakRequiresExactOrderProperty(t *testing.T) { - // A representative slice sorted by a non-unique selector requires an - // explicit stable identity tie-break. Traversal order is not a substitute. - sortedByDate := wp6TransferProperties(wp6Properties{identityUnique: true, retained: map[string]bool{"_id": true, "_key": true}}, "sort", "date", "_key") - if fmt.Sprint(sortedByDate.order) != "[date _key]" { - t.Fatalf("date slice order = %#v", sortedByDate.order) - } - if !wp6HasExactOrder(sortedByDate, []string{"date", "_key"}) { - t.Fatal("date slice lost explicit identity tie-break") - } - unknown := wp6UnknownProperties() - if wp6HasExactOrder(unknown, []string{"date", "_key"}) { - t.Fatal("unknown traversal order incorrectly satisfied slice order") - } - // `_key` is itself a unique identity key. Once a production property - // proves the source is identity-unique and sorted by _key, the renderer may - // normalize the current duplicate `_key, _key` tie-break text. This is a - // correctness cleanup; it is not counted as a meaningful execution win. - keySorted := wp6TransferProperties(wp6Properties{identityUnique: true, retained: map[string]bool{"_id": true, "_key": true}}, "sort", "_key") - if !wp6HasExactOrder(keySorted, []string{"_key"}) { - t.Fatal("unique _key order was not recognized") - } -} - -func wp6HasExactOrder(properties wp6Properties, required []string) bool { - if len(properties.order) != len(required) { - return false - } - for index := range required { - if properties.order[index] != required[index] { - return false - } - } - return true -} - -func wp6DedupRowsByKey[T any](rows []T, key func(T) string) []T { - seen := map[string]bool{} - out := make([]T, 0, len(rows)) - for _, row := range rows { - id := key(row) - if id == "" { - panic("identity proof requires non-empty _id") - } - if seen[id] { - continue - } - seen[id] = true - out = append(out, row) - } - return out -} - -func wp6ReadRepoFile(t *testing.T, relative string) string { - t.Helper() - _, filename, _, ok := runtime.Caller(0) - if !ok { - t.Fatal("runtime.Caller failed") - } - repo := filepath.Clean(filepath.Join(filepath.Dir(filename), "..", "..")) - contents, err := os.ReadFile(filepath.Join(repo, relative)) - if err != nil { - t.Fatalf("read %s: %v", relative, err) - } - return string(contents) -} - -func TestWP6BaselineHashEvidence(t *testing.T) { - aql := wp6ReadRepoFile(t, "docs/benchmarks/round3/wp0/baseline.aql") - if got := sha256.Sum256([]byte(aql)); hex.EncodeToString(got[:]) != "aea66e4cf03bfbe460df2d07d3bfd7c874f8176756fe99348288addd3c589642" { - t.Fatalf("raw baseline AQL hash changed: %x", got) - } - // The profile command hashes canonical AQL (normalized before hashing), so - // retain the checked-in canonical hash separately from the raw-file hash. - metadata := wp6ReadRepoFile(t, "docs/benchmarks/round3/wp0/baseline.json") - if !strings.Contains(metadata, `"aql_sha256": "c0b39eb0ec0f29a09b1661c78fc377159881aae81214e505a5427495c8a7e07c"`) { - t.Fatal("baseline metadata lost canonical AQL hash") - } - if !strings.Contains(metadata, `"result_sha256": "17faea7ac3ee7f308b37223f376530a0660f8068d5e015cc573cf99ccb4045ca"`) { - t.Fatal("baseline metadata lost canonical result hash") - } -} - -func TestWP6SortInventoryIsDeterministic(t *testing.T) { - aql := wp6ReadRepoFile(t, "docs/benchmarks/round3/wp0/baseline.aql") - var sortLines []string - for _, line := range strings.Split(aql, "\n") { - if strings.Contains(line, "SORT ") { - sortLines = append(sortLines, strings.TrimSpace(line)) - } - } - if len(sortLines) != 11 { - t.Fatalf("sort inventory = %d, want 11", len(sortLines)) - } - for index, line := range sortLines { - if strings.TrimSpace(line) == "" { - t.Fatalf("sort inventory line %d is empty", index) - } - } -} diff --git a/internal/dataframe/materialization/arango/registry.go b/internal/dataframe/materialization/arango/registry.go new file mode 100644 index 0000000..dafaacf --- /dev/null +++ b/internal/dataframe/materialization/arango/registry.go @@ -0,0 +1,93 @@ +package arango + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/calypr/loom/internal/dataframe/materialization" + arangostore "github.com/calypr/loom/internal/store/arango" +) + +const Collection = "loom_dataframe_materializations" + +type Client interface { + QueryRows(context.Context, string, int, map[string]interface{}, arangostore.RowVisitor) error + InsertBatchRaw(context.Context, string, []json.RawMessage, bool, string) error +} + +type Registry struct { + client Client + batchSize int +} + +func New(client Client) (*Registry, error) { + if client == nil { + return nil, fmt.Errorf("Arango materialization registry client is required") + } + return &Registry{client: client, batchSize: 32}, nil +} + +func BootstrapSpec() arangostore.BootstrapSpec { + return arangostore.BootstrapSpec{Collections: []arangostore.CollectionSpec{{ + Name: Collection, + Indexes: [][]string{{"project", "state"}, {"project", "datasetGeneration"}, {"state"}}, + }}} +} + +func (r *Registry) Save(ctx context.Context, m materialization.Materialization) error { + data, err := json.Marshal(m) + if err != nil { + return err + } + var doc map[string]any + if err := json.Unmarshal(data, &doc); err != nil { + return err + } + doc["_key"] = m.ID + data, err = json.Marshal(doc) + if err != nil { + return err + } + return r.client.InsertBatchRaw(ctx, Collection, []json.RawMessage{data}, true, "document") +} + +func (r *Registry) Get(ctx context.Context, id string) (materialization.Materialization, error) { + var found *materialization.Materialization + err := r.client.QueryRows(ctx, `FOR doc IN @@collection FILTER doc._key == @key RETURN doc`, r.batchSize, map[string]interface{}{"@collection": Collection, "key": id}, func(row map[string]any) error { + data, err := json.Marshal(row) + if err != nil { + return err + } + var value materialization.Materialization + if err := json.Unmarshal(data, &value); err != nil { + return err + } + found = &value + return nil + }) + if err != nil { + return materialization.Materialization{}, err + } + if found == nil { + return materialization.Materialization{}, fmt.Errorf("materialization %q not found", id) + } + return *found, nil +} + +func (r *Registry) ListReady(ctx context.Context, project string) ([]materialization.Materialization, error) { + out := []materialization.Materialization{} + err := r.client.QueryRows(ctx, `FOR doc IN @@collection FILTER doc.project == @project AND doc.state == @state SORT doc.createdAt ASC RETURN doc`, r.batchSize, map[string]interface{}{"@collection": Collection, "project": project, "state": string(materialization.StateReady)}, func(row map[string]any) error { + data, err := json.Marshal(row) + if err != nil { + return err + } + var value materialization.Materialization + if err := json.Unmarshal(data, &value); err != nil { + return err + } + out = append(out, value) + return nil + }) + return out, err +} diff --git a/internal/dataframe/materialization/integration_test.go b/internal/dataframe/materialization/integration_test.go new file mode 100644 index 0000000..a04f6dc --- /dev/null +++ b/internal/dataframe/materialization/integration_test.go @@ -0,0 +1,81 @@ +package materialization + +import ( + "context" + "os" + "testing" + "time" + + "github.com/google/uuid" + + clickhousestore "github.com/calypr/loom/internal/store/clickhouse" +) + +// This opt-in test exercises the actual materialization reader against +// ClickHouse, including keyset pagination and aggregate filters. +func TestClickHouseReaderPaginationAndFilteredAggregate(t *testing.T) { + url := os.Getenv("LOOM_CLICKHOUSE_URL") + if url == "" { + t.Skip("LOOM_CLICKHOUSE_URL is not set") + } + database := os.Getenv("LOOM_CLICKHOUSE_DATABASE") + if database == "" { + database = "loom_test" + } + client, err := clickhousestore.New(clickhousestore.Options{URL: url, Database: database, Timeout: 10 * time.Second}) + if err != nil { + t.Fatal(err) + } + defer client.Close() + ctx := context.Background() + if err := client.EnsureDatabase(ctx); err != nil { + t.Fatal(err) + } + table := "loom_reader_it_" + uuid.NewString()[:12] + defer client.DropTable(ctx, table) + columns := []clickhousestore.Column{ + {Name: "__loom_row_id", Type: "UInt64"}, + {Name: "status", Type: "String"}, + {Name: "score", Type: "Float64"}, + } + if err := client.CreateTable(ctx, table, columns); err != nil { + t.Fatal(err) + } + if err := client.InsertRows(ctx, table, columns, []map[string]any{ + {"__loom_row_id": uint64(1), "status": "active", "score": 1.0}, + {"__loom_row_id": uint64(2), "status": "inactive", "score": 2.0}, + {"__loom_row_id": uint64(3), "status": "active", "score": 3.0}, + }); err != nil { + t.Fatal(err) + } + registry := NewMemoryRegistry() + if err := registry.Save(ctx, Materialization{ID: "it", State: StateReady, PhysicalTable: table, Columns: []Column{ + {Name: "__loom_row_id", ClickHouse: "UInt64"}, + {Name: "status", ClickHouse: "String"}, + {Name: "score", ClickHouse: "Float64"}, + }}); err != nil { + t.Fatal(err) + } + reader := &Reader{ClickHouse: client, Registry: registry, MaxPage: 10} + first, err := reader.Page(ctx, PageRequest{MaterializationID: "it", Columns: []string{"status", "score"}, Sort: &Sort{Column: "score"}, First: 1}) + if err != nil { + t.Fatal(err) + } + if len(first.Rows) != 1 || !first.HasNext || first.NextCursor == "" { + t.Fatalf("first page = %#v", first) + } + second, err := reader.Page(ctx, PageRequest{MaterializationID: "it", Columns: []string{"status", "score"}, Sort: &Sort{Column: "score"}, First: 2, After: first.NextCursor}) + if err != nil { + t.Fatal(err) + } + if len(second.Rows) != 2 || second.Rows[0]["score"] != float64(2) { + t.Fatalf("second page = %#v", second) + } + aggregate, err := reader.Aggregate(ctx, AggregateRequest{MaterializationID: "it", GroupBy: []string{"status"}, Filters: []Filter{{Column: "status", Op: "EQ", Value: "active"}}, Operation: "COUNT"}) + if err != nil { + t.Fatal(err) + } + if len(aggregate.Rows) != 1 || aggregate.Rows[0]["count"] != float64(2) { + t.Fatalf("filtered aggregate = %#v", aggregate.Rows) + } +} diff --git a/internal/dataframe/materialization/read.go b/internal/dataframe/materialization/read.go new file mode 100644 index 0000000..c372935 --- /dev/null +++ b/internal/dataframe/materialization/read.go @@ -0,0 +1,361 @@ +package materialization + +import ( + "context" + "encoding/base64" + "encoding/json" + "fmt" + "strconv" + "strings" + + "github.com/calypr/loom/internal/store/clickhouse" +) + +type Reader struct { + ClickHouse *clickhouse.Client + Registry Registry + MaxPage int +} + +type Filter struct { + Column string + Op string + Value any +} + +type Sort struct { + Column string + Desc bool +} + +type PageRequest struct { + MaterializationID string + Columns []string + Filters []Filter + Sort *Sort + First int + After string +} + +type Page struct { + Materialization Materialization + Columns []string + Rows []map[string]any + HasNext bool + NextCursor string +} + +type AggregateRequest struct { + MaterializationID string + GroupBy []string + Filters []Filter + Operation string + Column string +} + +type AggregateResult struct { + Materialization Materialization + Columns []string + Rows []map[string]any +} + +func (r *Reader) Aggregate(ctx context.Context, req AggregateRequest) (AggregateResult, error) { + if r.ClickHouse == nil || r.Registry == nil { + return AggregateResult{}, fmt.Errorf("ClickHouse and registry dependencies are required") + } + m, err := r.Registry.Get(ctx, req.MaterializationID) + if err != nil { + return AggregateResult{}, err + } + if m.State != StateReady { + return AggregateResult{}, fmt.Errorf("materialization %q is not ready", m.ID) + } + allowed := map[string]struct{}{} + for _, column := range m.Columns { + allowed[column.Name] = struct{}{} + } + for _, column := range req.GroupBy { + if _, ok := allowed[column]; !ok { + return AggregateResult{}, fmt.Errorf("group column %q is not in materialization schema", column) + } + } + where, err := buildWhere(req.Filters, allowed) + if err != nil { + return AggregateResult{}, err + } + operation := strings.ToUpper(req.Operation) + if operation != "COUNT" && operation != "COUNT_DISTINCT" && operation != "SUM" && operation != "MIN" && operation != "MAX" { + return AggregateResult{}, fmt.Errorf("unsupported dataframe aggregate operation %q", req.Operation) + } + if operation != "COUNT" { + if _, ok := allowed[req.Column]; !ok { + return AggregateResult{}, fmt.Errorf("aggregate column %q is not in materialization schema", req.Column) + } + } + selects := make([]string, 0, len(req.GroupBy)+1) + columns := append([]string(nil), req.GroupBy...) + for _, column := range req.GroupBy { + selects = append(selects, fmt.Sprintf("`%s`", column)) + } + metric := "count()" + metricName := "count" + if operation == "COUNT_DISTINCT" { + metric = fmt.Sprintf("uniqExact(`%s`)", req.Column) + metricName = "count_distinct" + } + if operation == "SUM" { + metric = fmt.Sprintf("sum(`%s`)", req.Column) + metricName = "sum" + } + if operation == "MIN" { + metric = fmt.Sprintf("min(`%s`)", req.Column) + metricName = "min" + } + if operation == "MAX" { + metric = fmt.Sprintf("max(`%s`)", req.Column) + metricName = "max" + } + selects = append(selects, metric+" AS `"+metricName+"`") + columns = append(columns, metricName) + query := fmt.Sprintf("SELECT %s FROM `%s`", strings.Join(selects, ", "), m.PhysicalTable) + if len(where) > 0 { + query += " WHERE " + strings.Join(where, " AND ") + } + if len(req.GroupBy) > 0 { + query += " GROUP BY " + strings.Join(selects[:len(req.GroupBy)], ", ") + " ORDER BY " + strings.Join(selects[:len(req.GroupBy)], ", ") + } + rows, err := r.ClickHouse.QueryRows(ctx, query, columns) + if err != nil { + return AggregateResult{}, err + } + return AggregateResult{Materialization: m, Columns: columns, Rows: rows}, nil +} + +func (r *Reader) Page(ctx context.Context, req PageRequest) (Page, error) { + if r.ClickHouse == nil || r.Registry == nil { + return Page{}, fmt.Errorf("ClickHouse and registry dependencies are required") + } + m, err := r.Registry.Get(ctx, req.MaterializationID) + if err != nil { + return Page{}, err + } + if m.State != StateReady { + return Page{}, fmt.Errorf("materialization %q is not ready", m.ID) + } + allowed := map[string]struct{}{} + for _, column := range m.Columns { + allowed[column.Name] = struct{}{} + } + columns := req.Columns + if len(columns) == 0 { + columns = make([]string, 0, len(m.Columns)) + for _, column := range m.Columns { + if column.Name == "__loom_row_id" { + continue + } + columns = append(columns, column.Name) + } + } + for _, column := range columns { + if column == "__loom_row_id" { + return Page{}, fmt.Errorf("column %q is internal to dataframe pagination", column) + } + if _, ok := allowed[column]; !ok { + return Page{}, fmt.Errorf("column %q is not in materialization schema", column) + } + } + if req.Sort != nil { + if req.Sort.Column == "__loom_row_id" { + return Page{}, fmt.Errorf("column %q is internal to dataframe pagination", req.Sort.Column) + } + if _, ok := allowed[req.Sort.Column]; !ok { + return Page{}, fmt.Errorf("sort column %q is not in materialization schema", req.Sort.Column) + } + } + first := req.First + if first <= 0 { + first = 100 + } + if r.MaxPage > 0 && first > r.MaxPage { + first = r.MaxPage + } + cursor, err := decodeCursor(req.After) + if err != nil { + return Page{}, err + } + where, err := buildWhere(req.Filters, allowed) + if err != nil { + return Page{}, err + } + queryColumns := append([]string(nil), columns...) + if req.Sort != nil && !contains(queryColumns, req.Sort.Column) { + queryColumns = append(queryColumns, req.Sort.Column) + } + if !contains(queryColumns, "__loom_row_id") { + queryColumns = append(queryColumns, "__loom_row_id") + } + querySelects := make([]string, len(queryColumns)) + for i, column := range queryColumns { + querySelects[i] = fmt.Sprintf("`%s`", column) + } + query := fmt.Sprintf("SELECT %s FROM `%s`", strings.Join(querySelects, ", "), m.PhysicalTable) + if len(where) > 0 { + query += " WHERE " + strings.Join(where, " AND ") + } + if cursor != nil { + cursorWhere, err := cursorPredicate(cursor, req.Sort) + if err != nil { + return Page{}, err + } + if strings.Contains(query, " WHERE ") { + query += " AND " + cursorWhere + } else { + query += " WHERE " + cursorWhere + } + } + if req.Sort != nil { + direction := "ASC" + if req.Sort.Desc { + direction = "DESC" + } + query += fmt.Sprintf(" ORDER BY `%s` %s, `__loom_row_id` ASC", req.Sort.Column, direction) + } else { + query += " ORDER BY toUInt64(`__loom_row_id`) ASC" + } + query += fmt.Sprintf(" LIMIT %d", first+1) + rows, err := r.ClickHouse.QueryRows(ctx, query, queryColumns) + if err != nil { + return Page{}, err + } + hasNext := len(rows) > first + if hasNext { + rows = rows[:first] + } + next := "" + if hasNext { + last := rows[len(rows)-1] + var sortValue any + if req.Sort != nil { + sortValue = last[req.Sort.Column] + if sortValue == nil { + return Page{}, fmt.Errorf("cannot create keyset cursor from NULL sort value in %q", req.Sort.Column) + } + } + rowID, ok := last["__loom_row_id"].(string) + if !ok { + rowID = fmt.Sprint(last["__loom_row_id"]) + } + next = encodeCursor(rowID, sortValue) + } + for _, row := range rows { + delete(row, "__loom_row_id") + if req.Sort != nil && !contains(columns, req.Sort.Column) { + delete(row, req.Sort.Column) + } + } + return Page{Materialization: m, Columns: columns, Rows: rows, HasNext: hasNext, NextCursor: next}, nil +} + +func buildWhere(filters []Filter, allowed map[string]struct{}) ([]string, error) { + where := make([]string, 0, len(filters)) + for _, filter := range filters { + if _, ok := allowed[filter.Column]; !ok { + return nil, fmt.Errorf("filter column %q is not in materialization schema", filter.Column) + } + literal, err := jsonLiteral(filter.Value) + if err != nil { + return nil, err + } + switch strings.ToUpper(filter.Op) { + case "EQ": + where = append(where, fmt.Sprintf("`%s` = %s", filter.Column, literal)) + case "CONTAINS": + where = append(where, fmt.Sprintf("positionCaseInsensitive(toString(`%s`), %s) > 0", filter.Column, literal)) + default: + return nil, fmt.Errorf("unsupported dataframe filter operation %q", filter.Op) + } + } + return where, nil +} + +type pageCursor struct { + RowID string `json:"rowId"` + SortValue any `json:"sortValue,omitempty"` +} + +func encodeCursor(rowID string, sortValue any) string { + data, _ := json.Marshal(pageCursor{RowID: rowID, SortValue: sortValue}) + return base64.RawURLEncoding.EncodeToString(data) +} + +func decodeCursor(cursor string) (*pageCursor, error) { + if cursor == "" { + return nil, nil + } + data, err := base64.RawURLEncoding.DecodeString(cursor) + if err != nil { + return nil, fmt.Errorf("invalid dataframe cursor: %w", err) + } + var value pageCursor + if err := json.Unmarshal(data, &value); err != nil || value.RowID == "" { + return nil, fmt.Errorf("invalid dataframe cursor") + } + return &value, nil +} + +func cursorPredicate(cursor *pageCursor, sort *Sort) (string, error) { + rowID, err := jsonLiteral(cursor.RowID) + if err != nil { + return "", err + } + row := fmt.Sprintf("toUInt64(`__loom_row_id`) > toUInt64(%s)", rowID) + if sort == nil { + return row, nil + } + if cursor.SortValue == nil { + return "", fmt.Errorf("keyset cursor is missing sort value") + } + literal, err := jsonLiteral(cursor.SortValue) + if err != nil { + return "", err + } + operator := ">" + if sort.Desc { + operator = "<" + } + return fmt.Sprintf("(`%s` %s %s OR (`%s` = %s AND %s))", sort.Column, operator, literal, sort.Column, literal, row), nil +} + +func contains(values []string, needle string) bool { + for _, value := range values { + if value == needle { + return true + } + } + return false +} + +func jsonLiteral(value any) (string, error) { + data, err := json.Marshal(value) + if err != nil { + return "", err + } + return string(data), nil +} +func encodeOffset(value int) string { + return base64.RawURLEncoding.EncodeToString([]byte(strconv.Itoa(value))) +} +func decodeOffset(cursor string) (int, error) { + if cursor == "" { + return 0, nil + } + data, err := base64.RawURLEncoding.DecodeString(cursor) + if err != nil { + return 0, fmt.Errorf("invalid dataframe cursor: %w", err) + } + value, err := strconv.Atoi(string(data)) + if err != nil || value < 0 { + return 0, fmt.Errorf("invalid dataframe cursor") + } + return value, nil +} diff --git a/internal/dataframe/materialization/read_test.go b/internal/dataframe/materialization/read_test.go new file mode 100644 index 0000000..e1f9168 --- /dev/null +++ b/internal/dataframe/materialization/read_test.go @@ -0,0 +1,31 @@ +package materialization + +import "testing" + +func TestKeysetCursorRoundTrip(t *testing.T) { + cursor := encodeCursor("42", "alice") + decoded, err := decodeCursor(cursor) + if err != nil { + t.Fatal(err) + } + if decoded.RowID != "42" || decoded.SortValue != "alice" { + t.Fatalf("decoded cursor = %#v", decoded) + } + predicate, err := cursorPredicate(decoded, &Sort{Column: "name"}) + if err != nil { + t.Fatal(err) + } + if predicate == "" || predicate == "toUInt64(`__loom_row_id`) > toUInt64(\"42\")" { + t.Fatalf("unexpected sort predicate %q", predicate) + } +} + +func TestBuildWhereSupportsAggregateFilters(t *testing.T) { + where, err := buildWhere([]Filter{{Column: "status", Op: "EQ", Value: "active"}}, map[string]struct{}{"status": {}}) + if err != nil { + t.Fatal(err) + } + if len(where) != 1 || where[0] == "" { + t.Fatalf("where = %#v", where) + } +} diff --git a/internal/dataframe/materialization/schema.go b/internal/dataframe/materialization/schema.go new file mode 100644 index 0000000..7ce44bc --- /dev/null +++ b/internal/dataframe/materialization/schema.go @@ -0,0 +1,99 @@ +package materialization + +import ( + "fmt" + "reflect" + "regexp" + "strings" +) + +var schemaIdentifierRE = regexp.MustCompile(`^[A-Za-z_][A-Za-z0-9_]*$`) + +var supportedSchemaScalarRE = regexp.MustCompile(`^(String|Bool|Int8|Int16|Int32|Int64|Int128|Int256|UInt8|UInt16|UInt32|UInt64|UInt128|UInt256|Float32|Float64|Date|Date32|DateTime|DateTime64(\([^)]*\))?)$`) + +func validateSchemaColumn(column Column) error { + if column.Name == "" || !schemaIdentifierRE.MatchString(column.Name) || column.Name == "__loom_row_id" { + return fmt.Errorf("invalid dataframe schema column %q", column.Name) + } + if column.ClickHouse == "" || !validSchemaType(column.ClickHouse) { + return fmt.Errorf("unsupported ClickHouse type %q for schema column %q", column.ClickHouse, column.Name) + } + return nil +} + +func validSchemaType(typ string) bool { + if strings.HasPrefix(typ, "Nullable(") && strings.HasSuffix(typ, ")") { + typ = strings.TrimSuffix(strings.TrimPrefix(typ, "Nullable("), ")") + } + if strings.HasPrefix(typ, "Array(") && strings.HasSuffix(typ, ")") { + typ = strings.TrimSuffix(strings.TrimPrefix(typ, "Array("), ")") + } + return supportedSchemaScalarRE.MatchString(typ) +} + +func findColumn(columns []Column, name string) (Column, bool) { + for _, column := range columns { + if column.Name == name { + return column, true + } + } + return Column{}, false +} + +// ValidateValue checks the coarse Go-to-ClickHouse compatibility of a row +// value against an explicit schema column. It intentionally permits nil for +// every type; callers should use Nullable columns when missing values are +// expected in ClickHouse. +func ValidateValue(column Column, value any) error { + if value == nil { + return nil + } + t := column.ClickHouse + if strings.HasPrefix(t, "Nullable(") && strings.HasSuffix(t, ")") { + t = strings.TrimSuffix(strings.TrimPrefix(t, "Nullable("), ")") + } + if strings.HasPrefix(t, "Array(") && strings.HasSuffix(t, ")") { + valueType := strings.TrimSuffix(strings.TrimPrefix(t, "Array("), ")") + v := reflect.ValueOf(value) + if v.Kind() != reflect.Array && v.Kind() != reflect.Slice { + return fmt.Errorf("column %q expects %s but received %T", column.Name, column.ClickHouse, value) + } + for i := 0; i < v.Len(); i++ { + if err := validateScalar(column.Name, valueType, v.Index(i).Interface()); err != nil { + return err + } + } + return nil + } + return validateScalar(column.Name, t, value) +} + +func validateScalar(name, typ string, value any) error { + switch { + case typ == "String": + if _, ok := value.(string); !ok { + return fmt.Errorf("column %q expects String but received %T", name, value) + } + case typ == "Bool": + if _, ok := value.(bool); !ok { + return fmt.Errorf("column %q expects Bool but received %T", name, value) + } + case strings.HasPrefix(typ, "Int") || strings.HasPrefix(typ, "UInt"): + kind := reflect.ValueOf(value).Kind() + if kind < reflect.Int || kind > reflect.Uint64 { + return fmt.Errorf("column %q expects integer but received %T", name, value) + } + case strings.HasPrefix(typ, "Float"): + kind := reflect.ValueOf(value).Kind() + if (kind != reflect.Float32 && kind != reflect.Float64) && (kind < reflect.Int || kind > reflect.Uint64) { + return fmt.Errorf("column %q expects number but received %T", name, value) + } + case strings.HasPrefix(typ, "Date"): + if _, ok := value.(string); !ok { + return fmt.Errorf("column %q expects date text but received %T", name, value) + } + default: + return fmt.Errorf("unsupported ClickHouse scalar type %q", typ) + } + return nil +} diff --git a/internal/dataframe/materialization/service.go b/internal/dataframe/materialization/service.go new file mode 100644 index 0000000..d92d4d9 --- /dev/null +++ b/internal/dataframe/materialization/service.go @@ -0,0 +1,304 @@ +package materialization + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "fmt" + "sort" + "strings" + "sync" + "time" + + dataframeruntime "github.com/calypr/loom/internal/dataframe/runtime" + "github.com/calypr/loom/internal/store/clickhouse" + "github.com/google/uuid" +) + +type Service struct { + Dataframes DataframeStreamer + ClickHouse ClickHouseStore + Registry Registry + BatchSize int +} + +// DataframeStreamer and ClickHouseStore keep the materialization boundary +// testable without requiring ArangoDB or ClickHouse for every fixture test. +type DataframeStreamer interface { + Stream(context.Context, dataframeruntime.RunRequest, func(map[string]any) error) (dataframeruntime.StreamResult, error) +} + +type ClickHouseStore interface { + CreateTable(context.Context, string, []clickhouse.Column) error + AddColumn(context.Context, string, clickhouse.Column) error + InsertRows(context.Context, string, []clickhouse.Column, []map[string]any) error + DropTable(context.Context, string) error +} + +type Request struct { + Name string + Run dataframeruntime.RunRequest + Schema []SchemaColumn +} + +// Preflight validates an explicit output schema before any ClickHouse table +// is created. An empty schema preserves the original inference behavior. +func (s *Service) Preflight(req Request) ([]Column, error) { + if strings.TrimSpace(req.Name) == "" { + return nil, fmt.Errorf("materialization name is required") + } + if req.Run.Builder.Project == "" || req.Run.Builder.RootResourceType == "" { + return nil, fmt.Errorf("materialization dataframe project and root resource type are required") + } + if len(req.Schema) == 0 { + return nil, nil + } + seen := make(map[string]struct{}, len(req.Schema)) + result := make([]Column, 0, len(req.Schema)) + for _, column := range req.Schema { + if err := validateSchemaColumn(column); err != nil { + return nil, err + } + if _, ok := seen[column.Name]; ok { + return nil, fmt.Errorf("schema column %q is duplicated", column.Name) + } + seen[column.Name] = struct{}{} + result = append(result, column) + } + return result, nil +} + +func (s *Service) Materialize(ctx context.Context, req Request) (Materialization, error) { + if s.Dataframes == nil || s.ClickHouse == nil || s.Registry == nil { + return Materialization{}, fmt.Errorf("dataframe, ClickHouse, and registry dependencies are required") + } + explicitSchema, err := s.Preflight(req) + if err != nil { + return Materialization{}, err + } + batchSize := s.BatchSize + if batchSize <= 0 { + batchSize = 500 + } + id := uuid.NewString() + m := Materialization{ + ID: id, Name: req.Name, Project: req.Run.Builder.Project, + DatasetGeneration: req.Run.Builder.DatasetGeneration, + State: StatePending, AuthScopeMode: req.Run.Builder.AuthScopeMode, + AuthResourcePaths: append([]string(nil), req.Run.Builder.AuthResourcePaths...), + PhysicalTable: "loom_df_" + strings.ReplaceAll(id, "-", ""), CreatedAt: time.Now().UTC(), + } + if err := s.Registry.Save(ctx, m); err != nil { + return Materialization{}, err + } + m.State = StateLoading + if err := s.Registry.Save(ctx, m); err != nil { + return Materialization{}, err + } + + var columns []Column + known := map[string]struct{}{} + var batch []map[string]any + var rowCount int64 + created := false + flushWithColumns := func(physicalColumns []Column) error { + if len(batch) == 0 { + return nil + } + allColumns := append([]Column{{Name: "__loom_row_id", ClickHouse: "UInt64"}}, physicalColumns...) + if err := s.ClickHouse.InsertRows(ctx, m.PhysicalTable, toClickHouseColumns(allColumns), batch); err != nil { + return err + } + batch = batch[:0] + return nil + } + flush := func() error { + return flushWithColumns(columns) + } + fail := func(err error) (Materialization, error) { + if created { + if cleanupErr := s.ClickHouse.DropTable(context.Background(), m.PhysicalTable); cleanupErr != nil { + err = fmt.Errorf("%w (drop failed materialization table: %v)", err, cleanupErr) + } + } + m.State, m.Error = StateFailed, err.Error() + _ = s.Registry.Save(context.Background(), m) + return Materialization{}, err + } + if len(explicitSchema) > 0 { + columns = append(columns, explicitSchema...) + for _, column := range columns { + known[column.Name] = struct{}{} + } + all := append([]Column{{Name: "__loom_row_id", ClickHouse: "UInt64"}}, columns...) + if err := s.ClickHouse.CreateTable(ctx, m.PhysicalTable, toClickHouseColumns(all)); err != nil { + return fail(err) + } + created = true + } + streamResult, err := s.Dataframes.Stream(ctx, req.Run, func(row map[string]any) error { + rowCount++ + row = cloneMap(row) + row["__loom_row_id"] = rowCount + newColumns := make([]Column, 0) + for name, value := range row { + if name == "__loom_row_id" { + continue + } + if _, ok := known[name]; ok { + if len(explicitSchema) > 0 { + if column, ok := findColumn(columns, name); ok { + if err := ValidateValue(column, value); err != nil { + return err + } + } + } + continue + } + if len(explicitSchema) > 0 { + return fmt.Errorf("dataframe emitted column %q not declared in schema", name) + } + column, err := InferColumn(name, value) + if err != nil { + return err + } + known[name] = struct{}{} + columns = append(columns, column) + newColumns = append(newColumns, column) + } + sort.Slice(newColumns, func(i, j int) bool { return newColumns[i].Name < newColumns[j].Name }) + if !created { + all := append([]Column{{Name: "__loom_row_id", ClickHouse: "UInt64"}}, columns...) + if err := s.ClickHouse.CreateTable(ctx, m.PhysicalTable, toClickHouseColumns(all)); err != nil { + return err + } + created = true + } else if len(newColumns) > 0 { + previousColumns := columns[:len(columns)-len(newColumns)] + if err := flushWithColumns(previousColumns); err != nil { + return err + } + for _, column := range newColumns { + if err := s.ClickHouse.AddColumn(ctx, m.PhysicalTable, clickhouse.Column{Name: column.Name, Type: column.ClickHouse}); err != nil { + return err + } + } + } + batch = append(batch, row) + if len(batch) >= batchSize { + return flush() + } + return nil + }) + if err != nil { + return fail(err) + } + if rowCount == 0 && len(explicitSchema) == 0 { + return fail(fmt.Errorf("cannot materialize an empty dataframe without an output schema")) + } + if err := flush(); err != nil { + return fail(err) + } + if len(streamResult.Columns) > 0 { + // The runtime's finalized order is useful metadata, but the physical + // schema remains the deterministic order discovered above. + _ = streamResult + } + m.Columns = append([]Column{{Name: "__loom_row_id", ClickHouse: "UInt64"}}, columns...) + sort.Slice(m.Columns[1:], func(i, j int) bool { return m.Columns[i+1].Name < m.Columns[j+1].Name }) + m.RowCount = rowCount + now := time.Now().UTC() + m.ReadyAt, m.State = &now, StateReady + if err := s.Registry.Save(ctx, m); err != nil { + return fail(err) + } + return m, nil +} + +func InferColumn(name string, value any) (Column, error) { + if strings.TrimSpace(name) == "" || name == "__loom_row_id" { + return Column{}, fmt.Errorf("invalid output column %q", name) + } + t := "Nullable(String)" + switch value.(type) { + case bool: + t = "Nullable(Bool)" + case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, json.Number: + t = "Nullable(Int64)" + case float32, float64: + t = "Nullable(Float64)" + case []string: + t = "Array(String)" + case []int, []int8, []int16, []int32, []int64, []uint, []uint8, []uint16, []uint32, []uint64: + t = "Array(Int64)" + case []float32, []float64: + t = "Array(Float64)" + case []bool: + t = "Array(Bool)" + case []any: + t = "Array(String)" + case nil: + // The logical type is unknown until a non-null value arrives. String is + // the conservative ClickHouse type for an all-null output column. + } + return Column{Name: name, ClickHouse: t}, nil +} + +func toClickHouseColumns(in []Column) []clickhouse.Column { + out := make([]clickhouse.Column, 0, len(in)) + for _, column := range in { + out = append(out, clickhouse.Column{Name: column.Name, Type: column.ClickHouse}) + } + return out +} + +func cloneMap(in map[string]any) map[string]any { + out := make(map[string]any, len(in)+1) + for k, v := range in { + out[k] = v + } + return out +} + +// MemoryRegistry is useful for unit tests and local one-process experiments. +// Production wiring uses the Arango registry adapter. +type MemoryRegistry struct { + mu sync.RWMutex + byID map[string]Materialization +} + +func NewMemoryRegistry() *MemoryRegistry { return &MemoryRegistry{byID: map[string]Materialization{}} } +func (r *MemoryRegistry) Save(_ context.Context, m Materialization) error { + r.mu.Lock() + defer r.mu.Unlock() + r.byID[m.ID] = m + return nil +} +func (r *MemoryRegistry) Get(_ context.Context, id string) (Materialization, error) { + r.mu.RLock() + defer r.mu.RUnlock() + m, ok := r.byID[id] + if !ok { + return Materialization{}, fmt.Errorf("materialization %q not found", id) + } + return m, nil +} +func (r *MemoryRegistry) ListReady(_ context.Context, project string) ([]Materialization, error) { + r.mu.RLock() + defer r.mu.RUnlock() + out := []Materialization{} + for _, m := range r.byID { + if m.Project == project && m.State == StateReady { + out = append(out, m) + } + } + sort.Slice(out, func(i, j int) bool { return out[i].CreatedAt.Before(out[j].CreatedAt) }) + return out, nil +} + +func RecipeHash(value any) string { + data, _ := json.Marshal(value) + sum := sha256.Sum256(data) + return hex.EncodeToString(sum[:]) +} diff --git a/internal/dataframe/materialization/service_test.go b/internal/dataframe/materialization/service_test.go new file mode 100644 index 0000000..c517cff --- /dev/null +++ b/internal/dataframe/materialization/service_test.go @@ -0,0 +1,203 @@ +package materialization + +import ( + "context" + "errors" + "testing" + + dataframeruntime "github.com/calypr/loom/internal/dataframe/runtime" + "github.com/calypr/loom/internal/store/clickhouse" +) + +func TestInferColumnMapsPublishedDataframeValues(t *testing.T) { + cases := []struct { + name string + value any + want string + }{ + {"string", "x", "Nullable(String)"}, + {"integer", int64(1), "Nullable(Int64)"}, + {"float", 1.5, "Nullable(Float64)"}, + {"boolean", true, "Nullable(Bool)"}, + {"strings", []string{"a", "b"}, "Array(String)"}, + {"null", nil, "Nullable(String)"}, + } + for _, tc := range cases { + got, err := InferColumn(tc.name, tc.value) + if err != nil { + t.Fatalf("%s: %v", tc.name, err) + } + if got.ClickHouse != tc.want { + t.Fatalf("%s: type = %q, want %q", tc.name, got.ClickHouse, tc.want) + } + } +} + +func TestMemoryRegistryOnlyListsReadyRows(t *testing.T) { + registry := NewMemoryRegistry() + if err := registry.Save(nil, Materialization{ID: "pending", Project: "P", State: StatePending}); err != nil { + t.Fatal(err) + } + if err := registry.Save(nil, Materialization{ID: "ready", Project: "P", State: StateReady}); err != nil { + t.Fatal(err) + } + rows, err := registry.ListReady(nil, "P") + if err != nil { + t.Fatal(err) + } + if len(rows) != 1 || rows[0].ID != "ready" { + t.Fatalf("ready rows = %#v", rows) + } +} + +func TestPreflightValidatesExplicitSchema(t *testing.T) { + service := &Service{} + request := Request{ + Name: "patients", + Run: dataframeruntime.RunRequest{Builder: dataframeruntime.Builder{Project: "P", RootResourceType: "Patient"}}, + Schema: []SchemaColumn{{Name: "patient_id", ClickHouse: "Nullable(String)"}, {Name: "score", ClickHouse: "Nullable(Float64)"}}, + } + columns, err := service.Preflight(request) + if err != nil { + t.Fatal(err) + } + if len(columns) != 2 || columns[1].ClickHouse != "Nullable(Float64)" { + t.Fatalf("preflight schema = %#v", columns) + } + request.Schema[1].ClickHouse = "Map(String,String)" + if _, err := service.Preflight(request); err == nil { + t.Fatal("expected unsupported schema type error") + } +} + +func TestValidateValueAgainstSchema(t *testing.T) { + if err := ValidateValue(Column{Name: "tags", ClickHouse: "Array(String)"}, []string{"a"}); err != nil { + t.Fatal(err) + } + if err := ValidateValue(Column{Name: "score", ClickHouse: "Nullable(Float64)"}, "not-a-number"); err == nil { + t.Fatal("expected type validation error") + } +} + +type fixtureStreamer struct { + rows []map[string]any +} + +func (f fixtureStreamer) Stream(_ context.Context, _ dataframeruntime.RunRequest, visit func(map[string]any) error) (dataframeruntime.StreamResult, error) { + for _, row := range f.rows { + if err := visit(row); err != nil { + return dataframeruntime.StreamResult{}, err + } + } + return dataframeruntime.StreamResult{RowCount: len(f.rows)}, nil +} + +type fixtureClickHouse struct { + created []string + dropped []string + inserted []map[string]any + failInsert bool +} + +func (f *fixtureClickHouse) CreateTable(_ context.Context, table string, _ []clickhouse.Column) error { + f.created = append(f.created, table) + return nil +} + +func (f *fixtureClickHouse) AddColumn(_ context.Context, _ string, _ clickhouse.Column) error { + return nil +} + +func (f *fixtureClickHouse) InsertRows(_ context.Context, _ string, _ []clickhouse.Column, rows []map[string]any) error { + if f.failInsert { + return errors.New("fixture insert failed") + } + f.inserted = append(f.inserted, rows...) + return nil +} + +func (f *fixtureClickHouse) DropTable(_ context.Context, table string) error { + f.dropped = append(f.dropped, table) + return nil +} + +func fixtureRequest() Request { + return Request{ + Name: "fixture", + Run: dataframeruntime.RunRequest{Builder: dataframeruntime.Builder{Project: "P", RootResourceType: "Patient"}}, + Schema: []SchemaColumn{ + {Name: "patient_id", ClickHouse: "Nullable(String)"}, + {Name: "score", ClickHouse: "Nullable(Float64)"}, + {Name: "active", ClickHouse: "Nullable(Bool)"}, + {Name: "tags", ClickHouse: "Array(String)"}, + {Name: "note", ClickHouse: "Nullable(String)"}, + }, + } +} + +func TestMaterializeRepresentativeFixture(t *testing.T) { + store := &fixtureClickHouse{} + service := &Service{Dataframes: fixtureStreamer{rows: []map[string]any{ + {"patient_id": "p1", "score": 1.5, "active": true, "tags": []string{"a", "b"}, "note": nil}, + {"patient_id": "p2", "score": 2.5, "active": false, "tags": []string{}, "note": "ok"}, + }}, ClickHouse: store, Registry: NewMemoryRegistry(), BatchSize: 1} + result, err := service.Materialize(context.Background(), fixtureRequest()) + if err != nil { + t.Fatal(err) + } + if result.State != StateReady || result.RowCount != 2 || len(store.inserted) != 2 { + t.Fatalf("materialization = %#v, inserted = %#v", result, store.inserted) + } + if len(store.dropped) != 0 { + t.Fatalf("successful materialization dropped tables: %#v", store.dropped) + } +} + +func TestMaterializeExplicitSchemaAllowsEmptyResult(t *testing.T) { + store := &fixtureClickHouse{} + service := &Service{Dataframes: fixtureStreamer{}, ClickHouse: store, Registry: NewMemoryRegistry()} + result, err := service.Materialize(context.Background(), fixtureRequest()) + if err != nil { + t.Fatal(err) + } + if result.State != StateReady || result.RowCount != 0 || len(store.created) != 1 { + t.Fatalf("empty materialization = %#v, created = %#v", result, store.created) + } +} + +func TestMaterializeFailureDropsCreatedTable(t *testing.T) { + store := &fixtureClickHouse{failInsert: true} + registry := NewMemoryRegistry() + service := &Service{Dataframes: fixtureStreamer{rows: []map[string]any{{ + "patient_id": "p1", "score": 1.5, "active": true, "tags": []string{"a"}, "note": nil, + }}}, ClickHouse: store, Registry: registry} + _, err := service.Materialize(context.Background(), fixtureRequest()) + if err == nil { + t.Fatal("expected insert failure") + } + if len(store.created) != 1 || len(store.dropped) != 1 || store.created[0] != store.dropped[0] { + t.Fatalf("cleanup created=%#v dropped=%#v", store.created, store.dropped) + } + registry.mu.RLock() + defer registry.mu.RUnlock() + for _, materialization := range registry.byID { + if materialization.State != StateFailed { + t.Fatalf("failed materialization state = %s", materialization.State) + } + return + } + t.Fatal("materialization was not registered") +} + +func TestMaterializeRejectsFixtureTypeMismatchAndCleansUp(t *testing.T) { + store := &fixtureClickHouse{} + service := &Service{Dataframes: fixtureStreamer{rows: []map[string]any{{ + "patient_id": "p1", "score": "wrong", "active": true, "tags": []string{"a"}, "note": nil, + }}}, ClickHouse: store, Registry: NewMemoryRegistry()} + if _, err := service.Materialize(context.Background(), fixtureRequest()); err == nil { + t.Fatal("expected schema type mismatch") + } + if len(store.dropped) != 1 { + t.Fatalf("type mismatch cleanup = %#v", store.dropped) + } +} diff --git a/internal/dataframe/materialization/types.go b/internal/dataframe/materialization/types.go new file mode 100644 index 0000000..df399d7 --- /dev/null +++ b/internal/dataframe/materialization/types.go @@ -0,0 +1,49 @@ +package materialization + +import ( + "context" + "time" + + "github.com/calypr/loom/internal/authscope" +) + +type State string + +const ( + StatePending State = "PENDING" + StateLoading State = "LOADING" + StateReady State = "READY" + StateFailed State = "FAILED" +) + +type Column struct { + Name string `json:"name"` + ClickHouse string `json:"clickhouseType"` +} + +// SchemaColumn is the explicit output contract for a published dataframe. +// ClickHouse types are intentionally kept as strings so the contract can use +// native types such as Nullable(String), Array(Int64), and DateTime64. +type SchemaColumn = Column + +type Materialization struct { + ID string `json:"id"` + Name string `json:"name"` + Project string `json:"project"` + DatasetGeneration string `json:"datasetGeneration"` + State State `json:"state"` + AuthScopeMode authscope.ReadScopeMode `json:"authScopeMode"` + AuthResourcePaths []string `json:"authResourcePaths,omitempty"` + Columns []Column `json:"columns"` + PhysicalTable string `json:"physicalTable"` + RowCount int64 `json:"rowCount"` + CreatedAt time.Time `json:"createdAt"` + ReadyAt *time.Time `json:"readyAt,omitempty"` + Error string `json:"error,omitempty"` +} + +type Registry interface { + Save(context.Context, Materialization) error + Get(context.Context, string) (Materialization, error) + ListReady(context.Context, string) ([]Materialization, error) +} diff --git a/internal/dataframe/materialization_tournament_test.go b/internal/dataframe/materialization_tournament_test.go deleted file mode 100644 index aa90f91..0000000 --- a/internal/dataframe/materialization_tournament_test.go +++ /dev/null @@ -1,201 +0,0 @@ -package dataframe_test - -// Tournament C is an isolated AQL experiment. It freezes the current -// endpoint-first plus typed-selector query produced by the real compiler and -// replaces only the three nested DOCUMENT(edge._from) lookups. No production -// IR, renderer, storage route, or index is changed by this file. - -import ( - "context" - "encoding/json" - "fmt" - "os" - "path/filepath" - "runtime" - "strings" - "testing" - "time" - - dataframe "github.com/calypr/loom/internal/dataframe" - arangostore "github.com/calypr/loom/internal/store/arango" -) - -func TestMaterializationTournamentCandidateBuilds(t *testing.T) { - compiled := compileActualGDC(t, 1000) - candidate, binds, err := compactMaterializationCandidate(compiled.Query, compiled.BindVars) - if err != nil { - t.Fatal(err) - } - if strings.Count(compiled.Query, "DOCUMENT(child_set_3_edge._from)") != 1 || - strings.Count(compiled.Query, "DOCUMENT(child_set_4_edge._from)") != 1 || - strings.Count(compiled.Query, "DOCUMENT(child_set_5_edge._from)") != 1 { - t.Fatalf("current compiled request is not the expected endpoint-first baseline; document lookups=%d/%d/%d", strings.Count(compiled.Query, "DOCUMENT(child_set_3_edge._from)"), strings.Count(compiled.Query, "DOCUMENT(child_set_4_edge._from)"), strings.Count(compiled.Query, "DOCUMENT(child_set_5_edge._from)")) - } - for _, set := range []string{"3", "4", "5"} { - for _, fragment := range []string{ - "FOR child_set_" + set + "_doc IN @@child_set_" + set + "_node_collection", - "PARSE_IDENTIFIER(child_set_" + set + "_edge._from).key", - "KEEP(child_set_" + set + "_doc", - } { - if !strings.Contains(candidate, fragment) { - t.Fatalf("candidate missing compact materialization fragment %q", fragment) - } - } - if _, ok := binds["@child_set_"+set+"_node_collection"]; !ok { - t.Fatalf("candidate missing node collection bind for child_set_%s", set) - } - } - if strings.Contains(candidate, "DOCUMENT(child_set_3_edge._from)") || strings.Contains(candidate, "DOCUMENT(child_set_4_edge._from)") || strings.Contains(candidate, "DOCUMENT(child_set_5_edge._from)") { - t.Fatal("candidate retained a DOCUMENT endpoint lookup") - } -} - -func TestMaterializationTournamentProfilesActualGDC(t *testing.T) { - if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { - t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run materialization tournament against Arango") - } - compiled := compileActualGDC(t, 1000) - candidate, candidateBinds, err := compactMaterializationCandidate(compiled.Query, compiled.BindVars) - if err != nil { - t.Fatal(err) - } - url, database, _ := compilerArangoTarget() - client, err := arangostore.Open(context.Background(), url, database) - if err != nil { - t.Fatal(err) - } - defer client.Close(context.Background()) - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) - defer cancel() - - controlTimes := make([]float64, 0, 5) - candidateTimes := make([]float64, 0, 5) - controlBytes := make([]int, 0, 5) - candidateBytes := make([]int, 0, 5) - var controlHash, candidateHash string - for run := 0; run < 5; run++ { - controlQuery, controlBinds := cacheBust(compiled.Query, compiled.BindVars, 41000+run) - candidateQuery, binds := cacheBust(candidate, candidateBinds, 42000+run) - controlDuration, bytes, hash, err := executeOrdinary(ctx, client, controlQuery, controlBinds) - if err != nil { - t.Fatalf("control run %d: %v", run+1, err) - } - candidateDuration, candidateSize, candidateResultHash, err := executeOrdinary(ctx, client, candidateQuery, binds) - if err != nil { - t.Fatalf("candidate run %d: %v", run+1, err) - } - controlTimes = append(controlTimes, controlDuration) - candidateTimes = append(candidateTimes, candidateDuration) - controlBytes = append(controlBytes, bytes) - candidateBytes = append(candidateBytes, candidateSize) - controlHash, candidateHash = hash, candidateResultHash - } - if controlHash != candidateHash { - t.Fatalf("result parity mismatch control=%s candidate=%s", controlHash, candidateHash) - } - - controlProfileQuery, controlProfileBinds := cacheBust(compiled.Query, compiled.BindVars, 41999) - candidateProfileQuery, candidateProfileBinds := cacheBust(candidate, candidateBinds, 42999) - controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{ - Query: controlProfileQuery, BindVars: controlProfileBinds, BatchSize: 10000, Count: true, - Options: arangostore.ProfileOptions{Profile: 2}, - }) - if err != nil { - t.Fatalf("control PROFILE: %v", err) - } - candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{ - Query: candidateProfileQuery, BindVars: candidateProfileBinds, BatchSize: 10000, Count: true, - Options: arangostore.ProfileOptions{Profile: 2}, - }) - if err != nil { - t.Fatalf("candidate PROFILE: %v", err) - } - if hashRawRows(controlProfile.Result) != hashRawRows(candidateProfile.Result) { - t.Fatalf("PROFILE result parity mismatch control=%s candidate=%s", hashRawRows(controlProfile.Result), hashRawRows(candidateProfile.Result)) - } - controlExplain, err := client.Explain(ctx, arangostore.ExplainRequest{Query: controlProfileQuery, BindVars: controlProfileBinds}) - if err != nil { - t.Fatalf("control EXPLAIN: %v", err) - } - candidateExplain, err := client.Explain(ctx, arangostore.ExplainRequest{Query: candidateProfileQuery, BindVars: candidateProfileBinds}) - if err != nil { - t.Fatalf("candidate EXPLAIN: %v", err) - } - controlSummary := arangostore.SummarizeProfile(controlProfile) - candidateSummary := arangostore.SummarizeProfile(candidateProfile) - t.Logf("materialization tournament control median=%.6f candidate median=%.6f control profile=%+v candidate profile=%+v bytes=%v/%v", median(controlTimes), median(candidateTimes), controlSummary, candidateSummary, controlBytes, candidateBytes) - writeMaterializationEvidence(t, compiled, candidate, controlTimes, candidateTimes, controlBytes, candidateBytes, controlHash, candidateHash, controlProfile, candidateProfile, controlExplain, candidateExplain) - if median(candidateTimes) >= median(controlTimes)*0.95 { - t.Logf("candidate rejected: median does not clear 5%% whole-query gate control=%.6f candidate=%.6f", median(controlTimes), median(candidateTimes)) - } -} - -// compactMaterializationCandidate replaces DOCUMENT endpoint retrieval with a -// type-directed primary-key lookup. KEEP retains only fields used by the -// current child projections and scope checks. The node collection binds are -// derived from the compiled target-type binds; no FHIR route is hard-coded in -// production code. -func compactMaterializationCandidate(query string, sourceBinds map[string]any) (string, map[string]any, error) { - candidate := query - binds := make(map[string]any, len(sourceBinds)+3) - for key, value := range sourceBinds { - binds[key] = value - } - for _, set := range []string{"3", "4", "5"} { - setPrefix := "child_set_" + set - old := fmt.Sprintf("LET %s_node = DOCUMENT(%s_edge._from)", setPrefix, setPrefix) - new := fmt.Sprintf("FOR %s_doc IN @@%s_node_collection\n FILTER %s_doc._key == PARSE_IDENTIFIER(%s_edge._from).key\n FILTER %s_doc._id == %s_edge._from\n LET %s_node = KEEP(%s_doc, \"_id\", \"_key\", \"id\", \"resourceType\", \"project\", \"dataset_generation\", \"auth_resource_path\", \"payload\")", setPrefix, setPrefix, setPrefix, setPrefix, setPrefix, setPrefix, setPrefix, setPrefix) - if strings.Count(candidate, old) != 1 { - return "", nil, fmt.Errorf("expected one %s in endpoint baseline, found %d", old, strings.Count(candidate, old)) - } - candidate = strings.Replace(candidate, old, new, 1) - target, ok := binds[setPrefix+"_target_type"].(string) - if !ok || target == "" { - return "", nil, fmt.Errorf("missing compiled target type bind %s_target_type", setPrefix) - } - binds["@"+setPrefix+"_node_collection"] = target - } - return candidate, binds, nil -} - -func writeMaterializationEvidence(t *testing.T, compiled dataframe.CompiledQuery, candidate string, controlTimes, candidateTimes []float64, controlBytes, candidateBytes []int, controlHash, candidateHash string, controlProfile, candidateProfile arangostore.ProfileResult, controlExplain, candidateExplain arangostore.ExplainResult) { - _, source, _, _ := runtime.Caller(0) - directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "tournament_materialization") - if err := os.MkdirAll(directory, 0o755); err != nil { - t.Fatalf("create materialization evidence directory: %v", err) - } - writeJSON := func(name string, value any) { - data, err := json.MarshalIndent(value, "", " ") - if err != nil { - t.Fatalf("encode %s: %v", name, err) - } - if err := os.WriteFile(filepath.Join(directory, name), append(data, '\n'), 0o644); err != nil { - t.Fatalf("write %s: %v", name, err) - } - } - if err := os.WriteFile(filepath.Join(directory, "control.aql"), []byte(compiled.Query+"\n"), 0o644); err != nil { - t.Fatalf("write control AQL: %v", err) - } - if err := os.WriteFile(filepath.Join(directory, "candidate.aql"), []byte(candidate+"\n"), 0o644); err != nil { - t.Fatalf("write candidate AQL: %v", err) - } - writeJSON("control.profile.json", controlProfile) - writeJSON("candidate.profile.json", candidateProfile) - writeJSON("evidence.json", map[string]any{ - "fixture": "examples/meta_gdc_case_matrix.variables.json", - "limit": 1000, - "control_aql_sha256": sha256Hex(compiled.Query), - "candidate_aql_sha256": sha256Hex(candidate), - "control_result_sha256": controlHash, - "candidate_result_sha256": candidateHash, - "control_seconds": controlTimes, - "candidate_seconds": candidateTimes, - "control_bytes": controlBytes, - "candidate_bytes": candidateBytes, - "control_profile": arangostore.SummarizeProfile(controlProfile), - "candidate_profile": arangostore.SummarizeProfile(candidateProfile), - "control_explain": arangostore.AssessExplainResult(controlExplain), - "candidate_explain": arangostore.AssessExplainResult(candidateExplain), - "decision": "pending-threshold-review", - }) -} diff --git a/internal/dataframe/root_endpoint_experiment_test.go b/internal/dataframe/root_endpoint_experiment_test.go deleted file mode 100644 index 7017763..0000000 --- a/internal/dataframe/root_endpoint_experiment_test.go +++ /dev/null @@ -1,274 +0,0 @@ -package dataframe_test - -// Opt-in, read-only tournament for the broad root sibling hop. The incumbent -// is the current endpoint+typed-selector AQL artifact; this test rewrites only -// its root depth-one traversal and never edits compiler or index definitions. - -import ( - "context" - "encoding/json" - "fmt" - "os" - "path/filepath" - "regexp" - "runtime" - "strings" - "testing" - "time" - - arangostore "github.com/calypr/loom/internal/store/arango" -) - -const incumbentSelectorAQLSHA = "ad8542e8f158d6443b047c63f5cbffd54264c6d2c63fa5bfbbfe87d84e0fa79d" - -type rootEndpointRun struct { - Name string `json:"name"` - QuerySHA256 string `json:"query_sha256"` - ResultSHA256 string `json:"result_sha256"` - Rows int `json:"rows"` - Bytes []int `json:"bytes"` - WarmSeconds []float64 `json:"warm_seconds"` - MedianSeconds float64 `json:"median_seconds"` - MinSeconds float64 `json:"min_seconds"` - Explain arangostore.ExplainAssessment `json:"explain"` - Profile rootEndpointProfile `json:"profile"` - RawProfile arangostore.ProfileResult `json:"-"` -} - -type rootEndpointProfile struct { - ScannedFull int `json:"scanned_full"` - ScannedIndex int `json:"scanned_index"` - PeakMemoryBytes uint64 `json:"peak_memory_bytes"` - Phases arangostore.ProfilePhases `json:"phases"` - TopNodes []arangostore.ProfileNodeSummary `json:"top_nodes"` -} - -func TestRootEndpointCandidateRendersFromFrozenIncumbent(t *testing.T) { - incumbent, binds := loadFrozenIncumbent(t) - candidate, rewrite, err := rewriteRootEndpoint(incumbent) - if err != nil { - t.Fatal(err) - } - if rewrite.Direction != "INBOUND" || rewrite.Endpoint != "_to" || rewrite.TargetEndpoint != "_from" { - t.Fatalf("unexpected root rewrite metadata: %#v", rewrite) - } - if !strings.Contains(candidate, "FILTER "+rewrite.Edge+"._to == root._id") || !strings.Contains(candidate, "DOCUMENT("+rewrite.Edge+"._from)") { - t.Fatalf("candidate omitted endpoint equality/document lookup:\n%s", candidate[:minRootLen(len(candidate), 5000)]) - } - if strings.Contains(candidate, "IN 1..1 INBOUND root @@") { - t.Fatalf("candidate retained native root traversal") - } - if _, ok := binds["@root_collection"]; !ok { - t.Fatalf("frozen incumbent bind variables lost root collection bind") - } -} - -func TestRootEndpointProfilesAgainstFrozenIncumbent(t *testing.T) { - if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { - t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run root endpoint tournament against Arango") - } - incumbent, binds := loadFrozenIncumbent(t) - candidate, rewrite, err := rewriteRootEndpoint(incumbent) - if err != nil { - t.Fatal(err) - } - url, database, _ := compilerArangoTarget() - client, err := arangostore.Open(context.Background(), url, database) - if err != nil { - t.Fatal(err) - } - defer client.Close(context.Background()) - ctx, cancel := context.WithTimeout(context.Background(), 20*time.Minute) - defer cancel() - control, candidateRun, err := runRootEndpointAlternating(ctx, client, incumbent, candidate, binds) - if err != nil { - t.Fatal(err) - } - if control.ResultSHA256 != candidateRun.ResultSHA256 { - t.Fatalf("result parity mismatch control=%s candidate=%s", control.ResultSHA256, candidateRun.ResultSHA256) - } - if candidateRun.MedianSeconds >= control.MedianSeconds { - t.Logf("root endpoint candidate rejected for regression: control=%.6fs candidate=%.6fs", control.MedianSeconds, candidateRun.MedianSeconds) - } else { - t.Logf("root endpoint candidate improvement=%.2f%% control=%.6fs candidate=%.6fs direction=%s endpoint=%s target_endpoint=%s", 100*(control.MedianSeconds-candidateRun.MedianSeconds)/control.MedianSeconds, control.MedianSeconds, candidateRun.MedianSeconds, rewrite.Direction, rewrite.Endpoint, rewrite.TargetEndpoint) - } - writeRootEndpointArtifacts(t, incumbent, candidate, binds, rewrite, control, candidateRun) -} - -type rootEndpointRewrite struct { - Node string `json:"node"` - Edge string `json:"edge"` - Direction string `json:"direction"` - Endpoint string `json:"endpoint"` - TargetEndpoint string `json:"target_endpoint"` - Collection string `json:"collection"` -} - -var rootTraversalHeaderRE = regexp.MustCompile(`(?m)^(\s*)FOR ([A-Za-z_][A-Za-z0-9_]*_node), ([A-Za-z_][A-Za-z0-9_]*_edge) IN 1\.\.1 (INBOUND|OUTBOUND) root (@@[A-Za-z_][A-Za-z0-9_]*_edge_collection)\n`) - -func rewriteRootEndpoint(query string) (string, rootEndpointRewrite, error) { - matches := rootTraversalHeaderRE.FindAllStringSubmatchIndex(query, -1) - if len(matches) != 1 { - return query, rootEndpointRewrite{}, fmt.Errorf("expected one root depth-one traversal, found %d", len(matches)) - } - m := matches[0] - indent := query[m[2]:m[3]] - node := query[m[4]:m[5]] - edge := query[m[6]:m[7]] - direction := query[m[8]:m[9]] - collection := query[m[10]:m[11]] - endpoint, target := "_to", "_from" - if direction == "OUTBOUND" { - endpoint, target = "_from", "_to" - } - replacement := indent + "FOR " + edge + " IN " + collection + "\n" + - indent + " FILTER " + edge + "." + endpoint + " == root._id\n" + - indent + " LET " + node + " = DOCUMENT(" + edge + "." + target + ")\n" - return query[:m[0]] + replacement + query[m[1]:], rootEndpointRewrite{Node: node, Edge: edge, Direction: direction, Endpoint: endpoint, TargetEndpoint: target, Collection: collection}, nil -} - -func loadFrozenIncumbent(t *testing.T) (string, map[string]any) { - _, source, _, _ := runtime.Caller(0) - root := filepath.Join(filepath.Dir(source), "..", "..") - queryPath := filepath.Join(root, "docs", "benchmarks", "round4", "wp2_selector_combo", "candidate.aql") - reportPath := filepath.Join(root, "docs", "benchmarks", "round4", "wp2", "integrated.json") - queryBytes, err := os.ReadFile(queryPath) - if err != nil { - t.Fatalf("read incumbent selector AQL: %v", err) - } - query := strings.TrimSuffix(strings.TrimSuffix(string(queryBytes), "\n"), "\r") - if sha256Hex(query) != incumbentSelectorAQLSHA { - t.Fatalf("incumbent selector AQL hash changed: got %s want %s", sha256Hex(query), incumbentSelectorAQLSHA) - } - reportBytes, err := os.ReadFile(reportPath) - if err != nil { - t.Fatalf("read incumbent bind report: %v", err) - } - var report struct { - BindVars map[string]any `json:"bind_vars"` - } - if err := json.Unmarshal(reportBytes, &report); err != nil { - t.Fatalf("decode incumbent bind report: %v", err) - } - return query, report.BindVars -} - -func runRootEndpointAlternating(ctx context.Context, client *arangostore.Client, incumbent, candidate string, baseBinds map[string]any) (rootEndpointRun, rootEndpointRun, error) { - control := rootEndpointRun{Name: "incumbent_endpoint_selector", QuerySHA256: sha256Hex(incumbent)} - candidateRun := rootEndpointRun{Name: "root_endpoint_endpoint_selector", QuerySHA256: sha256Hex(candidate)} - for i := 0; i < 5; i++ { - controlQuery, controlBinds := cacheBust(incumbent, baseBinds, 12000+i) - candidateQuery, candidateBinds := cacheBust(candidate, baseBinds, 13000+i) - controlSeconds, controlBytes, controlHash, err := executeOrdinary(ctx, client, controlQuery, controlBinds) - if err != nil { - return control, candidateRun, fmt.Errorf("control run %d: %w", i+1, err) - } - candidateSeconds, candidateBytes, candidateHash, err := executeOrdinary(ctx, client, candidateQuery, candidateBinds) - if err != nil { - return control, candidateRun, fmt.Errorf("candidate run %d: %w", i+1, err) - } - control.WarmSeconds = append(control.WarmSeconds, controlSeconds) - control.Bytes = append(control.Bytes, controlBytes) - control.ResultSHA256 = controlHash - control.Rows = 1000 - candidateRun.WarmSeconds = append(candidateRun.WarmSeconds, candidateSeconds) - candidateRun.Bytes = append(candidateRun.Bytes, candidateBytes) - candidateRun.ResultSHA256 = candidateHash - candidateRun.Rows = 1000 - } - control.MedianSeconds, control.MinSeconds = median(control.WarmSeconds), minFloatRoot(control.WarmSeconds) - candidateRun.MedianSeconds, candidateRun.MinSeconds = median(candidateRun.WarmSeconds), minFloatRoot(candidateRun.WarmSeconds) - controlProfileQuery, controlProfileBinds := cacheBust(incumbent, baseBinds, 14001) - candidateProfileQuery, candidateProfileBinds := cacheBust(candidate, baseBinds, 14002) - controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: controlProfileQuery, BindVars: controlProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - return control, candidateRun, fmt.Errorf("control PROFILE: %w", err) - } - candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidateProfileQuery, BindVars: candidateProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - return control, candidateRun, fmt.Errorf("candidate PROFILE: %w", err) - } - control.Explain, err = explainRoot(ctx, client, incumbent, baseBinds) - if err != nil { - return control, candidateRun, err - } - candidateRun.Explain, err = explainRoot(ctx, client, candidate, baseBinds) - if err != nil { - return control, candidateRun, err - } - control.RawProfile, candidateRun.RawProfile = controlProfile, candidateProfile - control.Profile, candidateRun.Profile = summarizeRootProfile(controlProfile), summarizeRootProfile(candidateProfile) - return control, candidateRun, nil -} - -func explainRoot(ctx context.Context, client *arangostore.Client, query string, binds map[string]any) (arangostore.ExplainAssessment, error) { - explain, err := client.Explain(ctx, arangostore.ExplainRequest{Query: query, BindVars: binds}) - if err != nil { - return arangostore.ExplainAssessment{}, err - } - assessment := arangostore.AssessExplainResult(explain) - if len(assessment.FullCollectionScans) != 0 { - return assessment, fmt.Errorf("root endpoint candidate has full scans: %#v", assessment.FullCollectionScans) - } - return assessment, nil -} - -func summarizeRootProfile(profile arangostore.ProfileResult) rootEndpointProfile { - summary := arangostore.SummarizeProfile(profile) - nodes := append([]arangostore.ProfileNodeSummary(nil), summary.Nodes...) - if len(nodes) > 20 { - nodes = nodes[:20] - } - return rootEndpointProfile{ScannedFull: summary.ScannedFull, ScannedIndex: summary.ScannedIndex, PeakMemoryBytes: summary.PeakMemory, Phases: profile.Extra.Profile, TopNodes: nodes} -} - -func minFloatRoot(values []float64) float64 { - if len(values) == 0 { - return 0 - } - minimum := values[0] - for _, value := range values[1:] { - if value < minimum { - minimum = value - } - } - return minimum -} - -func minRootLen(length, maximum int) int { - if length < maximum { - return length - } - return maximum -} - -func writeRootEndpointArtifacts(t *testing.T, incumbent, candidate string, binds map[string]any, rewrite rootEndpointRewrite, control, candidateRun rootEndpointRun) { - _, source, _, _ := runtime.Caller(0) - root := filepath.Join(filepath.Dir(source), "..", "..") - directory := filepath.Join(root, "docs", "benchmarks", "round4", "tournament_root_endpoint") - if err := os.MkdirAll(directory, 0o755); err != nil { - t.Fatal(err) - } - for name, query := range map[string]string{"incumbent.aql": incumbent, "candidate.aql": candidate} { - if err := os.WriteFile(filepath.Join(directory, name), []byte(query+"\n"), 0o644); err != nil { - t.Fatal(err) - } - } - for name, profile := range map[string]arangostore.ProfileResult{"incumbent.profile.json": control.RawProfile, "candidate.profile.json": candidateRun.RawProfile} { - encoded, err := json.MarshalIndent(profile, "", " ") - if err != nil { - t.Fatal(err) - } - if err := os.WriteFile(filepath.Join(directory, name), append(encoded, '\n'), 0o644); err != nil { - t.Fatal(err) - } - } - payload := map[string]any{"incumbent": control, "candidate": candidateRun, "bind_vars": binds, "rewrite": rewrite} - encoded, err := json.MarshalIndent(payload, "", " ") - if err != nil { - t.Fatal(err) - } - if err := os.WriteFile(filepath.Join(directory, "RESULTS.json"), append(encoded, '\n'), 0o644); err != nil { - t.Fatal(err) - } -} diff --git a/internal/dataframe/root_endpoint_live_gate_test.go b/internal/dataframe/root_endpoint_live_gate_test.go deleted file mode 100644 index bf9b6b9..0000000 --- a/internal/dataframe/root_endpoint_live_gate_test.go +++ /dev/null @@ -1,214 +0,0 @@ -package dataframe_test - -import ( - "context" - "encoding/json" - "fmt" - "os" - "path/filepath" - "runtime" - "testing" - "time" - - dataframe "github.com/calypr/loom/internal/dataframe" - arangostore "github.com/calypr/loom/internal/store/arango" -) - -type rootEndpointGateShape struct { - Name string `json:"name"` - Limit int `json:"limit"` - Endpoint bool `json:"endpoint"` - AQLSHA256 string `json:"aql_sha256"` - ResultSHA256 string `json:"result_sha256"` - Rows int `json:"rows"` - Bytes []int `json:"bytes"` - WarmSeconds []float64 `json:"warm_seconds"` - MedianSeconds float64 `json:"median_seconds"` - Explain arangostore.ExplainAssessment `json:"explain"` - Profile rootEndpointGateProfile `json:"profile"` - RawProfile arangostore.ProfileResult `json:"-"` - Query string `json:"-"` - BindVars map[string]any `json:"-"` -} - -type rootEndpointGateProfile struct { - ScannedFull int `json:"scanned_full"` - ScannedIndex int `json:"scanned_index"` - PeakMemoryBytes uint64 `json:"peak_memory_bytes"` - Phases arangostore.ProfilePhases `json:"phases"` - TopNodes []arangostore.ProfileNodeSummary `json:"top_nodes"` -} - -// TestRootEndpointProductionGateAgainstArango is opt-in because it reads the -// provisioned META database. It compares endpoint policy on/off at both -// required limits through BuilderFromInput and consumes every result row. -func TestRootEndpointProductionGateAgainstArango(t *testing.T) { - if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { - t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run root endpoint production gate") - } - url, database, _ := compilerArangoTarget() - client, err := arangostore.Open(context.Background(), url, database) - if err != nil { - t.Fatal(err) - } - defer client.Close(context.Background()) - ctx, cancel := context.WithTimeout(context.Background(), 45*time.Minute) - defer cancel() - results := make([]rootEndpointGateShape, 0, 4) - for _, limit := range []int{25, 1000} { - for _, endpoint := range []bool{false, true} { - compiled := compileRootEndpointGateRequest(t, limit, endpoint) - shape, err := runRootEndpointGateShape(ctx, client, compiled, limit, endpoint) - if err != nil { - t.Fatalf("limit=%d endpoint=%t: %v", limit, endpoint, err) - } - results = append(results, shape) - t.Logf("root endpoint limit=%d endpoint=%t median=%.6fs executing=%.6fs rows=%d hash=%s indexes=%#v profile=%+v", limit, endpoint, shape.MedianSeconds, shape.Profile.Phases.Executing, shape.Rows, shape.ResultSHA256, shape.Explain.Indexes, shape.Profile) - } - } - for _, limit := range []int{25, 1000} { - control := findRootGateShape(results, limit, false) - candidate := findRootGateShape(results, limit, true) - if control.ResultSHA256 != candidate.ResultSHA256 { - t.Fatalf("limit=%d result parity mismatch control=%s candidate=%s", limit, control.ResultSHA256, candidate.ResultSHA256) - } - if control.Rows != candidate.Rows || control.Bytes[0] != candidate.Bytes[0] { - t.Fatalf("limit=%d row/response parity mismatch control rows/bytes=%d/%d candidate=%d/%d", limit, control.Rows, control.Bytes[0], candidate.Rows, candidate.Bytes[0]) - } - if candidate.Profile.PeakMemoryBytes >= 200000000 { - t.Fatalf("limit=%d candidate memory exceeds 200 MB: %d", limit, candidate.Profile.PeakMemoryBytes) - } - if len(candidate.Explain.FullCollectionScans) != 0 { - t.Fatalf("limit=%d candidate full scans: %#v", limit, candidate.Explain.FullCollectionScans) - } - if !hasRootEndpointCompoundIndex(candidate.Explain) { - t.Fatalf("limit=%d candidate did not select endpoint compound index: %#v", limit, candidate.Explain.Indexes) - } - if limit == 1000 && candidate.MedianSeconds >= control.MedianSeconds*0.90 { - t.Fatalf("1,000-row endpoint gate missed 10%% improvement: control=%.6fs candidate=%.6fs", control.MedianSeconds, candidate.MedianSeconds) - } - } - writeRootEndpointGateEvidence(t, results) -} - -func compileRootEndpointGateRequest(t *testing.T, limit int, endpoint bool) dataframe.CompiledQuery { - old, had := os.LookupEnv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL") - if endpoint { - _ = os.Unsetenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL") - } else { - _ = os.Setenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL", "off") - } - defer func() { - if had { - _ = os.Setenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL", old) - } else { - _ = os.Unsetenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL") - } - }() - return compileActualGDC(t, limit) -} - -func runRootEndpointGateShape(ctx context.Context, client *arangostore.Client, compiled dataframe.CompiledQuery, limit int, endpoint bool) (rootEndpointGateShape, error) { - shape := rootEndpointGateShape{Name: fmt.Sprintf("limit_%d_endpoint_%t", limit, endpoint), Limit: limit, Endpoint: endpoint, AQLSHA256: sha256Hex(compiled.Query), Query: compiled.Query, BindVars: compiled.BindVars} - runs := 5 - if limit == 25 { - runs = 3 - } - for run := 0; run < runs; run++ { - query, binds := cacheBust(compiled.Query, compiled.BindVars, 18000+limit+run) - seconds, bytes, hash, err := executeOrdinary(ctx, client, query, binds) - if err != nil { - return shape, err - } - shape.WarmSeconds = append(shape.WarmSeconds, seconds) - shape.Bytes = append(shape.Bytes, bytes) - shape.ResultSHA256 = hash - } - shape.MedianSeconds = median(shape.WarmSeconds) - shape.Rows = limit - query, binds := cacheBust(compiled.Query, compiled.BindVars, 19000+limit+boolInt(endpoint)) - explain, err := client.Explain(ctx, arangostore.ExplainRequest{Query: query, BindVars: binds}) - if err != nil { - return shape, err - } - shape.Explain = arangostore.AssessExplainResult(explain) - profile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: query, BindVars: binds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - return shape, err - } - shape.RawProfile = profile - summary := arangostore.SummarizeProfile(profile) - nodes := append([]arangostore.ProfileNodeSummary(nil), summary.Nodes...) - if len(nodes) > 20 { - nodes = nodes[:20] - } - shape.Profile = rootEndpointGateProfile{ScannedFull: summary.ScannedFull, ScannedIndex: summary.ScannedIndex, PeakMemoryBytes: summary.PeakMemory, Phases: profile.Extra.Profile, TopNodes: nodes} - return shape, nil -} - -func hasRootEndpointCompoundIndex(assessment arangostore.ExplainAssessment) bool { - want := []string{"_to", "project", "dataset_generation", "label", "from_type"} - for _, index := range assessment.Indexes { - if index.Collection != "fhir_edge" || len(index.Fields) != len(want) { - continue - } - match := true - for i := range want { - if index.Fields[i] != want[i] { - match = false - break - } - } - if match { - return true - } - } - return false -} - -func findRootGateShape(results []rootEndpointGateShape, limit int, endpoint bool) rootEndpointGateShape { - for _, result := range results { - if result.Limit == limit && result.Endpoint == endpoint { - return result - } - } - return rootEndpointGateShape{} -} - -func boolInt(value bool) int { - if value { - return 1 - } - return 0 -} - -func writeRootEndpointGateEvidence(t *testing.T, results []rootEndpointGateShape) { - _, source, _, _ := runtime.Caller(0) - root := filepath.Join(filepath.Dir(source), "..", "..") - directory := filepath.Join(root, "docs", "benchmarks", "round4", "root_endpoint_integration") - if err := os.MkdirAll(directory, 0o755); err != nil { - t.Fatal(err) - } - serializable := make([]map[string]any, 0, len(results)) - for _, result := range results { - name := fmt.Sprintf("limit_%d_endpoint_%t", result.Limit, result.Endpoint) - if err := os.WriteFile(filepath.Join(directory, name+".aql"), []byte(result.Query+"\n"), 0o644); err != nil { - t.Fatal(err) - } - encoded, err := json.MarshalIndent(result.RawProfile, "", " ") - if err != nil { - t.Fatal(err) - } - if err := os.WriteFile(filepath.Join(directory, name+".profile.json"), append(encoded, '\n'), 0o644); err != nil { - t.Fatal(err) - } - serializable = append(serializable, map[string]any{"name": result.Name, "limit": result.Limit, "endpoint": result.Endpoint, "aql_sha256": result.AQLSHA256, "result_sha256": result.ResultSHA256, "rows": result.Rows, "bytes": result.Bytes, "warm_seconds": result.WarmSeconds, "median_seconds": result.MedianSeconds, "explain": result.Explain, "profile": result.Profile}) - } - encoded, err := json.MarshalIndent(map[string]any{"results": serializable, "decision": "pending-coordinator-threshold-review"}, "", " ") - if err != nil { - t.Fatal(err) - } - if err := os.WriteFile(filepath.Join(directory, "RESULTS.json"), append(encoded, '\n'), 0o644); err != nil { - t.Fatal(err) - } -} diff --git a/internal/dataframe/root_endpoint_strategy_integration_test.go b/internal/dataframe/root_endpoint_strategy_integration_test.go deleted file mode 100644 index 4d33595..0000000 --- a/internal/dataframe/root_endpoint_strategy_integration_test.go +++ /dev/null @@ -1,68 +0,0 @@ -package dataframe_test - -import ( - "strings" - "testing" - - dataframe "github.com/calypr/loom/internal/dataframe" -) - -func TestRootSiblingEndpointStrategyIsTypedAndAblatable(t *testing.T) { - endpoint := compileActualGDCWithRules(t, true, true) - if !strings.Contains(endpoint.Query, "FOR child_set_1_edge IN @@child_set_1_edge_collection") { - t.Fatalf("endpoint policy did not lower the root sibling group:\n%s", endpoint.Query) - } - for _, want := range []string{ - "FILTER child_set_1_edge._to == root._id", - "FILTER POSITION(@shared_root_subject_Patient_neighbors_target_types, child_set_1_edge.from_type)", - "LET child_set_1_node = DOCUMENT(child_set_1_edge._from)", - "POSITION(@shared_root_subject_Patient_neighbors_target_types, child_set_1_node.resourceType)", - } { - if !strings.Contains(endpoint.Query, want) { - t.Fatalf("root endpoint policy omitted %q:\n%s", want, endpoint.Query) - } - } - - native := compileActualGDCWithRules(t, false, true) - if !strings.Contains(native.Query, "IN 1..1 INBOUND root @@child_set_1_edge_collection") { - t.Fatalf("endpoint policy off did not retain native root sibling traversal:\n%s", native.Query) - } - if strings.Contains(native.Query, "FOR child_set_1_edge IN @@child_set_1_edge_collection") { - t.Fatalf("endpoint policy off still rendered root endpoint lookup:\n%s", native.Query) - } -} - -func TestRootSiblingEndpointStrategyUsesGenericRouteMetadata(t *testing.T) { - // The production strategy must not be selected by a resource-specific - // branch. This generic two-sibling plan exercises the same generated route - // contract used by the GDC request without naming a FHIR type in production. - policy := dataframe.DefaultPhysicalOptimizationPolicy() - semantic, err := dataframe.BuildSemanticPlan(dataframe.Builder{ - Project: "ARANGODB_PROTO", - RootResourceType: "ResearchSubject", - Traversals: []dataframe.TraversalStep{{Label: "study", ToResourceType: "ResearchStudy", Alias: "study"}}, - }) - if err != nil { - t.Fatal(err) - } - physical, err := dataframe.BuildGenericPhysicalPlanWithPolicy(semantic, policy) - if err != nil { - t.Fatal(err) - } - found := false - for _, operation := range physical.Operations { - if operation.Traversal == nil { - continue - } - found = true - if operation.Traversal.Strategy != dataframe.PhysicalTraversalEndpointLookup { - t.Fatalf("proven outbound route strategy = %q", operation.Traversal.Strategy) - } - if operation.Traversal.EndpointField != "_from" || operation.Traversal.EndpointJoinField != "_to" { - t.Fatalf("outbound endpoint fields = %q/%q", operation.Traversal.EndpointField, operation.Traversal.EndpointJoinField) - } - } - if !found { - t.Fatal("generic outbound route produced no traversal") - } -} diff --git a/internal/dataframe/runtime/auth.go b/internal/dataframe/runtime/authorization.go similarity index 100% rename from internal/dataframe/runtime/auth.go rename to internal/dataframe/runtime/authorization.go diff --git a/internal/dataframe/runtime/validation.go b/internal/dataframe/runtime/catalog_validation.go similarity index 100% rename from internal/dataframe/runtime/validation.go rename to internal/dataframe/runtime/catalog_validation.go diff --git a/internal/dataframe/runtime/api.go b/internal/dataframe/runtime/compatibility.go similarity index 98% rename from internal/dataframe/runtime/api.go rename to internal/dataframe/runtime/compatibility.go index 80c5f31..224ca8c 100644 --- a/internal/dataframe/runtime/api.go +++ b/internal/dataframe/runtime/compatibility.go @@ -1,6 +1,8 @@ // Package runtime owns catalog-aware dataframe preparation and execution. -// Compiler contracts are aliased here so the runtime can preserve the -// historical unqualified names internally. +// +// Deprecated compatibility aliases in compatibility.go keep existing direct +// runtime importers source-compatible. New callers should import request and +// compiler contracts from their canonical spec/compiler owners instead. package runtime import ( @@ -15,10 +17,6 @@ type ( FieldSelect = compiler.FieldSelect PivotSelect = compiler.PivotSelect AggregateSelect = compiler.AggregateSelect - RunRequest = compiler.RunRequest - Result = compiler.Result - QueryDiagnostics = compiler.QueryDiagnostics - StreamResult = compiler.StreamResult CompiledQuery = compiler.CompiledQuery SemanticPlan = compiler.SemanticPlan SemanticNode = compiler.SemanticNode diff --git a/internal/dataframe/runtime/query_runtime.go b/internal/dataframe/runtime/cursor.go similarity index 100% rename from internal/dataframe/runtime/query_runtime.go rename to internal/dataframe/runtime/cursor.go diff --git a/internal/dataframe/runtime/execution.go b/internal/dataframe/runtime/execution_service.go similarity index 100% rename from internal/dataframe/runtime/execution.go rename to internal/dataframe/runtime/execution_service.go diff --git a/internal/dataframe/runtime/runtime_helpers.go b/internal/dataframe/runtime/helpers.go similarity index 100% rename from internal/dataframe/runtime/runtime_helpers.go rename to internal/dataframe/runtime/helpers.go diff --git a/internal/dataframe/runtime/pivots.go b/internal/dataframe/runtime/pivot_materialization.go similarity index 100% rename from internal/dataframe/runtime/pivots.go rename to internal/dataframe/runtime/pivot_materialization.go diff --git a/internal/dataframe/runtime/active_generation.go b/internal/dataframe/runtime/prepare_generation.go similarity index 100% rename from internal/dataframe/runtime/active_generation.go rename to internal/dataframe/runtime/prepare_generation.go diff --git a/internal/dataframe/runtime/validation_service.go b/internal/dataframe/runtime/request_validation.go similarity index 100% rename from internal/dataframe/runtime/validation_service.go rename to internal/dataframe/runtime/request_validation.go diff --git a/internal/dataframe/runtime/auth_scope.go b/internal/dataframe/runtime/scope.go similarity index 100% rename from internal/dataframe/runtime/auth_scope.go rename to internal/dataframe/runtime/scope.go diff --git a/internal/dataframe/runtime/types.go b/internal/dataframe/runtime/types.go new file mode 100644 index 0000000..f880035 --- /dev/null +++ b/internal/dataframe/runtime/types.go @@ -0,0 +1,43 @@ +package runtime + +import ( + "time" + + "github.com/calypr/loom/internal/dataframe/compiler" + "github.com/calypr/loom/internal/dataframe/spec" +) + +type RunRequest struct { + Builder spec.Builder + Limit int +} + +type Result struct { + Columns []string + Rows []map[string]any + RowCount int + Diagnostics QueryDiagnostics +} + +// QueryDiagnostics separates the cost of turning a dataframe request into +// rows. ArangoQuery is cursor time excluding Loom's per-row processing; +// RowMaterialization is the time spent flattening and delivering rows. +type QueryDiagnostics struct { + InputResolution time.Duration + RequestPreparation time.Duration + Compilation time.Duration + ArangoQuery time.Duration + RowMaterialization time.Duration + ResultAssembly time.Duration + Total time.Duration + Plan compiler.CompilerPlanDiagnostics +} + +// StreamResult describes rows delivered to a streaming caller. Columns are +// finalized only after iteration because flattened pivots can add bounded, +// data-dependent output keys. +type StreamResult struct { + Columns []string + RowCount int + Diagnostics QueryDiagnostics +} diff --git a/internal/dataframe/selector_expression_experiment_test.go b/internal/dataframe/selector_expression_experiment_test.go deleted file mode 100644 index 772e229..0000000 --- a/internal/dataframe/selector_expression_experiment_test.go +++ /dev/null @@ -1,665 +0,0 @@ -package dataframe_test - -// WP4 is intentionally an external, test-only experiment. It uses the real -// graphqlapi/dataframe.BuilderFromInput path, then rewrites only rendered AQL. -// No production physical IR or renderer is changed here. - -import ( - "context" - "crypto/sha256" - "encoding/hex" - "encoding/json" - "fmt" - "os" - "path/filepath" - "regexp" - "runtime" - "sort" - "strings" - "testing" - "time" - - dataframeapi "github.com/calypr/loom/graphqlapi/dataframe" - "github.com/calypr/loom/graphqlapi/model" - dataframe "github.com/calypr/loom/internal/dataframe" - arangostore "github.com/calypr/loom/internal/store/arango" -) - -type selectorLoweringReport struct { - SelectorSubqueries int `json:"selector_subqueries"` - LoweredSubqueries int `json:"lowered_subqueries"` - DirectScalars int `json:"direct_scalars"` - ConditionalArrays int `json:"conditional_arrays"` - SkippedPredicates int `json:"skipped_predicates"` - SkippedFallbacks int `json:"skipped_fallbacks"` -} - -type selectorStep struct { - Field string - Iterate bool -} - -type selectorSubquery struct { - Start int - End int - Source string - Steps []selectorStep - HasPred bool -} - -var ( - selectorRootRE = regexp.MustCompile(`(?m)FOR __root IN \[([^\]]+)\]`) - selectorLetRE = regexp.MustCompile(`^LET __s[0-9]+ = (__root|__s[0-9]+)\.([A-Za-z_][A-Za-z0-9_]*)$`) - selectorForRE = regexp.MustCompile(`^FOR __s[0-9]+ IN \((__root|__s[0-9]+)\.([A-Za-z_][A-Za-z0-9_]*) \? .* : \[\]\)$`) - selectorValueRE = regexp.MustCompile(`^LET __value = (__root|__s[0-9]+)\.([A-Za-z_][A-Za-z0-9_]*)$`) -) - -// TestSelectorExpressionExperimentLowersActualGDC compiles the actual -// frontend variables and verifies the candidate remains parameterized and -// structurally lowers only generic selector subqueries. -func TestSelectorExpressionExperimentLowersActualGDC(t *testing.T) { - compiled := compileActualGDC(t, 1000) - candidate, report, err := lowerRenderedSelectorExpressions(compiled.Query) - if err != nil { - t.Fatal(err) - } - t.Logf("WP4 selector lowering report: %+v", report) - if report.SelectorSubqueries == 0 || report.LoweredSubqueries == 0 { - // The typed production selector modes may have already removed every - // generic singleton selector loop. The old string-rewrite experiment is - // then intentionally a no-op; keep this structural test green while the - // live ablation remains owned by the typed renderer package. - t.Logf("production AQL already contains no generic lowerable selectors; typed lowering is active: %+v", report) - return - } - if strings.Contains(candidate, "FOR __loom_lowered_selector") == false { - t.Fatalf("candidate unexpectedly removed every selector loop; inspect lowering") - } - if strings.Contains(candidate, "FOR __root IN [") { - // Predicate-bearing or unsupported selector subqueries are allowed to - // remain, but the report must explain why each one was retained. - if report.SkippedPredicates+report.SkippedFallbacks == 0 { - t.Fatalf("candidate retained generic selector subquery without a reported fallback") - } - } - if strings.Contains(candidate, "@@") == false { - t.Fatalf("candidate lost collection binds") - } -} - -// TestSelectorExpressionExperimentProfilesActualGDC is opt-in. It alternates -// cache-busting control/candidate ordinary executions, profiles each shape, -// checks exact result parity and writes raw evidence under the owned WP4 dir. -func TestSelectorExpressionExperimentProfilesActualGDC(t *testing.T) { - if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { - t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run WP4 against Arango") - } - compiled := compileActualGDC(t, 1000) - candidateQuery, lowering, err := lowerRenderedSelectorExpressions(compiled.Query) - if err != nil { - t.Fatal(err) - } - controlQuery, _ := cacheBust(compiled.Query, compiled.BindVars, 0) - candidateQuery, _ = cacheBust(candidateQuery, compiled.BindVars, 0) - url, database, _ := compilerArangoTarget() - client, err := arangostore.Open(context.Background(), url, database) - if err != nil { - t.Fatal(err) - } - defer client.Close(context.Background()) - ctx, cancel := context.WithTimeout(context.Background(), 20*time.Minute) - defer cancel() - controlTimes := make([]float64, 0, 5) - candidateTimes := make([]float64, 0, 5) - controlBytes := make([]int, 0, 5) - candidateBytes := make([]int, 0, 5) - var controlResultHash, candidateResultHash string - for run := 0; run < 5; run++ { - controlQueryRun, controlBindsRun := cacheBust(compiled.Query, compiled.BindVars, run+1) - candidateQueryRun, candidateBindsRun := cacheBust(candidateQuery, compiled.BindVars, run+1) - controlDuration, controlSize, controlHash, err := executeOrdinary(ctx, client, controlQueryRun, controlBindsRun) - if err != nil { - t.Fatalf("control run %d: %v", run+1, err) - } - candidateDuration, candidateSize, candidateHash, err := executeOrdinary(ctx, client, candidateQueryRun, candidateBindsRun) - if err != nil { - t.Fatalf("candidate run %d: %v", run+1, err) - } - controlTimes = append(controlTimes, controlDuration) - candidateTimes = append(candidateTimes, candidateDuration) - controlBytes = append(controlBytes, controlSize) - candidateBytes = append(candidateBytes, candidateSize) - controlResultHash, candidateResultHash = controlHash, candidateHash - } - controlProfileQuery, controlProfileBinds := cacheBust(compiled.Query, compiled.BindVars, 9001) - candidateProfileQuery, candidateProfileBinds := cacheBust(candidateQuery, compiled.BindVars, 9001) - controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: controlProfileQuery, BindVars: controlProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - t.Fatalf("control PROFILE: %v", err) - } - candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidateProfileQuery, BindVars: candidateProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - t.Fatalf("candidate PROFILE: %v", err) - } - if controlResultHash != candidateResultHash || hashRawRows(controlProfile.Result) != hashRawRows(candidateProfile.Result) { - t.Fatalf("result parity mismatch control=%s candidate=%s profile_control=%s profile_candidate=%s", controlResultHash, candidateResultHash, hashRawRows(controlProfile.Result), hashRawRows(candidateProfile.Result)) - } - controlSummary := arangostore.SummarizeProfile(controlProfile) - candidateSummary := arangostore.SummarizeProfile(candidateProfile) - controlMedian := median(controlTimes) - candidateMedian := median(candidateTimes) - t.Logf("WP4 actual GDC selector lowering: report=%+v control_hash=%s candidate_hash=%s control_median=%.6f candidate_median=%.6f control_profile=%+v candidate_profile=%+v control_bytes=%v candidate_bytes=%v", lowering, controlResultHash, candidateResultHash, controlMedian, candidateMedian, controlSummary, candidateSummary, controlBytes, candidateBytes) - if candidateMedian >= controlMedian*0.95 { - t.Fatalf("WP4 candidate failed 5%% whole-query gate: control=%.6fs candidate=%.6fs", controlMedian, candidateMedian) - } - writeSelectorEvidence(t, compiled, controlQuery, candidateQuery, lowering, controlProfile, candidateProfile, controlResultHash, controlTimes, candidateTimes, controlBytes, candidateBytes) -} - -// TestTypedSelectorProfilesActualGDC compares the production typed selector -// mode against the same endpoint-enabled compiler with typed selectors -// disabled. It is the promotion gate for this package, not the legacy string -// rewrite experiment above. -func TestTypedSelectorProfilesActualGDC(t *testing.T) { - if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { - t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run typed selector live gate") - } - control := compileActualGDCWithTypedSelectors(t, false) - candidate := compileActualGDCWithTypedSelectors(t, true) - url, database, _ := compilerArangoTarget() - client, err := arangostore.Open(context.Background(), url, database) - if err != nil { - t.Fatalf("open Arango: %v", err) - } - defer client.Close(context.Background()) - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) - defer cancel() - controlTimes, candidateTimes := make([]float64, 0, 5), make([]float64, 0, 5) - var controlHash, candidateHash string - for run := 0; run < 5; run++ { - controlQuery, controlBinds := cacheBust(control.Query, control.BindVars, 61000+run) - candidateQuery, candidateBinds := cacheBust(candidate.Query, candidate.BindVars, 62000+run) - seconds, _, hash, err := executeOrdinary(ctx, client, controlQuery, controlBinds) - if err != nil { - t.Fatalf("typed selector control run %d: %v", run+1, err) - } - controlTimes = append(controlTimes, seconds) - controlHash = hash - seconds, _, hash, err = executeOrdinary(ctx, client, candidateQuery, candidateBinds) - if err != nil { - t.Fatalf("typed selector candidate run %d: %v", run+1, err) - } - candidateTimes = append(candidateTimes, seconds) - candidateHash = hash - } - if controlHash != candidateHash { - t.Fatalf("typed selector result parity mismatch control=%s candidate=%s", controlHash, candidateHash) - } - controlProfileQuery, controlProfileBinds := cacheBust(control.Query, control.BindVars, 63001) - candidateProfileQuery, candidateProfileBinds := cacheBust(candidate.Query, candidate.BindVars, 63002) - controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: controlProfileQuery, BindVars: controlProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - t.Fatalf("typed selector control PROFILE: %v", err) - } - candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidateProfileQuery, BindVars: candidateProfileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - t.Fatalf("typed selector candidate PROFILE: %v", err) - } - t.Logf("typed selector production control_hash=%s candidate_hash=%s control_median=%.6f candidate_median=%.6f control_profile=%+v candidate_profile=%+v", controlHash, candidateHash, median(controlTimes), median(candidateTimes), arangostore.SummarizeProfile(controlProfile), arangostore.SummarizeProfile(candidateProfile)) - writeTypedSelectorEvidence(t, control, candidate, controlHash, candidateHash, controlTimes, candidateTimes, controlProfile, candidateProfile) -} - -// TestTypedSelectorThreeShapeProfilesActualGDC is the production three-shape -// gate: native incumbent, endpoint-only, and endpoint-plus-typed-selector. -// All three are compiled through BuilderFromInput; no test-only AQL rewrite is -// involved. -func TestTypedSelectorThreeShapeProfilesActualGDC(t *testing.T) { - if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { - t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run three-shape selector gate") - } - native := compileActualGDCWithRules(t, false, false) - endpoint := compileActualGDCWithRules(t, true, false) - candidate := compileActualGDCWithRules(t, true, true) - url, database, _ := compilerArangoTarget() - client, err := arangostore.Open(context.Background(), url, database) - if err != nil { - t.Fatalf("open Arango: %v", err) - } - defer client.Close(context.Background()) - ctx, cancel := context.WithTimeout(context.Background(), 45*time.Minute) - defer cancel() - shapes := []struct { - name string - compiled dataframe.CompiledQuery - times []float64 - bytes []int - hash string - }{ - {name: "native", compiled: native}, - {name: "endpoint_only", compiled: endpoint}, - {name: "endpoint_typed_selector", compiled: candidate}, - } - for run := 0; run < 5; run++ { - for index := range shapes { - query, binds := cacheBust(shapes[index].compiled.Query, shapes[index].compiled.BindVars, 64000+run*10+index) - seconds, bytes, hash, err := executeOrdinary(ctx, client, query, binds) - if err != nil { - t.Fatalf("%s run %d: %v", shapes[index].name, run+1, err) - } - shapes[index].times = append(shapes[index].times, seconds) - shapes[index].bytes = append(shapes[index].bytes, bytes) - shapes[index].hash = hash - } - } - for index := 1; index < len(shapes); index++ { - if shapes[index].hash != shapes[0].hash { - t.Fatalf("three-shape result parity mismatch native=%s %s=%s", shapes[0].hash, shapes[index].name, shapes[index].hash) - } - } - profiles := make(map[string]arangostore.ProfileResult, len(shapes)) - for index := range shapes { - query, binds := cacheBust(shapes[index].compiled.Query, shapes[index].compiled.BindVars, 65000+index) - profile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: query, BindVars: binds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - t.Fatalf("%s PROFILE: %v", shapes[index].name, err) - } - if hashRawRows(profile.Result) != shapes[0].hash { - t.Fatalf("%s PROFILE result parity mismatch", shapes[index].name) - } - profiles[shapes[index].name] = profile - t.Logf("three-shape %s median=%.6f executing=%.6f hash=%s profile=%+v", shapes[index].name, median(shapes[index].times), profile.Extra.Profile.Executing, shapes[index].hash, arangostore.SummarizeProfile(profile)) - } - writeThreeShapeSelectorEvidence(t, shapes, profiles) -} - -func compileActualGDCWithRules(t *testing.T, endpoint, typed bool) dataframe.CompiledQuery { - oldEndpoint, hadEndpoint := os.LookupEnv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL") - oldTyped, hadTyped := os.LookupEnv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS") - if endpoint { - _ = os.Unsetenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL") - } else { - _ = os.Setenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL", "off") - } - if typed { - _ = os.Unsetenv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS") - } else { - _ = os.Setenv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS", "off") - } - defer func() { - if hadEndpoint { - _ = os.Setenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL", oldEndpoint) - } else { - _ = os.Unsetenv("LOOM_PHYSICAL_RULE_ENDPOINT_TRAVERSAL") - } - if hadTyped { - _ = os.Setenv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS", oldTyped) - } else { - _ = os.Unsetenv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS") - } - }() - return compileActualGDC(t, 1000) -} - -func writeThreeShapeSelectorEvidence(t *testing.T, shapes []struct { - name string - compiled dataframe.CompiledQuery - times []float64 - bytes []int - hash string -}, profiles map[string]arangostore.ProfileResult) { - _, source, _, _ := runtimeCaller() - directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "wp2") - if err := os.MkdirAll(directory, 0o755); err != nil { - t.Fatalf("create selector integration evidence directory: %v", err) - } - results := make([]map[string]any, 0, len(shapes)) - for _, shape := range shapes { - results = append(results, map[string]any{"name": shape.name, "aql_sha256": sha256Hex(shape.compiled.Query), "result_sha256": shape.hash, "seconds": shape.times, "bytes": shape.bytes, "profile": profiles[shape.name]}) - if err := os.WriteFile(filepath.Join(directory, "selector-integration-"+shape.name+".aql"), []byte(shape.compiled.Query+"\n"), 0o644); err != nil { - t.Fatalf("write %s AQL: %v", shape.name, err) - } - } - data, err := json.MarshalIndent(map[string]any{"fixture": "meta_gdc_case_matrix.variables.json", "limit": 1000, "results": results, "decision": "pending-coordinator-threshold-review"}, "", " ") - if err != nil { - t.Fatalf("encode selector integration evidence: %v", err) - } - if err := os.WriteFile(filepath.Join(directory, "selector-integration-evidence.json"), append(data, '\n'), 0o644); err != nil { - t.Fatalf("write selector integration evidence: %v", err) - } -} - -func compileActualGDCWithTypedSelectors(t *testing.T, enabled bool) dataframe.CompiledQuery { - old, present := os.LookupEnv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS") - if enabled { - _ = os.Unsetenv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS") - } else { - _ = os.Setenv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS", "off") - } - defer func() { - if present { - _ = os.Setenv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS", old) - } else { - _ = os.Unsetenv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS") - } - }() - return compileActualGDC(t, 1000) -} - -func writeTypedSelectorEvidence(t *testing.T, control, candidate dataframe.CompiledQuery, controlHash, candidateHash string, controlTimes, candidateTimes []float64, controlProfile, candidateProfile arangostore.ProfileResult) { - _, source, _, _ := runtimeCaller() - directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "wp4") - payload := map[string]any{ - "control_aql_sha256": sha256Hex(control.Query), "candidate_aql_sha256": sha256Hex(candidate.Query), - "control_result_sha256": controlHash, "candidate_result_sha256": candidateHash, - "control_seconds": controlTimes, "candidate_seconds": candidateTimes, - "control_profile": controlProfile, "candidate_profile": candidateProfile, - "decision": "pending-coordinator-threshold-review", - } - data, err := json.MarshalIndent(payload, "", " ") - if err != nil { - t.Fatalf("encode typed selector evidence: %v", err) - } - if err := os.WriteFile(filepath.Join(directory, "typed-production-evidence.json"), append(data, '\n'), 0o644); err != nil { - t.Fatalf("write typed selector evidence: %v", err) - } - if err := os.WriteFile(filepath.Join(directory, "typed-production-control.aql"), []byte(control.Query+"\n"), 0o644); err != nil { - t.Fatalf("write typed selector control AQL: %v", err) - } - if err := os.WriteFile(filepath.Join(directory, "typed-production-candidate.aql"), []byte(candidate.Query+"\n"), 0o644); err != nil { - t.Fatalf("write typed selector candidate AQL: %v", err) - } -} - -func compileActualGDC(t *testing.T, limit int) dataframe.CompiledQuery { - _, source, _, _ := runtimeCaller() - variablesPath := filepath.Join(filepath.Dir(source), "..", "..", "examples", "meta_gdc_case_matrix.variables.json") - data, err := os.ReadFile(variablesPath) - if err != nil { - t.Fatalf("read actual GDC variables: %v", err) - } - var payload struct { - Input model.FhirDataframeInput `json:"input"` - } - if err := json.Unmarshal(data, &payload); err != nil { - t.Fatalf("decode actual GDC variables: %v", err) - } - builder := dataframeapi.BuilderFromInput(payload.Input) - compiled, err := dataframe.CompileRequest(builder, limit) - if err != nil { - t.Fatalf("compile actual GDC builder: %v", err) - } - return compiled -} - -// runtimeCaller is kept in a helper so the experiment stays independent of -// the test process working directory (go test normally runs in this package's -// directory). -func runtimeCaller() (uintptr, string, int, bool) { - return runtime.Caller(0) -} - -func lowerRenderedSelectorExpressions(query string) (string, selectorLoweringReport, error) { - var report selectorLoweringReport - var candidates []selectorSubquery - for offset := 0; offset < len(query); { - match := selectorRootRE.FindStringSubmatchIndex(query[offset:]) - if match == nil { - break - } - start := offset + match[0] - rootEnd := offset + match[1] - source := query[offset+match[2] : offset+match[3]] - open := strings.LastIndex(query[:start], "(") - if open < 0 { - return "", report, fmt.Errorf("selector subquery at %d has no opening parenthesis", start) - } - end, err := matchingParen(query, open) - if err != nil { - return "", report, err - } - body := query[rootEnd:end] - steps, hasPredicate, ok := parseSelectorSteps(body) - if !ok { - offset = end + 1 - continue - } - report.SelectorSubqueries++ - candidates = append(candidates, selectorSubquery{Start: open, End: end + 1, Source: source, Steps: steps, HasPred: hasPredicate}) - offset = end + 1 - } - if len(candidates) == 0 { - return query, report, nil - } - var builder strings.Builder - last := 0 - for index, candidate := range candidates { - builder.WriteString(query[last:candidate.Start]) - if candidate.HasPred { - report.SkippedPredicates++ - builder.WriteString(query[candidate.Start:candidate.End]) - } else { - lowered := renderLoweredSelector(candidate.Source, candidate.Steps, index) - builder.WriteString(lowered) - report.LoweredSubqueries++ - if hasIterate(candidate.Steps) { - report.ConditionalArrays++ - } else { - report.DirectScalars++ - } - } - last = candidate.End - } - builder.WriteString(query[last:]) - return builder.String(), report, nil -} - -func matchingParen(query string, open int) (int, error) { - depth := 0 - for index := open; index < len(query); index++ { - switch query[index] { - case '(': - depth++ - case ')': - depth-- - if depth == 0 { - return index, nil - } - } - } - return 0, fmt.Errorf("unclosed selector subquery at %d", open) -} - -func parseSelectorSteps(body string) ([]selectorStep, bool, bool) { - lines := strings.Split(body, "\n") - steps := make([]selectorStep, 0, 4) - hasPredicate := false - current := "__root" - for _, raw := range lines { - line := strings.TrimSpace(raw) - if strings.HasPrefix(line, "FILTER CONTAINS(") { - hasPredicate = true - } - if match := selectorLetRE.FindStringSubmatch(line); match != nil { - if match[1] != current { - return nil, hasPredicate, false - } - steps = append(steps, selectorStep{Field: match[2]}) - current = strings.TrimPrefix(line[:strings.Index(line, " =")], "LET ") - continue - } - if match := selectorForRE.FindStringSubmatch(line); match != nil { - if match[1] != current { - return nil, hasPredicate, false - } - steps = append(steps, selectorStep{Field: match[2], Iterate: true}) - current = strings.TrimPrefix(line[:strings.Index(line, " IN")], "FOR ") - continue - } - if match := selectorValueRE.FindStringSubmatch(line); match != nil { - if match[1] != current { - return nil, hasPredicate, false - } - steps = append(steps, selectorStep{Field: match[2]}) - return steps, hasPredicate, true - } - } - return nil, hasPredicate, false -} - -func renderLoweredSelector(source string, steps []selectorStep, index int) string { - iterateAt := -1 - for stepIndex, step := range steps { - if step.Iterate { - iterateAt = stepIndex - break - } - } - if iterateAt < 0 { - path := source - for _, step := range steps { - path += "." + step.Field - } - return "(" + path + " == null ? [] : [" + path + "])" - } - prefix := source - for _, step := range steps[:iterateAt] { - prefix += "." + step.Field - } - lines := []string{"(" + prefix + " == null ? [] : ("} - current := "" - for stepIndex := iterateAt; stepIndex < len(steps); stepIndex++ { - step := steps[stepIndex] - variable := fmt.Sprintf("__loom_lowered_selector_%d_%d", index, stepIndex) - if step.Iterate { - arraySource := prefix - if current != "" { - arraySource = current - } - arraySource += "." + step.Field - lines = append(lines, " FOR "+variable+" IN ("+arraySource+" ? "+arraySource+" : [])") - current = variable - continue - } - if current == "" { - current = prefix - } - current += "." + step.Field - lines = append(lines, " LET "+variable+" = "+current, " FILTER "+variable+" != null") - current = variable - } - lines = append(lines, " RETURN "+current, "))") - return strings.Join(lines, "\n") -} - -func hasIterate(steps []selectorStep) bool { - for _, step := range steps { - if step.Iterate { - return true - } - } - return false -} - -func cacheBust(query string, binds map[string]any, nonce int) (string, map[string]any) { - copy := make(map[string]any, len(binds)+1) - for key, value := range binds { - copy[key] = value - } - copy["__loom_wp4_nonce"] = nonce - marker := "FOR root IN @@root_collection" - return strings.Replace(query, marker, marker+"\n FILTER @__loom_wp4_nonce == @__loom_wp4_nonce", 1), copy -} - -func executeOrdinary(ctx context.Context, client *arangostore.Client, query string, binds map[string]any) (float64, int, string, error) { - started := time.Now() - bytes := 0 - rows := make([]json.RawMessage, 0, 1000) - err := client.QueryRows(ctx, query, 10000, binds, func(row map[string]any) error { - encoded, err := json.Marshal(row) - if err != nil { - return err - } - bytes += len(encoded) - rows = append(rows, encoded) - return nil - }) - if err != nil { - return 0, 0, "", err - } - return time.Since(started).Seconds(), bytes, hashRawRows(rows), nil -} - -func hashRawRows(rows []json.RawMessage) string { - hash := sha256.New() - for _, row := range rows { - var value any - if json.Unmarshal(row, &value) != nil { - continue - } - canonical, _ := json.Marshal(value) - _, _ = hash.Write(canonical) - _, _ = hash.Write([]byte{'\n'}) - } - return hex.EncodeToString(hash.Sum(nil)) -} - -func median(values []float64) float64 { - ordered := append([]float64(nil), values...) - sort.Float64s(ordered) - if len(ordered) == 0 { - return 0 - } - if len(ordered)%2 == 1 { - return ordered[len(ordered)/2] - } - return (ordered[len(ordered)/2-1] + ordered[len(ordered)/2]) / 2 -} - -func writeSelectorEvidence(t *testing.T, compiled dataframe.CompiledQuery, controlQuery, candidateQuery string, lowering selectorLoweringReport, controlProfile, candidateProfile arangostore.ProfileResult, resultHash string, controlTimes, candidateTimes []float64, controlBytes, candidateBytes []int) { - _, source, _, _ := runtimeCaller() - directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "wp4") - if err := os.MkdirAll(directory, 0o755); err != nil { - t.Fatalf("create WP4 evidence directory: %v", err) - } - if err := os.WriteFile(filepath.Join(directory, "control.aql"), []byte(controlQuery), 0o644); err != nil { - t.Fatalf("write WP4 control AQL: %v", err) - } - if err := os.WriteFile(filepath.Join(directory, "candidate.aql"), []byte(candidateQuery), 0o644); err != nil { - t.Fatalf("write WP4 candidate AQL: %v", err) - } - payload := map[string]any{ - "control_aql_sha256": sha256Hex(controlQuery), "candidate_aql_sha256": sha256Hex(candidateQuery), - "result_sha256": resultHash, "rows": 1000, "lowering": lowering, - "control_profile": controlProfile, "candidate_profile": candidateProfile, - "control_seconds": controlTimes, "candidate_seconds": candidateTimes, - "control_bytes": controlBytes, "candidate_bytes": candidateBytes, - "compiled_columns": compiled.Columns, - } - data, err := json.MarshalIndent(payload, "", " ") - if err != nil { - t.Fatalf("encode WP4 evidence: %v", err) - } - if err := os.WriteFile(filepath.Join(directory, "evidence.json"), append(data, '\n'), 0o644); err != nil { - t.Fatalf("write WP4 evidence: %v", err) - } -} - -func sha256Hex(value string) string { - hash := sha256.Sum256([]byte(value)) - return hex.EncodeToString(hash[:]) -} - -func compilerArangoTarget() (string, string, string) { - url := os.Getenv("LOOM_ARANGO_URL") - if url == "" { - url = "http://127.0.0.1:8529" - } - database := os.Getenv("LOOM_ARANGO_DATABASE") - if database == "" { - database = "fhir_proto" - } - project := os.Getenv("LOOM_ARANGO_PROJECT") - if project == "" { - project = "ARANGODB_PROTO" - } - return url, database, project -} diff --git a/internal/dataframe/semantic/doc.go b/internal/dataframe/semantic/doc.go new file mode 100644 index 0000000..f9e8779 --- /dev/null +++ b/internal/dataframe/semantic/doc.go @@ -0,0 +1,3 @@ +// Package semantic converts a validated dataframe request into a logical FHIR +// dataframe plan without choosing storage routes or emitting AQL. +package semantic diff --git a/internal/dataframe/compiler/selection_semantics.go b/internal/dataframe/semantic/selection_semantics.go similarity index 68% rename from internal/dataframe/compiler/selection_semantics.go rename to internal/dataframe/semantic/selection_semantics.go index e84fad0..277e897 100644 --- a/internal/dataframe/compiler/selection_semantics.go +++ b/internal/dataframe/semantic/selection_semantics.go @@ -1,12 +1,12 @@ -package compiler +package semantic import ( "fmt" - "os" "sort" "strings" "github.com/calypr/loom/fhirschema" + "github.com/calypr/loom/internal/dataframe/spec" ) // SelectionSemanticSpec is the compiler-ready meaning of one field selection. @@ -69,12 +69,12 @@ func ResolveSemanticField(resourceType, nodeAlias string, index int, field Seman if !fhirschema.HasResource(resourceType) { return SelectionSemanticSpec{}, fmt.Errorf("field %q: resource type %q is not in the active FHIR schema", field.Name, resourceType) } - repeated, paths, err := selectorCardinality(resourceType, field.Selector) + repeated, paths, err := spec.SelectorCardinality(resourceType, field.Selector) if err != nil { return SelectionSemanticSpec{}, fmt.Errorf("field %q: %w", field.Name, err) } for fallbackIndex, fallback := range field.Fallbacks { - fallbackRepeated, fallbackPaths, err := selectorCardinality(resourceType, fallback) + fallbackRepeated, fallbackPaths, err := spec.SelectorCardinality(resourceType, fallback) if err != nil { return SelectionSemanticSpec{}, fmt.Errorf("field %q fallback %d: %w", field.Name, fallbackIndex, err) } @@ -135,59 +135,6 @@ func isKnownValueMode(valueMode string) bool { } } -func selectorCardinality(resourceType string, selector Selector) (bool, []string, error) { - if len(selector.Steps) == 0 { - return false, nil, fmt.Errorf("selector is required") - } - metadataParts := make([]string, 0, len(selector.Steps)) - repeatedPaths := make([]string, 0) - for _, step := range selector.Steps { - part := step.Field - probeParts := append(append([]string(nil), metadataParts...), part) - probe := strings.Join(probeParts, ".") - semantics, ok := fhirschema.ResolveFieldSemantics(resourceType, probe) - if !ok { - return false, nil, fmt.Errorf("selector path %q is not in the active FHIR schema", selector.CanonicalPath()) - } - if semantics.Kind == fhirschema.FieldKindArray { - if !step.Iterate && step.Index == nil { - return false, nil, fmt.Errorf("selector path %q crosses repeated field %q without [] or an explicit index", selector.CanonicalPath(), strings.Join(probeParts, ".")) - } - metadataParts = append(metadataParts, part+"[]") - if step.Index == nil { - repeatedPaths = append(repeatedPaths, strings.Join(metadataParts, ".")) - } - } else { - metadataParts = append(metadataParts, part) - } - } - return len(repeatedPaths) > 0, repeatedPaths, nil -} - -func selectorExecutionMode(resourceType string, selector Selector, fallbacks ...Selector) PhysicalSelectorExecutionMode { - switch strings.ToLower(strings.TrimSpace(os.Getenv("LOOM_PHYSICAL_RULE_TYPED_SELECTORS"))) { - case "off", "0", "false", "disabled": - return PhysicalSelectorGeneric - } - if len(fallbacks) != 0 { - return PhysicalSelectorGeneric - } - if selector.Filter != nil { - return PhysicalSelectorGeneric - } - metadata, ok := fhirschema.ResolveTerminalScalarMetadata(resourceType, selector.CanonicalPath()) - if !ok { - return PhysicalSelectorGeneric - } - if selectorHasNoArrays(selector) && !metadata.Repeated { - return PhysicalSelectorDirectScalar - } - if selectorHasIteratedArray(selector) && metadata.Repeated { - return PhysicalSelectorConditionalArray - } - return PhysicalSelectorGeneric -} - func sortedUniqueStrings(values []string) []string { seen := make(map[string]struct{}, len(values)) out := make([]string, 0, len(values)) diff --git a/internal/dataframe/semantic/selector_spec.go b/internal/dataframe/semantic/selector_spec.go new file mode 100644 index 0000000..3f17925 --- /dev/null +++ b/internal/dataframe/semantic/selector_spec.go @@ -0,0 +1,40 @@ +package semantic + +import ( + "fmt" + "strings" + + "github.com/calypr/loom/fhirschema" +) + +func selectorSpecFromSelector(sel Selector) fhirschema.FieldSelectorSpec { + sourcePath := "" + valuePath := "" + if len(sel.Steps) > 0 { + last := len(sel.Steps) - 1 + valuePath = selectorStepText(sel.Steps[last]) + if last > 0 { + parts := make([]string, 0, last) + for _, step := range sel.Steps[:last] { + parts = append(parts, selectorStepText(step)) + } + sourcePath = strings.Join(parts, ".") + } + } + var where *fhirschema.FieldPredicateSpec + if sel.Filter != nil { + where = &fhirschema.FieldPredicateSpec{Path: sel.Filter.Field, Op: fhirschema.PredicateContains, Value: sel.Filter.Needle} + } + return fhirschema.FieldSelectorSpec{SourcePath: sourcePath, Where: where, ValuePath: valuePath} +} + +func selectorStepText(step SelectorStep) string { + text := step.Field + if step.Iterate { + text += "[]" + } + if step.Index != nil { + text += "[" + fmt.Sprint(*step.Index) + "]" + } + return text +} diff --git a/internal/dataframe/compiler/semantic_plan.go b/internal/dataframe/semantic/semantic_plan.go similarity index 98% rename from internal/dataframe/compiler/semantic_plan.go rename to internal/dataframe/semantic/semantic_plan.go index ba0cb3d..ab42aa8 100644 --- a/internal/dataframe/compiler/semantic_plan.go +++ b/internal/dataframe/semantic/semantic_plan.go @@ -1,4 +1,4 @@ -package compiler +package semantic import ( "fmt" @@ -6,6 +6,7 @@ import ( "github.com/calypr/loom/fhirschema" "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/dataframe/spec" ) // SemanticPlan is the validated, backend-independent meaning of a dataframe @@ -104,7 +105,7 @@ func BuildSemanticPlan(builder Builder) (SemanticPlan, error) { plan := SemanticPlan{ Version: 1, Project: builder.Project, - DatasetGeneration: normalizeDatasetGeneration(builder.DatasetGeneration), + DatasetGeneration: strings.TrimSpace(builder.DatasetGeneration), AuthResourcePaths: cloneStrings(builder.AuthResourcePaths), AuthScopeMode: builder.AuthScopeMode, Root: root, @@ -357,7 +358,7 @@ func semanticNodeFromBuilder(alias, resourceType, edgeLabel string, matchMode Tr } func validateSemanticSelector(resourceType string, selector Selector) error { - _, _, err := selectorCardinality(resourceType, selector) + _, _, err := spec.SelectorCardinality(resourceType, selector) return err } @@ -427,6 +428,13 @@ func cloneRowIdentity(identity *RowIdentity) *RowIdentity { return © } +func cloneStrings(in []string) []string { + if in == nil { + return nil + } + return append([]string(nil), in...) +} + type SemanticNodeExplanation struct { Alias string ParentAlias string diff --git a/internal/dataframe/compiler/semantic_validation.go b/internal/dataframe/semantic/semantic_validation.go similarity index 93% rename from internal/dataframe/compiler/semantic_validation.go rename to internal/dataframe/semantic/semantic_validation.go index ef36cea..7d2d1c1 100644 --- a/internal/dataframe/compiler/semantic_validation.go +++ b/internal/dataframe/semantic/semantic_validation.go @@ -1,4 +1,4 @@ -package compiler +package semantic import ( "fmt" @@ -70,8 +70,8 @@ func (s *semanticValidationState) validateChildren(parent SemanticNode, depth in if strings.TrimSpace(child.EdgeLabel) == "" { return fmt.Errorf("semantic traversal edge label is required for %s -> %s at %s", parent.ResourceType, child.ResourceType, location) } - if _, err := resolveStorageRoute(parent.ResourceType, child.EdgeLabel, child.ResourceType); err != nil { - return fmt.Errorf("semantic traversal %s -> %s (%s) at %s: %w", parent.ResourceType, child.ResourceType, child.EdgeLabel, location, err) + if _, ok := fhirschema.LookupTraversal(parent.ResourceType, child.EdgeLabel, child.ResourceType); !ok { + return fmt.Errorf("semantic traversal %s -> %s (%s) at %s is not represented by the active generated FHIR schema", parent.ResourceType, child.ResourceType, child.EdgeLabel, location) } edge := fmt.Sprintf("%s -[%s]-> %s", parent.ResourceType, child.EdgeLabel, child.ResourceType) diff --git a/internal/dataframe/semantic/spec_aliases.go b/internal/dataframe/semantic/spec_aliases.go new file mode 100644 index 0000000..6fdbc02 --- /dev/null +++ b/internal/dataframe/semantic/spec_aliases.go @@ -0,0 +1,39 @@ +package semantic + +import "github.com/calypr/loom/internal/dataframe/spec" + +type ( + Builder = spec.Builder + TraversalStep = spec.TraversalStep + RepresentativeSlice = spec.RepresentativeSlice + FieldSelect = spec.FieldSelect + PivotSelect = spec.PivotSelect + AggregateSelect = spec.AggregateSelect + RowGrain = spec.RowGrain + ProjectionMode = spec.ProjectionMode + Cardinality = spec.Cardinality + RowIdentity = spec.RowIdentity + TraversalMatchMode = spec.TraversalMatchMode + TypedFilter = spec.TypedFilter + Selector = spec.Selector + SelectorStep = spec.SelectorStep +) + +const ( + ProjectionScalar = spec.ProjectionScalar + ProjectionFirst = spec.ProjectionFirst + ProjectionArray = spec.ProjectionArray + ProjectionDistinctArray = spec.ProjectionDistinctArray + CardinalityOptionalOne = spec.CardinalityOptionalOne + CardinalityMany = spec.CardinalityMany +) + +var ( + ParseSelector = spec.ParseSelector + ValidateTypedFilterForResource = spec.ValidateTypedFilterForResource + InferRowGrain = spec.InferRowGrain + RootResourceForGrain = spec.RootResourceForGrain + ValidateRootGrain = spec.ValidateRootGrain + DefaultRowIdentity = spec.DefaultRowIdentity + ValidateProjection = spec.ValidateProjection +) diff --git a/internal/dataframe/compiler/builder_types.go b/internal/dataframe/spec/builder_types.go similarity index 61% rename from internal/dataframe/compiler/builder_types.go rename to internal/dataframe/spec/builder_types.go index 3e35bf6..8702e50 100644 --- a/internal/dataframe/compiler/builder_types.go +++ b/internal/dataframe/spec/builder_types.go @@ -1,10 +1,6 @@ -package compiler +package spec -import ( - "time" - - "github.com/calypr/loom/internal/authscope" -) +import "github.com/calypr/loom/internal/authscope" type Builder struct { Project string @@ -85,51 +81,3 @@ type AggregateSelect struct { PredicateEquals string ValueMode string } - -type RunRequest struct { - Builder Builder - Limit int -} - -type Result struct { - Columns []string - Rows []map[string]any - RowCount int - Diagnostics QueryDiagnostics -} - -// QueryDiagnostics separates the cost of turning a dataframe request into -// rows. ArangoQuery is cursor time excluding Loom's per-row processing; -// RowMaterialization is the time spent flattening and delivering rows. -type QueryDiagnostics struct { - // InputResolution is populated by the GraphQL adapter while resolving field - // references from the catalog before this service is called. - InputResolution time.Duration - RequestPreparation time.Duration - Compilation time.Duration - ArangoQuery time.Duration - RowMaterialization time.Duration - ResultAssembly time.Duration - Total time.Duration - Plan CompilerPlanDiagnostics -} - -// StreamResult describes rows delivered to a streaming caller. Columns are -// finalized only after iteration because flattened pivots can add bounded, -// data-dependent output keys. The streaming callback itself receives each -// flattened row as it is read from Arango. -type StreamResult struct { - Columns []string - RowCount int - Diagnostics QueryDiagnostics -} - -func cloneStrings(in []string) []string { - if in == nil { - return nil - } - if len(in) == 0 { - return []string{} - } - return append([]string(nil), in...) -} diff --git a/internal/dataframe/spec/doc.go b/internal/dataframe/spec/doc.go new file mode 100644 index 0000000..d654792 --- /dev/null +++ b/internal/dataframe/spec/doc.go @@ -0,0 +1,4 @@ +// Package spec defines the backend-independent dataframe request language. +// FHIR schema metadata validates selectors and typed filters here; AQL and +// Arango execution do not belong in this package. +package spec diff --git a/internal/dataframe/compiler/filter.go b/internal/dataframe/spec/filter.go similarity index 99% rename from internal/dataframe/compiler/filter.go rename to internal/dataframe/spec/filter.go index 0e983d4..a39f679 100644 --- a/internal/dataframe/compiler/filter.go +++ b/internal/dataframe/spec/filter.go @@ -1,4 +1,4 @@ -package compiler +package spec import ( "errors" diff --git a/internal/dataframe/compiler/filter_semantics.go b/internal/dataframe/spec/filter_semantics.go similarity index 99% rename from internal/dataframe/compiler/filter_semantics.go rename to internal/dataframe/spec/filter_semantics.go index 6b4de39..350744f 100644 --- a/internal/dataframe/compiler/filter_semantics.go +++ b/internal/dataframe/spec/filter_semantics.go @@ -1,4 +1,4 @@ -package compiler +package spec import ( "fmt" diff --git a/internal/dataframe/compiler/grain.go b/internal/dataframe/spec/grain.go similarity index 99% rename from internal/dataframe/compiler/grain.go rename to internal/dataframe/spec/grain.go index a1a2ba0..9c0a814 100644 --- a/internal/dataframe/compiler/grain.go +++ b/internal/dataframe/spec/grain.go @@ -1,4 +1,4 @@ -package compiler +package spec import ( "fmt" diff --git a/internal/dataframe/compiler/relationship_match.go b/internal/dataframe/spec/relationship_match.go similarity index 91% rename from internal/dataframe/compiler/relationship_match.go rename to internal/dataframe/spec/relationship_match.go index 4355c1a..1a94bef 100644 --- a/internal/dataframe/compiler/relationship_match.go +++ b/internal/dataframe/spec/relationship_match.go @@ -1,4 +1,4 @@ -package compiler +package spec import ( "fmt" @@ -30,3 +30,7 @@ func (m TraversalMatchMode) Validate() error { func (m TraversalMatchMode) required() bool { return m == TraversalMatchRequired } + +func (m TraversalMatchMode) Required() bool { + return m.required() +} diff --git a/internal/dataframe/spec/selector_validation.go b/internal/dataframe/spec/selector_validation.go new file mode 100644 index 0000000..288423e --- /dev/null +++ b/internal/dataframe/spec/selector_validation.go @@ -0,0 +1,46 @@ +package spec + +import ( + "fmt" + "strings" + + "github.com/calypr/loom/fhirschema" +) + +// selectorCardinality is schema validation shared by typed filters and +// semantic selection normalization. It reports repeated paths without making +// a physical projection or AQL decision. +func selectorCardinality(resourceType string, selector Selector) (bool, []string, error) { + if len(selector.Steps) == 0 { + return false, nil, fmt.Errorf("selector is required") + } + metadataParts := make([]string, 0, len(selector.Steps)) + repeatedPaths := make([]string, 0) + for _, step := range selector.Steps { + part := step.Field + probeParts := append(append([]string(nil), metadataParts...), part) + probe := strings.Join(probeParts, ".") + semantics, ok := fhirschema.ResolveFieldSemantics(resourceType, probe) + if !ok { + return false, nil, fmt.Errorf("selector path %q is not in the active FHIR schema", selector.CanonicalPath()) + } + if semantics.Kind == fhirschema.FieldKindArray { + if !step.Iterate && step.Index == nil { + return false, nil, fmt.Errorf("selector path %q crosses repeated field %q without [] or an explicit index", selector.CanonicalPath(), strings.Join(probeParts, ".")) + } + metadataParts = append(metadataParts, part+"[]") + if step.Index == nil { + repeatedPaths = append(repeatedPaths, strings.Join(metadataParts, ".")) + } + } else { + metadataParts = append(metadataParts, part) + } + } + return len(repeatedPaths) > 0, repeatedPaths, nil +} + +// SelectorCardinality exposes schema-only cardinality to the semantic layer. +// It deliberately does not expose any physical lowering decision. +func SelectorCardinality(resourceType string, selector Selector) (bool, []string, error) { + return selectorCardinality(resourceType, selector) +} diff --git a/internal/dataframe/compiler/selectors.go b/internal/dataframe/spec/selectors.go similarity index 98% rename from internal/dataframe/compiler/selectors.go rename to internal/dataframe/spec/selectors.go index 68a5bdd..5f742b7 100644 --- a/internal/dataframe/compiler/selectors.go +++ b/internal/dataframe/spec/selectors.go @@ -1,4 +1,4 @@ -package compiler +package spec import ( "encoding/json" diff --git a/internal/dataframe/summary_pushdown_experiment_test.go b/internal/dataframe/summary_pushdown_experiment_test.go deleted file mode 100644 index f3d1e67..0000000 --- a/internal/dataframe/summary_pushdown_experiment_test.go +++ /dev/null @@ -1,262 +0,0 @@ -package dataframe - -// Round 4 WP8 is deliberately an experiment-only renderer. It starts from -// the real GraphQL production AQL captured by dataframe-profile and rewrites -// one leaf set's aggregate consumers into a typed summary object. No -// production physical IR or renderer is changed here. - -import ( - "context" - "crypto/sha256" - "encoding/hex" - "encoding/json" - "fmt" - "os" - "path/filepath" - "regexp" - "runtime" - "sort" - "strings" - "testing" - "time" - - arangostore "github.com/calypr/loom/internal/store/arango" -) - -type wp8SummaryReport struct { - SetVariable string `json:"set_variable"` - Fields []string `json:"aggregate_projection_fields"` - BeforeLoops int `json:"before_aggregate_loops"` - AfterLoops int `json:"after_aggregate_loops"` - BeforeSorts int `json:"before_sorts"` - AfterSorts int `json:"after_sorts"` - BeforeUnique int `json:"before_unique"` - AfterUnique int `json:"after_unique"` - CandidateHash string `json:"candidate_aql_hash"` - ControlHash string `json:"control_aql_hash"` - Decision string `json:"decision"` -} - -type wp8ProfileArtifact struct { - ControlHash string `json:"control_result_hash"` - CandidateHash string `json:"candidate_result_hash"` - ControlWarm []float64 `json:"control_warm_seconds"` - CandidateWarm []float64 `json:"candidate_warm_seconds"` - Control arangostore.ProfileResult `json:"control_profile"` - Candidate arangostore.ProfileResult `json:"candidate_profile"` - Report wp8SummaryReport `json:"report"` -} - -func TestWP8SummaryPushdownCandidateStructure(t *testing.T) { - control := wp8ReadProductionAQL(t) - candidate, report, err := wp8BuildSummaryCandidate(control) - if err != nil { - t.Fatal(err) - } - report.ControlHash = wp8Hash(control) - report.CandidateHash = wp8Hash(candidate) - if report.SetVariable == "" || len(report.Fields) < 2 { - t.Fatalf("did not find a rich leaf set: %+v", report) - } - if !strings.Contains(candidate, "COLLECT AGGREGATE") { - t.Fatalf("candidate has no typed summary aggregation:\n%s", candidate) - } - if report.AfterLoops >= report.BeforeLoops { - t.Fatalf("summary did not remove aggregate loops: %+v", report) - } - if !strings.Contains(candidate, "representative_files_limit") && !strings.Contains(candidate, "representative_diagnoses_limit") && !strings.Contains(candidate, "representative_samples_limit") { - t.Fatalf("candidate unexpectedly removed all representative slices") - } - t.Logf("WP8 structural summary candidate: %+v", report) -} - -// TestWP8SummaryPushdownProfilesGDC is opt-in. It consumes the exact AQL -// generated from examples/meta_gdc_case_matrix.variables.json (production.json -// records that BuilderFromInput path) and alternates control/candidate runs. -func TestWP8SummaryPushdownProfilesGDC(t *testing.T) { - if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { - t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run WP8 against Arango") - } - control := wp8ReadProductionAQL(t) - candidate, report, err := wp8BuildSummaryCandidate(control) - if err != nil { - t.Fatal(err) - } - bindVars := wp8ReadProductionBinds(t) - url, database, _ := compilerArangoTarget() - client, err := arangostore.Open(context.Background(), url, database) - if err != nil { - t.Fatal(err) - } - defer client.Close(context.Background()) - ctx, cancel := context.WithTimeout(context.Background(), 20*time.Minute) - defer cancel() - controlRows, controlHash, controlBytes, controlTimes := wp8RunAlternating(ctx, client, control, candidate, bindVars, true) - candidateRows, candidateHash, candidateBytes, candidateTimes := wp8RunAlternating(ctx, client, control, candidate, bindVars, false) - if controlRows != candidateRows || controlHash != candidateHash { - t.Fatalf("summary result parity mismatch control rows/hash=%d/%s candidate=%d/%s", controlRows, controlHash, candidateRows, candidateHash) - } - controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: control, BindVars: bindVars, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - t.Fatal(err) - } - candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidate, BindVars: bindVars, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - t.Fatal(err) - } - report.ControlHash = wp8Hash(control) - report.CandidateHash = wp8Hash(candidate) - artifact := wp8ProfileArtifact{ControlHash: controlHash, CandidateHash: candidateHash, ControlWarm: controlTimes, CandidateWarm: candidateTimes, Control: controlProfile, Candidate: candidateProfile, Report: report} - if os.Getenv("LOOM_WP8_WRITE_ARTIFACTS") != "" { - wp8WriteArtifacts(t, control, candidate, artifact) - } - t.Logf("WP8 report=%+v control_rows=%d candidate_rows=%d control_bytes=%d candidate_bytes=%d control_times=%v candidate_times=%v", report, controlRows, candidateRows, controlBytes, candidateBytes, controlTimes, candidateTimes) -} - -func wp8ReadProductionAQL(t *testing.T) string { - _, source, _, _ := runtime.Caller(0) - path := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round3", "wp4", "production.aql") - data, err := os.ReadFile(path) - if err != nil { - t.Fatalf("read production AQL %q: %v", path, err) - } - return string(data) -} - -func wp8ReadProductionBinds(t *testing.T) map[string]any { - _, source, _, _ := runtime.Caller(0) - path := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round3", "wp4", "production.json") - data, err := os.ReadFile(path) - if err != nil { - t.Fatalf("read production profile %q: %v", path, err) - } - var payload struct { - BindVars map[string]any `json:"bind_vars"` - } - if err := json.Unmarshal(data, &payload); err != nil { - t.Fatalf("decode production profile: %v", err) - } - return payload.BindVars -} - -func wp8BuildSummaryCandidate(control string) (string, wp8SummaryReport, error) { - // Locate the richest leaf set structurally. The regex only recognizes - // renderer-owned set syntax and never names a FHIR type or example alias. - setRE := regexp.MustCompile(`(?ms)^ LET ([A-Za-z0-9_]+) = UNIQUE\(\(.*?^ {2,}\)\)\n`) - blocks := setRE.FindAllStringSubmatchIndex(control, -1) - if len(blocks) == 0 { - return "", wp8SummaryReport{}, fmt.Errorf("no child set materialization found") - } - fieldRE := regexp.MustCompile(`__loom_projection_[0-9]+`) - chosen := blocks[0] - chosenFields := fieldRE.FindAllString(control[chosen[0]:chosen[1]], -1) - for _, block := range blocks[1:] { - fields := fieldRE.FindAllString(control[block[0]:block[1]], -1) - if len(fields) > len(chosenFields) { - chosen, chosenFields = block, fields - } - } - setVariable := control[chosen[2]:chosen[3]] - // Keep one occurrence of each projection field and only select fields used - // by aggregate loops in RETURN. Slice projections remain independent and - // retain their exact sort-before-limit semantics. - seen := map[string]bool{} - fields := make([]string, 0, len(chosenFields)) - returnStart := strings.LastIndex(control, "\nRETURN ") - if returnStart < 0 { - return "", wp8SummaryReport{}, fmt.Errorf("production AQL has no RETURN") - } - returnText := control[returnStart:] - for _, field := range chosenFields { - if seen[field] || !strings.Contains(returnText, "FOR __loom_prepared_value IN "+setVariable+" RETURN __loom_prepared_value."+field) { - continue - } - seen[field] = true - fields = append(fields, field) - } - if len(fields) < 2 { - return "", wp8SummaryReport{}, fmt.Errorf("rich set %q has fewer than two aggregate selector fields: candidates=%v return=%s", setVariable, chosenFields, returnText) - } - sort.Strings(fields) - summaryVariable := "__loom_summary_" + setVariable - parts := make([]string, 0, len(fields)) - outputs := make([]string, 0, len(fields)+1) - for index, field := range fields { - name := fmt.Sprintf("values_%d", index) - parts = append(parts, fmt.Sprintf(" __loom_summary_%d = UNIQUE(__loom_summary_item.%s)", index, field)) - outputs = append(outputs, fmt.Sprintf("%s: SORTED_UNIQUE(FLATTEN(__loom_summary_%d))", name, index)) - } - summary := fmt.Sprintf(" LET %s = FIRST((\n FOR __loom_summary_item IN %s\n COLLECT AGGREGATE\n __loom_summary_count = COUNT(),\n%s\n RETURN { count: __loom_summary_count, %s }\n )) || { count: 0, %s }\n", summaryVariable, setVariable, strings.Join(parts, ",\n"), strings.Join(outputs, ", "), strings.Join(outputs, ", ")) - // Inject immediately after the selected set's materialization. The source - // set remains unchanged, so scope, identity, ordering, and optional roots - // are untouched; only rich aggregate reads are redirected. - candidate := control[:chosen[1]] + summary + control[chosen[1]:] - candidateReturnStart := strings.LastIndex(candidate, "\nRETURN ") - candidateReturn := candidate[candidateReturnStart:] - candidateReturn = strings.ReplaceAll(candidateReturn, "LENGTH("+setVariable+")", summaryVariable+".count") - for index, field := range fields { - old := "SORTED_UNIQUE(FLATTEN((FOR __loom_prepared_value IN " + setVariable + " RETURN __loom_prepared_value." + field + ")))" - newValue := fmt.Sprintf("%s.values_%d", summaryVariable, index) - candidateReturn = strings.ReplaceAll(candidateReturn, old, newValue) - } - candidate = candidate[:candidateReturnStart] + candidateReturn - report := wp8SummaryReport{SetVariable: setVariable, Fields: fields, BeforeLoops: strings.Count(controlReturnText(control), "FOR __loom_prepared_value IN "+setVariable), AfterLoops: strings.Count(controlReturnText(candidate), "FOR __loom_prepared_value IN "+setVariable), BeforeSorts: strings.Count(control, "\n SORT "), AfterSorts: strings.Count(candidate, "\n SORT "), BeforeUnique: strings.Count(control, "UNIQUE("), AfterUnique: strings.Count(candidate, "UNIQUE(")} - return candidate, report, nil -} - -func controlReturnText(aql string) string { - if index := strings.LastIndex(aql, "\nRETURN "); index >= 0 { - return aql[index:] - } - return aql -} - -func wp8Hash(value string) string { - hash := sha256.Sum256([]byte(value)) - return hex.EncodeToString(hash[:]) -} - -func wp8RunAlternating(ctx context.Context, client *arangostore.Client, control, candidate string, binds map[string]any, runControl bool) (int, string, int, []float64) { - times := make([]float64, 0, 5) - rows := 0 - bytes := 0 - hash := sha256.New() - for run := 0; run < 5; run++ { - query := candidate - if runControl { - query = control - } - started := time.Now() - _ = client.QueryRows(ctx, query, 10000, binds, func(row map[string]any) error { - rows++ - encoded, _ := json.Marshal(row) - bytes += len(encoded) - _, _ = hash.Write(encoded) - _, _ = hash.Write([]byte{'\n'}) - return nil - }) - times = append(times, time.Since(started).Seconds()) - } - return rows / 5, hex.EncodeToString(hash.Sum(nil)), bytes / 5, times -} - -func wp8WriteArtifacts(t *testing.T, control, candidate string, artifact wp8ProfileArtifact) { - _, source, _, _ := runtime.Caller(0) - directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "wp8") - if err := os.MkdirAll(directory, 0o755); err != nil { - t.Fatal(err) - } - if err := os.WriteFile(filepath.Join(directory, "control.aql"), []byte(control), 0o644); err != nil { - t.Fatal(err) - } - if err := os.WriteFile(filepath.Join(directory, "candidate.aql"), []byte(candidate), 0o644); err != nil { - t.Fatal(err) - } - data, err := json.MarshalIndent(artifact, "", " ") - if err != nil { - t.Fatal(err) - } - if err := os.WriteFile(filepath.Join(directory, "evidence.json"), append(data, '\n'), 0o644); err != nil { - t.Fatal(err) - } -} diff --git a/internal/dataframe/tournament_pivot_test.go b/internal/dataframe/tournament_pivot_test.go deleted file mode 100644 index 57b1cf3..0000000 --- a/internal/dataframe/tournament_pivot_test.go +++ /dev/null @@ -1,409 +0,0 @@ -package dataframe_test - -// Round 4 pivot tournament. This is an isolated AQL experiment over the -// endpoint+typed-selector production shape; no production compiler changes. - -import ( - "context" - "encoding/json" - "fmt" - "os" - "path/filepath" - "runtime" - "strings" - "testing" - "time" - - arangostore "github.com/calypr/loom/internal/store/arango" -) - -type pivotTournamentRun struct { - ControlSeconds []float64 `json:"control_seconds"` - CandidateSeconds []float64 `json:"candidate_seconds"` - ControlBytes []int `json:"control_bytes"` - CandidateBytes []int `json:"candidate_bytes"` - ControlHash string `json:"control_result_sha256"` - CandidateHash string `json:"candidate_result_sha256"` - ControlProfile arangostore.ProfileResult `json:"control_profile"` - CandidateProfile arangostore.ProfileResult `json:"candidate_profile"` -} - -type pivotTournamentMeasurement struct { - Seconds []float64 `json:"seconds"` - Bytes []int `json:"bytes"` - Hash string `json:"result_sha256"` - Profile arangostore.ProfileResult `json:"profile"` -} - -func TestPivotCandidateStructure(t *testing.T) { - control := readPivotAQL(t) - candidate, err := buildPivotCandidate(control) - if err != nil { - t.Fatal(err) - } - if !strings.Contains(candidate, "FOR __pivot_key IN @pivot_child_set_6_observation_values_columns") || !strings.Contains(candidate, "SORTED_UNIQUE(FLATTEN((") { - t.Fatalf("candidate did not build fixed-column pivot reduction:\n%s", candidate) - } - if strings.Contains(candidate, "COLLECT __pivot_key = __pair.key") { - t.Fatal("candidate retained the old per-pair COLLECT pivot reduction") - } - if !strings.Contains(candidate, "FOR __pivot_key IN @pivot_child_set_6_observation_values_columns") { - t.Fatal("candidate lost fixed pivot-column order") - } - t.Logf("pivot candidate control_hash=%s candidate_hash=%s", sha256Hex(control), sha256Hex(candidate)) -} - -func TestPivotCandidateProfilesActualGDC(t *testing.T) { - if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { - t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run pivot tournament") - } - control := readPivotAQL(t) - candidate, err := buildPivotCandidate(control) - if err != nil { - t.Fatal(err) - } - binds := readPivotBinds(t) - url, database, _ := compilerArangoTarget() - client, err := arangostore.Open(context.Background(), url, database) - if err != nil { - t.Fatalf("open Arango: %v", err) - } - defer client.Close(context.Background()) - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) - defer cancel() - run := pivotTournamentRun{} - for index := 0; index < 5; index++ { - controlQuery, controlBinds := cacheBust(control, binds, 68000+index*2) - candidateQuery, candidateBinds := cacheBust(candidate, binds, 68001+index*2) - seconds, bytes, hash, err := executeOrdinary(ctx, client, controlQuery, controlBinds) - if err != nil { - t.Fatalf("control run %d: %v", index+1, err) - } - run.ControlSeconds = append(run.ControlSeconds, seconds) - run.ControlBytes = append(run.ControlBytes, bytes) - run.ControlHash = hash - seconds, bytes, hash, err = executeOrdinary(ctx, client, candidateQuery, candidateBinds) - if err != nil { - t.Fatalf("candidate run %d: %v", index+1, err) - } - run.CandidateSeconds = append(run.CandidateSeconds, seconds) - run.CandidateBytes = append(run.CandidateBytes, bytes) - run.CandidateHash = hash - } - if run.ControlHash != run.CandidateHash { - t.Fatalf("pivot result parity mismatch control=%s candidate=%s", run.ControlHash, run.CandidateHash) - } - controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: control, BindVars: binds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - t.Fatalf("control PROFILE: %v", err) - } - candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidate, BindVars: binds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - t.Fatalf("candidate PROFILE: %v", err) - } - if hashRawRows(controlProfile.Result) != hashRawRows(candidateProfile.Result) { - t.Fatalf("pivot PROFILE result parity mismatch") - } - run.ControlProfile = controlProfile - run.CandidateProfile = candidateProfile - t.Logf("pivot control_median=%.6f candidate_median=%.6f control_profile=%+v candidate_profile=%+v", median(run.ControlSeconds), median(run.CandidateSeconds), arangostore.SummarizeProfile(controlProfile), arangostore.SummarizeProfile(candidateProfile)) - writePivotEvidence(t, control, candidate, run) -} - -// TestPivotMiniTournamentProfilesReductionShapes compares only pivot reduction -// shapes. The source child_set_6 and every non-pivot expression remain frozen, -// so a result or timing change is attributable to the pivot lowering. -func TestPivotMiniTournamentProfilesReductionShapes(t *testing.T) { - if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { - t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run pivot tournament") - } - control := readPivotAQL(t) - columns := readPivotColumns(t) - candidates := map[string]string{ - "min_zip": buildPivotReduction(control, pivotMinZipBody(false, false)), - "min_zip_hash": buildPivotReduction(control, pivotMinZipBody(true, false)), - "min_zip_has": buildPivotReduction(control, pivotMinZipBody(false, true)), - "sorted_unique": buildPivotReduction(control, pivotSortedUniqueZipBody()), - } - binds := readPivotBinds(t) - allowed := make(map[string]bool, len(columns)) - for _, column := range columns { - allowed[column] = true - } - candidateBinds := make(map[string]any, len(binds)+1) - for key, value := range binds { - candidateBinds[key] = value - } - candidateBinds["pivot_allowed"] = allowed - mapCandidateBinds := make(map[string]any, len(candidateBinds)) - for key, value := range candidateBinds { - if key != "pivot_child_set_6_observation_values_columns" { - mapCandidateBinds[key] = value - } - } - url, database, _ := compilerArangoTarget() - client, err := arangostore.Open(context.Background(), url, database) - if err != nil { - t.Fatalf("open Arango: %v", err) - } - defer client.Close(context.Background()) - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) - defer cancel() - - runs := map[string]*pivotTournamentMeasurement{"control": {}} - for name := range candidates { - runs[name] = &pivotTournamentMeasurement{} - } - runCount := 5 - if value := os.Getenv("LOOM_PIVOT_TOURNAMENT_RUNS"); value != "" { - if _, scanErr := fmt.Sscanf(value, "%d", &runCount); scanErr != nil || runCount < 1 { - t.Fatalf("LOOM_PIVOT_TOURNAMENT_RUNS must be a positive integer, got %q", value) - } - } - candidateNames := sortedPivotCandidateNames(candidates) - for index := 0; index < runCount; index++ { - t.Logf("pivot tournament run %d/%d: control", index+1, runCount) - query, queryBinds := cacheBust(control, binds, 72000+index*10) - seconds, bytes, hash, runErr := executeOrdinary(ctx, client, query, queryBinds) - if runErr != nil { - t.Fatalf("control run %d: %v", index+1, runErr) - } - runs["control"].Seconds = append(runs["control"].Seconds, seconds) - runs["control"].Bytes = append(runs["control"].Bytes, bytes) - runs["control"].Hash = hash - for candidateIndex, name := range candidateNames { - t.Logf("pivot tournament run %d/%d: candidate %s", index+1, runCount, name) - candidateRunBindsBase := binds - if name == "min_zip_has" { - candidateRunBindsBase = mapCandidateBinds - } - candidateQuery, candidateRunBinds := cacheBust(candidates[name], candidateRunBindsBase, 72001+index*10+candidateIndex) - seconds, bytes, hash, runErr = executeOrdinary(ctx, client, candidateQuery, candidateRunBinds) - if runErr != nil { - t.Fatalf("%s run %d: %v", name, index+1, runErr) - } - runs[name].Seconds = append(runs[name].Seconds, seconds) - runs[name].Bytes = append(runs[name].Bytes, bytes) - runs[name].Hash = hash - } - } - for _, name := range append([]string{"control"}, candidateNames...) { - run := runs[name] - if run.Hash != runs["control"].Hash { - t.Logf("pivot result parity mismatch candidate=%s control=%s candidate_hash=%s", name, runs["control"].Hash, run.Hash) - } - } - queries := map[string]string{"control": control} - for _, name := range candidateNames { - queries[name] = candidates[name] - } - writePivotTournamentEvidence(t, control, candidates, runs) - if os.Getenv("LOOM_PIVOT_TOURNAMENT_SKIP_PROFILE") != "" { - for _, name := range append([]string{"control"}, candidateNames...) { - run := runs[name] - t.Logf("pivot %s median=%.6fs bytes=%d hash=%s", name, median(run.Seconds), run.Bytes[0], run.Hash) - } - return - } - for name, query := range queries { - profileBinds := binds - if name == "min_zip_has" { - profileBinds = mapCandidateBinds - } - profile, profileErr := client.Profile(ctx, arangostore.ProfileRequest{Query: query, BindVars: profileBinds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if profileErr != nil { - t.Fatalf("%s PROFILE: %v", name, profileErr) - } - runs[name].Profile = profile - assessment := arangostore.SummarizeProfile(profile) - t.Logf("pivot %s median=%.6fs bytes=%d profile_runtime=%.6fs scanned_index=%d scanned_full=%d peak_memory=%d", name, median(runs[name].Seconds), runs[name].Bytes[0], assessment.RuntimeSeconds, assessment.ScannedIndex, assessment.ScannedFull, assessment.PeakMemory) - } -} - -func readPivotColumns(t *testing.T) []string { - binds := readPivotBinds(t) - columns, ok := binds["pivot_child_set_6_observation_values_columns"].([]any) - if !ok { - t.Fatalf("pivot columns bind has unexpected type %T", binds["pivot_child_set_6_observation_values_columns"]) - } - result := make([]string, 0, len(columns)) - for _, column := range columns { - value, ok := column.(string) - if !ok { - t.Fatalf("pivot column has unexpected type %T", column) - } - result = append(result, value) - } - return result -} - -func sortedPivotCandidateNames(candidates map[string]string) []string { - if only := os.Getenv("LOOM_PIVOT_TOURNAMENT_ONLY"); only != "" { - if _, ok := candidates[only]; ok { - return []string{only} - } - } - return []string{"min_zip", "min_zip_hash", "min_zip_has", "sorted_unique"} -} - -func buildPivotReduction(control, body string) string { - marker := ", [@__loom_physical_projection_20_name]: MERGE(" - start := strings.Index(control, marker) - if start < 0 { - panic("pivot marker not found") - } - endRel := strings.Index(control[start:], "\n) }\n") - if endRel < 0 { - panic("pivot expression end not found") - } - return control[:start] + ", [@__loom_physical_projection_20_name]: " + body + control[start+endRel:] -} - -func pivotMinZipBody(hash, hasMap bool) string { - membership := "POSITION(@pivot_child_set_6_observation_values_columns, __pivot_key)" - if hasMap { - membership = "HAS(@pivot_allowed, __pivot_key)" - } - method := "" - if hash { - method = " OPTIONS { method: \"hash\" }" - } - return fmt.Sprintf(`FIRST(( - LET __pivot_pairs = ( - FOR __pivot_item IN child_set_6 - LET __pivot_keys = UNIQUE(__pivot_item.__loom_projection_0) - LET __pivot_values = __pivot_item.__loom_projection_1 - FILTER LENGTH(__pivot_values) > 0 - FOR __pivot_key IN __pivot_keys - FILTER %s - FOR __pivot_value IN __pivot_values - COLLECT __pivot_group_key = __pivot_key AGGREGATE __pivot_selected = MIN(__pivot_value)%s - RETURN [__pivot_group_key, __pivot_selected] - ) - RETURN ZIP(__pivot_pairs[*][0], __pivot_pairs[*][1]) -) -`, membership, method) -} - -func pivotSortedUniqueZipBody() string { - return `FIRST(( - LET __pivot_pairs = ( - FOR __pivot_item IN child_set_6 - LET __pivot_keys = UNIQUE(__pivot_item.__loom_projection_0) - LET __pivot_values = __pivot_item.__loom_projection_1 - FILTER LENGTH(__pivot_values) > 0 - FOR __pivot_key IN __pivot_keys - FILTER POSITION(@pivot_child_set_6_observation_values_columns, __pivot_key) - FOR __pivot_value IN __pivot_values - COLLECT __pivot_group_key = __pivot_key AGGREGATE __pivot_values_sorted = SORTED_UNIQUE(__pivot_value) - RETURN [__pivot_group_key, FIRST(__pivot_values_sorted)] - ) - RETURN ZIP(__pivot_pairs[*][0], __pivot_pairs[*][1]) -) -` -} - -func writePivotTournamentEvidence(t *testing.T, control string, candidates map[string]string, runs map[string]*pivotTournamentMeasurement) { - _, source, _, _ := runtime.Caller(0) - directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "tournament_pivot_mini") - if err := os.MkdirAll(directory, 0o755); err != nil { - t.Fatalf("create pivot tournament evidence directory: %v", err) - } - files := map[string]string{"incumbent.aql": control} - for name, query := range candidates { - files[name+".aql"] = query - } - for name, contents := range files { - if err := os.WriteFile(filepath.Join(directory, name), []byte(contents), 0o644); err != nil { - t.Fatalf("write pivot tournament %s: %v", name, err) - } - } - hashes := make(map[string]string, len(candidates)) - for name, query := range candidates { - hashes[name] = sha256Hex(query) - } - payload := map[string]any{ - "incumbent_aql_sha256": sha256Hex(control), - "candidate_aql_sha256": hashes, - "runs": runs, - "candidate_names": sortedPivotCandidateNames(candidates), - "promotion_threshold": "10% wall-time or peak-memory improvement with exact result parity", - } - data, err := json.MarshalIndent(payload, "", " ") - if err != nil { - t.Fatalf("encode pivot tournament evidence: %v", err) - } - if err := os.WriteFile(filepath.Join(directory, "RESULTS.json"), append(data, '\n'), 0o644); err != nil { - t.Fatalf("write pivot tournament RESULTS.json: %v", err) - } -} - -func readPivotAQL(t *testing.T) string { - _, source, _, _ := runtime.Caller(0) - path := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "wp2", "selector-integration-endpoint_typed_selector.aql") - data, err := os.ReadFile(path) - if err != nil { - t.Fatalf("read frozen pivot AQL: %v", err) - } - return string(data) -} - -func readPivotBinds(t *testing.T) map[string]any { - _, source, _, _ := runtime.Caller(0) - path := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round3", "wp4", "production.json") - data, err := os.ReadFile(path) - if err != nil { - t.Fatalf("read pivot binds: %v", err) - } - var payload struct { - BindVars map[string]any `json:"bind_vars"` - } - if err := json.Unmarshal(data, &payload); err != nil { - t.Fatalf("decode pivot binds: %v", err) - } - return payload.BindVars -} - -func buildPivotCandidate(control string) (string, error) { - marker := ", [@__loom_physical_projection_20_name]: MERGE(" - start := strings.Index(control, marker) - if start < 0 { - return "", fmt.Errorf("pivot marker not found") - } - endRel := strings.Index(control[start:], "\n) }\n") - if endRel < 0 { - return "", fmt.Errorf("pivot expression end not found") - } - end := start + endRel - candidatePivot := `, [@__loom_physical_projection_20_name]: MERGE( - FOR __pivot_key IN @pivot_child_set_6_observation_values_columns - LET __pivot_values = SORTED_UNIQUE(FLATTEN(( - FOR __pivot_item IN child_set_6 - FILTER POSITION(__pivot_item.__loom_projection_0, __pivot_key) - RETURN __pivot_item.__loom_projection_1 - ))) - FILTER LENGTH(__pivot_values) > 0 - RETURN { [__pivot_key]: FIRST(__pivot_values) } -` - return control[:start] + candidatePivot + control[end:], nil -} - -func writePivotEvidence(t *testing.T, control, candidate string, run pivotTournamentRun) { - _, source, _, _ := runtime.Caller(0) - directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "tournament_pivot") - if err := os.MkdirAll(directory, 0o755); err != nil { - t.Fatalf("create pivot evidence directory: %v", err) - } - for name, value := range map[string]string{"control.aql": control, "candidate.aql": candidate} { - if err := os.WriteFile(filepath.Join(directory, name), []byte(value), 0o644); err != nil { - t.Fatalf("write pivot %s: %v", name, err) - } - } - payload, err := json.MarshalIndent(map[string]any{"control_aql_sha256": sha256Hex(control), "candidate_aql_sha256": sha256Hex(candidate), "run": run, "decision": "pending-coordinator-threshold-review"}, "", " ") - if err != nil { - t.Fatalf("encode pivot evidence: %v", err) - } - if err := os.WriteFile(filepath.Join(directory, "evidence.json"), append(payload, '\n'), 0o644); err != nil { - t.Fatalf("write pivot evidence: %v", err) - } -} diff --git a/internal/dataframe/tournament_sort_order_test.go b/internal/dataframe/tournament_sort_order_test.go deleted file mode 100644 index b971b9b..0000000 --- a/internal/dataframe/tournament_sort_order_test.go +++ /dev/null @@ -1,192 +0,0 @@ -package dataframe_test - -// Round 4 sort/order tournament. This is deliberately an AQL-only experiment -// over the current endpoint+typed-selector production shape; no optimizer or -// renderer code is changed here. - -import ( - "context" - "encoding/json" - "os" - "path/filepath" - "runtime" - "strings" - "testing" - "time" - - arangostore "github.com/calypr/loom/internal/store/arango" -) - -type sortOrderRun struct { - ControlSeconds []float64 `json:"control_seconds"` - CandidateSeconds []float64 `json:"candidate_seconds"` - ControlBytes []int `json:"control_bytes"` - CandidateBytes []int `json:"candidate_bytes"` - ControlHash string `json:"control_result_sha256"` - CandidateHash string `json:"candidate_result_sha256"` - ControlProfile arangostore.ProfileResult `json:"control_profile"` - CandidateProfile arangostore.ProfileResult `json:"candidate_profile"` -} - -func TestSortOrderCandidateStructure(t *testing.T) { - control := readSortOrderAQL(t) - candidate, removed, err := buildSortOrderCandidate(control) - if err != nil { - t.Fatal(err) - } - if removed != 6 { - t.Fatalf("removed sort operations = %d, want 6 (three child sorts plus three duplicate slice keys)", removed) - } - for _, fragment := range []string{ - "SORT child_set_1_node._key", - "SORT child_set_2_item._key", - "SORT child_set_3_node._key", - "SORT __loom_physical_slice_item._key ASC\n", - "SORT __loom_physical_slice_item_1._key ASC\n", - "SORT __loom_physical_slice_item_2._key ASC\n", - } { - if !strings.Contains(candidate, fragment) { - t.Fatalf("candidate removed required order fragment %q:\n%s", fragment, candidate) - } - } - if strings.Contains(candidate, "SORT child_set_4_node._key") || strings.Contains(candidate, "SORT child_set_5_node._key") || strings.Contains(candidate, "SORT child_set_6_item._key") { - t.Fatalf("candidate retained an order-insensitive child sort") - } - if strings.Contains(candidate, "ASC, __loom_physical_slice_item._key ASC") { - t.Fatalf("candidate retained duplicate slice sort key") - } - t.Logf("sort/order candidate removed=%d control_hash=%s candidate_hash=%s", removed, sha256Hex(control), sha256Hex(candidate)) -} - -func TestSortOrderCandidateProfilesActualGDC(t *testing.T) { - if os.Getenv("LOOM_COMPILER_ARANGO_INTEGRATION") == "" { - t.Skip("set LOOM_COMPILER_ARANGO_INTEGRATION=1 to run sort/order tournament") - } - control := readSortOrderAQL(t) - candidate, removed, err := buildSortOrderCandidate(control) - if err != nil { - t.Fatal(err) - } - url, database, _ := compilerArangoTarget() - client, err := arangostore.Open(context.Background(), url, database) - if err != nil { - t.Fatalf("open Arango: %v", err) - } - defer client.Close(context.Background()) - binds := readSortOrderBinds(t) - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) - defer cancel() - run := sortOrderRun{} - for index := 0; index < 5; index++ { - controlQuery, controlBinds := cacheBust(control, binds, 67000+index*2) - candidateQuery, candidateBinds := cacheBust(candidate, binds, 67001+index*2) - seconds, bytes, hash, err := executeOrdinary(ctx, client, controlQuery, controlBinds) - if err != nil { - t.Fatalf("control run %d: %v", index+1, err) - } - run.ControlSeconds = append(run.ControlSeconds, seconds) - run.ControlBytes = append(run.ControlBytes, bytes) - run.ControlHash = hash - seconds, bytes, hash, err = executeOrdinary(ctx, client, candidateQuery, candidateBinds) - if err != nil { - t.Fatalf("candidate run %d: %v", index+1, err) - } - run.CandidateSeconds = append(run.CandidateSeconds, seconds) - run.CandidateBytes = append(run.CandidateBytes, bytes) - run.CandidateHash = hash - } - if run.ControlHash != run.CandidateHash { - t.Fatalf("sort/order result parity mismatch control=%s candidate=%s", run.ControlHash, run.CandidateHash) - } - controlProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: control, BindVars: binds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - t.Fatalf("control PROFILE: %v", err) - } - candidateProfile, err := client.Profile(ctx, arangostore.ProfileRequest{Query: candidate, BindVars: binds, BatchSize: 10000, Count: true, Options: arangostore.ProfileOptions{Profile: 2}}) - if err != nil { - t.Fatalf("candidate PROFILE: %v", err) - } - if hashRawRows(controlProfile.Result) != hashRawRows(candidateProfile.Result) { - t.Fatalf("sort/order PROFILE result parity mismatch") - } - run.ControlProfile = controlProfile - run.CandidateProfile = candidateProfile - t.Logf("sort/order removed=%d control_median=%.6f candidate_median=%.6f control_profile=%+v candidate_profile=%+v", removed, median(run.ControlSeconds), median(run.CandidateSeconds), arangostore.SummarizeProfile(controlProfile), arangostore.SummarizeProfile(candidateProfile)) - writeSortOrderEvidence(t, control, candidate, run, removed) -} - -func readSortOrderAQL(t *testing.T) string { - _, source, _, _ := runtime.Caller(0) - path := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "wp2", "selector-integration-endpoint_typed_selector.aql") - data, err := os.ReadFile(path) - if err != nil { - t.Fatalf("read frozen endpoint+typed-selector AQL %q: %v", path, err) - } - return string(data) -} - -func readSortOrderBinds(t *testing.T) map[string]any { - _, source, _, _ := runtime.Caller(0) - path := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round3", "wp4", "production.json") - data, err := os.ReadFile(path) - if err != nil { - t.Fatalf("read frozen production binds %q: %v", path, err) - } - var payload struct { - BindVars map[string]any `json:"bind_vars"` - } - if err := json.Unmarshal(data, &payload); err != nil { - t.Fatalf("decode frozen production binds: %v", err) - } - return payload.BindVars -} - -func buildSortOrderCandidate(control string) (string, int, error) { - candidate := control - removed := 0 - for _, line := range []string{ - " SORT child_set_4_node._key\n", - " SORT child_set_5_node._key\n", - " SORT child_set_6_item._key\n", - } { - if !strings.Contains(candidate, line) { - return "", removed, nilError("required order-insensitive sort not found: " + strings.TrimSpace(line)) - } - candidate = strings.Replace(candidate, line, "", 1) - removed++ - } - for _, name := range []string{"__loom_physical_slice_item", "__loom_physical_slice_item_1", "__loom_physical_slice_item_2"} { - old := "SORT " + name + "._key ASC, " + name + "._key ASC\n" - if !strings.Contains(candidate, old) { - return "", removed, nilError("duplicate slice sort not found: " + name) - } - candidate = strings.Replace(candidate, old, "SORT "+name+"._key ASC\n", 1) - removed++ - } - return candidate, removed, nil -} - -type sortOrderError string - -func (e sortOrderError) Error() string { return string(e) } -func nilError(message string) error { return sortOrderError(message) } - -func writeSortOrderEvidence(t *testing.T, control, candidate string, run sortOrderRun, removed int) { - _, source, _, _ := runtime.Caller(0) - directory := filepath.Join(filepath.Dir(source), "..", "..", "docs", "benchmarks", "round4", "tournament_sort_order") - if err := os.MkdirAll(directory, 0o755); err != nil { - t.Fatalf("create sort/order evidence directory: %v", err) - } - for name, value := range map[string]string{"control.aql": control, "candidate.aql": candidate} { - if err := os.WriteFile(filepath.Join(directory, name), []byte(value), 0o644); err != nil { - t.Fatalf("write sort/order %s: %v", name, err) - } - } - payload, err := json.MarshalIndent(map[string]any{"control_aql_sha256": sha256Hex(control), "candidate_aql_sha256": sha256Hex(candidate), "removed_sort_operations": removed, "run": run, "decision": "pending-coordinator-threshold-review"}, "", " ") - if err != nil { - t.Fatalf("encode sort/order evidence: %v", err) - } - if err := os.WriteFile(filepath.Join(directory, "evidence.json"), append(payload, '\n'), 0o644); err != nil { - t.Fatalf("write sort/order evidence: %v", err) - } -} diff --git a/internal/graphstore/documents.go b/internal/graphstore/documents.go new file mode 100644 index 0000000..fbcd722 --- /dev/null +++ b/internal/graphstore/documents.go @@ -0,0 +1,128 @@ +// Package graphstore contains Loom's small Arango document adapter. +// +// The upstream jsonschemagraph module exposes these document contracts only +// from an unpublished package path. Keeping the adapter here makes the Loom +// server build reproducibly from the public module graph while preserving the +// existing vertex/edge wire shape. +package graphstore + +import ( + "fmt" + "maps" + "regexp" + "strings" + + "github.com/bmeg/grip/gripql" +) + +var validKeyPart = regexp.MustCompile(`[^A-Za-z0-9_\-:.@()+,=;$!*'%]`) + +type VertexDocument struct { + Key string `json:"_key"` + ID string `json:"id"` + Project string `json:"project"` + ResourceType string `json:"resourceType"` + AuthResourcePath string `json:"auth_resource_path,omitempty"` + Payload any `json:"payload"` +} + +type EdgeDocument struct { + Key string `json:"_key"` + From string `json:"_from"` + To string `json:"_to"` + Label string `json:"label"` + Project string `json:"project"` + FromType string `json:"from_type"` + ToType string `json:"to_type"` +} + +func VertexFromFHIR(project, resourceType string, payload map[string]any) (VertexDocument, error) { + return VertexFromFHIRWithExtra(project, resourceType, payload, nil) +} + +func VertexFromFHIRWithExtra(project, resourceType string, payload, extraArgs map[string]any) (VertexDocument, error) { + id, ok := payload["id"].(string) + if !ok || strings.TrimSpace(id) == "" { + return VertexDocument{}, fmt.Errorf("%s payload missing string id", resourceType) + } + payloadCopy := maps.Clone(payload) + authResourcePath := "" + if extraArgs != nil { + maps.Copy(payloadCopy, extraArgs) + if auth, ok := extraArgs["auth_resource_path"].(string); ok { + authResourcePath = auth + } + } + return VertexDocument{ + Key: SanitizeKey(id), + ID: id, + Project: project, + ResourceType: resourceType, + AuthResourcePath: authResourcePath, + Payload: payloadCopy, + }, nil +} + +func EdgeFromGrip(project, sourceType string, edge *gripql.Edge) (EdgeDocument, error) { + if edge == nil { + return EdgeDocument{}, fmt.Errorf("nil edge") + } + if strings.TrimSpace(edge.From) == "" { + return EdgeDocument{}, fmt.Errorf("edge %q missing source id", edge.Id) + } + targetType, targetID := "", edge.To + if strings.Contains(edge.To, "/") { + var err error + targetType, targetID, err = splitFHIRReference(edge.To) + if err != nil { + return EdgeDocument{}, fmt.Errorf("edge %q target: %w", edge.Id, err) + } + } else { + var err error + targetType, err = targetTypeFromLabel(edge.Label) + if err != nil { + return EdgeDocument{}, fmt.Errorf("edge %q target type: %w", edge.Id, err) + } + } + return EdgeDocument{ + Key: SanitizeKey(edge.Id), + From: collectionID(sourceType, edge.From), + To: collectionID(targetType, targetID), + Label: edge.Label, + Project: project, + FromType: sourceType, + ToType: targetType, + }, nil +} + +func SanitizeKey(value string) string { + value = strings.TrimSpace(value) + if value == "" { + return "_" + } + return validKeyPart.ReplaceAllString(value, "_") +} + +func splitFHIRReference(ref string) (string, string, error) { + parts := strings.Split(ref, "/") + if len(parts) < 2 || parts[0] == "" || parts[1] == "" { + return "", "", fmt.Errorf("malformed FHIR reference %q", ref) + } + return parts[0], parts[1], nil +} + +func targetTypeFromLabel(label string) (string, error) { + parts := strings.Split(label, "_") + if len(parts) == 0 { + return "", fmt.Errorf("empty edge label") + } + targetType := parts[len(parts)-1] + if strings.TrimSpace(targetType) == "" { + return "", fmt.Errorf("malformed edge label %q", label) + } + return targetType, nil +} + +func collectionID(resourceType, id string) string { + return SanitizeKey(resourceType) + "/" + SanitizeKey(id) +} diff --git a/internal/ingest/bench_test.go b/internal/ingest/bench_test.go index 7606a0d..d4fe1d3 100644 --- a/internal/ingest/bench_test.go +++ b/internal/ingest/bench_test.go @@ -8,12 +8,12 @@ import ( "strings" "testing" - "github.com/calypr/loom/internal/catalog" fhir "github.com/calypr/loom/fhirstructs" + "github.com/calypr/loom/internal/catalog" - jsgarango "github.com/bmeg/jsonschemagraph/arango" "github.com/bmeg/jsonschemagraph/graph" "github.com/bytedance/sonic" + jsgarango "github.com/calypr/loom/internal/graphstore" ) func BenchmarkValidateAndExtract(b *testing.B) { diff --git a/internal/ingest/generated_load.go b/internal/ingest/generated_load.go index b71793a..285aef6 100644 --- a/internal/ingest/generated_load.go +++ b/internal/ingest/generated_load.go @@ -7,8 +7,8 @@ import ( fhir "github.com/calypr/loom/fhirstructs" - jsgarango "github.com/bmeg/jsonschemagraph/arango" "github.com/bytedance/sonic" + jsgarango "github.com/calypr/loom/internal/graphstore" ) // supportsGeneratedLoad reports whether the optimized generated-loader diff --git a/internal/ingest/parity_test.go b/internal/ingest/parity_test.go index c22f33e..058719d 100644 --- a/internal/ingest/parity_test.go +++ b/internal/ingest/parity_test.go @@ -12,9 +12,9 @@ import ( fhir "github.com/calypr/loom/fhirstructs" - jsgarango "github.com/bmeg/jsonschemagraph/arango" "github.com/bmeg/jsonschemagraph/graph" "github.com/bytedance/sonic" + jsgarango "github.com/calypr/loom/internal/graphstore" ) type EdgeDocument = jsgarango.EdgeDocument diff --git a/internal/ingest/row_builder.go b/internal/ingest/row_builder.go index 53d4d31..15936c9 100644 --- a/internal/ingest/row_builder.go +++ b/internal/ingest/row_builder.go @@ -2,12 +2,14 @@ package ingest import ( "encoding/json" + "maps" "time" + "github.com/bmeg/grip/gripql" "github.com/bmeg/jsonschema/v6" - jsgarango "github.com/bmeg/jsonschemagraph/arango" "github.com/bmeg/jsonschemagraph/graph" "github.com/bytedance/sonic" + jsgarango "github.com/calypr/loom/internal/graphstore" ) type rowErrorType string @@ -110,7 +112,7 @@ func (b *GenericRowBuilder) Build(resourceType string, line []byte, stageSeconds stageSeconds["decode"] += time.Since(decodeStart).Seconds() validateStart := time.Now() - if err := b.class.ValidateFast(payload); err != nil { + if err := b.class.Validate(payload); err != nil { stageSeconds["validate"] += time.Since(validateStart).Seconds() return rowBuildResult{}, rowErrorValidation, err } @@ -123,20 +125,23 @@ func (b *GenericRowBuilder) Build(resourceType string, line []byte, stageSeconds return rowBuildResult{}, rowErrorValidation, err } - objectIDStart := time.Now() - objectID, err := graphObjectID(payload, b.class) - stageSeconds["object_id"] += time.Since(objectIDStart).Seconds() - if err != nil { - return rowBuildResult{}, rowErrorGeneration, err - } - edgeStart := time.Now() - gripEdges, err := b.schema.BuildEdgesWithID(resourceType, objectID, payload, b.extraArgs, true) + // Generate is the public jsonschemagraph API. The repository's historical + // BuildEdgesWithID helper is not part of the published module, so select the + // edge elements from Generate while preserving the same edge conversion and + // authorization propagation below. + elements, err := b.schema.Generate(resourceType, payload, maps.Clone(b.extraArgs)) stageSeconds["edge_generation"] += time.Since(edgeStart).Seconds() if err != nil { return rowBuildResult{}, rowErrorGeneration, err } + gripEdges := make([]*gripql.Edge, 0, len(elements)) + for _, element := range elements { + if element != nil && element.Edge != nil { + gripEdges = append(gripEdges, element.Edge) + } + } convertedEdges := make([]json.RawMessage, 0, len(gripEdges)) authResourcePath, _ := b.extraArgs["auth_resource_path"].(string) for _, generatedEdge := range gripEdges { diff --git a/internal/store/clickhouse/client.go b/internal/store/clickhouse/client.go new file mode 100644 index 0000000..8e58713 --- /dev/null +++ b/internal/store/clickhouse/client.go @@ -0,0 +1,272 @@ +// Package clickhouse is Loom's narrow typed boundary around the official +// ClickHouse Go driver. The materialization service never receives a raw SQL +// connection or a table name from the browser. +package clickhouse + +import ( + "context" + "encoding/json" + "fmt" + "regexp" + "strings" + "time" + + ch "github.com/ClickHouse/clickhouse-go/v2" + "github.com/ClickHouse/clickhouse-go/v2/lib/driver" +) + +type Options struct { + // URL accepts clickhouse://host:9000 or http://host:8123 URLs. The + // official driver supports both protocols; native TCP is the default + // recommended production transport. + URL string + Database string + Username string + Password string + Timeout time.Duration +} + +type Client struct { + opts Options + conn driver.Conn +} + +type Column struct { + Name string + Type string +} + +var identifierRE = regexp.MustCompile(`^[A-Za-z_][A-Za-z0-9_]*$`) + +func New(opts Options) (*Client, error) { + if strings.TrimSpace(opts.URL) == "" { + return nil, fmt.Errorf("clickhouse URL is required") + } + if opts.Database == "" { + opts.Database = "default" + } + if opts.Timeout <= 0 { + opts.Timeout = 60 * time.Second + } + parsed, err := parseOptions(opts) + if err != nil { + return nil, err + } + conn, err := ch.Open(parsed) + if err != nil { + return nil, fmt.Errorf("open ClickHouse connection: %w", err) + } + return &Client{opts: opts, conn: conn}, nil +} + +func (c *Client) Close() error { + if c == nil || c.conn == nil { + return nil + } + return c.conn.Close() +} + +func (c *Client) CreateTable(ctx context.Context, table string, columns []Column) error { + if err := validateIdentifier(table); err != nil { + return err + } + if len(columns) == 0 { + return fmt.Errorf("at least one ClickHouse column is required") + } + parts := make([]string, 0, len(columns)) + for _, column := range columns { + if err := validateIdentifier(column.Name); err != nil { + return err + } + if strings.TrimSpace(column.Type) == "" { + return fmt.Errorf("ClickHouse type for %q is required", column.Name) + } + parts = append(parts, fmt.Sprintf("`%s` %s", column.Name, column.Type)) + } + query := fmt.Sprintf("CREATE TABLE `%s` (%s) ENGINE = MergeTree ORDER BY (`__loom_row_id`)", table, strings.Join(parts, ", ")) + return c.conn.Exec(ctx, query) +} + +func (c *Client) EnsureDatabase(ctx context.Context) error { + if err := validateIdentifier(c.opts.Database); err != nil { + return err + } + // CREATE DATABASE must execute through a connection whose default database + // is known to exist; the main connection intentionally targets the new DB. + options, err := parseOptions(c.opts) + if err != nil { + return err + } + options.Auth.Database = "default" + bootstrap, err := ch.Open(options) + if err != nil { + return err + } + defer bootstrap.Close() + return bootstrap.Exec(ctx, fmt.Sprintf("CREATE DATABASE IF NOT EXISTS `%s`", c.opts.Database)) +} + +func (c *Client) AddColumn(ctx context.Context, table string, column Column) error { + if err := validateIdentifier(table); err != nil { + return err + } + if err := validateIdentifier(column.Name); err != nil { + return err + } + return c.conn.Exec(ctx, fmt.Sprintf("ALTER TABLE `%s` ADD COLUMN IF NOT EXISTS `%s` %s", table, column.Name, column.Type)) +} + +func (c *Client) DropTable(ctx context.Context, table string) error { + if err := validateIdentifier(table); err != nil { + return err + } + return c.conn.Exec(ctx, fmt.Sprintf("DROP TABLE IF EXISTS `%s`", table)) +} + +// InsertJSONEachRow is retained as a compatibility name for callers, but the +// implementation is now a native typed PrepareBatch. Values are appended in +// deterministic map-key order only for this low-level compatibility method; +// materialization uses InsertRows with the persisted schema order. +func (c *Client) InsertJSONEachRow(ctx context.Context, table string, rows []map[string]any) error { + if len(rows) == 0 { + return nil + } + columns := make([]string, 0, len(rows[0])) + for name := range rows[0] { + columns = append(columns, name) + } + sortStrings(columns) + values := make([]Column, 0, len(columns)) + for _, name := range columns { + values = append(values, Column{Name: name, Type: inferType(rows[0][name])}) + } + return c.InsertRows(ctx, table, values, rows) +} + +func inferType(value any) string { + switch value.(type) { + case bool: + return "Bool" + case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64: + return "Int64" + case float32, float64: + return "Float64" + case []string: + return "Array(String)" + case []int, []int8, []int16, []int32, []int64, []uint, []uint8, []uint16, []uint32, []uint64: + return "Array(Int64)" + case []float32, []float64: + return "Array(Float64)" + case []bool: + return "Array(Bool)" + default: + return "String" + } +} + +func (c *Client) InsertRows(ctx context.Context, table string, columns []Column, rows []map[string]any) error { + if err := validateIdentifier(table); err != nil { + return err + } + if len(rows) == 0 { + return nil + } + names := make([]string, len(columns)) + for i, column := range columns { + if err := validateIdentifier(column.Name); err != nil { + return err + } + names[i] = fmt.Sprintf("`%s`", column.Name) + } + batch, err := c.conn.PrepareBatch(ctx, fmt.Sprintf("INSERT INTO `%s` (%s)", table, strings.Join(names, ", "))) + if err != nil { + return fmt.Errorf("prepare ClickHouse batch: %w", err) + } + defer batch.Close() + for _, row := range rows { + values := make([]any, len(columns)) + for i, column := range columns { + values[i] = row[column.Name] + } + if err := batch.Append(values...); err != nil { + return fmt.Errorf("append ClickHouse batch row: %w", err) + } + } + if err := batch.Send(); err != nil { + return fmt.Errorf("send ClickHouse batch: %w", err) + } + return nil +} + +// QueryRows executes a SELECT and decodes each row through ClickHouse's native +// driver. The tuple JSON projection preserves arrays and mixed scalar types +// while keeping the generic dataframe result shape map[string]any. +func (c *Client) QueryRows(ctx context.Context, query string, columns []string) ([]map[string]any, error) { + if len(columns) == 0 { + return nil, fmt.Errorf("ClickHouse query columns are required") + } + base := strings.TrimSpace(strings.TrimSuffix(strings.TrimSpace(query), "FORMAT JSONEachRow")) + quoted := make([]string, len(columns)) + for i, column := range columns { + if err := validateIdentifier(column); err != nil { + return nil, err + } + quoted[i] = fmt.Sprintf("`%s`", column) + } + wrapped := fmt.Sprintf("SELECT toJSONString(tuple(%s)) AS __loom_json FROM (%s) AS __loom_rows", strings.Join(quoted, ", "), base) + rows, err := c.conn.Query(ctx, wrapped) + if err != nil { + return nil, err + } + defer rows.Close() + out := []map[string]any{} + for rows.Next() { + var encoded string + if err := rows.Scan(&encoded); err != nil { + return nil, fmt.Errorf("scan ClickHouse dataframe row: %w", err) + } + var values []any + if err := json.Unmarshal([]byte(encoded), &values); err != nil { + return nil, fmt.Errorf("decode ClickHouse dataframe row: %w", err) + } + row := make(map[string]any, len(columns)) + for i, column := range columns { + if i < len(values) { + row[column] = values[i] + } + } + out = append(out, row) + } + if err := rows.Err(); err != nil { + return nil, err + } + return out, nil +} + +func parseOptions(opts Options) (*ch.Options, error) { + parsed, err := ch.ParseDSN(opts.URL) + if err != nil { + return nil, fmt.Errorf("parse ClickHouse URL: %w", err) + } + parsed.Auth.Database = opts.Database + parsed.Auth.Username = opts.Username + parsed.Auth.Password = opts.Password + parsed.DialTimeout = opts.Timeout + parsed.ReadTimeout = opts.Timeout + return parsed, nil +} + +func validateIdentifier(value string) error { + if !identifierRE.MatchString(value) { + return fmt.Errorf("invalid ClickHouse identifier %q", value) + } + return nil +} + +func sortStrings(values []string) { + for i := 1; i < len(values); i++ { + for j := i; j > 0 && values[j] < values[j-1]; j-- { + values[j], values[j-1] = values[j-1], values[j] + } + } +} diff --git a/internal/store/clickhouse/client_test.go b/internal/store/clickhouse/client_test.go new file mode 100644 index 0000000..77fc67e --- /dev/null +++ b/internal/store/clickhouse/client_test.go @@ -0,0 +1,33 @@ +package clickhouse + +import "testing" + +func TestNewUsesOfficialDriverDSN(t *testing.T) { + client, err := New(Options{URL: "clickhouse://127.0.0.1:9000", Database: "loom", Username: "default"}) + if err != nil { + t.Fatal(err) + } + if client.conn == nil { + t.Fatal("official ClickHouse driver connection was not created") + } + _ = client.Close() +} + +func TestParseOptionsPreservesAuthAndTimeout(t *testing.T) { + options, err := parseOptions(Options{URL: "clickhouse://127.0.0.1:9000", Database: "loom", Username: "u", Password: "p"}) + if err != nil { + t.Fatal(err) + } + if options.Auth.Database != "loom" || options.Auth.Username != "u" || options.Auth.Password != "p" { + t.Fatalf("auth options = %#v", options.Auth) + } +} + +func TestValidateIdentifier(t *testing.T) { + if err := validateIdentifier("loom_df_123"); err != nil { + t.Fatal(err) + } + if err := validateIdentifier("bad;DROP TABLE"); err == nil { + t.Fatal("expected invalid identifier") + } +} diff --git a/internal/store/clickhouse/integration_test.go b/internal/store/clickhouse/integration_test.go new file mode 100644 index 0000000..d65397f --- /dev/null +++ b/internal/store/clickhouse/integration_test.go @@ -0,0 +1,58 @@ +package clickhouse + +import ( + "context" + "os" + "testing" + "time" + + "github.com/google/uuid" +) + +// Run with LOOM_CLICKHOUSE_URL=clickhouse://127.0.0.1:9000 to exercise the +// native driver against a real ClickHouse instance. The default unit suite +// remains hermetic when ClickHouse is not running locally. +func TestClickHouseNativeRoundTrip(t *testing.T) { + url := os.Getenv("LOOM_CLICKHOUSE_URL") + if url == "" { + t.Skip("LOOM_CLICKHOUSE_URL is not set") + } + database := os.Getenv("LOOM_CLICKHOUSE_DATABASE") + if database == "" { + database = "loom_test" + } + client, err := New(Options{URL: url, Database: database, Timeout: 10 * time.Second}) + if err != nil { + t.Fatal(err) + } + defer client.Close() + ctx := context.Background() + if err := client.EnsureDatabase(ctx); err != nil { + t.Fatal(err) + } + table := "loom_it_" + uuid.NewString()[:12] + defer client.DropTable(ctx, table) + if err := client.CreateTable(ctx, table, []Column{ + {Name: "__loom_row_id", Type: "UInt64"}, + {Name: "name", Type: "Nullable(String)"}, + {Name: "score", Type: "Nullable(Float64)"}, + {Name: "tags", Type: "Array(String)"}, + }); err != nil { + t.Fatal(err) + } + if err := client.InsertRows(ctx, table, []Column{ + {Name: "__loom_row_id", Type: "UInt64"}, + {Name: "name", Type: "Nullable(String)"}, + {Name: "score", Type: "Nullable(Float64)"}, + {Name: "tags", Type: "Array(String)"}, + }, []map[string]any{{"__loom_row_id": uint64(1), "name": "alice", "score": 2.5, "tags": []string{"a", "b"}}}); err != nil { + t.Fatal(err) + } + rows, err := client.QueryRows(ctx, "SELECT `name`, `score`, `tags` FROM `"+table+"`", []string{"name", "score", "tags"}) + if err != nil { + t.Fatal(err) + } + if len(rows) != 1 || rows[0]["name"] != "alice" { + t.Fatalf("round-trip rows = %#v", rows) + } +} From bff6b79e0e0904604231ea128110df1d70303bb2 Mon Sep 17 00:00:00 2001 From: matthewpeterkort Date: Mon, 13 Jul 2026 10:56:10 -0700 Subject: [PATCH 08/15] add schema --- schemas/graph-fhir.json | 68660 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 68660 insertions(+) create mode 100644 schemas/graph-fhir.json diff --git a/schemas/graph-fhir.json b/schemas/graph-fhir.json new file mode 100644 index 0000000..fa11fde --- /dev/null +++ b/schemas/graph-fhir.json @@ -0,0 +1,68660 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "http://graph-fhir.io/schema/0.0.2", + "$defs": { + "Directory": { + "$id": "http://graph-fhir.io/schema/0.0.2/Directory", + "additionalProperties": false, + "description": "POSIX Directory of a research study's document references from root (/) to the native location of the document references themselves.", + "links": [ + { + "href": "{id}", + "rel": "child_Directory", + "targetHints": { + "backref": [], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Directory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Directory" + }, + "templatePointers": { + "id": "/child/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "child_DocumentReference", + "targetHints": { + "backref": [], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/child/-/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "name": { + "binding_strength": "required", + "element_property": true, + "title": "The name of the directory", + "type": "string" + }, + "path": { + "type": "string", + "description": "The full POSIX path of the directory starting from the bucket or root.", + "title": "Full Path", + "element_property": true + }, + "child": { + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "backref": "directory", + "description": "a child directory of the current directory", + "element_property": true, + "enum_reference_types": [ + "Directory", + "DocumentReference" + ], + "title": "A reference to a downstream node in the directory tree", + "type": "array" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "resourceType": { + "const": "Directory", + "default": "Directory", + "description": "One of the resource types defined as part of CALYPR", + "title": "Resource Type", + "type": "string" + } + }, + "required": [ + "name", + "child" + ], + "title": "Directory", + "type": "object" + }, + "MedicationAdministration": { + "$id": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration", + "additionalProperties": false, + "description": "Administration of medication to a patient. Describes the event of a patient consuming or otherwise being administered a medication. This may be as simple as swallowing a tablet or it may be a long running infusion. Related resources tie this event to the authorizing prescription, and the specific encounter between patient and health care practitioner. [See https://hl7.org/fhir/R5/MedicationAdministration.html]", + "links": [ + { + "href": "{id}", + "rel": "partOf_MedicationAdministration", + "targetHints": { + "backref": [ + "partOf_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/partOf/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "partOf_Procedure", + "targetHints": { + "backref": [ + "partOf_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/partOf/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "request", + "targetHints": { + "backref": [ + "medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/request/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Patient", + "targetHints": { + "backref": [ + "medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Group", + "targetHints": { + "backref": [ + "medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_Organization", + "targetHints": { + "backref": [ + "supportingInformation_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_Group", + "targetHints": { + "backref": [ + "supportingInformation_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_Practitioner", + "targetHints": { + "backref": [ + "supportingInformation_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_PractitionerRole", + "targetHints": { + "backref": [ + "supportingInformation_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_ResearchStudy", + "targetHints": { + "backref": [ + "supportingInformation_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_Patient", + "targetHints": { + "backref": [ + "supportingInformation_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_ResearchSubject", + "targetHints": { + "backref": [ + "supportingInformation_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_Substance", + "targetHints": { + "backref": [ + "supportingInformation_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_SubstanceDefinition", + "targetHints": { + "backref": [ + "supportingInformation_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_Specimen", + "targetHints": { + "backref": [ + "supportingInformation_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_Observation", + "targetHints": { + "backref": [ + "supportingInformation_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_DiagnosticReport", + "targetHints": { + "backref": [ + "supportingInformation_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_Condition", + "targetHints": { + "backref": [ + "supportingInformation_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_Medication", + "targetHints": { + "backref": [ + "supportingInformation_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_MedicationAdministration", + "targetHints": { + "backref": [ + "supportingInformation_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_MedicationStatement", + "targetHints": { + "backref": [ + "supportingInformation_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_MedicationRequest", + "targetHints": { + "backref": [ + "supportingInformation_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_Procedure", + "targetHints": { + "backref": [ + "supportingInformation_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_DocumentReference", + "targetHints": { + "backref": [ + "supportingInformation_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_Task", + "targetHints": { + "backref": [ + "supportingInformation_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_ImagingStudy", + "targetHints": { + "backref": [ + "supportingInformation_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_FamilyMemberHistory", + "targetHints": { + "backref": [ + "supportingInformation_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_BodyStructure", + "targetHints": { + "backref": [ + "supportingInformation_medication_administration" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Practitioner", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_PractitionerRole", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Patient", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Organization", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_isSubPotent": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'isSubPotent'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "_occurenceDateTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'occurenceDateTime'." + }, + "_recorded": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'recorded'." + }, + "_status": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'status'." + }, + "basedOn": { + "backref": "basedOn_medication_administration", + "description": "A plan that is fulfilled in whole or in part by this MedicationAdministration.", + "element_property": true, + "enum_reference_types": [ + "CarePlan" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Plan this is fulfilled by this administration", + "type": "array" + }, + "category": { + "binding_description": "A coded concept describing where the medication administered is expected to occur.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/medication-admin-location", + "binding_version": null, + "description": "The type of medication administration (for example, drug classification like ATC, where meds would be administered, legal category of the medication).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Type of medication administration", + "type": "array" + }, + "contained": { + "description": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, nor can they have their own independent transaction scope. This is allowed to be a Parameters resource if and only if it is referenced by a resource that provides context/meaning.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + "title": "Contained, inline Resources", + "type": "array" + }, + "device": { + "backref": "device_medication_administration", + "description": "The device that is to be used for the administration of the medication (for example, PCA Pump).", + "element_property": true, + "enum_reference_types": [ + "Device" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference" + }, + "title": "Device used to administer", + "type": "array" + }, + "dosage": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministrationDosage", + "description": "Describes the medication dosage information details e.g. dose, rate, site, route, etc.", + "element_property": true, + "title": "Details of how medication was taken" + }, + "encounter": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "medication_administration", + "description": "The visit, admission, or other contact between patient and health care provider during which the medication administration was performed.", + "element_property": true, + "enum_reference_types": [ + "Encounter" + ], + "title": "Encounter administered as part of" + }, + "eventHistory": { + "backref": "eventHistory_medication_administration", + "description": "A summary of the events of interest that have occurred, such as when the administration was verified.", + "element_property": true, + "enum_reference_types": [ + "Provenance" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "A list of events of interest in the lifecycle", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "identifier": { + "description": "Identifiers associated with this Medication Administration that are defined by business processes and/or used to refer to it when a direct URL reference to the resource itself is not appropriate. They are business identifiers assigned to this resource by the performer or other systems and remain constant as the resource is updated and propagates from server to server.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "External identifier", + "type": "array" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "isSubPotent": { + "description": "An indication that the full dose was not administered.", + "element_property": true, + "title": "Full dose was not administered", + "type": "boolean" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "medication": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference", + "backref": "medication_administration", + "binding_description": "Codes identifying substance or product that can be administered.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/medication-codes", + "binding_version": null, + "description": "Identifies the medication that was administered. This is either a link to a resource representing the details of the medication or a simple attribute carrying a code that identifies the medication from a known list of medications.", + "element_property": true, + "enum_reference_types": [ + "Medication" + ], + "title": "What was administered" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored", + "type": "array" + }, + "note": { + "description": "Extra information about the medication administration that is not conveyed by the other attributes.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Annotation" + }, + "title": "Information about the administration", + "type": "array" + }, + "occurenceDateTime": { + "description": "A specific date/time or interval of time during which the administration took place (or did not take place). For many administrations, such as swallowing a tablet the use of dateTime is more appropriate.", + "element_property": true, + "format": "date-time", + "one_of_many": "occurence", + "one_of_many_required": true, + "title": "Specific date/time or interval of time during which the administration took place (or did not take place)", + "type": "string" + }, + "occurencePeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "A specific date/time or interval of time during which the administration took place (or did not take place). For many administrations, such as swallowing a tablet the use of dateTime is more appropriate.", + "element_property": true, + "one_of_many": "occurence", + "one_of_many_required": true, + "title": "Specific date/time or interval of time during which the administration took place (or did not take place)" + }, + "occurenceTiming": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Timing", + "description": "A specific date/time or interval of time during which the administration took place (or did not take place). For many administrations, such as swallowing a tablet the use of dateTime is more appropriate.", + "element_property": true, + "one_of_many": "occurence", + "one_of_many_required": true, + "title": "Specific date/time or interval of time during which the administration took place (or did not take place)" + }, + "partOf": { + "backref": "partOf_medication_administration", + "description": "A larger event of which this particular event is a component or step.", + "element_property": true, + "enum_reference_types": [ + "MedicationAdministration", + "Procedure", + "MedicationDispense" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Part of referenced event", + "type": "array" + }, + "performer": { + "description": "The performer of the medication treatment. For devices this is the device that performed the administration of the medication. An IV Pump would be an example of a device that is performing the administration. Both the IV Pump and the practitioner that set the rate or bolus on the pump can be listed as performers.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministrationPerformer" + }, + "title": "Who or what performed the medication administration and what type of performance they did", + "type": "array" + }, + "reason": { + "backref": "reason_medication_administration", + "binding_description": "A set of codes indicating the reason why the MedicationAdministration was made.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/reason-medication-given-codes", + "binding_version": null, + "description": "A code, Condition or observation that supports why the medication was administered.", + "element_property": true, + "enum_reference_types": [ + "Condition", + "Observation", + "DiagnosticReport" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference" + }, + "title": "Concept, condition or observation that supports why the medication was administered", + "type": "array" + }, + "recorded": { + "description": "The date the occurrence of the MedicationAdministration was first captured in the record - potentially significantly after the occurrence of the event.", + "element_property": true, + "format": "date-time", + "title": "When the MedicationAdministration was first captured in the subject's record", + "type": "string" + }, + "request": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "medication_administration", + "description": "The original request, instruction or authority to perform the administration.", + "element_property": true, + "enum_reference_types": [ + "MedicationRequest" + ], + "title": "Request administration performed against" + }, + "resourceType": { + "const": "MedicationAdministration", + "default": "MedicationAdministration", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "status": { + "binding_description": "A set of codes indicating the current status of a MedicationAdministration.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/medication-admin-status", + "binding_version": "5.0.0", + "description": "Will generally be set to show that the administration has been completed. For some long running administrations such as infusions, it is possible for an administration to be started but not completed or it may be paused while some other process is under way.", + "element_property": true, + "element_required": true, + "enum_values": [ + "in-progress", + "not-done", + "on-hold", + "completed", + "entered-in-error", + "stopped", + "unknown" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "in-progress | not-done | on-hold | completed | entered-in-error | stopped | unknown", + "type": "string" + }, + "statusReason": { + "binding_description": "A set of codes indicating the reason why the MedicationAdministration is negated.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/reason-medication-not-given-codes", + "binding_version": null, + "description": "A code indicating why the administration was not performed.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Reason administration not performed", + "type": "array" + }, + "subPotentReason": { + "binding_description": null, + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/administration-subpotent-reason", + "binding_version": null, + "description": "The reason or reasons why the full dose was not administered.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Reason full dose was not administered", + "type": "array" + }, + "subject": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "medication_administration", + "description": "The person or animal or group receiving the medication.", + "element_property": true, + "enum_reference_types": [ + "Patient", + "Group" + ], + "title": "Who received medication" + }, + "supportingInformation": { + "backref": "supportingInformation_medication_administration", + "description": "Additional information (for example, patient height and weight) that supports the administration of the medication. This attribute can be used to provide documentation of specific characteristics of the patient present at the time of administration. For example, if the dose says \"give \"x\" if the heartrate exceeds \"y\"\", then the heart rate can be included using this attribute.", + "element_property": true, + "enum_reference_types": [ + "Organization", + "Group", + "Practitioner", + "PractitionerRole", + "ResearchStudy", + "Patient", + "ResearchSubject", + "Substance", + "SubstanceDefinition", + "Specimen", + "Observation", + "DiagnosticReport", + "Condition", + "Medication", + "MedicationAdministration", + "MedicationStatement", + "MedicationRequest", + "Procedure", + "DocumentReference", + "Task", + "ImagingStudy", + "FamilyMemberHistory", + "BodyStructure" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Additional information to support administration", + "type": "array" + }, + "text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative", + "description": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "element_property": true, + "title": "Text summary of the resource, for human interpretation" + } + }, + "required": [ + "medication", + "subject" + ], + "title": "MedicationAdministration", + "type": "object" + }, + "DocumentReference": { + "$id": "http://graph-fhir.io/schema/0.0.2/DocumentReference", + "additionalProperties": false, + "description": "A reference to a document. A reference to a document of any kind for any purpose. While the term \u201cdocument\u201d implies a more narrow focus, for this resource this \"document\" encompasses *any* serialized object with a mime-type, it includes formal patient-centric documents (CDA), clinical notes, scanned paper, non-patient specific documents like policy text, as well as a photo, video, or audio recording acquired or used in healthcare. The DocumentReference resource provides metadata about the document so that the document can be discovered and managed. The actual content may be inline base64 encoded data or provided by direct reference. [See https://hl7.org/fhir/R5/DocumentReference.html]", + "links": [ + { + "href": "{id}", + "rel": "author_Practitioner", + "targetHints": { + "backref": [ + "author_document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/author/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "author_PractitionerRole", + "targetHints": { + "backref": [ + "author_document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/author/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "author_Organization", + "targetHints": { + "backref": [ + "author_document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/author/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "author_Patient", + "targetHints": { + "backref": [ + "author_document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/author/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "basedOn_MedicationRequest", + "targetHints": { + "backref": [ + "basedOn_document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "custodian", + "targetHints": { + "backref": [ + "custodian_document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/custodian/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Organization", + "targetHints": { + "backref": [ + "document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Group", + "targetHints": { + "backref": [ + "document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Practitioner", + "targetHints": { + "backref": [ + "document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_PractitionerRole", + "targetHints": { + "backref": [ + "document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_ResearchStudy", + "targetHints": { + "backref": [ + "document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Patient", + "targetHints": { + "backref": [ + "document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_ResearchSubject", + "targetHints": { + "backref": [ + "document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Substance", + "targetHints": { + "backref": [ + "document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_SubstanceDefinition", + "targetHints": { + "backref": [ + "document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Specimen", + "targetHints": { + "backref": [ + "document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Observation", + "targetHints": { + "backref": [ + "document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_DiagnosticReport", + "targetHints": { + "backref": [ + "document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Condition", + "targetHints": { + "backref": [ + "document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Medication", + "targetHints": { + "backref": [ + "document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_MedicationAdministration", + "targetHints": { + "backref": [ + "document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_MedicationStatement", + "targetHints": { + "backref": [ + "document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_MedicationRequest", + "targetHints": { + "backref": [ + "document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Procedure", + "targetHints": { + "backref": [ + "document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_DocumentReference", + "targetHints": { + "backref": [ + "document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Task", + "targetHints": { + "backref": [ + "document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_ImagingStudy", + "targetHints": { + "backref": [ + "document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_FamilyMemberHistory", + "targetHints": { + "backref": [ + "document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_BodyStructure", + "targetHints": { + "backref": [ + "document_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From DocumentReferenceAttester/attester", + "href": "{id}", + "rel": "attester_party_Patient", + "targetHints": { + "backref": [ + "document_reference_attester" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/attester/-/party/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From DocumentReferenceAttester/attester", + "href": "{id}", + "rel": "attester_party_Practitioner", + "targetHints": { + "backref": [ + "document_reference_attester" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/attester/-/party/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From DocumentReferenceAttester/attester", + "href": "{id}", + "rel": "attester_party_PractitionerRole", + "targetHints": { + "backref": [ + "document_reference_attester" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/attester/-/party/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From DocumentReferenceAttester/attester", + "href": "{id}", + "rel": "attester_party_Organization", + "targetHints": { + "backref": [ + "document_reference_attester" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/attester/-/party/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/bodySite/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/bodySite/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/bodySite/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/bodySite/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/bodySite/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/bodySite/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/bodySite/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/bodySite/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/bodySite/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/bodySite/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/bodySite/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/bodySite/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/bodySite/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/bodySite/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/bodySite/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/bodySite/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/bodySite/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/bodySite/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/bodySite/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/bodySite/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/bodySite/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/bodySite/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/bodySite/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/event", + "href": "{id}", + "rel": "event_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/event/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/event", + "href": "{id}", + "rel": "event_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/event/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/event", + "href": "{id}", + "rel": "event_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/event/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/event", + "href": "{id}", + "rel": "event_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/event/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/event", + "href": "{id}", + "rel": "event_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/event/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/event", + "href": "{id}", + "rel": "event_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/event/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/event", + "href": "{id}", + "rel": "event_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/event/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/event", + "href": "{id}", + "rel": "event_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/event/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/event", + "href": "{id}", + "rel": "event_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/event/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/event", + "href": "{id}", + "rel": "event_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/event/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/event", + "href": "{id}", + "rel": "event_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/event/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/event", + "href": "{id}", + "rel": "event_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/event/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/event", + "href": "{id}", + "rel": "event_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/event/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/event", + "href": "{id}", + "rel": "event_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/event/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/event", + "href": "{id}", + "rel": "event_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/event/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/event", + "href": "{id}", + "rel": "event_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/event/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/event", + "href": "{id}", + "rel": "event_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/event/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/event", + "href": "{id}", + "rel": "event_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/event/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/event", + "href": "{id}", + "rel": "event_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/event/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/event", + "href": "{id}", + "rel": "event_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/event/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/event", + "href": "{id}", + "rel": "event_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/event/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/event", + "href": "{id}", + "rel": "event_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/event/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/event", + "href": "{id}", + "rel": "event_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/event/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From DocumentReferenceRelatesTo/relatesTo", + "href": "{id}", + "rel": "relatesTo_target", + "targetHints": { + "backref": [ + "document_reference_relates_to" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/relatesTo/-/target/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_date": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'date'." + }, + "_description": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'description'." + }, + "_docStatus": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'docStatus'." + }, + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "_status": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'status'." + }, + "_version": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'version'." + }, + "attester": { + "description": "A participant who has authenticated the accuracy of the document.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReferenceAttester" + }, + "title": "Attests to accuracy of the document", + "type": "array" + }, + "author": { + "backref": "author_document_reference", + "description": "Identifies who is responsible for adding the information to the document.", + "element_property": true, + "enum_reference_types": [ + "Practitioner", + "PractitionerRole", + "Organization", + "Device", + "Patient", + "RelatedPerson", + "CareTeam" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Who and/or what authored the document", + "type": "array" + }, + "basedOn": { + "backref": "basedOn_document_reference", + "description": "A procedure that is fulfilled in whole or in part by the creation of this media.", + "element_property": true, + "enum_reference_types": [ + "Appointment", + "AppointmentResponse", + "CarePlan", + "Claim", + "CommunicationRequest", + "Contract", + "CoverageEligibilityRequest", + "DeviceRequest", + "EnrollmentRequest", + "ImmunizationRecommendation", + "MedicationRequest", + "NutritionOrder", + "RequestOrchestration", + "ServiceRequest", + "SupplyRequest", + "VisionPrescription" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Procedure that caused this media to be created", + "type": "array" + }, + "bodySite": { + "backref": "bodySite_document_reference", + "binding_description": "SNOMED CT Body site concepts", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/body-site", + "binding_version": null, + "description": "The anatomic structures included in the document.", + "element_property": true, + "enum_reference_types": [ + "BodyStructure" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference" + }, + "title": "Body part included", + "type": "array" + }, + "category": { + "binding_description": "High-level kind of document at a macro level.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/referenced-item-category", + "binding_version": null, + "description": "A categorization for the type of document referenced - helps for indexing and searching. This may be implied by or derived from the code specified in the DocumentReference.type.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Categorization of document", + "type": "array" + }, + "contained": { + "description": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, nor can they have their own independent transaction scope. This is allowed to be a Parameters resource if and only if it is referenced by a resource that provides context/meaning.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + "title": "Contained, inline Resources", + "type": "array" + }, + "content": { + "description": "The document and format referenced. If there are multiple content element repetitions, these must all represent the same document in different format, or attachment metadata.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReferenceContent" + }, + "title": "Document referenced", + "type": "array" + }, + "context": { + "backref": "context_document_reference", + "description": "Describes the clinical encounter or type of care that the document content is associated with.", + "element_property": true, + "enum_reference_types": [ + "Appointment", + "Encounter", + "EpisodeOfCare" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Context of the document content", + "type": "array" + }, + "custodian": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "custodian_document_reference", + "description": "Identifies the organization or group who is responsible for ongoing maintenance of and access to the document.", + "element_property": true, + "enum_reference_types": [ + "Organization" + ], + "title": "Organization which maintains the document" + }, + "date": { + "description": "When the document reference was created.", + "element_property": true, + "format": "date-time", + "title": "When this document reference was created", + "type": "string" + }, + "description": { + "description": "Human-readable description of the source document.", + "element_property": true, + "pattern": "\\s*(\\S|\\s)*", + "title": "Human-readable description", + "type": "string" + }, + "docStatus": { + "binding_description": "Status of the underlying document.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/composition-status", + "binding_version": "5.0.0", + "description": "The status of the underlying document.", + "element_property": true, + "enum_values": [ + "registered", + "partial", + "preliminary", + "final", + "amended", + "corrected", + "appended", + "cancelled", + "entered-in-error", + "deprecated", + "unknown" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "registered | partial | preliminary | final | amended | corrected | appended | cancelled | entered-in-error | deprecated | unknown", + "type": "string" + }, + "event": { + "backref": "event_document_reference", + "binding_description": "This list of codes represents the main clinical acts being documented.", + "binding_strength": "example", + "binding_uri": "http://terminology.hl7.org/ValueSet/v3-ActCode", + "binding_version": null, + "description": "This list of codes represents the main clinical acts, such as a colonoscopy or an appendectomy, being documented. In some cases, the event is inherent in the type Code, such as a \"History and Physical Report\" in which the procedure being documented is necessarily a \"History and Physical\" act.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference" + }, + "title": "Main clinical acts documented", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "facilityType": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "XDS Facility Type.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/c80-facilitycodes", + "binding_version": null, + "description": "The kind of facility where the patient was seen.", + "element_property": true, + "title": "Kind of facility where patient was seen" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "identifier": { + "description": "Other business identifiers associated with the document, including version independent identifiers.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "Business identifiers for the document", + "type": "array" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "modality": { + "binding_description": "Type of acquired data in the instance.", + "binding_strength": "extensible", + "binding_uri": "http://dicom.nema.org/medical/dicom/current/output/chtml/part16/sect_CID_33.html", + "binding_version": null, + "description": "Imaging modality used. This may include both acquisition and non-acquisition modalities.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Imaging modality used", + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored", + "type": "array" + }, + "period": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "The time period over which the service that is described by the document was provided.", + "element_property": true, + "title": "Time of service that is being documented" + }, + "practiceSetting": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Additional details about where the content was created (e.g. clinical specialty).", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/c80-practice-codes", + "binding_version": null, + "description": "This property may convey specifics about the practice setting where the content was created, often reflecting the clinical specialty.", + "element_property": true, + "title": "Additional details about where the content was created (e.g. clinical specialty)" + }, + "relatesTo": { + "description": "Relationships that this document has with other document references that already exist.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReferenceRelatesTo" + }, + "title": "Relationships to other documents", + "type": "array" + }, + "resourceType": { + "const": "DocumentReference", + "default": "DocumentReference", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "securityLabel": { + "binding_description": "Example Security Labels from the Healthcare Privacy and Security Classification System.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/security-label-examples", + "binding_version": null, + "description": "A set of Security-Tag codes specifying the level of privacy/security of the Document found at DocumentReference.content.attachment.url. Note that DocumentReference.meta.security contains the security labels of the data elements in DocumentReference, while DocumentReference.securityLabel contains the security labels for the document the reference refers to. The distinction recognizes that the document may contain sensitive information, while the DocumentReference is metadata about the document and thus might not be as sensitive as the document. For example: a psychotherapy episode may contain highly sensitive information, while the metadata may simply indicate that some episode happened.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Document security-tags", + "type": "array" + }, + "status": { + "binding_description": "The status of the document reference.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/document-reference-status", + "binding_version": "5.0.0", + "description": "The status of this document reference.", + "element_property": true, + "element_required": true, + "enum_values": [ + "current", + "superseded", + "entered-in-error" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "current | superseded | entered-in-error", + "type": "string" + }, + "subject": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "document_reference", + "description": "Who or what the document is about. The document can be about a person, (patient or healthcare practitioner), a device (e.g. a machine) or even a group of subjects (such as a document about a herd of farm animals, or a set of patients that share a common exposure).", + "element_property": true, + "enum_reference_types": [ + "Organization", + "Group", + "Practitioner", + "PractitionerRole", + "ResearchStudy", + "Patient", + "ResearchSubject", + "Substance", + "SubstanceDefinition", + "Specimen", + "Observation", + "DiagnosticReport", + "Condition", + "Medication", + "MedicationAdministration", + "MedicationStatement", + "MedicationRequest", + "Procedure", + "DocumentReference", + "Task", + "ImagingStudy", + "FamilyMemberHistory", + "BodyStructure" + ], + "title": "Who/what is the subject of the document" + }, + "text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative", + "description": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "element_property": true, + "title": "Text summary of the resource, for human interpretation" + }, + "type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Precise type of clinical document.", + "binding_strength": "preferred", + "binding_uri": "http://hl7.org/fhir/ValueSet/doc-typecodes", + "binding_version": null, + "description": "Specifies the particular kind of document referenced (e.g. History and Physical, Discharge Summary, Progress Note). This usually equates to the purpose of making the document referenced.", + "element_property": true, + "title": "Kind of document (LOINC if possible)" + }, + "version": { + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "An explicitly assigned identifer of a variation of the content in the DocumentReference", + "type": "string" + } + }, + "required": [ + "content" + ], + "title": "DocumentReference", + "type": "object" + }, + "ImagingStudySeriesPerformer": { + "$id": "http://graph-fhir.io/schema/0.0.2/ImagingStudySeriesPerformer", + "additionalProperties": false, + "description": "Who performed the series. Indicates who or what performed the series and how they were involved. [See https://hl7.org/fhir/R5/ImagingStudySeriesPerformer.html]", + "links": [ + { + "href": "{id}", + "rel": "actor_Practitioner", + "targetHints": { + "backref": [ + "imaging_study_series_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "actor_PractitionerRole", + "targetHints": { + "backref": [ + "imaging_study_series_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "actor_Organization", + "targetHints": { + "backref": [ + "imaging_study_series_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "actor_Patient", + "targetHints": { + "backref": [ + "imaging_study_series_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/actor/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "actor": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "imaging_study_series_performer", + "description": "Indicates who or what performed the series.", + "element_property": true, + "enum_reference_types": [ + "Practitioner", + "PractitionerRole", + "Organization", + "CareTeam", + "Patient", + "Device", + "RelatedPerson", + "HealthcareService" + ], + "title": "Who performed the series" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "function": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The type of involvement of the performer.", + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/series-performer-function", + "binding_version": null, + "description": "Distinguishes the type of involvement of the performer in the series.", + "element_property": true, + "title": "Type of performance" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "ImagingStudySeriesPerformer", + "default": "ImagingStudySeriesPerformer", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "required": [ + "actor" + ], + "title": "ImagingStudySeriesPerformer", + "type": "object" + }, + "TaskPerformer": { + "$id": "http://graph-fhir.io/schema/0.0.2/TaskPerformer", + "additionalProperties": false, + "description": "Who or what performed the task. The entity who performed the requested task. [See https://hl7.org/fhir/R5/TaskPerformer.html]", + "links": [ + { + "href": "{id}", + "rel": "actor_Practitioner", + "targetHints": { + "backref": [ + "task_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "actor_PractitionerRole", + "targetHints": { + "backref": [ + "task_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "actor_Organization", + "targetHints": { + "backref": [ + "task_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "actor_Patient", + "targetHints": { + "backref": [ + "task_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/actor/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "actor": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "task_performer", + "description": "The actor or entity who performed the task.", + "element_property": true, + "enum_reference_types": [ + "Practitioner", + "PractitionerRole", + "Organization", + "CareTeam", + "Patient", + "RelatedPerson" + ], + "title": "Who performed the task" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "function": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "description": "A code or description of the performer of the task.", + "element_property": true, + "title": "Type of performance" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "TaskPerformer", + "default": "TaskPerformer", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "required": [ + "actor" + ], + "title": "TaskPerformer", + "type": "object" + }, + "Timing": { + "$id": "http://graph-fhir.io/schema/0.0.2/Timing", + "additionalProperties": false, + "description": "A timing schedule that specifies an event that may occur multiple times. Specifies an event that may occur multiple times. Timing schedules are used to record when things are planned, expected or requested to occur. The most common usage is in dosage instructions for medications. They are also used when planning care of various kinds, and may be used for reporting the schedule to which past regular activities were carried out. [See https://hl7.org/fhir/R5/Timing.html]", + "links": [], + "properties": { + "_event": { + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension" + }, + "title": "Extension field for 'event'.", + "type": "array" + }, + "code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Code for a known / defined timing pattern.", + "binding_strength": "preferred", + "binding_uri": "http://hl7.org/fhir/ValueSet/timing-abbreviation", + "binding_version": null, + "description": "A code for the timing schedule (or just text in code.text). Some codes such as BID are ubiquitous, but many institutions define their own additional codes. If a code is provided, the code is understood to be a complete statement of whatever is specified in the structured timing data, and either the code or the data may be used to interpret the Timing, with the exception that .repeat.bounds still applies over the code (and is not contained in the code).", + "element_property": true, + "title": "C | BID | TID | QID | AM | PM | QD | QOD | +" + }, + "event": { + "description": "Identifies specific times when the event occurs.", + "element_property": true, + "items": { + "format": "date-time", + "type": "string" + }, + "title": "When the event occurs", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "repeat": { + "$ref": "http://graph-fhir.io/schema/0.0.2/TimingRepeat", + "description": "A set of rules that describe when the event is scheduled.", + "element_property": true, + "title": "When the event is to occur" + }, + "resourceType": { + "const": "Timing", + "default": "Timing", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "title": "Timing", + "type": "object" + }, + "SampledData": { + "$id": "http://graph-fhir.io/schema/0.0.2/SampledData", + "additionalProperties": false, + "description": "A series of measurements taken by a device. A series of measurements taken by a device, with upper and lower limits. There may be more than one dimension in the data. [See https://hl7.org/fhir/R5/SampledData.html]", + "links": [], + "properties": { + "_codeMap": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'codeMap'." + }, + "_data": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'data'." + }, + "_dimensions": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'dimensions'." + }, + "_factor": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'factor'." + }, + "_interval": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'interval'." + }, + "_intervalUnit": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'intervalUnit'." + }, + "_lowerLimit": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'lowerLimit'." + }, + "_offsets": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'offsets'." + }, + "_upperLimit": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'upperLimit'." + }, + "codeMap": { + "description": "Reference to ConceptMap that defines the codes used in the data.", + "element_property": true, + "enum_reference_types": [ + "ConceptMap" + ], + "pattern": "\\S*", + "title": "Defines the codes used in the data", + "type": "string" + }, + "data": { + "description": "A series of data points which are decimal values or codes separated by a single space (character u20). The special codes \"E\" (error), \"L\" (below detection limit) and \"U\" (above detection limit) are also defined for used in place of decimal values.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Decimal values with spaces, or \"E\" | \"U\" | \"L\", or another code", + "type": "string" + }, + "dimensions": { + "description": "The number of sample points at each time point. If this value is greater than one, then the dimensions will be interlaced - all the sample points for a point in time will be recorded at once.", + "element_property": true, + "element_required": true, + "exclusiveMinimum": 0, + "title": "Number of sample points at each time point", + "type": "integer" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "factor": { + "description": "A correction factor that is applied to the sampled data points before they are added to the origin.", + "element_property": true, + "title": "Multiply data by this before adding to origin", + "type": "number" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "interval": { + "description": "Amount of intervalUnits between samples, e.g. milliseconds for time-based sampling.", + "element_property": true, + "title": "Number of intervalUnits between samples", + "type": "number" + }, + "intervalUnit": { + "binding_description": "Units of measure allowed for an element.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/ucum-units", + "binding_version": "5.0.0", + "description": "The measurement unit in which the sample interval is expressed.", + "element_property": true, + "element_required": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "The measurement unit of the interval between samples", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "lowerLimit": { + "description": "The lower limit of detection of the measured points. This is needed if any of the data points have the value \"L\" (lower than detection limit).", + "element_property": true, + "title": "Lower limit of detection", + "type": "number" + }, + "offsets": { + "description": "A series of data points which are decimal values separated by a single space (character u20). The units in which the offsets are expressed are found in intervalUnit. The absolute point at which the measurements begin SHALL be conveyed outside the scope of this datatype, e.g. Observation.effectiveDateTime for a timing offset.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Offsets, typically in time, at which data values were taken", + "type": "string" + }, + "origin": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "The base quantity that a measured value of zero represents. In addition, this provides the units of the entire measurement series.", + "element_property": true, + "title": "Zero value and units" + }, + "resourceType": { + "const": "SampledData", + "default": "SampledData", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "upperLimit": { + "description": "The upper limit of detection of the measured points. This is needed if any of the data points have the value \"U\" (higher than detection limit).", + "element_property": true, + "title": "Upper limit of detection", + "type": "number" + } + }, + "required": [ + "origin" + ], + "title": "SampledData", + "type": "object" + }, + "ResearchStudyComparisonGroup": { + "$id": "http://graph-fhir.io/schema/0.0.2/ResearchStudyComparisonGroup", + "additionalProperties": false, + "description": "Defined path through the study for a subject. Describes an expected event or sequence of events for one of the subjects of a study. E.g. for a living subject: exposure to drug A, wash-out, exposure to drug B, wash-out, follow-up. E.g. for a stability study: {store sample from lot A at 25 degrees for 1 month}, {store sample from lot A at 40 degrees for 1 month}. [See https://hl7.org/fhir/R5/ResearchStudyComparisonGroup.html]", + "links": [ + { + "href": "{id}", + "rel": "observedGroup", + "targetHints": { + "backref": [ + "research_study_comparison_group" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/observedGroup/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_description": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'description'." + }, + "_linkId": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'linkId'." + }, + "_name": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'name'." + }, + "description": { + "description": "A succinct description of the path through the study that would be followed by a subject adhering to this comparisonGroup.", + "element_property": true, + "pattern": "\\s*(\\S|\\s)*", + "title": "Short explanation of study path", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "intendedExposure": { + "backref": "intendedExposure_research_study_comparison_group", + "element_property": true, + "enum_reference_types": [ + "EvidenceVariable" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Interventions or exposures in this comparisonGroup or cohort", + "type": "array" + }, + "linkId": { + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Allows the comparisonGroup for the study and the comparisonGroup for the subject to be linked easily", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "name": { + "description": "Unique, human-readable label for this comparisonGroup of the study.", + "element_property": true, + "element_required": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Label for study comparisonGroup", + "type": "string" + }, + "observedGroup": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "research_study_comparison_group", + "element_property": true, + "enum_reference_types": [ + "Group" + ], + "title": "Group of participants who were enrolled in study comparisonGroup" + }, + "resourceType": { + "const": "ResearchStudyComparisonGroup", + "default": "ResearchStudyComparisonGroup", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "desc.", + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/research-study-arm-type", + "binding_version": null, + "description": "Categorization of study comparisonGroup, e.g. experimental, active comparator, placebo comparater.", + "element_property": true, + "title": "Categorization of study comparisonGroup" + } + }, + "title": "ResearchStudyComparisonGroup", + "type": "object" + }, + "FamilyMemberHistory": { + "$id": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory", + "additionalProperties": false, + "description": "Information about patient's relatives, relevant for patient. Significant health conditions for a person related to the patient relevant in the context of care for the patient. [See https://hl7.org/fhir/R5/FamilyMemberHistory.html]", + "links": [ + { + "href": "{id}", + "rel": "patient", + "targetHints": { + "backref": [ + "family_member_history" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/patient/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Practitioner", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_PractitionerRole", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Patient", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Organization", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From FamilyMemberHistoryParticipant/participant", + "href": "{id}", + "rel": "participant_actor_Practitioner", + "targetHints": { + "backref": [ + "family_member_history_participant" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/participant/-/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From FamilyMemberHistoryParticipant/participant", + "href": "{id}", + "rel": "participant_actor_PractitionerRole", + "targetHints": { + "backref": [ + "family_member_history_participant" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/participant/-/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From FamilyMemberHistoryParticipant/participant", + "href": "{id}", + "rel": "participant_actor_Patient", + "targetHints": { + "backref": [ + "family_member_history_participant" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/participant/-/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From FamilyMemberHistoryParticipant/participant", + "href": "{id}", + "rel": "participant_actor_Organization", + "targetHints": { + "backref": [ + "family_member_history_participant" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/participant/-/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_ageString": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'ageString'." + }, + "_bornDate": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'bornDate'." + }, + "_bornString": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'bornString'." + }, + "_date": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'date'." + }, + "_deceasedBoolean": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'deceasedBoolean'." + }, + "_deceasedDate": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'deceasedDate'." + }, + "_deceasedString": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'deceasedString'." + }, + "_estimatedAge": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'estimatedAge'." + }, + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_instantiatesCanonical": { + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension" + }, + "title": "Extension field for 'instantiatesCanonical'.", + "type": "array" + }, + "_instantiatesUri": { + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension" + }, + "title": "Extension field for 'instantiatesUri'.", + "type": "array" + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "_name": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'name'." + }, + "_status": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'status'." + }, + "ageAge": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Age", + "description": "The age of the relative at the time the family member history is recorded.", + "element_property": true, + "one_of_many": "age", + "one_of_many_required": false, + "title": "(approximate) age" + }, + "ageRange": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Range", + "description": "The age of the relative at the time the family member history is recorded.", + "element_property": true, + "one_of_many": "age", + "one_of_many_required": false, + "title": "(approximate) age" + }, + "ageString": { + "description": "The age of the relative at the time the family member history is recorded.", + "element_property": true, + "one_of_many": "age", + "one_of_many_required": false, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "(approximate) age", + "type": "string" + }, + "bornDate": { + "description": "The actual or approximate date of birth of the relative.", + "element_property": true, + "format": "date", + "one_of_many": "born", + "one_of_many_required": false, + "title": "(approximate) date of birth", + "type": "string" + }, + "bornPeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "The actual or approximate date of birth of the relative.", + "element_property": true, + "one_of_many": "born", + "one_of_many_required": false, + "title": "(approximate) date of birth" + }, + "bornString": { + "description": "The actual or approximate date of birth of the relative.", + "element_property": true, + "one_of_many": "born", + "one_of_many_required": false, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "(approximate) date of birth", + "type": "string" + }, + "condition": { + "description": "The significant Conditions (or condition) that the family member had. This is a repeating section to allow a system to represent more than one condition per resource, though there is nothing stopping multiple resources - one per condition.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistoryCondition" + }, + "title": "Condition that the related person had", + "type": "array" + }, + "contained": { + "description": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, nor can they have their own independent transaction scope. This is allowed to be a Parameters resource if and only if it is referenced by a resource that provides context/meaning.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + "title": "Contained, inline Resources", + "type": "array" + }, + "dataAbsentReason": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Codes describing the reason why a family member's history is not available.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/history-absent-reason", + "binding_version": null, + "description": "Describes why the family member's history is not available.", + "element_property": true, + "title": "subject-unknown | withheld | unable-to-obtain | deferred" + }, + "date": { + "description": "The date (and possibly time) when the family member history was recorded or last updated.", + "element_property": true, + "format": "date-time", + "title": "When history was recorded or last updated", + "type": "string" + }, + "deceasedAge": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Age", + "description": "Deceased flag or the actual or approximate age of the relative at the time of death for the family member history record.", + "element_property": true, + "one_of_many": "deceased", + "one_of_many_required": false, + "title": "Dead? How old/when?" + }, + "deceasedBoolean": { + "description": "Deceased flag or the actual or approximate age of the relative at the time of death for the family member history record.", + "element_property": true, + "one_of_many": "deceased", + "one_of_many_required": false, + "title": "Dead? How old/when?", + "type": "boolean" + }, + "deceasedDate": { + "description": "Deceased flag or the actual or approximate age of the relative at the time of death for the family member history record.", + "element_property": true, + "format": "date", + "one_of_many": "deceased", + "one_of_many_required": false, + "title": "Dead? How old/when?", + "type": "string" + }, + "deceasedRange": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Range", + "description": "Deceased flag or the actual or approximate age of the relative at the time of death for the family member history record.", + "element_property": true, + "one_of_many": "deceased", + "one_of_many_required": false, + "title": "Dead? How old/when?" + }, + "deceasedString": { + "description": "Deceased flag or the actual or approximate age of the relative at the time of death for the family member history record.", + "element_property": true, + "one_of_many": "deceased", + "one_of_many_required": false, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Dead? How old/when?", + "type": "string" + }, + "estimatedAge": { + "description": "If true, indicates that the age value specified is an estimated value.", + "element_property": true, + "title": "Age is estimated?", + "type": "boolean" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "identifier": { + "description": "Business identifiers assigned to this family member history by the performer or other systems which remain constant as the resource is updated and propagates from server to server.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "External Id(s) for this record", + "type": "array" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "instantiatesCanonical": { + "description": "The URL pointing to a FHIR-defined protocol, guideline, orderset or other definition that is adhered to in whole or in part by this FamilyMemberHistory.", + "element_property": true, + "enum_reference_types": [ + "PlanDefinition", + "Questionnaire", + "ActivityDefinition", + "Measure", + "OperationDefinition" + ], + "items": { + "pattern": "\\S*", + "type": "string" + }, + "title": "Instantiates FHIR protocol or definition", + "type": "array" + }, + "instantiatesUri": { + "description": "The URL pointing to an externally maintained protocol, guideline, orderset or other definition that is adhered to in whole or in part by this FamilyMemberHistory.", + "element_property": true, + "items": { + "pattern": "\\S*", + "type": "string" + }, + "title": "Instantiates external protocol or definition", + "type": "array" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored", + "type": "array" + }, + "name": { + "description": "This will either be a name or a description; e.g. \"Aunt Susan\", \"my cousin with the red hair\".", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "The family member described", + "type": "string" + }, + "note": { + "description": "This property allows a non condition-specific note to the made about the related person. Ideally, the note would be in the condition property, but this is not always possible.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Annotation" + }, + "title": "General note about related person", + "type": "array" + }, + "participant": { + "description": "Indicates who or what participated in the activities related to the family member history and how they were involved.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistoryParticipant" + }, + "title": "Who or what participated in the activities related to the family member history and how they were involved", + "type": "array" + }, + "patient": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "family_member_history", + "description": "The person who this history concerns.", + "element_property": true, + "enum_reference_types": [ + "Patient" + ], + "title": "Patient history is about" + }, + "procedure": { + "description": "The significant Procedures (or procedure) that the family member had. This is a repeating section to allow a system to represent more than one procedure per resource, though there is nothing stopping multiple resources - one per procedure.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistoryProcedure" + }, + "title": "Procedures that the related person had", + "type": "array" + }, + "reason": { + "backref": "reason_family_member_history", + "binding_description": "Codes indicating why the family member history was done.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/clinical-findings", + "binding_version": null, + "description": "Describes why the family member history occurred in coded or textual form, or Indicates a Condition, Observation, AllergyIntolerance, or QuestionnaireResponse that justifies this family member history event.", + "element_property": true, + "enum_reference_types": [ + "Condition", + "Observation", + "AllergyIntolerance", + "QuestionnaireResponse", + "DiagnosticReport", + "DocumentReference" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference" + }, + "title": "Why was family member history performed?", + "type": "array" + }, + "relationship": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The nature of the relationship between the patient and the related person being described in the family member history.", + "binding_strength": "example", + "binding_uri": "http://terminology.hl7.org/ValueSet/v3-FamilyMember", + "binding_version": null, + "description": "The type of relationship this person has to the patient (father, mother, brother etc.).", + "element_property": true, + "title": "Relationship to the subject" + }, + "resourceType": { + "const": "FamilyMemberHistory", + "default": "FamilyMemberHistory", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "sex": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Codes describing the sex assigned at birth as documented on the birth registration.", + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/administrative-gender", + "binding_version": null, + "description": "The birth sex of the family member.", + "element_property": true, + "title": "male | female | other | unknown" + }, + "status": { + "binding_description": "A code that identifies the status of the family history record.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/history-status", + "binding_version": "5.0.0", + "description": "A code specifying the status of the record of the family history of a specific family member.", + "element_property": true, + "element_required": true, + "enum_values": [ + "partial", + "completed", + "entered-in-error", + "health-unknown" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "partial | completed | entered-in-error | health-unknown", + "type": "string" + }, + "text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative", + "description": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "element_property": true, + "title": "Text summary of the resource, for human interpretation" + } + }, + "required": [ + "patient", + "relationship" + ], + "title": "FamilyMemberHistory", + "type": "object" + }, + "RelatedArtifact": { + "$id": "http://graph-fhir.io/schema/0.0.2/RelatedArtifact", + "additionalProperties": false, + "description": "Related artifacts for a knowledge resource. Related artifacts such as additional documentation, justification, or bibliographic references. [See https://hl7.org/fhir/R5/RelatedArtifact.html]", + "links": [ + { + "href": "{id}", + "rel": "resourceReference_Organization", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resourceReference_Group", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resourceReference_Practitioner", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resourceReference_PractitionerRole", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resourceReference_ResearchStudy", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resourceReference_Patient", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resourceReference_ResearchSubject", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resourceReference_Substance", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resourceReference_SubstanceDefinition", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resourceReference_Specimen", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resourceReference_Observation", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resourceReference_DiagnosticReport", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resourceReference_Condition", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resourceReference_Medication", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resourceReference_MedicationAdministration", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resourceReference_MedicationStatement", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resourceReference_MedicationRequest", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resourceReference_Procedure", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resourceReference_DocumentReference", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resourceReference_Task", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resourceReference_ImagingStudy", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resourceReference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resourceReference_BodyStructure", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_citation": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'citation'." + }, + "_display": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'display'." + }, + "_label": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'label'." + }, + "_publicationDate": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'publicationDate'." + }, + "_publicationStatus": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'publicationStatus'." + }, + "_resource": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'resource'." + }, + "_type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'type'." + }, + "citation": { + "description": "A bibliographic citation for the related artifact. This text SHOULD be formatted according to an accepted citation format.", + "element_property": true, + "pattern": "\\s*(\\S|\\s)*", + "title": "Bibliographic citation for the artifact", + "type": "string" + }, + "classifier": { + "binding_description": "Additional classifiers for the related artifact.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/citation-artifact-classifier", + "binding_version": null, + "description": "Provides additional classifiers of the related artifact.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Additional classifiers", + "type": "array" + }, + "display": { + "description": "A brief description of the document or knowledge resource being referenced, suitable for display to a consumer.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Brief description of the related artifact", + "type": "string" + }, + "document": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Attachment", + "description": "The document being referenced, represented as an attachment. This is exclusive with the resource element.", + "element_property": true, + "title": "What document is being referenced" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "label": { + "description": "A short label that can be used to reference the citation from elsewhere in the containing artifact, such as a footnote index.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Short label", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "publicationDate": { + "description": "The date of publication of the artifact being referred to.", + "element_property": true, + "format": "date", + "title": "Date of publication of the artifact being referred to", + "type": "string" + }, + "publicationStatus": { + "binding_description": "Publication status of an artifact being referred to.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/publication-status", + "binding_version": "5.0.0", + "description": "The publication status of the artifact being referred to.", + "element_property": true, + "enum_values": [ + "draft", + "active", + "retired", + "unknown" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "draft | active | retired | unknown", + "type": "string" + }, + "resource": { + "description": "The related artifact, such as a library, value set, profile, or other knowledge resource.", + "element_property": true, + "enum_reference_types": [ + "Resource" + ], + "pattern": "\\S*", + "title": "What artifact is being referenced", + "type": "string" + }, + "resourceReference": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "related_artifact", + "description": "The related artifact, if the artifact is not a canonical resource, or a resource reference to a canonical resource.", + "element_property": true, + "enum_reference_types": [ + "Organization", + "Group", + "Practitioner", + "PractitionerRole", + "ResearchStudy", + "Patient", + "ResearchSubject", + "Substance", + "SubstanceDefinition", + "Specimen", + "Observation", + "DiagnosticReport", + "Condition", + "Medication", + "MedicationAdministration", + "MedicationStatement", + "MedicationRequest", + "Procedure", + "DocumentReference", + "Task", + "ImagingStudy", + "FamilyMemberHistory", + "BodyStructure" + ], + "title": "What artifact, if not a conformance resource" + }, + "resourceType": { + "const": "RelatedArtifact", + "default": "RelatedArtifact", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "type": { + "binding_description": "The type of relationship to the related artifact.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/related-artifact-type", + "binding_version": "5.0.0", + "description": "The type of relationship to the related artifact.", + "element_property": true, + "element_required": true, + "enum_values": [ + "documentation", + "justification", + "citation", + "predecessor", + "successor", + "derived-from", + "depends-on", + "composed-of", + "part-of", + "amends", + "amended-with", + "appends", + "appended-with", + "cites", + "cited-by", + "comments-on", + "comment-in", + "contains", + "contained-in", + "corrects", + "correction-in", + "replaces", + "replaced-with", + "retracts", + "retracted-by", + "signs", + "similar-to", + "supports", + "supported-with", + "transforms", + "transformed-into", + "transformed-with", + "documents", + "specification-of", + "created-with", + "cite-as" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "documentation | justification | citation | predecessor | successor | derived-from | depends-on | composed-of | part-of | amends | amended-with | appends | appended-with | cites | cited-by | comments-on | comment-in | contains | contained-in | corrects | correction-in | replaces | replaced-with | retracts | retracted-by | signs | similar-to | supports | supported-with | transforms | transformed-into | transformed-with | documents | specification-of | created-with | cite-as", + "type": "string" + } + }, + "title": "RelatedArtifact", + "type": "object" + }, + "Observation": { + "$id": "http://graph-fhir.io/schema/0.0.2/Observation", + "additionalProperties": false, + "description": "Measurements and simple assertions. Measurements and simple assertions made about a patient, device or other subject. [See https://hl7.org/fhir/R5/Observation.html]", + "links": [ + { + "href": "{id}", + "rel": "basedOn_MedicationRequest", + "targetHints": { + "backref": [ + "basedOn_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "bodyStructure", + "targetHints": { + "backref": [ + "observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/bodyStructure/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_DocumentReference", + "targetHints": { + "backref": [ + "derivedFrom_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_ImagingStudy", + "targetHints": { + "backref": [ + "derivedFrom_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_Observation", + "targetHints": { + "backref": [ + "derivedFrom_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Organization", + "targetHints": { + "backref": [ + "focus_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/focus/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Group", + "targetHints": { + "backref": [ + "focus_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/focus/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Practitioner", + "targetHints": { + "backref": [ + "focus_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/focus/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_PractitionerRole", + "targetHints": { + "backref": [ + "focus_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/focus/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_ResearchStudy", + "targetHints": { + "backref": [ + "focus_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/focus/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Patient", + "targetHints": { + "backref": [ + "focus_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/focus/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_ResearchSubject", + "targetHints": { + "backref": [ + "focus_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/focus/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Substance", + "targetHints": { + "backref": [ + "focus_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/focus/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_SubstanceDefinition", + "targetHints": { + "backref": [ + "focus_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/focus/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Specimen", + "targetHints": { + "backref": [ + "focus_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/focus/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Observation", + "targetHints": { + "backref": [ + "focus_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/focus/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_DiagnosticReport", + "targetHints": { + "backref": [ + "focus_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/focus/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Condition", + "targetHints": { + "backref": [ + "focus_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/focus/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Medication", + "targetHints": { + "backref": [ + "focus_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/focus/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_MedicationAdministration", + "targetHints": { + "backref": [ + "focus_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/focus/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_MedicationStatement", + "targetHints": { + "backref": [ + "focus_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/focus/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_MedicationRequest", + "targetHints": { + "backref": [ + "focus_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/focus/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Procedure", + "targetHints": { + "backref": [ + "focus_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/focus/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_DocumentReference", + "targetHints": { + "backref": [ + "focus_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/focus/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Task", + "targetHints": { + "backref": [ + "focus_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/focus/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_ImagingStudy", + "targetHints": { + "backref": [ + "focus_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/focus/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_FamilyMemberHistory", + "targetHints": { + "backref": [ + "focus_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/focus/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_BodyStructure", + "targetHints": { + "backref": [ + "focus_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/focus/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "hasMember_Observation", + "targetHints": { + "backref": [ + "hasMember_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/hasMember/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "partOf_MedicationAdministration", + "targetHints": { + "backref": [ + "partOf_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/partOf/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "partOf_MedicationStatement", + "targetHints": { + "backref": [ + "partOf_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/partOf/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "partOf_Procedure", + "targetHints": { + "backref": [ + "partOf_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/partOf/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "partOf_ImagingStudy", + "targetHints": { + "backref": [ + "partOf_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/partOf/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "performer_Practitioner", + "targetHints": { + "backref": [ + "performer_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/performer/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "performer_PractitionerRole", + "targetHints": { + "backref": [ + "performer_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/performer/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "performer_Organization", + "targetHints": { + "backref": [ + "performer_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/performer/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "performer_Patient", + "targetHints": { + "backref": [ + "performer_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/performer/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "specimen_Specimen", + "targetHints": { + "backref": [ + "specimen_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/specimen/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "specimen_Group", + "targetHints": { + "backref": [ + "specimen_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/specimen/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Patient", + "targetHints": { + "backref": [ + "subject_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Group", + "targetHints": { + "backref": [ + "subject_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Organization", + "targetHints": { + "backref": [ + "subject_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Procedure", + "targetHints": { + "backref": [ + "subject_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Practitioner", + "targetHints": { + "backref": [ + "subject_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Medication", + "targetHints": { + "backref": [ + "subject_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Substance", + "targetHints": { + "backref": [ + "subject_observation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Practitioner", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_PractitionerRole", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Patient", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Organization", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ObservationTriggeredBy/triggeredBy", + "href": "{id}", + "rel": "triggeredBy_observation", + "targetHints": { + "backref": [ + "observation_triggered_by" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/triggeredBy/-/observation/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_effectiveDateTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'effectiveDateTime'." + }, + "_effectiveInstant": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'effectiveInstant'." + }, + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_instantiatesCanonical": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'instantiatesCanonical'." + }, + "_issued": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'issued'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "_status": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'status'." + }, + "_valueBoolean": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueBoolean'." + }, + "_valueDateTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueDateTime'." + }, + "_valueInteger": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueInteger'." + }, + "_valueString": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueString'." + }, + "_valueTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueTime'." + }, + "basedOn": { + "backref": "basedOn_observation", + "description": "A plan, proposal or order that is fulfilled in whole or in part by this event. For example, a MedicationRequest may require a patient to have laboratory test performed before it is dispensed.", + "element_property": true, + "enum_reference_types": [ + "CarePlan", + "DeviceRequest", + "ImmunizationRecommendation", + "MedicationRequest", + "NutritionOrder", + "ServiceRequest" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Fulfills plan, proposal or order", + "type": "array" + }, + "bodySite": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "SNOMED CT Body site concepts", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/body-site", + "binding_version": null, + "description": "Indicates the site on the subject's body where the observation was made (i.e. the target site).", + "element_property": true, + "title": "Observed body part" + }, + "bodyStructure": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "observation", + "description": "Indicates the body structure on the subject's body where the observation was made (i.e. the target site).", + "element_property": true, + "enum_reference_types": [ + "BodyStructure" + ], + "title": "Observed body structure" + }, + "category": { + "binding_description": "Codes for high level observation categories.", + "binding_strength": "preferred", + "binding_uri": "http://hl7.org/fhir/ValueSet/observation-category", + "binding_version": null, + "description": "A code that classifies the general type of observation being made.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Classification of type of observation", + "type": "array" + }, + "code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "LDL Cholesterol codes - measured or calculated.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/lipid-ldl-codes", + "binding_version": null, + "description": "Describes what was observed. Sometimes this is called the observation \"name\".", + "element_property": true, + "title": "Type of observation (code / type)" + }, + "component": { + "description": "Some observations have multiple component observations. These component observations are expressed as separate code value pairs that share the same attributes. Examples include systolic and diastolic component observations for blood pressure measurement and multiple component observations for genetics observations.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ObservationComponent" + }, + "title": "Component results", + "type": "array" + }, + "contained": { + "description": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, nor can they have their own independent transaction scope. This is allowed to be a Parameters resource if and only if it is referenced by a resource that provides context/meaning.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + "title": "Contained, inline Resources", + "type": "array" + }, + "dataAbsentReason": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Codes specifying why the result (`Observation.value[x]`) is missing.", + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/data-absent-reason", + "binding_version": null, + "description": "Provides a reason why the expected value in the element Observation.value[x] is missing.", + "element_property": true, + "title": "Why the result is missing" + }, + "derivedFrom": { + "backref": "derivedFrom_observation", + "description": "The target resource that represents a measurement from which this observation value is derived. For example, a calculated anion gap or a fetal measurement based on an ultrasound image.", + "element_property": true, + "enum_reference_types": [ + "DocumentReference", + "ImagingStudy", + "ImagingSelection", + "QuestionnaireResponse", + "Observation", + "MolecularSequence", + "GenomicStudy" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Related resource from which the observation is made", + "type": "array" + }, + "device": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "device_observation", + "element_property": true, + "enum_reference_types": [ + "Device", + "DeviceMetric" + ], + "title": "A reference to the device that generates the measurements or the device settings for the device" + }, + "effectiveDateTime": { + "description": "The time or time-period the observed value is asserted as being true. For biological subjects - e.g. human patients - this is usually called the \"physiologically relevant time\". This is usually either the time of the procedure or of specimen collection, but very often the source of the date/time is not known, only the date/time itself.", + "element_property": true, + "format": "date-time", + "one_of_many": "effective", + "one_of_many_required": false, + "title": "Clinically relevant time/time-period for observation", + "type": "string" + }, + "effectiveInstant": { + "description": "The time or time-period the observed value is asserted as being true. For biological subjects - e.g. human patients - this is usually called the \"physiologically relevant time\". This is usually either the time of the procedure or of specimen collection, but very often the source of the date/time is not known, only the date/time itself.", + "element_property": true, + "format": "date-time", + "one_of_many": "effective", + "one_of_many_required": false, + "title": "Clinically relevant time/time-period for observation", + "type": "string" + }, + "effectivePeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "The time or time-period the observed value is asserted as being true. For biological subjects - e.g. human patients - this is usually called the \"physiologically relevant time\". This is usually either the time of the procedure or of specimen collection, but very often the source of the date/time is not known, only the date/time itself.", + "element_property": true, + "one_of_many": "effective", + "one_of_many_required": false, + "title": "Clinically relevant time/time-period for observation" + }, + "effectiveTiming": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Timing", + "description": "The time or time-period the observed value is asserted as being true. For biological subjects - e.g. human patients - this is usually called the \"physiologically relevant time\". This is usually either the time of the procedure or of specimen collection, but very often the source of the date/time is not known, only the date/time itself.", + "element_property": true, + "one_of_many": "effective", + "one_of_many_required": false, + "title": "Clinically relevant time/time-period for observation" + }, + "encounter": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "observation", + "description": "The healthcare event (e.g. a patient and healthcare provider interaction) during which this observation is made.", + "element_property": true, + "enum_reference_types": [ + "Encounter" + ], + "title": "Healthcare event during which this observation is made" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "focus": { + "backref": "focus_observation", + "description": "The actual focus of an observation when it is not the patient of record representing something or someone associated with the patient such as a spouse, parent, fetus, or donor. For example, fetus observations in a mother's record. The focus of an observation could also be an existing condition, an intervention, the subject's diet, another observation of the subject, or a body structure such as tumor or implanted device. An example use case would be using the Observation resource to capture whether the mother is trained to change her child's tracheostomy tube. In this example, the child is the patient of record and the mother is the focus.", + "element_property": true, + "enum_reference_types": [ + "Organization", + "Group", + "Practitioner", + "PractitionerRole", + "ResearchStudy", + "Patient", + "ResearchSubject", + "Substance", + "SubstanceDefinition", + "Specimen", + "Observation", + "DiagnosticReport", + "Condition", + "Medication", + "MedicationAdministration", + "MedicationStatement", + "MedicationRequest", + "Procedure", + "DocumentReference", + "Task", + "ImagingStudy", + "FamilyMemberHistory", + "BodyStructure" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "What the observation is about, when it is not about the subject of record", + "type": "array" + }, + "hasMember": { + "backref": "hasMember_observation", + "description": "This observation is a group observation (e.g. a battery, a panel of tests, a set of vital sign measurements) that includes the target as a member of the group.", + "element_property": true, + "enum_reference_types": [ + "Observation", + "QuestionnaireResponse", + "MolecularSequence" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Related resource that belongs to the Observation group", + "type": "array" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "identifier": { + "description": "A unique identifier assigned to this observation.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "Business Identifier for observation", + "type": "array" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "instantiatesCanonical": { + "description": "The reference to a FHIR ObservationDefinition resource that provides the definition that is adhered to in whole or in part by this Observation instance.", + "element_property": true, + "enum_reference_types": [ + "ObservationDefinition" + ], + "one_of_many": "instantiates", + "one_of_many_required": false, + "pattern": "\\S*", + "title": "Instantiates FHIR ObservationDefinition", + "type": "string" + }, + "instantiatesReference": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "observation", + "description": "The reference to a FHIR ObservationDefinition resource that provides the definition that is adhered to in whole or in part by this Observation instance.", + "element_property": true, + "enum_reference_types": [ + "ObservationDefinition" + ], + "one_of_many": "instantiates", + "one_of_many_required": false, + "title": "Instantiates FHIR ObservationDefinition" + }, + "interpretation": { + "binding_description": "Codes identifying interpretations of observations.", + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/observation-interpretation", + "binding_version": null, + "description": "A categorical assessment of an observation value. For example, high, low, normal.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "High, low, normal, etc", + "type": "array" + }, + "issued": { + "description": "The date and time this version of the observation was made available to providers, typically after the results have been reviewed and verified.", + "element_property": true, + "format": "date-time", + "title": "Date/Time this version was made available", + "type": "string" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "method": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Methods for simple observations.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/observation-methods", + "binding_version": null, + "description": "Indicates the mechanism used to perform the observation.", + "element_property": true, + "title": "How it was done" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored", + "type": "array" + }, + "note": { + "description": "Comments about the observation or the results.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Annotation" + }, + "title": "Comments about the observation", + "type": "array" + }, + "partOf": { + "backref": "partOf_observation", + "description": "A larger event of which this particular Observation is a component or step. For example, an observation as part of a procedure.", + "element_property": true, + "enum_reference_types": [ + "MedicationAdministration", + "MedicationDispense", + "MedicationStatement", + "Procedure", + "Immunization", + "ImagingStudy", + "GenomicStudy" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Part of referenced event", + "type": "array" + }, + "performer": { + "backref": "performer_observation", + "description": "Who was responsible for asserting the observed value as \"true\".", + "element_property": true, + "enum_reference_types": [ + "Practitioner", + "PractitionerRole", + "Organization", + "CareTeam", + "Patient", + "RelatedPerson" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Who is responsible for the observation", + "type": "array" + }, + "referenceRange": { + "description": "Guidance on how to interpret the value by comparison to a normal or recommended range. Multiple reference ranges are interpreted as an \"OR\". In other words, to represent two distinct target populations, two `referenceRange` elements would be used.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ObservationReferenceRange" + }, + "title": "Provides guide for interpretation", + "type": "array" + }, + "resourceType": { + "const": "Observation", + "default": "Observation", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "specimen": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "specimen_observation", + "description": "The specimen that was used when this observation was made.", + "element_property": true, + "enum_reference_types": [ + "Specimen", + "Group" + ], + "title": "Specimen used for this observation" + }, + "status": { + "binding_description": "Codes providing the status of an observation.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/observation-status", + "binding_version": "5.0.0", + "description": "The status of the result value.", + "element_property": true, + "element_required": true, + "enum_values": [ + "registered", + "preliminary", + "final", + "amended", + "+" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "registered | preliminary | final | amended +", + "type": "string" + }, + "subject": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "subject_observation", + "description": "The patient, or group of patients, location, device, organization, procedure or practitioner this observation is about and into whose or what record the observation is placed. If the actual focus of the observation is different from the subject (or a sample of, part, or region of the subject), the `focus` element or the `code` itself specifies the actual focus of the observation.", + "element_property": true, + "enum_reference_types": [ + "Patient", + "Group", + "Device", + "Location", + "Organization", + "Procedure", + "Practitioner", + "Medication", + "Substance", + "BiologicallyDerivedProduct", + "NutritionProduct" + ], + "title": "Who and/or what the observation is about" + }, + "text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative", + "description": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "element_property": true, + "title": "Text summary of the resource, for human interpretation" + }, + "triggeredBy": { + "description": "Identifies the observation(s) that triggered the performance of this observation.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ObservationTriggeredBy" + }, + "title": "Triggering observation(s)", + "type": "array" + }, + "valueAttachment": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Attachment", + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual result" + }, + "valueBoolean": { + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual result", + "type": "boolean" + }, + "valueCodeableConcept": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual result" + }, + "valueDateTime": { + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "format": "date-time", + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual result", + "type": "string" + }, + "valueInteger": { + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual result", + "type": "integer" + }, + "valuePeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual result" + }, + "valueQuantity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual result" + }, + "valueRange": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Range", + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual result" + }, + "valueRatio": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Ratio", + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual result" + }, + "valueReference": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "valueReference_observation", + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "enum_reference_types": [ + "MolecularSequence" + ], + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual result" + }, + "valueSampledData": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SampledData", + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual result" + }, + "valueString": { + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Actual result", + "type": "string" + }, + "valueTime": { + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "format": "time", + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual result", + "type": "string" + } + }, + "required": [ + "code" + ], + "title": "Observation", + "type": "object" + }, + "ObservationTriggeredBy": { + "$id": "http://graph-fhir.io/schema/0.0.2/ObservationTriggeredBy", + "additionalProperties": false, + "description": "Triggering observation(s). Identifies the observation(s) that triggered the performance of this observation. [See https://hl7.org/fhir/R5/ObservationTriggeredBy.html]", + "links": [ + { + "href": "{id}", + "rel": "observation", + "targetHints": { + "backref": [ + "observation_triggered_by" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/observation/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_reason": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'reason'." + }, + "_type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'type'." + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "observation": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "observation_triggered_by", + "description": "Reference to the triggering observation.", + "element_property": true, + "enum_reference_types": [ + "Observation" + ], + "title": "Triggering observation" + }, + "reason": { + "description": "Provides the reason why this observation was performed as a result of the observation(s) referenced.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Reason that the observation was triggered", + "type": "string" + }, + "resourceType": { + "const": "ObservationTriggeredBy", + "default": "ObservationTriggeredBy", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "type": { + "binding_description": "The type of TriggeredBy Observation.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/observation-triggeredbytype", + "binding_version": "5.0.0", + "description": "The type of trigger. Reflex | Repeat | Re-run.", + "element_property": true, + "element_required": true, + "enum_values": [ + "reflex", + "repeat", + "re-run" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "reflex | repeat | re-run", + "type": "string" + } + }, + "required": [ + "observation" + ], + "title": "ObservationTriggeredBy", + "type": "object" + }, + "SubstanceDefinitionCode": { + "$id": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionCode", + "additionalProperties": false, + "description": "Codes associated with the substance. [See https://hl7.org/fhir/R5/SubstanceDefinitionCode.html]", + "links": [ + { + "href": "{id}", + "rel": "source", + "targetHints": { + "backref": [ + "source_substance_definition_code" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/source/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Practitioner", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_PractitionerRole", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Patient", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Organization", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_statusDate": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'statusDate'." + }, + "code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "element_property": true, + "title": "The specific code" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "note": { + "description": "Any comment can be provided in this field, if necessary.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Annotation" + }, + "title": "Any comment can be provided in this field", + "type": "array" + }, + "resourceType": { + "const": "SubstanceDefinitionCode", + "default": "SubstanceDefinitionCode", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "source": { + "backref": "source_substance_definition_code", + "element_property": true, + "enum_reference_types": [ + "DocumentReference" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Supporting literature", + "type": "array" + }, + "status": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The lifecycle status of an artifact.", + "binding_strength": "preferred", + "binding_uri": "http://hl7.org/fhir/ValueSet/publication-status", + "binding_version": null, + "element_property": true, + "title": "Status of the code assignment, for example 'provisional', 'approved'" + }, + "statusDate": { + "description": "The date at which the code status was changed as part of the terminology maintenance.", + "element_property": true, + "format": "date-time", + "title": "The date at which the code status was changed", + "type": "string" + } + }, + "title": "SubstanceDefinitionCode", + "type": "object" + }, + "DataRequirementCodeFilter": { + "$id": "http://graph-fhir.io/schema/0.0.2/DataRequirementCodeFilter", + "additionalProperties": false, + "description": "What codes are expected. Code filters specify additional constraints on the data, specifying the value set of interest for a particular element of the data. Each code filter defines an additional constraint on the data, i.e. code filters are AND'ed, not OR'ed. [See https://hl7.org/fhir/R5/DataRequirementCodeFilter.html]", + "links": [], + "properties": { + "_path": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'path'." + }, + "_searchParam": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'searchParam'." + }, + "_valueSet": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueSet'." + }, + "code": { + "description": "The codes for the code filter. If values are given, the filter will return only those data items for which the code-valued attribute specified by the path has a value that is one of the specified codes. If codes are specified in addition to a value set, the filter returns items matching a code in the value set or one of the specified codes.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Coding" + }, + "title": "What code is expected", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "path": { + "description": "The code-valued attribute of the filter. The specified path SHALL be a FHIRPath resolvable on the specified type of the DataRequirement, and SHALL consist only of identifiers, constant indexers, and .resolve(). The path is allowed to contain qualifiers (.) to traverse sub-elements, as well as indexers ([x]) to traverse multiple-cardinality sub-elements (see the [Simple FHIRPath Profile](fhirpath.html#simple) for full details). Note that the index must be an integer constant. The path must resolve to an element of type code, Coding, or CodeableConcept.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "A code-valued attribute to filter on", + "type": "string" + }, + "resourceType": { + "const": "DataRequirementCodeFilter", + "default": "DataRequirementCodeFilter", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "searchParam": { + "description": "A token parameter that refers to a search parameter defined on the specified type of the DataRequirement, and which searches on elements of type code, Coding, or CodeableConcept.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "A coded (token) parameter to search on", + "type": "string" + }, + "valueSet": { + "description": "The valueset for the code filter. The valueSet and code elements are additive. If valueSet is specified, the filter will return only those data items for which the value of the code-valued element specified in the path is a member of the specified valueset.", + "element_property": true, + "enum_reference_types": [ + "ValueSet" + ], + "pattern": "\\S*", + "title": "ValueSet for the filter", + "type": "string" + } + }, + "title": "DataRequirementCodeFilter", + "type": "object" + }, + "FamilyMemberHistoryParticipant": { + "$id": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistoryParticipant", + "additionalProperties": false, + "description": "Who or what participated in the activities related to the family member history and how they were involved. Indicates who or what participated in the activities related to the family member history and how they were involved. [See https://hl7.org/fhir/R5/FamilyMemberHistoryParticipant.html]", + "links": [ + { + "href": "{id}", + "rel": "actor_Practitioner", + "targetHints": { + "backref": [ + "family_member_history_participant" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "actor_PractitionerRole", + "targetHints": { + "backref": [ + "family_member_history_participant" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "actor_Patient", + "targetHints": { + "backref": [ + "family_member_history_participant" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "actor_Organization", + "targetHints": { + "backref": [ + "family_member_history_participant" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/actor/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "actor": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "family_member_history_participant", + "description": "Indicates who or what participated in the activities related to the family member history.", + "element_property": true, + "enum_reference_types": [ + "Practitioner", + "PractitionerRole", + "Patient", + "RelatedPerson", + "Device", + "Organization", + "CareTeam" + ], + "title": "Who or what participated in the activities related to the family member history" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "function": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": null, + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/participation-role-type", + "binding_version": null, + "description": "Distinguishes the type of involvement of the actor in the activities related to the family member history.", + "element_property": true, + "title": "Type of involvement" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "FamilyMemberHistoryParticipant", + "default": "FamilyMemberHistoryParticipant", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "required": [ + "actor" + ], + "title": "FamilyMemberHistoryParticipant", + "type": "object" + }, + "PatientLink": { + "$id": "http://graph-fhir.io/schema/0.0.2/PatientLink", + "additionalProperties": false, + "description": "Link to a Patient or RelatedPerson resource that concerns the same actual individual. [See https://hl7.org/fhir/R5/PatientLink.html]", + "links": [ + { + "href": "{id}", + "rel": "other_Patient", + "targetHints": { + "backref": [ + "patient_link" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/other/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'type'." + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "other": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "patient_link", + "description": "Link to a Patient or RelatedPerson resource that concerns the same actual individual.", + "element_property": true, + "enum_reference_types": [ + "Patient", + "RelatedPerson" + ], + "title": "The other patient or related person resource that the link refers to" + }, + "resourceType": { + "const": "PatientLink", + "default": "PatientLink", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "type": { + "binding_description": "The type of link between this patient resource and another Patient resource, or Patient/RelatedPerson when using the `seealso` code", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/link-type", + "binding_version": "5.0.0", + "description": "The type of link between this patient resource and another patient resource.", + "element_property": true, + "element_required": true, + "enum_values": [ + "replaced-by", + "replaces", + "refer", + "seealso" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "replaced-by | replaces | refer | seealso", + "type": "string" + } + }, + "required": [ + "other" + ], + "title": "PatientLink", + "type": "object" + }, + "TaskOutput": { + "$id": "http://graph-fhir.io/schema/0.0.2/TaskOutput", + "additionalProperties": false, + "description": "Information produced as part of task. Outputs produced by the Task. [See https://hl7.org/fhir/R5/TaskOutput.html]", + "links": [ + { + "href": "{id}", + "rel": "valueReference_Organization", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Group", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Practitioner", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_PractitionerRole", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_ResearchStudy", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Patient", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_ResearchSubject", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Substance", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_SubstanceDefinition", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Specimen", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Observation", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_DiagnosticReport", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Condition", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Medication", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_MedicationAdministration", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_MedicationStatement", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_MedicationRequest", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Procedure", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_DocumentReference", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Task", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_ImagingStudy", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_BodyStructure", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/valueAnnotation", + "href": "{id}", + "rel": "valueAnnotation_authorReference_Practitioner", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/valueAnnotation/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/valueAnnotation", + "href": "{id}", + "rel": "valueAnnotation_authorReference_PractitionerRole", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/valueAnnotation/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/valueAnnotation", + "href": "{id}", + "rel": "valueAnnotation_authorReference_Patient", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/valueAnnotation/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/valueAnnotation", + "href": "{id}", + "rel": "valueAnnotation_authorReference_Organization", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueAnnotation/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From DataRequirement/valueDataRequirement", + "href": "{id}", + "rel": "valueDataRequirement_subjectReference", + "targetHints": { + "backref": [ + "data_requirement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/valueDataRequirement/subjectReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ExtendedContactDetail/valueExtendedContactDetail", + "href": "{id}", + "rel": "valueExtendedContactDetail_organization", + "targetHints": { + "backref": [ + "extended_contact_detail" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueExtendedContactDetail/organization/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Organization", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Group", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Practitioner", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_PractitionerRole", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_ResearchStudy", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Patient", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_ResearchSubject", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Substance", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_SubstanceDefinition", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Specimen", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Observation", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_DiagnosticReport", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Condition", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Medication", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_MedicationAdministration", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_MedicationStatement", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_MedicationRequest", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Procedure", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_DocumentReference", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Task", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_ImagingStudy", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_BodyStructure", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_onBehalfOf_Practitioner", + "targetHints": { + "backref": [ + "onBehalfOf_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/valueSignature/onBehalfOf/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_onBehalfOf_PractitionerRole", + "targetHints": { + "backref": [ + "onBehalfOf_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/valueSignature/onBehalfOf/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_onBehalfOf_Patient", + "targetHints": { + "backref": [ + "onBehalfOf_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/valueSignature/onBehalfOf/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_onBehalfOf_Organization", + "targetHints": { + "backref": [ + "onBehalfOf_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueSignature/onBehalfOf/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_who_Practitioner", + "targetHints": { + "backref": [ + "who_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/valueSignature/who/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_who_PractitionerRole", + "targetHints": { + "backref": [ + "who_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/valueSignature/who/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_who_Patient", + "targetHints": { + "backref": [ + "who_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/valueSignature/who/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_who_Organization", + "targetHints": { + "backref": [ + "who_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueSignature/who/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From UsageContext/valueUsageContext", + "href": "{id}", + "rel": "valueUsageContext_valueReference_ResearchStudy", + "targetHints": { + "backref": [ + "usage_context" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/valueUsageContext/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From UsageContext/valueUsageContext", + "href": "{id}", + "rel": "valueUsageContext_valueReference_Group", + "targetHints": { + "backref": [ + "usage_context" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/valueUsageContext/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From UsageContext/valueUsageContext", + "href": "{id}", + "rel": "valueUsageContext_valueReference_Organization", + "targetHints": { + "backref": [ + "usage_context" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueUsageContext/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_valueBase64Binary": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueBase64Binary'." + }, + "_valueBoolean": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueBoolean'." + }, + "_valueCanonical": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueCanonical'." + }, + "_valueCode": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueCode'." + }, + "_valueDate": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueDate'." + }, + "_valueDateTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueDateTime'." + }, + "_valueDecimal": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueDecimal'." + }, + "_valueId": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueId'." + }, + "_valueInstant": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueInstant'." + }, + "_valueInteger": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueInteger'." + }, + "_valueInteger64": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueInteger64'." + }, + "_valueMarkdown": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueMarkdown'." + }, + "_valueOid": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueOid'." + }, + "_valuePositiveInt": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valuePositiveInt'." + }, + "_valueString": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueString'." + }, + "_valueTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueTime'." + }, + "_valueUnsignedInt": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueUnsignedInt'." + }, + "_valueUri": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueUri'." + }, + "_valueUrl": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueUrl'." + }, + "_valueUuid": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueUuid'." + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "TaskOutput", + "default": "TaskOutput", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "description": "The name of the Output parameter.", + "element_property": true, + "title": "Label for output" + }, + "valueAddress": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Address", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueAge": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Age", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueAnnotation": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Annotation", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueAttachment": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Attachment", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueAvailability": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Availability", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueBase64Binary": { + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "format": "binary", + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output", + "type": "string" + }, + "valueBoolean": { + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output", + "type": "boolean" + }, + "valueCanonical": { + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "pattern": "\\S*", + "title": "Result of output", + "type": "string" + }, + "valueCode": { + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Result of output", + "type": "string" + }, + "valueCodeableConcept": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueCodeableReference": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference", + "backref": "task_output", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueCoding": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Coding", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueContactDetail": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ContactDetail", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueContactPoint": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ContactPoint", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueCount": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Count", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueDataRequirement": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DataRequirement", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueDate": { + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "format": "date", + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output", + "type": "string" + }, + "valueDateTime": { + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "format": "date-time", + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output", + "type": "string" + }, + "valueDecimal": { + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output", + "type": "number" + }, + "valueDistance": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Distance", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueDosage": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Dosage", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueDuration": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Duration", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueExpression": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Expression", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueExtendedContactDetail": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ExtendedContactDetail", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueHumanName": { + "$ref": "http://graph-fhir.io/schema/0.0.2/HumanName", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueId": { + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "one_of_many": "value", + "one_of_many_required": true, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Result of output", + "type": "string" + }, + "valueIdentifier": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueInstant": { + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "format": "date-time", + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output", + "type": "string" + }, + "valueInteger": { + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output", + "type": "integer" + }, + "valueInteger64": { + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output", + "type": "integer" + }, + "valueMarkdown": { + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "pattern": "\\s*(\\S|\\s)*", + "title": "Result of output", + "type": "string" + }, + "valueMeta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueMoney": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Money", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueOid": { + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "pattern": "^urn:oid:[0-2](\\.(0|[1-9][0-9]*))+$", + "title": "Result of output", + "type": "string" + }, + "valueParameterDefinition": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ParameterDefinition", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valuePeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valuePositiveInt": { + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "exclusiveMinimum": 0, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output", + "type": "integer" + }, + "valueQuantity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueRange": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Range", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueRatio": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Ratio", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueRatioRange": { + "$ref": "http://graph-fhir.io/schema/0.0.2/RatioRange", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueReference": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "task_output", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "enum_reference_types": [ + "Organization", + "Group", + "Practitioner", + "PractitionerRole", + "ResearchStudy", + "Patient", + "ResearchSubject", + "Substance", + "SubstanceDefinition", + "Specimen", + "Observation", + "DiagnosticReport", + "Condition", + "Medication", + "MedicationAdministration", + "MedicationStatement", + "MedicationRequest", + "Procedure", + "DocumentReference", + "Task", + "ImagingStudy", + "FamilyMemberHistory", + "BodyStructure" + ], + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueRelatedArtifact": { + "$ref": "http://graph-fhir.io/schema/0.0.2/RelatedArtifact", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueSampledData": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SampledData", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueSignature": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Signature", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueString": { + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Result of output", + "type": "string" + }, + "valueTime": { + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "format": "time", + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output", + "type": "string" + }, + "valueTiming": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Timing", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueTriggerDefinition": { + "$ref": "http://graph-fhir.io/schema/0.0.2/TriggerDefinition", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueUnsignedInt": { + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "minimum": 0, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output", + "type": "integer" + }, + "valueUri": { + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "pattern": "\\S*", + "title": "Result of output", + "type": "string" + }, + "valueUrl": { + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "format": "uri", + "maxLength": 65536, + "minLength": 1, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output", + "type": "string" + }, + "valueUsageContext": { + "$ref": "http://graph-fhir.io/schema/0.0.2/UsageContext", + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output" + }, + "valueUuid": { + "description": "The value of the Output parameter as a basic type.", + "element_property": true, + "format": "uuid", + "one_of_many": "value", + "one_of_many_required": true, + "title": "Result of output", + "type": "string" + } + }, + "required": [ + "type" + ], + "title": "TaskOutput", + "type": "object" + }, + "Patient": { + "$id": "http://graph-fhir.io/schema/0.0.2/Patient", + "additionalProperties": false, + "description": "Information about an individual or animal receiving health care services. Demographics and other administrative information about an individual or animal receiving care or other health-related services. [See https://hl7.org/fhir/R5/Patient.html]", + "links": [ + { + "href": "{id}", + "rel": "generalPractitioner_Organization", + "targetHints": { + "backref": [ + "generalPractitioner_patient" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/generalPractitioner/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "generalPractitioner_Practitioner", + "targetHints": { + "backref": [ + "generalPractitioner_patient" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/generalPractitioner/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "generalPractitioner_PractitionerRole", + "targetHints": { + "backref": [ + "generalPractitioner_patient" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/generalPractitioner/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "managingOrganization", + "targetHints": { + "backref": [ + "managingOrganization_patient" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/managingOrganization/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From PatientContact/contact", + "href": "{id}", + "rel": "contact_organization", + "targetHints": { + "backref": [ + "patient_contact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/contact/-/organization/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From PatientLink/link", + "href": "{id}", + "rel": "link_other_Patient", + "targetHints": { + "backref": [ + "patient_link" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/link/-/other/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_active": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'active'." + }, + "_birthDate": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'birthDate'." + }, + "_deceasedBoolean": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'deceasedBoolean'." + }, + "_deceasedDateTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'deceasedDateTime'." + }, + "_gender": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'gender'." + }, + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "_multipleBirthBoolean": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'multipleBirthBoolean'." + }, + "_multipleBirthInteger": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'multipleBirthInteger'." + }, + "active": { + "description": "Whether this patient record is in active use. Many systems use this property to mark as non-current patients, such as those that have not been seen for a period of time based on an organization's business rules. It is often used to filter patient lists to exclude inactive patients Deceased patients may also be marked as inactive for the same reasons, but may be active for some time after death.", + "element_property": true, + "title": "Whether this patient's record is in active use", + "type": "boolean" + }, + "address": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Address" + }, + "title": "An address for the individual", + "type": "array" + }, + "birthDate": { + "element_property": true, + "format": "date", + "title": "The date of birth for the individual", + "type": "string" + }, + "communication": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PatientCommunication" + }, + "title": "A language which may be used to communicate with the patient about his or her health", + "type": "array" + }, + "contact": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PatientContact" + }, + "title": "A contact party (e.g. guardian, partner, friend) for the patient", + "type": "array" + }, + "contained": { + "description": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, nor can they have their own independent transaction scope. This is allowed to be a Parameters resource if and only if it is referenced by a resource that provides context/meaning.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + "title": "Contained, inline Resources", + "type": "array" + }, + "deceasedBoolean": { + "element_property": true, + "one_of_many": "deceased", + "one_of_many_required": false, + "title": "Indicates if the individual is deceased or not", + "type": "boolean" + }, + "deceasedDateTime": { + "element_property": true, + "format": "date-time", + "one_of_many": "deceased", + "one_of_many_required": false, + "title": "Indicates if the individual is deceased or not", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "gender": { + "binding_description": "The gender of a person used for administrative purposes.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/administrative-gender", + "binding_version": "5.0.0", + "description": "Administrative Gender - the gender that the patient is considered to have for administration and record keeping purposes.", + "element_property": true, + "enum_values": [ + "male", + "female", + "other", + "unknown" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "male | female | other | unknown", + "type": "string" + }, + "generalPractitioner": { + "backref": "generalPractitioner_patient", + "description": "Patient's nominated care provider.", + "element_property": true, + "enum_reference_types": [ + "Organization", + "Practitioner", + "PractitionerRole" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Patient's nominated primary care provider", + "type": "array" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "identifier": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "An identifier for this patient", + "type": "array" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "link": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PatientLink" + }, + "title": "Link to a Patient or RelatedPerson resource that concerns the same actual individual", + "type": "array" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "managingOrganization": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "managingOrganization_patient", + "element_property": true, + "enum_reference_types": [ + "Organization" + ], + "title": "Organization that is the custodian of the patient record" + }, + "maritalStatus": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The domestic partnership status of a person.", + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/marital-status", + "binding_version": null, + "description": "This field contains a patient's most recent marital (civil) status.", + "element_property": true, + "title": "Marital (civil) status of a patient" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored", + "type": "array" + }, + "multipleBirthBoolean": { + "description": "Indicates whether the patient is part of a multiple (boolean) or indicates the actual birth order (integer).", + "element_property": true, + "one_of_many": "multipleBirth", + "one_of_many_required": false, + "title": "Whether patient is part of a multiple birth", + "type": "boolean" + }, + "multipleBirthInteger": { + "description": "Indicates whether the patient is part of a multiple (boolean) or indicates the actual birth order (integer).", + "element_property": true, + "one_of_many": "multipleBirth", + "one_of_many_required": false, + "title": "Whether patient is part of a multiple birth", + "type": "integer" + }, + "name": { + "description": "A name associated with the individual.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/HumanName" + }, + "title": "A name associated with the patient", + "type": "array" + }, + "photo": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Attachment" + }, + "title": "Image of the patient", + "type": "array" + }, + "resourceType": { + "const": "Patient", + "default": "Patient", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "telecom": { + "description": "A contact detail (e.g. a telephone number or an email address) by which the individual may be contacted.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ContactPoint" + }, + "title": "A contact detail for the individual", + "type": "array" + }, + "text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative", + "description": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "element_property": true, + "title": "Text summary of the resource, for human interpretation" + } + }, + "title": "Patient", + "type": "object" + }, + "Practitioner": { + "$id": "http://graph-fhir.io/schema/0.0.2/Practitioner", + "additionalProperties": false, + "description": "A person with a formal responsibility in the provisioning of healthcare or related services. A person who is directly or indirectly involved in the provisioning of healthcare or related services. [See https://hl7.org/fhir/R5/Practitioner.html]", + "links": [ + { + "$comment": "From PractitionerQualification/qualification", + "href": "{id}", + "rel": "qualification_issuer", + "targetHints": { + "backref": [ + "practitioner_qualification" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/qualification/-/issuer/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_active": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'active'." + }, + "_birthDate": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'birthDate'." + }, + "_deceasedBoolean": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'deceasedBoolean'." + }, + "_deceasedDateTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'deceasedDateTime'." + }, + "_gender": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'gender'." + }, + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "active": { + "element_property": true, + "title": "Whether this practitioner's record is in active use", + "type": "boolean" + }, + "address": { + "description": "Address(es) of the practitioner that are not role specific (typically home address). Work addresses are not typically entered in this property as they are usually role dependent.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Address" + }, + "title": "Address(es) of the practitioner that are not role specific (typically home address)", + "type": "array" + }, + "birthDate": { + "description": "The date of birth for the practitioner.", + "element_property": true, + "format": "date", + "title": "The date on which the practitioner was born", + "type": "string" + }, + "communication": { + "description": "A language which may be used to communicate with the practitioner, often for correspondence/administrative purposes. The `PractitionerRole.communication` property should be used for publishing the languages that a practitioner is able to communicate with patients (on a per Organization/Role basis).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerCommunication" + }, + "title": "A language which may be used to communicate with the practitioner", + "type": "array" + }, + "contained": { + "description": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, nor can they have their own independent transaction scope. This is allowed to be a Parameters resource if and only if it is referenced by a resource that provides context/meaning.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + "title": "Contained, inline Resources", + "type": "array" + }, + "deceasedBoolean": { + "element_property": true, + "one_of_many": "deceased", + "one_of_many_required": false, + "title": "Indicates if the practitioner is deceased or not", + "type": "boolean" + }, + "deceasedDateTime": { + "element_property": true, + "format": "date-time", + "one_of_many": "deceased", + "one_of_many_required": false, + "title": "Indicates if the practitioner is deceased or not", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "gender": { + "binding_description": "The gender of a person used for administrative purposes.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/administrative-gender", + "binding_version": "5.0.0", + "description": "Administrative Gender - the gender that the person is considered to have for administration and record keeping purposes.", + "element_property": true, + "enum_values": [ + "male", + "female", + "other", + "unknown" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "male | female | other | unknown", + "type": "string" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "identifier": { + "description": "An identifier that applies to this person in this role.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "An identifier for the person as this agent", + "type": "array" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored", + "type": "array" + }, + "name": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/HumanName" + }, + "title": "The name(s) associated with the practitioner", + "type": "array" + }, + "photo": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Attachment" + }, + "title": "Image of the person", + "type": "array" + }, + "qualification": { + "description": "The official qualifications, certifications, accreditations, training, licenses (and other types of educations/skills/capabilities) that authorize or otherwise pertain to the provision of care by the practitioner. For example, a medical license issued by a medical board of licensure authorizing the practitioner to practice medicine within a certain locality.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerQualification" + }, + "title": "Qualifications, certifications, accreditations, licenses, training, etc. pertaining to the provision of care", + "type": "array" + }, + "resourceType": { + "const": "Practitioner", + "default": "Practitioner", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "telecom": { + "description": "A contact detail for the practitioner, e.g. a telephone number or an email address.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ContactPoint" + }, + "title": "A contact detail for the practitioner (that apply to all roles)", + "type": "array" + }, + "text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative", + "description": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "element_property": true, + "title": "Text summary of the resource, for human interpretation" + } + }, + "title": "Practitioner", + "type": "object" + }, + "SubstanceDefinitionProperty": { + "$id": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionProperty", + "additionalProperties": false, + "description": "General specifications for this substance. [See https://hl7.org/fhir/R5/SubstanceDefinitionProperty.html]", + "links": [], + "properties": { + "_valueBoolean": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueBoolean'." + }, + "_valueDate": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueDate'." + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "SubstanceDefinitionProperty", + "default": "SubstanceDefinitionProperty", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "This value set includes all observable entity codes from SNOMED CT - provided as an exemplar value set.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/product-characteristic-codes", + "binding_version": null, + "element_property": true, + "title": "A code expressing the type of property" + }, + "valueAttachment": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Attachment", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "A value for the property" + }, + "valueBoolean": { + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "A value for the property", + "type": "boolean" + }, + "valueCodeableConcept": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "A value for the property" + }, + "valueDate": { + "element_property": true, + "format": "date", + "one_of_many": "value", + "one_of_many_required": false, + "title": "A value for the property", + "type": "string" + }, + "valueQuantity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "A value for the property" + } + }, + "required": [ + "type" + ], + "title": "SubstanceDefinitionProperty", + "type": "object" + }, + "Annotation": { + "$id": "http://graph-fhir.io/schema/0.0.2/Annotation", + "additionalProperties": false, + "description": "Text node with attribution. A text note which also contains information about who made the statement and when. [See https://hl7.org/fhir/R5/Annotation.html]", + "links": [ + { + "href": "{id}", + "rel": "authorReference_Practitioner", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "authorReference_PractitionerRole", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "authorReference_Patient", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "authorReference_Organization", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_authorString": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'authorString'." + }, + "_text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'text'." + }, + "_time": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'time'." + }, + "authorReference": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "annotation", + "description": "The individual responsible for making the annotation.", + "element_property": true, + "enum_reference_types": [ + "Practitioner", + "PractitionerRole", + "Patient", + "RelatedPerson", + "Organization" + ], + "one_of_many": "author", + "one_of_many_required": false, + "title": "Individual responsible for the annotation" + }, + "authorString": { + "description": "The individual responsible for making the annotation.", + "element_property": true, + "one_of_many": "author", + "one_of_many_required": false, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Individual responsible for the annotation", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "resourceType": { + "const": "Annotation", + "default": "Annotation", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "text": { + "description": "The text of the annotation in markdown format.", + "element_property": true, + "element_required": true, + "pattern": "\\s*(\\S|\\s)*", + "title": "The annotation - text content (as markdown)", + "type": "string" + }, + "time": { + "description": "Indicates when this particular annotation was made.", + "element_property": true, + "format": "date-time", + "title": "When the annotation was made", + "type": "string" + } + }, + "title": "Annotation", + "type": "object" + }, + "Substance": { + "$id": "http://graph-fhir.io/schema/0.0.2/Substance", + "additionalProperties": false, + "description": "A homogeneous material with a definite composition. [See https://hl7.org/fhir/R5/Substance.html]", + "links": [ + { + "$comment": "From CodeableReference/code", + "href": "{id}", + "rel": "code_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/code/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/code", + "href": "{id}", + "rel": "code_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/code/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/code", + "href": "{id}", + "rel": "code_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/code/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/code", + "href": "{id}", + "rel": "code_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/code/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/code", + "href": "{id}", + "rel": "code_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/code/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/code", + "href": "{id}", + "rel": "code_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/code/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/code", + "href": "{id}", + "rel": "code_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/code/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/code", + "href": "{id}", + "rel": "code_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/code/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/code", + "href": "{id}", + "rel": "code_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/code/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/code", + "href": "{id}", + "rel": "code_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/code/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/code", + "href": "{id}", + "rel": "code_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/code/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/code", + "href": "{id}", + "rel": "code_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/code/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/code", + "href": "{id}", + "rel": "code_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/code/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/code", + "href": "{id}", + "rel": "code_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/code/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/code", + "href": "{id}", + "rel": "code_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/code/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/code", + "href": "{id}", + "rel": "code_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/code/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/code", + "href": "{id}", + "rel": "code_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/code/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/code", + "href": "{id}", + "rel": "code_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/code/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/code", + "href": "{id}", + "rel": "code_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/code/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/code", + "href": "{id}", + "rel": "code_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/code/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/code", + "href": "{id}", + "rel": "code_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/code/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/code", + "href": "{id}", + "rel": "code_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/code/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/code", + "href": "{id}", + "rel": "code_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/code/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From SubstanceIngredient/ingredient", + "href": "{id}", + "rel": "ingredient_substanceReference", + "targetHints": { + "backref": [ + "substance_ingredient" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/ingredient/-/substanceReference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_description": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'description'." + }, + "_expiry": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'expiry'." + }, + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_instance": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'instance'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "_status": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'status'." + }, + "category": { + "binding_description": "Category or classification of substance.", + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-category", + "binding_version": null, + "description": "A code that classifies the general type of substance. This is used for searching, sorting and display purposes.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "What class/type of substance this is", + "type": "array" + }, + "code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference", + "backref": "substance", + "binding_description": "Substance codes.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-code", + "binding_version": null, + "description": "A code (or set of codes) that identify this substance.", + "element_property": true, + "enum_reference_types": [ + "SubstanceDefinition" + ], + "title": "What substance this is" + }, + "contained": { + "description": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, nor can they have their own independent transaction scope. This is allowed to be a Parameters resource if and only if it is referenced by a resource that provides context/meaning.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + "title": "Contained, inline Resources", + "type": "array" + }, + "description": { + "description": "A description of the substance - its appearance, handling requirements, and other usage notes.", + "element_property": true, + "pattern": "\\s*(\\S|\\s)*", + "title": "Textual description of the substance, comments", + "type": "string" + }, + "expiry": { + "description": "When the substance is no longer valid to use. For some substances, a single arbitrary date is used for expiry.", + "element_property": true, + "format": "date-time", + "title": "When no longer valid to use", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "identifier": { + "description": "Unique identifier for the substance. For an instance, an identifier associated with the package/container (usually a label affixed directly).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "Unique identifier", + "type": "array" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "ingredient": { + "description": "A substance can be composed of other substances.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceIngredient" + }, + "title": "Composition information about the substance", + "type": "array" + }, + "instance": { + "description": "A boolean to indicate if this an instance of a substance or a kind of one (a definition).", + "element_property": true, + "element_required": true, + "title": "Is this an instance of a substance or a kind of one", + "type": "boolean" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored", + "type": "array" + }, + "quantity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "The amount of the substance.", + "element_property": true, + "title": "Amount of substance in the package" + }, + "resourceType": { + "const": "Substance", + "default": "Substance", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "status": { + "binding_description": "A code to indicate if the substance is actively used.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-status", + "binding_version": "5.0.0", + "description": "A code to indicate if the substance is actively used.", + "element_property": true, + "enum_values": [ + "active", + "inactive", + "entered-in-error" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "active | inactive | entered-in-error", + "type": "string" + }, + "text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative", + "description": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "element_property": true, + "title": "Text summary of the resource, for human interpretation" + } + }, + "required": [ + "code" + ], + "title": "Substance", + "type": "object" + }, + "UsageContext": { + "$id": "http://graph-fhir.io/schema/0.0.2/UsageContext", + "additionalProperties": false, + "description": "Describes the context of use for a conformance or knowledge resource. Specifies clinical/business/etc. metadata that can be used to retrieve, index and/or categorize an artifact. This metadata can either be specific to the applicable population (e.g., age category, DRG) or the specific context of care (e.g., venue, care setting, provider of care). [See https://hl7.org/fhir/R5/UsageContext.html]", + "links": [ + { + "href": "{id}", + "rel": "valueReference_ResearchStudy", + "targetHints": { + "backref": [ + "usage_context" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Group", + "targetHints": { + "backref": [ + "usage_context" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Organization", + "targetHints": { + "backref": [ + "usage_context" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Coding", + "binding_description": "A code that specifies a type of context being specified by a usage context.", + "binding_strength": "extensible", + "binding_uri": "http://terminology.hl7.org/ValueSet/usage-context-type", + "binding_version": null, + "description": "A code that identifies the type of context being specified by this usage context.", + "element_property": true, + "title": "Type of context being specified" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "resourceType": { + "const": "UsageContext", + "default": "UsageContext", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "valueCodeableConcept": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "description": "A value that defines the context specified in this context of use. The interpretation of the value is defined by the code.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Value that defines the context" + }, + "valueQuantity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "A value that defines the context specified in this context of use. The interpretation of the value is defined by the code.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Value that defines the context" + }, + "valueRange": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Range", + "description": "A value that defines the context specified in this context of use. The interpretation of the value is defined by the code.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Value that defines the context" + }, + "valueReference": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "usage_context", + "description": "A value that defines the context specified in this context of use. The interpretation of the value is defined by the code.", + "element_property": true, + "enum_reference_types": [ + "PlanDefinition", + "ResearchStudy", + "InsurancePlan", + "HealthcareService", + "Group", + "Location", + "Organization" + ], + "one_of_many": "value", + "one_of_many_required": true, + "title": "Value that defines the context" + } + }, + "required": [ + "code" + ], + "title": "UsageContext", + "type": "object" + }, + "CodeableReference": { + "$id": "http://graph-fhir.io/schema/0.0.2/CodeableReference", + "additionalProperties": false, + "description": "Reference to a resource or a concept. A reference to a resource (by instance), or instead, a reference to a concept defined in a terminology or ontology (by class). [See https://hl7.org/fhir/R5/CodeableReference.html]", + "links": [ + { + "href": "{id}", + "rel": "reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "concept": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "description": "A reference to a concept - e.g. the information is identified by its general class to the degree of precision found in the terminology.", + "element_property": true, + "title": "Reference to a concept (by class)" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "reference": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "codeable_reference", + "description": "A reference to a resource the provides exact details about the information being referenced.", + "element_property": true, + "enum_reference_types": [ + "Organization", + "Group", + "Practitioner", + "PractitionerRole", + "ResearchStudy", + "Patient", + "ResearchSubject", + "Substance", + "SubstanceDefinition", + "Specimen", + "Observation", + "DiagnosticReport", + "Condition", + "Medication", + "MedicationAdministration", + "MedicationStatement", + "MedicationRequest", + "Procedure", + "DocumentReference", + "Task", + "ImagingStudy", + "FamilyMemberHistory", + "BodyStructure" + ], + "title": "Reference to a resource (by instance)" + }, + "resourceType": { + "const": "CodeableReference", + "default": "CodeableReference", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "title": "CodeableReference", + "type": "object" + }, + "DiagnosticReportSupportingInfo": { + "$id": "http://graph-fhir.io/schema/0.0.2/DiagnosticReportSupportingInfo", + "additionalProperties": false, + "description": "Additional information supporting the diagnostic report. This backbone element contains supporting information that was used in the creation of the report not included in the results already included in the report. [See https://hl7.org/fhir/R5/DiagnosticReportSupportingInfo.html]", + "links": [ + { + "href": "{id}", + "rel": "reference_Procedure", + "targetHints": { + "backref": [ + "diagnostic_report_supporting_info" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_Observation", + "targetHints": { + "backref": [ + "diagnostic_report_supporting_info" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reference_DiagnosticReport", + "targetHints": { + "backref": [ + "diagnostic_report_supporting_info" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/reference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "reference": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "diagnostic_report_supporting_info", + "description": "The reference for the supporting information in the diagnostic report.", + "element_property": true, + "enum_reference_types": [ + "Procedure", + "Observation", + "DiagnosticReport", + "Citation" + ], + "title": "Supporting information reference" + }, + "resourceType": { + "const": "DiagnosticReportSupportingInfo", + "default": "DiagnosticReportSupportingInfo", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The code value for the role of the supporting information in the diagnostic report.", + "binding_strength": "example", + "binding_uri": "http://terminology.hl7.org/ValueSet/v2-0936", + "binding_version": null, + "description": "The code value for the role of the supporting information in the diagnostic report.", + "element_property": true, + "title": "Supporting information role code" + } + }, + "required": [ + "reference", + "type" + ], + "title": "DiagnosticReportSupportingInfo", + "type": "object" + }, + "MedicationRequest": { + "$id": "http://graph-fhir.io/schema/0.0.2/MedicationRequest", + "additionalProperties": false, + "description": "Ordering of medication for patient or group. An order or request for both supply of the medication and the instructions for administration of the medication to a patient. The resource is called \"MedicationRequest\" rather than \"MedicationPrescription\" or \"MedicationOrder\" to generalize the use across inpatient and outpatient settings, including care plans, etc., and to harmonize with workflow patterns. [See https://hl7.org/fhir/R5/MedicationRequest.html]", + "links": [ + { + "href": "{id}", + "rel": "basedOn_MedicationRequest", + "targetHints": { + "backref": [ + "basedOn_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "informationSource_Patient", + "targetHints": { + "backref": [ + "informationSource_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/informationSource/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "informationSource_Practitioner", + "targetHints": { + "backref": [ + "informationSource_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/informationSource/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "informationSource_PractitionerRole", + "targetHints": { + "backref": [ + "informationSource_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/informationSource/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "informationSource_Organization", + "targetHints": { + "backref": [ + "informationSource_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/informationSource/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "performer_Practitioner", + "targetHints": { + "backref": [ + "performer_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/performer/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "performer_PractitionerRole", + "targetHints": { + "backref": [ + "performer_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/performer/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "performer_Organization", + "targetHints": { + "backref": [ + "performer_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/performer/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "performer_Patient", + "targetHints": { + "backref": [ + "performer_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/performer/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "priorPrescription", + "targetHints": { + "backref": [ + "priorPrescription_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/priorPrescription/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "recorder_Practitioner", + "targetHints": { + "backref": [ + "recorder_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/recorder/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "recorder_PractitionerRole", + "targetHints": { + "backref": [ + "recorder_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/recorder/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "requester_Practitioner", + "targetHints": { + "backref": [ + "requester_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/requester/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "requester_PractitionerRole", + "targetHints": { + "backref": [ + "requester_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/requester/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "requester_Organization", + "targetHints": { + "backref": [ + "requester_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/requester/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "requester_Patient", + "targetHints": { + "backref": [ + "requester_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/requester/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Patient", + "targetHints": { + "backref": [ + "subject_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Group", + "targetHints": { + "backref": [ + "subject_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_Organization", + "targetHints": { + "backref": [ + "supportingInformation_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_Group", + "targetHints": { + "backref": [ + "supportingInformation_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_Practitioner", + "targetHints": { + "backref": [ + "supportingInformation_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_PractitionerRole", + "targetHints": { + "backref": [ + "supportingInformation_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_ResearchStudy", + "targetHints": { + "backref": [ + "supportingInformation_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_Patient", + "targetHints": { + "backref": [ + "supportingInformation_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_ResearchSubject", + "targetHints": { + "backref": [ + "supportingInformation_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_Substance", + "targetHints": { + "backref": [ + "supportingInformation_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_SubstanceDefinition", + "targetHints": { + "backref": [ + "supportingInformation_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_Specimen", + "targetHints": { + "backref": [ + "supportingInformation_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_Observation", + "targetHints": { + "backref": [ + "supportingInformation_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_DiagnosticReport", + "targetHints": { + "backref": [ + "supportingInformation_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_Condition", + "targetHints": { + "backref": [ + "supportingInformation_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_Medication", + "targetHints": { + "backref": [ + "supportingInformation_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_MedicationAdministration", + "targetHints": { + "backref": [ + "supportingInformation_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_MedicationStatement", + "targetHints": { + "backref": [ + "supportingInformation_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_MedicationRequest", + "targetHints": { + "backref": [ + "supportingInformation_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_Procedure", + "targetHints": { + "backref": [ + "supportingInformation_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_DocumentReference", + "targetHints": { + "backref": [ + "supportingInformation_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_Task", + "targetHints": { + "backref": [ + "supportingInformation_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_ImagingStudy", + "targetHints": { + "backref": [ + "supportingInformation_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_FamilyMemberHistory", + "targetHints": { + "backref": [ + "supportingInformation_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInformation_BodyStructure", + "targetHints": { + "backref": [ + "supportingInformation_medication_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/supportingInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From MedicationRequestDispenseRequest/dispenseRequest", + "href": "{id}", + "rel": "dispenseRequest_dispenser", + "targetHints": { + "backref": [ + "medication_request_dispense_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/dispenseRequest/dispenser/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Practitioner", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_PractitionerRole", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Patient", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Organization", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_authoredOn": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'authoredOn'." + }, + "_doNotPerform": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'doNotPerform'." + }, + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_intent": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'intent'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "_priority": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'priority'." + }, + "_renderedDosageInstruction": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'renderedDosageInstruction'." + }, + "_reported": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'reported'." + }, + "_status": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'status'." + }, + "_statusChanged": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'statusChanged'." + }, + "authoredOn": { + "description": "The date (and perhaps time) when the prescription was initially written or authored on.", + "element_property": true, + "format": "date-time", + "title": "When request was initially authored", + "type": "string" + }, + "basedOn": { + "backref": "basedOn_medication_request", + "element_property": true, + "enum_reference_types": [ + "CarePlan", + "MedicationRequest", + "ServiceRequest", + "ImmunizationRecommendation" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "A plan or request that is fulfilled in whole or in part by this medication request", + "type": "array" + }, + "category": { + "binding_description": "A coded concept identifying where the medication is to be consumed or administered.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/medicationrequest-admin-location", + "binding_version": null, + "description": "An arbitrary categorization or grouping of the medication request. It could be used for indicating where meds are intended to be administered, eg. in an inpatient setting or in a patient's home, or a legal category of the medication.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Grouping or category of medication request", + "type": "array" + }, + "contained": { + "description": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, nor can they have their own independent transaction scope. This is allowed to be a Parameters resource if and only if it is referenced by a resource that provides context/meaning.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + "title": "Contained, inline Resources", + "type": "array" + }, + "courseOfTherapyType": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Identifies the overall pattern of medication administratio.", + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/medicationrequest-course-of-therapy", + "binding_version": null, + "description": "The description of the overall pattern of the administration of the medication to the patient.", + "element_property": true, + "title": "Overall pattern of medication administration" + }, + "device": { + "backref": "device_medication_request", + "description": "The intended type of device that is to be used for the administration of the medication (for example, PCA Pump).", + "element_property": true, + "enum_reference_types": [ + "DeviceDefinition" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference" + }, + "title": "Intended type of device for the administration", + "type": "array" + }, + "dispenseRequest": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequestDispenseRequest", + "description": "Indicates the specific details for the dispense or medication supply part of a medication request (also known as a Medication Prescription or Medication Order). Note that this information is not always sent with the order. There may be in some settings (e.g. hospitals) institutional or system support for completing the dispense details in the pharmacy department.", + "element_property": true, + "title": "Medication supply authorization" + }, + "doNotPerform": { + "description": "If true, indicates that the provider is asking for the patient to either stop taking or to not start taking the specified medication. For example, the patient is taking an existing medication and the provider is changing their medication. They want to create two seperate requests: one to stop using the current medication and another to start the new medication.", + "element_property": true, + "title": "True if patient is to stop taking or not to start taking the medication", + "type": "boolean" + }, + "dosageInstruction": { + "description": "Specific instructions for how the medication is to be used by the patient.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Dosage" + }, + "title": "Specific instructions for how the medication should be taken", + "type": "array" + }, + "effectiveDosePeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "The period over which the medication is to be taken. Where there are multiple dosageInstruction lines (for example, tapering doses), this is the earliest date and the latest end date of the dosageInstructions.", + "element_property": true, + "title": "Period over which the medication is to be taken" + }, + "encounter": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "medication_request", + "description": "The Encounter during which this [x] was created or to which the creation of this record is tightly associated.", + "element_property": true, + "enum_reference_types": [ + "Encounter" + ], + "title": "Encounter created as part of encounter/admission/stay" + }, + "eventHistory": { + "backref": "eventHistory_medication_request", + "description": "Links to Provenance records for past versions of this resource or fulfilling request or event resources that identify key state transitions or updates that are likely to be relevant to a user looking at the current version of the resource.", + "element_property": true, + "enum_reference_types": [ + "Provenance" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "A list of events of interest in the lifecycle", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "groupIdentifier": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier", + "description": "A shared identifier common to multiple independent Request instances that were activated/authorized more or less simultaneously by a single author. The presence of the same identifier on each request ties those requests together and may have business ramifications in terms of reporting of results, billing, etc. E.g. a requisition number shared by a set of lab tests ordered together, or a prescription number shared by all meds ordered at one time.", + "element_property": true, + "title": "Composite request this is part of" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "identifier": { + "description": "Identifiers associated with this medication request that are defined by business processes and/or used to refer to it when a direct URL reference to the resource itself is not appropriate. They are business identifiers assigned to this resource by the performer or other systems and remain constant as the resource is updated and propagates from server to server.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "External ids for this request", + "type": "array" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "informationSource": { + "backref": "informationSource_medication_request", + "description": "The person or organization who provided the information about this request, if the source is someone other than the requestor. This is often used when the MedicationRequest is reported by another person.", + "element_property": true, + "enum_reference_types": [ + "Patient", + "Practitioner", + "PractitionerRole", + "RelatedPerson", + "Organization" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "The person or organization who provided the information about this request, if the source is someone other than the requestor", + "type": "array" + }, + "insurance": { + "backref": "insurance_medication_request", + "description": "Insurance plans, coverage extensions, pre-authorizations and/or pre-determinations that may be required for delivering the requested service.", + "element_property": true, + "enum_reference_types": [ + "Coverage", + "ClaimResponse" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Associated insurance coverage", + "type": "array" + }, + "intent": { + "binding_description": "The kind of medication order.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/medicationrequest-intent", + "binding_version": "5.0.0", + "description": "Whether the request is a proposal, plan, or an original order.", + "element_property": true, + "element_required": true, + "enum_values": [ + "proposal", + "plan", + "order", + "original-order", + "reflex-order", + "filler-order", + "instance-order", + "option" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "proposal | plan | order | original-order | reflex-order | filler-order | instance-order | option", + "type": "string" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "medication": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference", + "backref": "medication_request", + "binding_description": "A coded concept identifying substance or product that can be ordered.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/medication-codes", + "binding_version": null, + "description": "Identifies the medication being requested. This is a link to a resource that represents the medication which may be the details of the medication or simply an attribute carrying a code that identifies the medication from a known list of medications.", + "element_property": true, + "enum_reference_types": [ + "Medication" + ], + "title": "Medication to be taken" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored", + "type": "array" + }, + "note": { + "description": "Extra information about the prescription that could not be conveyed by the other attributes.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Annotation" + }, + "title": "Information about the prescription", + "type": "array" + }, + "performer": { + "backref": "performer_medication_request", + "description": "The specified desired performer of the medication treatment (e.g. the performer of the medication administration). For devices, this is the device that is intended to perform the administration of the medication. An IV Pump would be an example of a device that is performing the administration. Both the IV Pump and the practitioner that set the rate or bolus on the pump can be listed as performers.", + "element_property": true, + "enum_reference_types": [ + "Practitioner", + "PractitionerRole", + "Organization", + "Patient", + "DeviceDefinition", + "RelatedPerson", + "CareTeam", + "HealthcareService" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Intended performer of administration", + "type": "array" + }, + "performerType": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Identifies the type of individual that is desired to administer the medication.", + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/medication-intended-performer-role", + "binding_version": null, + "description": "Indicates the type of performer of the administration of the medication.", + "element_property": true, + "title": "Desired kind of performer of the medication administration" + }, + "priorPrescription": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "priorPrescription_medication_request", + "element_property": true, + "enum_reference_types": [ + "MedicationRequest" + ], + "title": "Reference to an order/prescription that is being replaced by this MedicationRequest" + }, + "priority": { + "binding_description": "Identifies the level of importance to be assigned to actioning the request.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/request-priority", + "binding_version": "5.0.0", + "description": "Indicates how quickly the Medication Request should be addressed with respect to other requests.", + "element_property": true, + "enum_values": [ + "routine", + "urgent", + "asap", + "stat" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "routine | urgent | asap | stat", + "type": "string" + }, + "reason": { + "backref": "reason_medication_request", + "binding_description": "A coded concept indicating why the medication was ordered.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/condition-code", + "binding_version": null, + "description": "The reason or the indication for ordering or not ordering the medication.", + "element_property": true, + "enum_reference_types": [ + "Condition", + "Observation" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference" + }, + "title": "Reason or indication for ordering or not ordering the medication", + "type": "array" + }, + "recorder": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "recorder_medication_request", + "description": "The person who entered the order on behalf of another individual for example in the case of a verbal or a telephone order.", + "element_property": true, + "enum_reference_types": [ + "Practitioner", + "PractitionerRole" + ], + "title": "Person who entered the request" + }, + "renderedDosageInstruction": { + "description": "The full representation of the dose of the medication included in all dosage instructions. To be used when multiple dosage instructions are included to represent complex dosing such as increasing or tapering doses.", + "element_property": true, + "pattern": "\\s*(\\S|\\s)*", + "title": "Full representation of the dosage instructions", + "type": "string" + }, + "reported": { + "description": "Indicates if this record was captured as a secondary 'reported' record rather than as an original primary source-of-truth record. It may also indicate the source of the report.", + "element_property": true, + "title": "Reported rather than primary record", + "type": "boolean" + }, + "requester": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "requester_medication_request", + "description": "The individual, organization, or device that initiated the request and has responsibility for its activation.", + "element_property": true, + "enum_reference_types": [ + "Practitioner", + "PractitionerRole", + "Organization", + "Patient", + "RelatedPerson", + "Device" + ], + "title": "Who/What requested the Request" + }, + "resourceType": { + "const": "MedicationRequest", + "default": "MedicationRequest", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "status": { + "binding_description": "A coded concept specifying the state of the prescribing event. Describes the lifecycle of the prescription.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/medicationrequest-status", + "binding_version": "5.0.0", + "description": "A code specifying the current state of the order. Generally, this will be active or completed state.", + "element_property": true, + "element_required": true, + "enum_values": [ + "active", + "on-hold", + "ended", + "stopped", + "completed", + "cancelled", + "entered-in-error", + "draft", + "unknown" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "active | on-hold | ended | stopped | completed | cancelled | entered-in-error | draft | unknown", + "type": "string" + }, + "statusChanged": { + "description": "The date (and perhaps time) when the status was changed.", + "element_property": true, + "format": "date-time", + "title": "When the status was changed", + "type": "string" + }, + "statusReason": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Identifies the reasons for a given status.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/medicationrequest-status-reason", + "binding_version": null, + "description": "Captures the reason for the current state of the MedicationRequest.", + "element_property": true, + "title": "Reason for current status" + }, + "subject": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "subject_medication_request", + "description": "The individual or group for whom the medication has been requested.", + "element_property": true, + "enum_reference_types": [ + "Patient", + "Group" + ], + "title": "Individual or group for whom the medication has been requested" + }, + "substitution": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequestSubstitution", + "description": "Indicates whether or not substitution can or should be part of the dispense. In some cases, substitution must happen, in other cases substitution must not happen. This block explains the prescriber's intent. If nothing is specified substitution may be done.", + "element_property": true, + "title": "Any restrictions on medication substitution" + }, + "supportingInformation": { + "backref": "supportingInformation_medication_request", + "description": "Information to support fulfilling (i.e. dispensing or administering) of the medication, for example, patient height and weight, a MedicationStatement for the patient).", + "element_property": true, + "enum_reference_types": [ + "Organization", + "Group", + "Practitioner", + "PractitionerRole", + "ResearchStudy", + "Patient", + "ResearchSubject", + "Substance", + "SubstanceDefinition", + "Specimen", + "Observation", + "DiagnosticReport", + "Condition", + "Medication", + "MedicationAdministration", + "MedicationStatement", + "MedicationRequest", + "Procedure", + "DocumentReference", + "Task", + "ImagingStudy", + "FamilyMemberHistory", + "BodyStructure" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Information to support fulfilling of the medication", + "type": "array" + }, + "text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative", + "description": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "element_property": true, + "title": "Text summary of the resource, for human interpretation" + } + }, + "required": [ + "medication", + "subject" + ], + "title": "MedicationRequest", + "type": "object" + }, + "PractitionerCommunication": { + "$id": "http://graph-fhir.io/schema/0.0.2/PractitionerCommunication", + "additionalProperties": false, + "description": "A language which may be used to communicate with the practitioner. A language which may be used to communicate with the practitioner, often for correspondence/administrative purposes. The `PractitionerRole.communication` property should be used for publishing the languages that a practitioner is able to communicate with patients (on a per Organization/Role basis). [See https://hl7.org/fhir/R5/PractitionerCommunication.html]", + "links": [], + "properties": { + "_preferred": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'preferred'." + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The ISO-639-1 alpha 2 code in lower case for the language, optionally followed by a hyphen and the ISO-3166-1 alpha 2 code for the region in upper case; e.g. \"en\" for English, or \"en-US\" for American English versus \"en-AU\" for Australian English.", + "element_property": true, + "title": "The language code used to communicate with the practitioner" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "preferred": { + "description": "Indicates whether or not the person prefers this language (over other languages he masters up a certain level).", + "element_property": true, + "title": "Language preference indicator", + "type": "boolean" + }, + "resourceType": { + "const": "PractitionerCommunication", + "default": "PractitionerCommunication", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "required": [ + "language" + ], + "title": "PractitionerCommunication", + "type": "object" + }, + "GroupCharacteristic": { + "$id": "http://graph-fhir.io/schema/0.0.2/GroupCharacteristic", + "additionalProperties": false, + "description": "Include / Exclude group members by Trait. Identifies traits whose presence r absence is shared by members of the group. [See https://hl7.org/fhir/R5/GroupCharacteristic.html]", + "links": [ + { + "href": "{id}", + "rel": "valueReference_Organization", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Group", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Practitioner", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_PractitionerRole", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_ResearchStudy", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Patient", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_ResearchSubject", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Substance", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_SubstanceDefinition", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Specimen", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Observation", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_DiagnosticReport", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Condition", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Medication", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_MedicationAdministration", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_MedicationStatement", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_MedicationRequest", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Procedure", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_DocumentReference", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Task", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_ImagingStudy", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_BodyStructure", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_exclude": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'exclude'." + }, + "_valueBoolean": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueBoolean'." + }, + "code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "description": "A code that identifies the kind of trait being asserted.", + "element_property": true, + "title": "Kind of characteristic" + }, + "exclude": { + "description": "If true, indicates the characteristic is one that is NOT held by members of the group.", + "element_property": true, + "element_required": true, + "title": "Group includes or excludes", + "type": "boolean" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "period": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "The period over which the characteristic is tested; e.g. the patient had an operation during the month of June.", + "element_property": true, + "title": "Period over which characteristic is tested" + }, + "resourceType": { + "const": "GroupCharacteristic", + "default": "GroupCharacteristic", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "valueBoolean": { + "description": "The value of the trait that holds (or does not hold - see 'exclude') for members of the group.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Value held by characteristic", + "type": "boolean" + }, + "valueCodeableConcept": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "description": "The value of the trait that holds (or does not hold - see 'exclude') for members of the group.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Value held by characteristic" + }, + "valueQuantity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "The value of the trait that holds (or does not hold - see 'exclude') for members of the group.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Value held by characteristic" + }, + "valueRange": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Range", + "description": "The value of the trait that holds (or does not hold - see 'exclude') for members of the group.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Value held by characteristic" + }, + "valueReference": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "group_characteristic", + "description": "The value of the trait that holds (or does not hold - see 'exclude') for members of the group.", + "element_property": true, + "enum_reference_types": [ + "Organization", + "Group", + "Practitioner", + "PractitionerRole", + "ResearchStudy", + "Patient", + "ResearchSubject", + "Substance", + "SubstanceDefinition", + "Specimen", + "Observation", + "DiagnosticReport", + "Condition", + "Medication", + "MedicationAdministration", + "MedicationStatement", + "MedicationRequest", + "Procedure", + "DocumentReference", + "Task", + "ImagingStudy", + "FamilyMemberHistory", + "BodyStructure" + ], + "one_of_many": "value", + "one_of_many_required": true, + "title": "Value held by characteristic" + } + }, + "required": [ + "code" + ], + "title": "GroupCharacteristic", + "type": "object" + }, + "MedicationRequestDispenseRequest": { + "$id": "http://graph-fhir.io/schema/0.0.2/MedicationRequestDispenseRequest", + "additionalProperties": false, + "description": "Medication supply authorization. Indicates the specific details for the dispense or medication supply part of a medication request (also known as a Medication Prescription or Medication Order). Note that this information is not always sent with the order. There may be in some settings (e.g. hospitals) institutional or system support for completing the dispense details in the pharmacy department. [See https://hl7.org/fhir/R5/MedicationRequestDispenseRequest.html]", + "links": [ + { + "href": "{id}", + "rel": "dispenser", + "targetHints": { + "backref": [ + "medication_request_dispense_request" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/dispenser/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/dispenserInstruction", + "href": "{id}", + "rel": "dispenserInstruction_authorReference_Practitioner", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/dispenserInstruction/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/dispenserInstruction", + "href": "{id}", + "rel": "dispenserInstruction_authorReference_PractitionerRole", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/dispenserInstruction/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/dispenserInstruction", + "href": "{id}", + "rel": "dispenserInstruction_authorReference_Patient", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/dispenserInstruction/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/dispenserInstruction", + "href": "{id}", + "rel": "dispenserInstruction_authorReference_Organization", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/dispenserInstruction/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_numberOfRepeatsAllowed": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'numberOfRepeatsAllowed'." + }, + "dispenseInterval": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Duration", + "description": "The minimum period of time that must occur between dispenses of the medication.", + "element_property": true, + "title": "Minimum period of time between dispenses" + }, + "dispenser": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "medication_request_dispense_request", + "description": "Indicates the intended performing Organization that will dispense the medication as specified by the prescriber.", + "element_property": true, + "enum_reference_types": [ + "Organization" + ], + "title": "Intended performer of dispense" + }, + "dispenserInstruction": { + "description": "Provides additional information to the dispenser, for example, counselling to be provided to the patient.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Annotation" + }, + "title": "Additional information for the dispenser", + "type": "array" + }, + "doseAdministrationAid": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": null, + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/medication-dose-aid", + "binding_version": null, + "description": "Provides information about the type of adherence packaging to be supplied for the medication dispense.", + "element_property": true, + "title": "Type of adherence packaging to use for the dispense" + }, + "expectedSupplyDuration": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Duration", + "description": "Identifies the period time over which the supplied product is expected to be used, or the length of time the dispense is expected to last.", + "element_property": true, + "title": "Number of days supply per dispense" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "initialFill": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequestDispenseRequestInitialFill", + "description": "Indicates the quantity or duration for the first dispense of the medication.", + "element_property": true, + "title": "First fill details" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "numberOfRepeatsAllowed": { + "description": "An integer indicating the number of times, in addition to the original dispense, (aka refills or repeats) that the patient can receive the prescribed medication. Usage Notes: This integer does not include the original order dispense. This means that if an order indicates dispense 30 tablets plus \"3 repeats\", then the order can be dispensed a total of 4 times and the patient can receive a total of 120 tablets. A prescriber may explicitly say that zero refills are permitted after the initial dispense.", + "element_property": true, + "minimum": 0, + "title": "Number of refills authorized", + "type": "integer" + }, + "quantity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "The amount that is to be dispensed for one fill.", + "element_property": true, + "title": "Amount of medication to supply per dispense" + }, + "resourceType": { + "const": "MedicationRequestDispenseRequest", + "default": "MedicationRequestDispenseRequest", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "validityPeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "This indicates the validity period of a prescription (stale dating the Prescription).", + "element_property": true, + "title": "Time period supply is authorized for" + } + }, + "title": "MedicationRequestDispenseRequest", + "type": "object" + }, + "Period": { + "$id": "http://graph-fhir.io/schema/0.0.2/Period", + "additionalProperties": false, + "description": "Time range defined by start and end date/time. A time period defined by a start and end date and optionally time. [See https://hl7.org/fhir/R5/Period.html]", + "links": [], + "properties": { + "_end": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'end'." + }, + "_start": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'start'." + }, + "end": { + "description": "The end of the period. If the end of the period is missing, it means no end was known or planned at the time the instance was created. The start may be in the past, and the end date in the future, which means that period is expected/planned to end at that time.", + "element_property": true, + "format": "date-time", + "title": "End time with inclusive boundary, if not ongoing", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "resourceType": { + "const": "Period", + "default": "Period", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "start": { + "description": "The start of the period. The boundary is inclusive.", + "element_property": true, + "format": "date-time", + "title": "Starting time with inclusive boundary", + "type": "string" + } + }, + "title": "Period", + "type": "object" + }, + "PractitionerQualification": { + "$id": "http://graph-fhir.io/schema/0.0.2/PractitionerQualification", + "additionalProperties": false, + "description": "Qualifications, certifications, accreditations, licenses, training, etc. pertaining to the provision of care. The official qualifications, certifications, accreditations, training, licenses (and other types of educations/skills/capabilities) that authorize or otherwise pertain to the provision of care by the practitioner. For example, a medical license issued by a medical board of licensure authorizing the practitioner to practice medicine within a certain locality. [See https://hl7.org/fhir/R5/PractitionerQualification.html]", + "links": [ + { + "href": "{id}", + "rel": "issuer", + "targetHints": { + "backref": [ + "practitioner_qualification" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/issuer/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Specific qualification the practitioner has to provide a service.", + "binding_strength": "example", + "binding_uri": "http://terminology.hl7.org/ValueSet/v2-0360", + "binding_version": null, + "element_property": true, + "title": "Coded representation of the qualification" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "identifier": { + "description": "An identifier that applies to this person's qualification.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "An identifier for this qualification for the practitioner", + "type": "array" + }, + "issuer": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "practitioner_qualification", + "element_property": true, + "enum_reference_types": [ + "Organization" + ], + "title": "Organization that regulates and issues the qualification" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "period": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "element_property": true, + "title": "Period during which the qualification is valid" + }, + "resourceType": { + "const": "PractitionerQualification", + "default": "PractitionerQualification", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "required": [ + "code" + ], + "title": "PractitionerQualification", + "type": "object" + }, + "AvailabilityNotAvailableTime": { + "$id": "http://graph-fhir.io/schema/0.0.2/AvailabilityNotAvailableTime", + "additionalProperties": false, + "description": "Not available during this time due to provided reason. [See https://hl7.org/fhir/R5/AvailabilityNotAvailableTime.html]", + "links": [], + "properties": { + "_description": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'description'." + }, + "description": { + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Reason presented to the user explaining why time not available", + "type": "string" + }, + "during": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "element_property": true, + "title": "Service not available during this period" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "resourceType": { + "const": "AvailabilityNotAvailableTime", + "default": "AvailabilityNotAvailableTime", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "title": "AvailabilityNotAvailableTime", + "type": "object" + }, + "SubstanceDefinitionMolecularWeight": { + "$id": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionMolecularWeight", + "additionalProperties": false, + "description": "The average mass of a molecule of a compound. The average mass of a molecule of a compound compared to 1/12 the mass of carbon 12 and calculated as the sum of the atomic weights of the constituent atoms. [See https://hl7.org/fhir/R5/SubstanceDefinitionMolecularWeight.html]", + "links": [], + "properties": { + "amount": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "Used to capture quantitative values for a variety of elements. If only limits are given, the arithmetic mean would be the average. If only a single definite value for a given element is given, it would be captured in this field.", + "element_property": true, + "title": "Used to capture quantitative values for a variety of elements" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "method": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The method by which the substance weight was measured.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-weight-method", + "binding_version": null, + "description": "The method by which the molecular weight was determined.", + "element_property": true, + "title": "The method by which the weight was determined" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "SubstanceDefinitionMolecularWeight", + "default": "SubstanceDefinitionMolecularWeight", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The type of substance weight measurement.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-weight-type", + "binding_version": null, + "description": "Type of molecular weight such as exact, average (also known as. number average), weight average.", + "element_property": true, + "title": "Type of molecular weight e.g. exact, average, weight average" + } + }, + "required": [ + "amount" + ], + "title": "SubstanceDefinitionMolecularWeight", + "type": "object" + }, + "BodyStructureIncludedStructureBodyLandmarkOrientation": { + "$id": "http://graph-fhir.io/schema/0.0.2/BodyStructureIncludedStructureBodyLandmarkOrientation", + "additionalProperties": false, + "description": "Landmark relative location. Body locations in relation to a specific body landmark (tatoo, scar, other body structure). [See https://hl7.org/fhir/R5/BodyStructureIncludedStructureBodyLandmarkOrientation.html]", + "links": [], + "properties": { + "clockFacePosition": { + "binding_description": "Select SNOMED CT codes. A set of codes that describe a things orientation based on a hourly positions of a clock face.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/bodystructure-bodylandmarkorientation-clockface-position", + "binding_version": null, + "description": "An description of the direction away from a landmark something is located based on a radial clock dial.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Clockface orientation", + "type": "array" + }, + "distanceFromLandmark": { + "description": "The distance in centimeters a certain observation is made from a body landmark.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark" + }, + "title": "Landmark relative location", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "landmarkDescription": { + "binding_description": "Select SNOMED code system values. Values used in a podiatry setting to decsribe landmarks on the body.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/body-site", + "binding_version": null, + "description": "A description of a landmark on the body used as a reference to locate something else.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Body ]andmark description", + "type": "array" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "BodyStructureIncludedStructureBodyLandmarkOrientation", + "default": "BodyStructureIncludedStructureBodyLandmarkOrientation", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "surfaceOrientation": { + "binding_description": "Select SNOMED code system values. The surface area a body location is in relation to a landmark.", + "binding_strength": "preferred", + "binding_uri": "http://hl7.org/fhir/ValueSet/bodystructure-relative-location", + "binding_version": null, + "description": "The surface area a body location is in relation to a landmark.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Relative landmark surface orientation", + "type": "array" + } + }, + "title": "BodyStructureIncludedStructureBodyLandmarkOrientation", + "type": "object" + }, + "ConditionParticipant": { + "$id": "http://graph-fhir.io/schema/0.0.2/ConditionParticipant", + "additionalProperties": false, + "description": "Who or what participated in the activities related to the condition and how they were involved. Indicates who or what participated in the activities related to the condition and how they were involved. [See https://hl7.org/fhir/R5/ConditionParticipant.html]", + "links": [ + { + "href": "{id}", + "rel": "actor_Practitioner", + "targetHints": { + "backref": [ + "condition_participant" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "actor_PractitionerRole", + "targetHints": { + "backref": [ + "condition_participant" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "actor_Patient", + "targetHints": { + "backref": [ + "condition_participant" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "actor_Organization", + "targetHints": { + "backref": [ + "condition_participant" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/actor/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "actor": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "condition_participant", + "description": "Indicates who or what participated in the activities related to the condition.", + "element_property": true, + "enum_reference_types": [ + "Practitioner", + "PractitionerRole", + "Patient", + "RelatedPerson", + "Device", + "Organization", + "CareTeam" + ], + "title": "Who or what participated in the activities related to the condition" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "function": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": null, + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/participation-role-type", + "binding_version": null, + "description": "Distinguishes the type of involvement of the actor in the activities related to the condition.", + "element_property": true, + "title": "Type of involvement" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "ConditionParticipant", + "default": "ConditionParticipant", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "required": [ + "actor" + ], + "title": "ConditionParticipant", + "type": "object" + }, + "SubstanceDefinitionSourceMaterial": { + "$id": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionSourceMaterial", + "additionalProperties": false, + "description": "Material or taxonomic/anatomical source. Material or taxonomic/anatomical source for the substance. [See https://hl7.org/fhir/R5/SubstanceDefinitionSourceMaterial.html]", + "links": [], + "properties": { + "countryOfOrigin": { + "binding_description": "Jurisdiction codes", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/country", + "binding_version": "5.0.0", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "The country or countries where the material is harvested", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "genus": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The genus of an organism, typically referring to the Latin epithet of the genus element of the plant/animal scientific name.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-source-material-genus", + "binding_version": null, + "description": "The genus of an organism, typically referring to the Latin epithet of the genus element of the plant/animal scientific name.", + "element_property": true, + "title": "The genus of an organism e.g. the Latin epithet of the plant/animal scientific name" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "part": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "An anatomical origin of the source material within an organism.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-source-material-part", + "binding_version": null, + "element_property": true, + "title": "An anatomical origin of the source material within an organism" + }, + "resourceType": { + "const": "SubstanceDefinitionSourceMaterial", + "default": "SubstanceDefinitionSourceMaterial", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "species": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "A species of origin a substance raw material.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-source-material-species", + "binding_version": null, + "description": "The species of an organism, typically referring to the Latin epithet of the species of the plant/animal.", + "element_property": true, + "title": "The species of an organism e.g. the Latin epithet of the species of the plant/animal" + }, + "type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "A classification that provides the origin of the substance raw material.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-source-material-type", + "binding_version": null, + "description": "A classification that provides the origin of the raw material. Example: cat hair would be an Animal source type.", + "element_property": true, + "title": "Classification of the origin of the raw material. e.g. cat hair is an Animal source type" + } + }, + "title": "SubstanceDefinitionSourceMaterial", + "type": "object" + }, + "FHIRPrimitiveExtension": { + "$id": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "additionalProperties": false, + "description": " [See https://hl7.org/fhir/R5/FHIRPrimitiveExtension.html]", + "links": [], + "properties": { + "extension": { + "description": "Additional content defined by implementations", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "List of `Extension` items (represented as `dict` in JSON)", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for inter-element referencing", + "element_property": false, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Type `String`", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "resourceType": { + "const": "FHIRPrimitiveExtension", + "default": "FHIRPrimitiveExtension", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "title": "FHIRPrimitiveExtension", + "type": "object" + }, + "ExtendedContactDetail": { + "$id": "http://graph-fhir.io/schema/0.0.2/ExtendedContactDetail", + "additionalProperties": false, + "description": "Contact information. Specifies contact information for a specific purpose over a period of time, might be handled/monitored by a specific named person or organization. [See https://hl7.org/fhir/R5/ExtendedContactDetail.html]", + "links": [ + { + "href": "{id}", + "rel": "organization", + "targetHints": { + "backref": [ + "extended_contact_detail" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/organization/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "address": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Address", + "element_property": true, + "title": "Address for the contact" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "name": { + "description": "The name of an individual to contact, some types of contact detail are usually blank.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/HumanName" + }, + "title": "Name of an individual to contact", + "type": "array" + }, + "organization": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "extended_contact_detail", + "description": "This contact detail is handled/monitored by a specific organization. If the name is provided in the contact, then it is referring to the named individual within this organization.", + "element_property": true, + "enum_reference_types": [ + "Organization" + ], + "title": "This contact detail is handled/monitored by a specific organization" + }, + "period": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "element_property": true, + "title": "Period that this contact was valid for usage" + }, + "purpose": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The purpose for which an extended contact detail should be used.", + "binding_strength": "preferred", + "binding_uri": "http://terminology.hl7.org/ValueSet/contactentity-type", + "binding_version": null, + "description": "The purpose/type of contact.", + "element_property": true, + "title": "The type of contact" + }, + "resourceType": { + "const": "ExtendedContactDetail", + "default": "ExtendedContactDetail", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "telecom": { + "description": "The contact details application for the purpose defined.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ContactPoint" + }, + "title": "Contact details (e.g.phone/fax/url)", + "type": "array" + } + }, + "title": "ExtendedContactDetail", + "type": "object" + }, + "DataRequirementValueFilter": { + "$id": "http://graph-fhir.io/schema/0.0.2/DataRequirementValueFilter", + "additionalProperties": false, + "description": "What values are expected. Value filters specify additional constraints on the data for elements other than code-valued or date-valued. Each value filter specifies an additional constraint on the data (i.e. valueFilters are AND'ed, not OR'ed). [See https://hl7.org/fhir/R5/DataRequirementValueFilter.html]", + "links": [], + "properties": { + "_comparator": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'comparator'." + }, + "_path": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'path'." + }, + "_searchParam": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'searchParam'." + }, + "_valueDateTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueDateTime'." + }, + "comparator": { + "binding_description": "Possible comparators for the valueFilter element.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/value-filter-comparator", + "binding_version": "5.0.0", + "description": "The comparator to be used to determine whether the value is matching.", + "element_property": true, + "enum_values": [ + "eq", + "gt", + "lt", + "ge", + "le", + "sa", + "eb" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "eq | gt | lt | ge | le | sa | eb", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "path": { + "description": "The attribute of the filter. The specified path SHALL be a FHIRPath resolvable on the specified type of the DataRequirement, and SHALL consist only of identifiers, constant indexers, and .resolve(). The path is allowed to contain qualifiers (.) to traverse sub-elements, as well as indexers ([x]) to traverse multiple-cardinality sub-elements (see the [Simple FHIRPath Profile](fhirpath.html#simple) for full details). Note that the index must be an integer constant. The path must resolve to an element of a type that is comparable to the valueFilter.value[x] element for the filter.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "An attribute to filter on", + "type": "string" + }, + "resourceType": { + "const": "DataRequirementValueFilter", + "default": "DataRequirementValueFilter", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "searchParam": { + "description": "A search parameter defined on the specified type of the DataRequirement, and which searches on elements of a type compatible with the type of the valueFilter.value[x] for the filter.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "A parameter to search on", + "type": "string" + }, + "valueDateTime": { + "description": "The value of the filter.", + "element_property": true, + "format": "date-time", + "one_of_many": "value", + "one_of_many_required": false, + "title": "The value of the filter, as a Period, DateTime, or Duration value", + "type": "string" + }, + "valueDuration": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Duration", + "description": "The value of the filter.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "The value of the filter, as a Period, DateTime, or Duration value" + }, + "valuePeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "The value of the filter.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "The value of the filter, as a Period, DateTime, or Duration value" + } + }, + "title": "DataRequirementValueFilter", + "type": "object" + }, + "DataRequirementSort": { + "$id": "http://graph-fhir.io/schema/0.0.2/DataRequirementSort", + "additionalProperties": false, + "description": "Order of the results. Specifies the order of the results to be returned. [See https://hl7.org/fhir/R5/DataRequirementSort.html]", + "links": [], + "properties": { + "_direction": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'direction'." + }, + "_path": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'path'." + }, + "direction": { + "binding_description": "The possible sort directions, ascending or descending.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/sort-direction", + "binding_version": "5.0.0", + "description": "The direction of the sort, ascending or descending.", + "element_property": true, + "element_required": true, + "enum_values": [ + "ascending", + "descending" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "ascending | descending", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "path": { + "description": "The attribute of the sort. The specified path must be resolvable from the type of the required data. The path is allowed to contain qualifiers (.) to traverse sub-elements, as well as indexers ([x]) to traverse multiple-cardinality sub-elements. Note that the index must be an integer constant.", + "element_property": true, + "element_required": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "The name of the attribute to perform the sort", + "type": "string" + }, + "resourceType": { + "const": "DataRequirementSort", + "default": "DataRequirementSort", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "title": "DataRequirementSort", + "type": "object" + }, + "ImagingStudySeries": { + "$id": "http://graph-fhir.io/schema/0.0.2/ImagingStudySeries", + "additionalProperties": false, + "description": "Each study has one or more series of instances. Each study has one or more series of images or other content. [See https://hl7.org/fhir/R5/ImagingStudySeries.html]", + "links": [ + { + "href": "{id}", + "rel": "specimen", + "targetHints": { + "backref": [ + "specimen_imaging_study_series" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/specimen/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ImagingStudySeriesPerformer/performer", + "href": "{id}", + "rel": "performer_actor_Practitioner", + "targetHints": { + "backref": [ + "imaging_study_series_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/performer/-/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ImagingStudySeriesPerformer/performer", + "href": "{id}", + "rel": "performer_actor_PractitionerRole", + "targetHints": { + "backref": [ + "imaging_study_series_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/performer/-/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ImagingStudySeriesPerformer/performer", + "href": "{id}", + "rel": "performer_actor_Organization", + "targetHints": { + "backref": [ + "imaging_study_series_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/performer/-/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ImagingStudySeriesPerformer/performer", + "href": "{id}", + "rel": "performer_actor_Patient", + "targetHints": { + "backref": [ + "imaging_study_series_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/performer/-/actor/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_description": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'description'." + }, + "_number": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'number'." + }, + "_numberOfInstances": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'numberOfInstances'." + }, + "_started": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'started'." + }, + "_uid": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'uid'." + }, + "bodySite": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference", + "backref": "imaging_study_series", + "binding_description": "SNOMED CT Body site concepts", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/body-site", + "binding_version": null, + "description": "The anatomic structures examined. See DICOM Part 16 Annex L (http://dicom.nema.org/medical/dicom/current/output/chtml/part16/chapter_L.html) for DICOM to SNOMED-CT mappings. The bodySite may indicate the laterality of body part imaged; if so, it shall be consistent with any content of ImagingStudy.series.laterality.", + "element_property": true, + "enum_reference_types": [ + "BodyStructure" + ], + "title": "Body part examined" + }, + "description": { + "description": "A description of the series.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "A short human readable summary of the series", + "type": "string" + }, + "endpoint": { + "backref": "endpoint_imaging_study_series", + "description": "The network service providing access (e.g., query, view, or retrieval) for this series. See implementation notes for information about using DICOM endpoints. A series-level endpoint, if present, has precedence over a study-level endpoint with the same Endpoint.connectionType.", + "element_property": true, + "enum_reference_types": [ + "Endpoint" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Series access endpoint", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "instance": { + "description": "A single SOP instance within the series, e.g. an image, or presentation state.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudySeriesInstance" + }, + "title": "A single SOP instance from the series", + "type": "array" + }, + "laterality": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Codes describing body site laterality (left, right, etc.).", + "binding_strength": "example", + "binding_uri": "http://dicom.nema.org/medical/dicom/current/output/chtml/part16/sect_CID_244.html", + "binding_version": null, + "description": "The laterality of the (possibly paired) anatomic structures examined. E.g., the left knee, both lungs, or unpaired abdomen. If present, shall be consistent with any laterality information indicated in ImagingStudy.series.bodySite.", + "element_property": true, + "title": "Body part laterality" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modality": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Type of acquired data in the instance.", + "binding_strength": "extensible", + "binding_uri": "http://dicom.nema.org/medical/dicom/current/output/chtml/part16/sect_CID_33.html", + "binding_version": null, + "description": "The distinct modality for this series. This may include both acquisition and non-acquisition modalities.", + "element_property": true, + "title": "The modality used for this series" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "number": { + "description": "The numeric identifier of this series in the study.", + "element_property": true, + "minimum": 0, + "title": "Numeric identifier of this series", + "type": "integer" + }, + "numberOfInstances": { + "description": "Number of SOP Instances in the Study. The value given may be larger than the number of instance elements this resource contains due to resource availability, security, or other factors. This element should be present if any instance elements are present.", + "element_property": true, + "minimum": 0, + "title": "Number of Series Related Instances", + "type": "integer" + }, + "performer": { + "description": "Indicates who or what performed the series and how they were involved.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudySeriesPerformer" + }, + "title": "Who performed the series", + "type": "array" + }, + "resourceType": { + "const": "ImagingStudySeries", + "default": "ImagingStudySeries", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "specimen": { + "backref": "specimen_imaging_study_series", + "description": "The specimen imaged, e.g., for whole slide imaging of a biopsy.", + "element_property": true, + "enum_reference_types": [ + "Specimen" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Specimen imaged", + "type": "array" + }, + "started": { + "description": "The date and time the series was started.", + "element_property": true, + "format": "date-time", + "title": "When the series started", + "type": "string" + }, + "uid": { + "description": "The DICOM Series Instance UID for the series.", + "element_property": true, + "element_required": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "DICOM Series Instance UID for the series", + "type": "string" + } + }, + "required": [ + "modality" + ], + "title": "ImagingStudySeries", + "type": "object" + }, + "SubstanceDefinitionRelationship": { + "$id": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionRelationship", + "additionalProperties": false, + "description": "A link between this substance and another. A link between this substance and another, with details of the relationship. [See https://hl7.org/fhir/R5/SubstanceDefinitionRelationship.html]", + "links": [ + { + "href": "{id}", + "rel": "source", + "targetHints": { + "backref": [ + "source_substance_definition_relationship" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/source/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "substanceDefinitionReference", + "targetHints": { + "backref": [ + "substance_definition_relationship" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/substanceDefinitionReference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_amountString": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'amountString'." + }, + "_isDefining": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'isDefining'." + }, + "amountQuantity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "A numeric factor for the relationship, for instance to express that the salt of a substance has some percentage of the active substance in relation to some other.", + "element_property": true, + "one_of_many": "amount", + "one_of_many_required": false, + "title": "A numeric factor for the relationship, e.g. that a substance salt has some percentage of active substance in relation to some other" + }, + "amountRatio": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Ratio", + "description": "A numeric factor for the relationship, for instance to express that the salt of a substance has some percentage of the active substance in relation to some other.", + "element_property": true, + "one_of_many": "amount", + "one_of_many_required": false, + "title": "A numeric factor for the relationship, e.g. that a substance salt has some percentage of active substance in relation to some other" + }, + "amountString": { + "description": "A numeric factor for the relationship, for instance to express that the salt of a substance has some percentage of the active substance in relation to some other.", + "element_property": true, + "one_of_many": "amount", + "one_of_many_required": false, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "A numeric factor for the relationship, e.g. that a substance salt has some percentage of active substance in relation to some other", + "type": "string" + }, + "comparator": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The relationship between two substance types.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-amount-type", + "binding_version": null, + "element_property": true, + "title": "An operator for the amount, for example \"average\", \"approximately\", \"less than\"" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "isDefining": { + "description": "For example where an enzyme strongly bonds with a particular substance, this is a defining relationship for that enzyme, out of several possible substance relationships.", + "element_property": true, + "title": "For example where an enzyme strongly bonds with a particular substance, this is a defining relationship for that enzyme, out of several possible relationships", + "type": "boolean" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "ratioHighLimitAmount": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Ratio", + "element_property": true, + "title": "For use when the numeric has an uncertain range" + }, + "resourceType": { + "const": "SubstanceDefinitionRelationship", + "default": "SubstanceDefinitionRelationship", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "source": { + "backref": "source_substance_definition_relationship", + "element_property": true, + "enum_reference_types": [ + "DocumentReference" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Supporting literature", + "type": "array" + }, + "substanceDefinitionCodeableConcept": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "description": "A pointer to another substance, as a resource or just a representational code.", + "element_property": true, + "one_of_many": "substanceDefinition", + "one_of_many_required": false, + "title": "A pointer to another substance, as a resource or a representational code" + }, + "substanceDefinitionReference": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "substance_definition_relationship", + "description": "A pointer to another substance, as a resource or just a representational code.", + "element_property": true, + "enum_reference_types": [ + "SubstanceDefinition" + ], + "one_of_many": "substanceDefinition", + "one_of_many_required": false, + "title": "A pointer to another substance, as a resource or a representational code" + }, + "type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The relationship between two substance types.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-relationship-type", + "binding_version": null, + "description": "For example \"salt to parent\", \"active moiety\", \"starting material\", \"polymorph\", \"impurity of\".", + "element_property": true, + "title": "For example \"salt to parent\", \"active moiety\"" + } + }, + "required": [ + "type" + ], + "title": "SubstanceDefinitionRelationship", + "type": "object" + }, + "MedicationStatement": { + "$id": "http://graph-fhir.io/schema/0.0.2/MedicationStatement", + "additionalProperties": false, + "description": "Record of medication being taken by a patient. A record of a medication that is being consumed by a patient. A MedicationStatement may indicate that the patient may be taking the medication now or has taken the medication in the past or will be taking the medication in the future. The source of this information can be the patient, significant other (such as a family member or spouse), or a clinician. A common scenario where this information is captured is during the history taking process during a patient visit or stay. The medication information may come from sources such as the patient's memory, from a prescription bottle, or from a list of medications the patient, clinician or other party maintains. The primary difference between a medicationstatement and a medicationadministration is that the medication administration has complete administration information and is based on actual administration information from the person who administered the medication. A medicationstatement is often, if not always, less specific. There is no required date/time when the medication was administered, in fact we only know that a source has reported the patient is taking this medication, where details such as time, quantity, or rate or even medication product may be incomplete or missing or less precise. As stated earlier, the Medication Statement information may come from the patient's memory, from a prescription bottle or from a list of medications the patient, clinician or other party maintains. Medication administration is more formal and is not missing detailed information. The MedicationStatement resource was previously called MedicationStatement. [See https://hl7.org/fhir/R5/MedicationStatement.html]", + "links": [ + { + "href": "{id}", + "rel": "derivedFrom_Organization", + "targetHints": { + "backref": [ + "derivedFrom_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_Group", + "targetHints": { + "backref": [ + "derivedFrom_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_Practitioner", + "targetHints": { + "backref": [ + "derivedFrom_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_PractitionerRole", + "targetHints": { + "backref": [ + "derivedFrom_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_ResearchStudy", + "targetHints": { + "backref": [ + "derivedFrom_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_Patient", + "targetHints": { + "backref": [ + "derivedFrom_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_ResearchSubject", + "targetHints": { + "backref": [ + "derivedFrom_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_Substance", + "targetHints": { + "backref": [ + "derivedFrom_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_SubstanceDefinition", + "targetHints": { + "backref": [ + "derivedFrom_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_Specimen", + "targetHints": { + "backref": [ + "derivedFrom_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_Observation", + "targetHints": { + "backref": [ + "derivedFrom_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_DiagnosticReport", + "targetHints": { + "backref": [ + "derivedFrom_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_Condition", + "targetHints": { + "backref": [ + "derivedFrom_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_Medication", + "targetHints": { + "backref": [ + "derivedFrom_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_MedicationAdministration", + "targetHints": { + "backref": [ + "derivedFrom_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_MedicationStatement", + "targetHints": { + "backref": [ + "derivedFrom_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_MedicationRequest", + "targetHints": { + "backref": [ + "derivedFrom_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_Procedure", + "targetHints": { + "backref": [ + "derivedFrom_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_DocumentReference", + "targetHints": { + "backref": [ + "derivedFrom_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_Task", + "targetHints": { + "backref": [ + "derivedFrom_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_ImagingStudy", + "targetHints": { + "backref": [ + "derivedFrom_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_FamilyMemberHistory", + "targetHints": { + "backref": [ + "derivedFrom_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "derivedFrom_BodyStructure", + "targetHints": { + "backref": [ + "derivedFrom_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/derivedFrom/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "informationSource_Patient", + "targetHints": { + "backref": [ + "informationSource_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/informationSource/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "informationSource_Practitioner", + "targetHints": { + "backref": [ + "informationSource_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/informationSource/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "informationSource_PractitionerRole", + "targetHints": { + "backref": [ + "informationSource_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/informationSource/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "informationSource_Organization", + "targetHints": { + "backref": [ + "informationSource_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/informationSource/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "partOf_Procedure", + "targetHints": { + "backref": [ + "partOf_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/partOf/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "partOf_MedicationStatement", + "targetHints": { + "backref": [ + "partOf_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/partOf/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "relatedClinicalInformation_Observation", + "targetHints": { + "backref": [ + "relatedClinicalInformation_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/relatedClinicalInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "relatedClinicalInformation_Condition", + "targetHints": { + "backref": [ + "relatedClinicalInformation_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/relatedClinicalInformation/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Patient", + "targetHints": { + "backref": [ + "subject_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Group", + "targetHints": { + "backref": [ + "subject_medication_statement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/medication", + "href": "{id}", + "rel": "medication_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/medication/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Practitioner", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_PractitionerRole", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Patient", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Organization", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_dateAsserted": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'dateAsserted'." + }, + "_effectiveDateTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'effectiveDateTime'." + }, + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "_renderedDosageInstruction": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'renderedDosageInstruction'." + }, + "_status": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'status'." + }, + "adherence": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatementAdherence", + "element_property": true, + "title": "Indicates whether the medication is or is not being consumed or administered" + }, + "category": { + "binding_description": "A coded concept identifying where the medication included in the MedicationStatement is expected to be consumed or administered.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/medicationrequest-admin-location", + "binding_version": null, + "description": "Type of medication statement (for example, drug classification like ATC, where meds would be administered, legal category of the medication.).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Type of medication statement", + "type": "array" + }, + "contained": { + "description": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, nor can they have their own independent transaction scope. This is allowed to be a Parameters resource if and only if it is referenced by a resource that provides context/meaning.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + "title": "Contained, inline Resources", + "type": "array" + }, + "dateAsserted": { + "description": "The date when the Medication Statement was asserted by the information source.", + "element_property": true, + "format": "date-time", + "title": "When the usage was asserted?", + "type": "string" + }, + "derivedFrom": { + "backref": "derivedFrom_medication_statement", + "description": "Allows linking the MedicationStatement to the underlying MedicationRequest, or to other information that supports or is used to derive the MedicationStatement.", + "element_property": true, + "enum_reference_types": [ + "Organization", + "Group", + "Practitioner", + "PractitionerRole", + "ResearchStudy", + "Patient", + "ResearchSubject", + "Substance", + "SubstanceDefinition", + "Specimen", + "Observation", + "DiagnosticReport", + "Condition", + "Medication", + "MedicationAdministration", + "MedicationStatement", + "MedicationRequest", + "Procedure", + "DocumentReference", + "Task", + "ImagingStudy", + "FamilyMemberHistory", + "BodyStructure" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Link to information used to derive the MedicationStatement", + "type": "array" + }, + "dosage": { + "description": "Indicates how the medication is/was or should be taken by the patient.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Dosage" + }, + "title": "Details of how medication is/was taken or should be taken", + "type": "array" + }, + "effectiveDateTime": { + "description": "The interval of time during which it is being asserted that the patient is/was/will be taking the medication (or was not taking, when the MedicationStatement.adherence element is Not Taking).", + "element_property": true, + "format": "date-time", + "one_of_many": "effective", + "one_of_many_required": false, + "title": "The date/time or interval when the medication is/was/will be taken", + "type": "string" + }, + "effectivePeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "The interval of time during which it is being asserted that the patient is/was/will be taking the medication (or was not taking, when the MedicationStatement.adherence element is Not Taking).", + "element_property": true, + "one_of_many": "effective", + "one_of_many_required": false, + "title": "The date/time or interval when the medication is/was/will be taken" + }, + "effectiveTiming": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Timing", + "description": "The interval of time during which it is being asserted that the patient is/was/will be taking the medication (or was not taking, when the MedicationStatement.adherence element is Not Taking).", + "element_property": true, + "one_of_many": "effective", + "one_of_many_required": false, + "title": "The date/time or interval when the medication is/was/will be taken" + }, + "encounter": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "medication_statement", + "description": "The encounter that establishes the context for this MedicationStatement.", + "element_property": true, + "enum_reference_types": [ + "Encounter" + ], + "title": "Encounter associated with MedicationStatement" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "identifier": { + "description": "Identifiers associated with this Medication Statement that are defined by business processes and/or used to refer to it when a direct URL reference to the resource itself is not appropriate. They are business identifiers assigned to this resource by the performer or other systems and remain constant as the resource is updated and propagates from server to server.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "External identifier", + "type": "array" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "informationSource": { + "backref": "informationSource_medication_statement", + "description": "The person or organization that provided the information about the taking of this medication. Note: Use derivedFrom when a MedicationStatement is derived from other resources, e.g. Claim or MedicationRequest.", + "element_property": true, + "enum_reference_types": [ + "Patient", + "Practitioner", + "PractitionerRole", + "RelatedPerson", + "Organization" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Person or organization that provided the information about the taking of this medication", + "type": "array" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "medication": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference", + "backref": "medication_statement", + "binding_description": "A coded concept identifying the substance or product being taken.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/medication-codes", + "binding_version": null, + "description": "Identifies the medication being administered. This is either a link to a resource representing the details of the medication or a simple attribute carrying a code that identifies the medication from a known list of medications.", + "element_property": true, + "enum_reference_types": [ + "Medication" + ], + "title": "What medication was taken" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored", + "type": "array" + }, + "note": { + "description": "Provides extra information about the Medication Statement that is not conveyed by the other attributes.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Annotation" + }, + "title": "Further information about the usage", + "type": "array" + }, + "partOf": { + "backref": "partOf_medication_statement", + "description": "A larger event of which this particular MedicationStatement is a component or step.", + "element_property": true, + "enum_reference_types": [ + "Procedure", + "MedicationStatement" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Part of referenced event", + "type": "array" + }, + "reason": { + "backref": "reason_medication_statement", + "binding_description": "A coded concept identifying why the medication is being taken.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/condition-code", + "binding_version": null, + "description": "A concept, Condition or observation that supports why the medication is being/was taken.", + "element_property": true, + "enum_reference_types": [ + "Condition", + "Observation", + "DiagnosticReport" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference" + }, + "title": "Reason for why the medication is being/was taken", + "type": "array" + }, + "relatedClinicalInformation": { + "backref": "relatedClinicalInformation_medication_statement", + "description": "Link to information that is relevant to a medication statement, for example, illicit drug use, gestational age, etc.", + "element_property": true, + "enum_reference_types": [ + "Observation", + "Condition" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Link to information relevant to the usage of a medication", + "type": "array" + }, + "renderedDosageInstruction": { + "description": "The full representation of the dose of the medication included in all dosage instructions. To be used when multiple dosage instructions are included to represent complex dosing such as increasing or tapering doses.", + "element_property": true, + "pattern": "\\s*(\\S|\\s)*", + "title": "Full representation of the dosage instructions", + "type": "string" + }, + "resourceType": { + "const": "MedicationStatement", + "default": "MedicationStatement", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "status": { + "binding_description": "A coded concept indicating the current status of a MedicationStatement.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/medication-statement-status", + "binding_version": "5.0.0", + "description": "A code representing the status of recording the medication statement.", + "element_property": true, + "element_required": true, + "enum_values": [ + "recorded", + "entered-in-error", + "draft" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "recorded | entered-in-error | draft", + "type": "string" + }, + "subject": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "subject_medication_statement", + "description": "The person, animal or group who is/was taking the medication.", + "element_property": true, + "enum_reference_types": [ + "Patient", + "Group" + ], + "title": "Who is/was taking the medication" + }, + "text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative", + "description": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "element_property": true, + "title": "Text summary of the resource, for human interpretation" + } + }, + "required": [ + "medication", + "subject" + ], + "title": "MedicationStatement", + "type": "object" + }, + "DiagnosticReport": { + "$id": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport", + "additionalProperties": false, + "description": "A Diagnostic report - a combination of request information, atomic results, images, interpretation, as well as formatted reports. The findings and interpretation of diagnostic tests performed on patients, groups of patients, products, substances, devices, and locations, and/or specimens derived from these. The report includes clinical context such as requesting provider information, and some mix of atomic results, images, textual and coded interpretations, and formatted representation of diagnostic reports. The report also includes non-clinical context such as batch analysis and stability reporting of products and substances. [See https://hl7.org/fhir/R5/DiagnosticReport.html]", + "links": [ + { + "href": "{id}", + "rel": "basedOn_MedicationRequest", + "targetHints": { + "backref": [ + "basedOn_diagnostic_report" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "performer_Practitioner", + "targetHints": { + "backref": [ + "performer_diagnostic_report" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/performer/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "performer_PractitionerRole", + "targetHints": { + "backref": [ + "performer_diagnostic_report" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/performer/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "performer_Organization", + "targetHints": { + "backref": [ + "performer_diagnostic_report" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/performer/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "result", + "targetHints": { + "backref": [ + "result_diagnostic_report" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/result/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resultsInterpreter_Practitioner", + "targetHints": { + "backref": [ + "resultsInterpreter_diagnostic_report" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/resultsInterpreter/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resultsInterpreter_PractitionerRole", + "targetHints": { + "backref": [ + "resultsInterpreter_diagnostic_report" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/resultsInterpreter/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "resultsInterpreter_Organization", + "targetHints": { + "backref": [ + "resultsInterpreter_diagnostic_report" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/resultsInterpreter/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "specimen", + "targetHints": { + "backref": [ + "specimen_diagnostic_report" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/specimen/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "study_ImagingStudy", + "targetHints": { + "backref": [ + "study_diagnostic_report" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/study/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Patient", + "targetHints": { + "backref": [ + "subject_diagnostic_report" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Group", + "targetHints": { + "backref": [ + "subject_diagnostic_report" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Organization", + "targetHints": { + "backref": [ + "subject_diagnostic_report" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Practitioner", + "targetHints": { + "backref": [ + "subject_diagnostic_report" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Medication", + "targetHints": { + "backref": [ + "subject_diagnostic_report" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Substance", + "targetHints": { + "backref": [ + "subject_diagnostic_report" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From DiagnosticReportMedia/media", + "href": "{id}", + "rel": "media_link", + "targetHints": { + "backref": [ + "diagnostic_report_media" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/media/-/link/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Practitioner", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_PractitionerRole", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Patient", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Organization", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From DiagnosticReportSupportingInfo/supportingInfo", + "href": "{id}", + "rel": "supportingInfo_reference_Procedure", + "targetHints": { + "backref": [ + "diagnostic_report_supporting_info" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From DiagnosticReportSupportingInfo/supportingInfo", + "href": "{id}", + "rel": "supportingInfo_reference_Observation", + "targetHints": { + "backref": [ + "diagnostic_report_supporting_info" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From DiagnosticReportSupportingInfo/supportingInfo", + "href": "{id}", + "rel": "supportingInfo_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "diagnostic_report_supporting_info" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_conclusion": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'conclusion'." + }, + "_effectiveDateTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'effectiveDateTime'." + }, + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_issued": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'issued'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "_status": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'status'." + }, + "basedOn": { + "backref": "basedOn_diagnostic_report", + "description": "Details concerning a service requested.", + "element_property": true, + "enum_reference_types": [ + "CarePlan", + "ImmunizationRecommendation", + "MedicationRequest", + "NutritionOrder", + "ServiceRequest" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "What was requested", + "type": "array" + }, + "category": { + "binding_description": "HL7 V2 table 0074", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/diagnostic-service-sections", + "binding_version": null, + "description": "A code that classifies the clinical discipline, department or diagnostic service that created the report (e.g. cardiology, biochemistry, hematology, MRI). This is used for searching, sorting and display purposes.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Service category", + "type": "array" + }, + "code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "LOINC Codes for Diagnostic Reports", + "binding_strength": "preferred", + "binding_uri": "http://hl7.org/fhir/ValueSet/report-codes", + "binding_version": null, + "description": "A code or name that describes this diagnostic report.", + "element_property": true, + "title": "Name/Code for this diagnostic report" + }, + "composition": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "diagnostic_report", + "description": "Reference to a Composition resource instance that provides structure for organizing the contents of the DiagnosticReport.", + "element_property": true, + "enum_reference_types": [ + "Composition" + ], + "title": "Reference to a Composition resource for the DiagnosticReport structure" + }, + "conclusion": { + "description": "Concise and clinically contextualized summary conclusion (interpretation/impression) of the diagnostic report.", + "element_property": true, + "pattern": "\\s*(\\S|\\s)*", + "title": "Clinical conclusion (interpretation) of test results", + "type": "string" + }, + "conclusionCode": { + "binding_description": "SNOMED CT Clinical Findings", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/clinical-findings", + "binding_version": null, + "description": "One or more codes that represent the summary conclusion (interpretation/impression) of the diagnostic report.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Codes for the clinical conclusion of test results", + "type": "array" + }, + "contained": { + "description": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, nor can they have their own independent transaction scope. This is allowed to be a Parameters resource if and only if it is referenced by a resource that provides context/meaning.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + "title": "Contained, inline Resources", + "type": "array" + }, + "effectiveDateTime": { + "description": "The time or time-period the observed values are related to. When the subject of the report is a patient, this is usually either the time of the procedure or of specimen collection(s), but very often the source of the date/time is not known, only the date/time itself.", + "element_property": true, + "format": "date-time", + "one_of_many": "effective", + "one_of_many_required": false, + "title": "Clinically relevant time/time-period for report", + "type": "string" + }, + "effectivePeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "The time or time-period the observed values are related to. When the subject of the report is a patient, this is usually either the time of the procedure or of specimen collection(s), but very often the source of the date/time is not known, only the date/time itself.", + "element_property": true, + "one_of_many": "effective", + "one_of_many_required": false, + "title": "Clinically relevant time/time-period for report" + }, + "encounter": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "diagnostic_report", + "description": "The healthcare event (e.g. a patient and healthcare provider interaction) which this DiagnosticReport is about.", + "element_property": true, + "enum_reference_types": [ + "Encounter" + ], + "title": "Health care event when test ordered" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "identifier": { + "description": "Identifiers assigned to this report by the performer or other systems.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "Business identifier for report", + "type": "array" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "issued": { + "description": "The date and time that this version of the report was made available to providers, typically after the report was reviewed and verified.", + "element_property": true, + "format": "date-time", + "title": "DateTime this version was made", + "type": "string" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "media": { + "description": "A list of key images or data associated with this report. The images or data are generally created during the diagnostic process, and may be directly of the patient, or of treated specimens (i.e. slides of interest).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReportMedia" + }, + "title": "Key images or data associated with this report", + "type": "array" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored", + "type": "array" + }, + "note": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Annotation" + }, + "title": "Comments about the diagnostic report", + "type": "array" + }, + "performer": { + "backref": "performer_diagnostic_report", + "description": "The diagnostic service that is responsible for issuing the report.", + "element_property": true, + "enum_reference_types": [ + "Practitioner", + "PractitionerRole", + "Organization", + "CareTeam" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Responsible Diagnostic Service", + "type": "array" + }, + "presentedForm": { + "description": "Rich text representation of the entire result as issued by the diagnostic service. Multiple formats are allowed but they SHALL be semantically equivalent.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Attachment" + }, + "title": "Entire report as issued", + "type": "array" + }, + "resourceType": { + "const": "DiagnosticReport", + "default": "DiagnosticReport", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "result": { + "backref": "result_diagnostic_report", + "description": "[Observations](observation.html) that are part of this diagnostic report.", + "element_property": true, + "enum_reference_types": [ + "Observation" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Observations", + "type": "array" + }, + "resultsInterpreter": { + "backref": "resultsInterpreter_diagnostic_report", + "description": "The practitioner or organization that is responsible for the report's conclusions and interpretations.", + "element_property": true, + "enum_reference_types": [ + "Practitioner", + "PractitionerRole", + "Organization", + "CareTeam" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Primary result interpreter", + "type": "array" + }, + "specimen": { + "backref": "specimen_diagnostic_report", + "description": "Details about the specimens on which this diagnostic report is based.", + "element_property": true, + "enum_reference_types": [ + "Specimen" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Specimens this report is based on", + "type": "array" + }, + "status": { + "binding_description": "The status of the diagnostic report.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/diagnostic-report-status", + "binding_version": "5.0.0", + "description": "The status of the diagnostic report.", + "element_property": true, + "element_required": true, + "enum_values": [ + "registered", + "partial", + "preliminary", + "modified", + "final", + "amended", + "corrected", + "appended", + "cancelled", + "entered-in-error", + "unknown" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "registered | partial | preliminary | modified | final | amended | corrected | appended | cancelled | entered-in-error | unknown", + "type": "string" + }, + "study": { + "backref": "study_diagnostic_report", + "description": "One or more links to full details of any study performed during the diagnostic investigation. An ImagingStudy might comprise a set of radiologic images obtained via a procedure that are analyzed as a group. Typically, this is imaging performed by DICOM enabled modalities, but this is not required. A fully enabled PACS viewer can use this information to provide views of the source images. A GenomicStudy might comprise one or more analyses, each serving a specific purpose. These analyses may vary in method (e.g., karyotyping, CNV, or SNV detection), performer, software, devices used, or regions targeted.", + "element_property": true, + "enum_reference_types": [ + "GenomicStudy", + "ImagingStudy" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Reference to full details of an analysis associated with the diagnostic report", + "type": "array" + }, + "subject": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "subject_diagnostic_report", + "description": "The subject of the report. Usually, but not always, this is a patient. However, diagnostic services also perform analyses on specimens collected from a variety of other sources.", + "element_property": true, + "enum_reference_types": [ + "Patient", + "Group", + "Device", + "Location", + "Organization", + "Practitioner", + "Medication", + "Substance", + "BiologicallyDerivedProduct" + ], + "title": "The subject of the report - usually, but not always, the patient" + }, + "supportingInfo": { + "description": "This backbone element contains supporting information that was used in the creation of the report not included in the results already included in the report.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReportSupportingInfo" + }, + "title": "Additional information supporting the diagnostic report", + "type": "array" + }, + "text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative", + "description": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "element_property": true, + "title": "Text summary of the resource, for human interpretation" + } + }, + "required": [ + "code" + ], + "title": "DiagnosticReport", + "type": "object" + }, + "OrganizationQualification": { + "$id": "http://graph-fhir.io/schema/0.0.2/OrganizationQualification", + "additionalProperties": false, + "description": "Qualifications, certifications, accreditations, licenses, training, etc. pertaining to the provision of care. The official certifications, accreditations, training, designations and licenses that authorize and/or otherwise endorse the provision of care by the organization. For example, an approval to provide a type of services issued by a certifying body (such as the US Joint Commission) to an organization. [See https://hl7.org/fhir/R5/OrganizationQualification.html]", + "links": [ + { + "href": "{id}", + "rel": "issuer", + "targetHints": { + "backref": [ + "organization_qualification" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/issuer/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "element_property": true, + "title": "Coded representation of the qualification" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "identifier": { + "description": "An identifier allocated to this qualification for this organization.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "An identifier for this qualification for the organization", + "type": "array" + }, + "issuer": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "organization_qualification", + "element_property": true, + "enum_reference_types": [ + "Organization" + ], + "title": "Organization that regulates and issues the qualification" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "period": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "element_property": true, + "title": "Period during which the qualification is valid" + }, + "resourceType": { + "const": "OrganizationQualification", + "default": "OrganizationQualification", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "required": [ + "code" + ], + "title": "OrganizationQualification", + "type": "object" + }, + "Task": { + "$id": "http://graph-fhir.io/schema/0.0.2/Task", + "additionalProperties": false, + "description": "A task to be performed. [See https://hl7.org/fhir/R5/Task.html]", + "links": [ + { + "href": "{id}", + "rel": "basedOn_Organization", + "targetHints": { + "backref": [ + "basedOn_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "basedOn_Group", + "targetHints": { + "backref": [ + "basedOn_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "basedOn_Practitioner", + "targetHints": { + "backref": [ + "basedOn_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "basedOn_PractitionerRole", + "targetHints": { + "backref": [ + "basedOn_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "basedOn_ResearchStudy", + "targetHints": { + "backref": [ + "basedOn_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "basedOn_Patient", + "targetHints": { + "backref": [ + "basedOn_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "basedOn_ResearchSubject", + "targetHints": { + "backref": [ + "basedOn_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "basedOn_Substance", + "targetHints": { + "backref": [ + "basedOn_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "basedOn_SubstanceDefinition", + "targetHints": { + "backref": [ + "basedOn_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "basedOn_Specimen", + "targetHints": { + "backref": [ + "basedOn_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "basedOn_Observation", + "targetHints": { + "backref": [ + "basedOn_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "basedOn_DiagnosticReport", + "targetHints": { + "backref": [ + "basedOn_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "basedOn_Condition", + "targetHints": { + "backref": [ + "basedOn_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "basedOn_Medication", + "targetHints": { + "backref": [ + "basedOn_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "basedOn_MedicationAdministration", + "targetHints": { + "backref": [ + "basedOn_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "basedOn_MedicationStatement", + "targetHints": { + "backref": [ + "basedOn_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "basedOn_MedicationRequest", + "targetHints": { + "backref": [ + "basedOn_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "basedOn_Procedure", + "targetHints": { + "backref": [ + "basedOn_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "basedOn_DocumentReference", + "targetHints": { + "backref": [ + "basedOn_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "basedOn_Task", + "targetHints": { + "backref": [ + "basedOn_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "basedOn_ImagingStudy", + "targetHints": { + "backref": [ + "basedOn_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "basedOn_FamilyMemberHistory", + "targetHints": { + "backref": [ + "basedOn_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "basedOn_BodyStructure", + "targetHints": { + "backref": [ + "basedOn_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Organization", + "targetHints": { + "backref": [ + "focus_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Group", + "targetHints": { + "backref": [ + "focus_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Practitioner", + "targetHints": { + "backref": [ + "focus_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_PractitionerRole", + "targetHints": { + "backref": [ + "focus_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_ResearchStudy", + "targetHints": { + "backref": [ + "focus_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Patient", + "targetHints": { + "backref": [ + "focus_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_ResearchSubject", + "targetHints": { + "backref": [ + "focus_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Substance", + "targetHints": { + "backref": [ + "focus_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_SubstanceDefinition", + "targetHints": { + "backref": [ + "focus_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Specimen", + "targetHints": { + "backref": [ + "focus_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Observation", + "targetHints": { + "backref": [ + "focus_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_DiagnosticReport", + "targetHints": { + "backref": [ + "focus_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Condition", + "targetHints": { + "backref": [ + "focus_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Medication", + "targetHints": { + "backref": [ + "focus_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_MedicationAdministration", + "targetHints": { + "backref": [ + "focus_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_MedicationStatement", + "targetHints": { + "backref": [ + "focus_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_MedicationRequest", + "targetHints": { + "backref": [ + "focus_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Procedure", + "targetHints": { + "backref": [ + "focus_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_DocumentReference", + "targetHints": { + "backref": [ + "focus_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Task", + "targetHints": { + "backref": [ + "focus_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_ImagingStudy", + "targetHints": { + "backref": [ + "focus_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_FamilyMemberHistory", + "targetHints": { + "backref": [ + "focus_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_BodyStructure", + "targetHints": { + "backref": [ + "focus_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "for_fhir_Organization", + "targetHints": { + "backref": [ + "for_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/for_fhir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "for_fhir_Group", + "targetHints": { + "backref": [ + "for_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/for_fhir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "for_fhir_Practitioner", + "targetHints": { + "backref": [ + "for_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/for_fhir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "for_fhir_PractitionerRole", + "targetHints": { + "backref": [ + "for_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/for_fhir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "for_fhir_ResearchStudy", + "targetHints": { + "backref": [ + "for_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/for_fhir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "for_fhir_Patient", + "targetHints": { + "backref": [ + "for_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/for_fhir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "for_fhir_ResearchSubject", + "targetHints": { + "backref": [ + "for_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/for_fhir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "for_fhir_Substance", + "targetHints": { + "backref": [ + "for_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/for_fhir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "for_fhir_SubstanceDefinition", + "targetHints": { + "backref": [ + "for_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/for_fhir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "for_fhir_Specimen", + "targetHints": { + "backref": [ + "for_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/for_fhir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "for_fhir_Observation", + "targetHints": { + "backref": [ + "for_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/for_fhir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "for_fhir_DiagnosticReport", + "targetHints": { + "backref": [ + "for_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/for_fhir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "for_fhir_Condition", + "targetHints": { + "backref": [ + "for_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/for_fhir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "for_fhir_Medication", + "targetHints": { + "backref": [ + "for_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/for_fhir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "for_fhir_MedicationAdministration", + "targetHints": { + "backref": [ + "for_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/for_fhir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "for_fhir_MedicationStatement", + "targetHints": { + "backref": [ + "for_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/for_fhir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "for_fhir_MedicationRequest", + "targetHints": { + "backref": [ + "for_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/for_fhir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "for_fhir_Procedure", + "targetHints": { + "backref": [ + "for_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/for_fhir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "for_fhir_DocumentReference", + "targetHints": { + "backref": [ + "for_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/for_fhir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "for_fhir_Task", + "targetHints": { + "backref": [ + "for_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/for_fhir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "for_fhir_ImagingStudy", + "targetHints": { + "backref": [ + "for_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/for_fhir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "for_fhir_FamilyMemberHistory", + "targetHints": { + "backref": [ + "for_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/for_fhir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "for_fhir_BodyStructure", + "targetHints": { + "backref": [ + "for_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/for_fhir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "owner_Practitioner", + "targetHints": { + "backref": [ + "owner_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/owner/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "owner_PractitionerRole", + "targetHints": { + "backref": [ + "owner_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/owner/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "owner_Organization", + "targetHints": { + "backref": [ + "owner_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/owner/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "owner_Patient", + "targetHints": { + "backref": [ + "owner_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/owner/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "partOf", + "targetHints": { + "backref": [ + "partOf_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/partOf/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "requester_Organization", + "targetHints": { + "backref": [ + "requester_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/requester/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "requester_Patient", + "targetHints": { + "backref": [ + "requester_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/requester/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "requester_Practitioner", + "targetHints": { + "backref": [ + "requester_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/requester/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "requester_PractitionerRole", + "targetHints": { + "backref": [ + "requester_task" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/requester/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskInput/input", + "href": "{id}", + "rel": "input_valueReference_Organization", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/input/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskInput/input", + "href": "{id}", + "rel": "input_valueReference_Group", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/input/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskInput/input", + "href": "{id}", + "rel": "input_valueReference_Practitioner", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/input/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskInput/input", + "href": "{id}", + "rel": "input_valueReference_PractitionerRole", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/input/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskInput/input", + "href": "{id}", + "rel": "input_valueReference_ResearchStudy", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/input/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskInput/input", + "href": "{id}", + "rel": "input_valueReference_Patient", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/input/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskInput/input", + "href": "{id}", + "rel": "input_valueReference_ResearchSubject", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/input/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskInput/input", + "href": "{id}", + "rel": "input_valueReference_Substance", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/input/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskInput/input", + "href": "{id}", + "rel": "input_valueReference_SubstanceDefinition", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/input/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskInput/input", + "href": "{id}", + "rel": "input_valueReference_Specimen", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/input/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskInput/input", + "href": "{id}", + "rel": "input_valueReference_Observation", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/input/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskInput/input", + "href": "{id}", + "rel": "input_valueReference_DiagnosticReport", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/input/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskInput/input", + "href": "{id}", + "rel": "input_valueReference_Condition", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/input/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskInput/input", + "href": "{id}", + "rel": "input_valueReference_Medication", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/input/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskInput/input", + "href": "{id}", + "rel": "input_valueReference_MedicationAdministration", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/input/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskInput/input", + "href": "{id}", + "rel": "input_valueReference_MedicationStatement", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/input/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskInput/input", + "href": "{id}", + "rel": "input_valueReference_MedicationRequest", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/input/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskInput/input", + "href": "{id}", + "rel": "input_valueReference_Procedure", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/input/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskInput/input", + "href": "{id}", + "rel": "input_valueReference_DocumentReference", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/input/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskInput/input", + "href": "{id}", + "rel": "input_valueReference_Task", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/input/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskInput/input", + "href": "{id}", + "rel": "input_valueReference_ImagingStudy", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/input/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskInput/input", + "href": "{id}", + "rel": "input_valueReference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/input/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskInput/input", + "href": "{id}", + "rel": "input_valueReference_BodyStructure", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/input/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Practitioner", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_PractitionerRole", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Patient", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Organization", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskOutput/output", + "href": "{id}", + "rel": "output_valueReference_Organization", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/output/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskOutput/output", + "href": "{id}", + "rel": "output_valueReference_Group", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/output/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskOutput/output", + "href": "{id}", + "rel": "output_valueReference_Practitioner", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/output/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskOutput/output", + "href": "{id}", + "rel": "output_valueReference_PractitionerRole", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/output/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskOutput/output", + "href": "{id}", + "rel": "output_valueReference_ResearchStudy", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/output/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskOutput/output", + "href": "{id}", + "rel": "output_valueReference_Patient", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/output/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskOutput/output", + "href": "{id}", + "rel": "output_valueReference_ResearchSubject", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/output/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskOutput/output", + "href": "{id}", + "rel": "output_valueReference_Substance", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/output/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskOutput/output", + "href": "{id}", + "rel": "output_valueReference_SubstanceDefinition", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/output/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskOutput/output", + "href": "{id}", + "rel": "output_valueReference_Specimen", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/output/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskOutput/output", + "href": "{id}", + "rel": "output_valueReference_Observation", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/output/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskOutput/output", + "href": "{id}", + "rel": "output_valueReference_DiagnosticReport", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/output/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskOutput/output", + "href": "{id}", + "rel": "output_valueReference_Condition", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/output/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskOutput/output", + "href": "{id}", + "rel": "output_valueReference_Medication", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/output/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskOutput/output", + "href": "{id}", + "rel": "output_valueReference_MedicationAdministration", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/output/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskOutput/output", + "href": "{id}", + "rel": "output_valueReference_MedicationStatement", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/output/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskOutput/output", + "href": "{id}", + "rel": "output_valueReference_MedicationRequest", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/output/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskOutput/output", + "href": "{id}", + "rel": "output_valueReference_Procedure", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/output/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskOutput/output", + "href": "{id}", + "rel": "output_valueReference_DocumentReference", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/output/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskOutput/output", + "href": "{id}", + "rel": "output_valueReference_Task", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/output/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskOutput/output", + "href": "{id}", + "rel": "output_valueReference_ImagingStudy", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/output/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskOutput/output", + "href": "{id}", + "rel": "output_valueReference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/output/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskOutput/output", + "href": "{id}", + "rel": "output_valueReference_BodyStructure", + "targetHints": { + "backref": [ + "task_output" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/output/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskPerformer/performer", + "href": "{id}", + "rel": "performer_actor_Practitioner", + "targetHints": { + "backref": [ + "task_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/performer/-/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskPerformer/performer", + "href": "{id}", + "rel": "performer_actor_PractitionerRole", + "targetHints": { + "backref": [ + "task_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/performer/-/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskPerformer/performer", + "href": "{id}", + "rel": "performer_actor_Organization", + "targetHints": { + "backref": [ + "task_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/performer/-/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskPerformer/performer", + "href": "{id}", + "rel": "performer_actor_Patient", + "targetHints": { + "backref": [ + "task_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/performer/-/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/requestedPerformer", + "href": "{id}", + "rel": "requestedPerformer_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/requestedPerformer/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/requestedPerformer", + "href": "{id}", + "rel": "requestedPerformer_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/requestedPerformer/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/requestedPerformer", + "href": "{id}", + "rel": "requestedPerformer_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/requestedPerformer/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/requestedPerformer", + "href": "{id}", + "rel": "requestedPerformer_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/requestedPerformer/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/requestedPerformer", + "href": "{id}", + "rel": "requestedPerformer_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/requestedPerformer/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/requestedPerformer", + "href": "{id}", + "rel": "requestedPerformer_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/requestedPerformer/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/requestedPerformer", + "href": "{id}", + "rel": "requestedPerformer_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/requestedPerformer/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/requestedPerformer", + "href": "{id}", + "rel": "requestedPerformer_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/requestedPerformer/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/requestedPerformer", + "href": "{id}", + "rel": "requestedPerformer_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/requestedPerformer/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/requestedPerformer", + "href": "{id}", + "rel": "requestedPerformer_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/requestedPerformer/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/requestedPerformer", + "href": "{id}", + "rel": "requestedPerformer_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/requestedPerformer/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/requestedPerformer", + "href": "{id}", + "rel": "requestedPerformer_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/requestedPerformer/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/requestedPerformer", + "href": "{id}", + "rel": "requestedPerformer_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/requestedPerformer/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/requestedPerformer", + "href": "{id}", + "rel": "requestedPerformer_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/requestedPerformer/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/requestedPerformer", + "href": "{id}", + "rel": "requestedPerformer_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/requestedPerformer/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/requestedPerformer", + "href": "{id}", + "rel": "requestedPerformer_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/requestedPerformer/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/requestedPerformer", + "href": "{id}", + "rel": "requestedPerformer_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/requestedPerformer/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/requestedPerformer", + "href": "{id}", + "rel": "requestedPerformer_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/requestedPerformer/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/requestedPerformer", + "href": "{id}", + "rel": "requestedPerformer_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/requestedPerformer/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/requestedPerformer", + "href": "{id}", + "rel": "requestedPerformer_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/requestedPerformer/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/requestedPerformer", + "href": "{id}", + "rel": "requestedPerformer_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/requestedPerformer/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/requestedPerformer", + "href": "{id}", + "rel": "requestedPerformer_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/requestedPerformer/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/requestedPerformer", + "href": "{id}", + "rel": "requestedPerformer_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/requestedPerformer/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskRestriction/restriction", + "href": "{id}", + "rel": "restriction_recipient_Patient", + "targetHints": { + "backref": [ + "recipient_task_restriction" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/restriction/recipient/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskRestriction/restriction", + "href": "{id}", + "rel": "restriction_recipient_Practitioner", + "targetHints": { + "backref": [ + "recipient_task_restriction" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/restriction/recipient/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskRestriction/restriction", + "href": "{id}", + "rel": "restriction_recipient_PractitionerRole", + "targetHints": { + "backref": [ + "recipient_task_restriction" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/restriction/recipient/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskRestriction/restriction", + "href": "{id}", + "rel": "restriction_recipient_Group", + "targetHints": { + "backref": [ + "recipient_task_restriction" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/restriction/recipient/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From TaskRestriction/restriction", + "href": "{id}", + "rel": "restriction_recipient_Organization", + "targetHints": { + "backref": [ + "recipient_task_restriction" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/restriction/recipient/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/statusReason", + "href": "{id}", + "rel": "statusReason_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/statusReason/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/statusReason", + "href": "{id}", + "rel": "statusReason_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/statusReason/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/statusReason", + "href": "{id}", + "rel": "statusReason_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/statusReason/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/statusReason", + "href": "{id}", + "rel": "statusReason_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/statusReason/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/statusReason", + "href": "{id}", + "rel": "statusReason_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/statusReason/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/statusReason", + "href": "{id}", + "rel": "statusReason_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/statusReason/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/statusReason", + "href": "{id}", + "rel": "statusReason_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/statusReason/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/statusReason", + "href": "{id}", + "rel": "statusReason_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/statusReason/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/statusReason", + "href": "{id}", + "rel": "statusReason_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/statusReason/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/statusReason", + "href": "{id}", + "rel": "statusReason_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/statusReason/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/statusReason", + "href": "{id}", + "rel": "statusReason_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/statusReason/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/statusReason", + "href": "{id}", + "rel": "statusReason_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/statusReason/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/statusReason", + "href": "{id}", + "rel": "statusReason_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/statusReason/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/statusReason", + "href": "{id}", + "rel": "statusReason_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/statusReason/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/statusReason", + "href": "{id}", + "rel": "statusReason_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/statusReason/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/statusReason", + "href": "{id}", + "rel": "statusReason_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/statusReason/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/statusReason", + "href": "{id}", + "rel": "statusReason_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/statusReason/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/statusReason", + "href": "{id}", + "rel": "statusReason_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/statusReason/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/statusReason", + "href": "{id}", + "rel": "statusReason_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/statusReason/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/statusReason", + "href": "{id}", + "rel": "statusReason_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/statusReason/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/statusReason", + "href": "{id}", + "rel": "statusReason_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/statusReason/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/statusReason", + "href": "{id}", + "rel": "statusReason_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/statusReason/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/statusReason", + "href": "{id}", + "rel": "statusReason_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/statusReason/reference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_authoredOn": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'authoredOn'." + }, + "_description": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'description'." + }, + "_doNotPerform": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'doNotPerform'." + }, + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_instantiatesCanonical": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'instantiatesCanonical'." + }, + "_instantiatesUri": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'instantiatesUri'." + }, + "_intent": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'intent'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "_lastModified": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'lastModified'." + }, + "_priority": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'priority'." + }, + "_status": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'status'." + }, + "authoredOn": { + "description": "The date and time this task was created.", + "element_property": true, + "format": "date-time", + "title": "Task Creation Date", + "type": "string" + }, + "basedOn": { + "backref": "basedOn_task", + "description": "BasedOn refers to a higher-level authorization that triggered the creation of the task. It references a \"request\" resource such as a ServiceRequest, MedicationRequest, CarePlan, etc. which is distinct from the \"request\" resource the task is seeking to fulfill. This latter resource is referenced by focus. For example, based on a CarePlan (= basedOn), a task is created to fulfill a ServiceRequest ( = focus ) to collect a specimen from a patient.", + "element_property": true, + "enum_reference_types": [ + "Organization", + "Group", + "Practitioner", + "PractitionerRole", + "ResearchStudy", + "Patient", + "ResearchSubject", + "Substance", + "SubstanceDefinition", + "Specimen", + "Observation", + "DiagnosticReport", + "Condition", + "Medication", + "MedicationAdministration", + "MedicationStatement", + "MedicationRequest", + "Procedure", + "DocumentReference", + "Task", + "ImagingStudy", + "FamilyMemberHistory", + "BodyStructure" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Request fulfilled by this task", + "type": "array" + }, + "businessStatus": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "description": "Contains business-specific nuances of the business state.", + "element_property": true, + "title": "E.g. \"Specimen collected\", \"IV prepped\"" + }, + "code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Codes to identify what the task involves. These will typically be specific to a particular workflow.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/task-code", + "binding_version": null, + "description": "A name or code (or both) briefly describing what the task involves.", + "element_property": true, + "title": "Task Type" + }, + "contained": { + "description": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, nor can they have their own independent transaction scope. This is allowed to be a Parameters resource if and only if it is referenced by a resource that provides context/meaning.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + "title": "Contained, inline Resources", + "type": "array" + }, + "description": { + "description": "A free-text description of what is to be performed.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Human-readable explanation of task", + "type": "string" + }, + "doNotPerform": { + "description": "If true indicates that the Task is asking for the specified action to *not* occur.", + "element_property": true, + "title": "True if Task is prohibiting action", + "type": "boolean" + }, + "encounter": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "task", + "description": "The healthcare event (e.g. a patient and healthcare provider interaction) during which this task was created.", + "element_property": true, + "enum_reference_types": [ + "Encounter" + ], + "title": "Healthcare event during which this task originated" + }, + "executionPeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "Identifies the time action was first taken against the task (start) and/or the time final action was taken against the task prior to marking it as completed (end).", + "element_property": true, + "title": "Start and end time of execution" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "focus": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "focus_task", + "description": "The request being fulfilled or the resource being manipulated (changed, suspended, etc.) by this task.", + "element_property": true, + "enum_reference_types": [ + "Organization", + "Group", + "Practitioner", + "PractitionerRole", + "ResearchStudy", + "Patient", + "ResearchSubject", + "Substance", + "SubstanceDefinition", + "Specimen", + "Observation", + "DiagnosticReport", + "Condition", + "Medication", + "MedicationAdministration", + "MedicationStatement", + "MedicationRequest", + "Procedure", + "DocumentReference", + "Task", + "ImagingStudy", + "FamilyMemberHistory", + "BodyStructure" + ], + "title": "What task is acting on" + }, + "for_fhir": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "for_task", + "description": "[Reserved word `for` renamed to `for_fhir`] The entity who benefits from the performance of the service specified in the task (e.g., the patient).", + "element_property": true, + "enum_reference_types": [ + "Organization", + "Group", + "Practitioner", + "PractitionerRole", + "ResearchStudy", + "Patient", + "ResearchSubject", + "Substance", + "SubstanceDefinition", + "Specimen", + "Observation", + "DiagnosticReport", + "Condition", + "Medication", + "MedicationAdministration", + "MedicationStatement", + "MedicationRequest", + "Procedure", + "DocumentReference", + "Task", + "ImagingStudy", + "FamilyMemberHistory", + "BodyStructure" + ], + "title": "Beneficiary of the Task" + }, + "groupIdentifier": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier", + "description": "A shared identifier common to multiple independent Task and Request instances that were activated/authorized more or less simultaneously by a single author. The presence of the same identifier on each request ties those requests together and may have business ramifications in terms of reporting of results, billing, etc. E.g. a requisition number shared by a set of lab tests ordered together, or a prescription number shared by all meds ordered at one time.", + "element_property": true, + "title": "Requisition or grouper id" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "identifier": { + "description": "The business identifier for this task.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "Task Instance Identifier", + "type": "array" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "input": { + "description": "Additional information that may be needed in the execution of the task.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/TaskInput" + }, + "title": "Information used to perform task", + "type": "array" + }, + "instantiatesCanonical": { + "description": "The URL pointing to a *FHIR*-defined protocol, guideline, orderset or other definition that is adhered to in whole or in part by this Task.", + "element_property": true, + "enum_reference_types": [ + "ActivityDefinition" + ], + "pattern": "\\S*", + "title": "Formal definition of task", + "type": "string" + }, + "instantiatesUri": { + "description": "The URL pointing to an *externally* maintained protocol, guideline, orderset or other definition that is adhered to in whole or in part by this Task.", + "element_property": true, + "pattern": "\\S*", + "title": "Formal definition of task", + "type": "string" + }, + "insurance": { + "backref": "insurance_task", + "description": "Insurance plans, coverage extensions, pre-authorizations and/or pre-determinations that may be relevant to the Task.", + "element_property": true, + "enum_reference_types": [ + "Coverage", + "ClaimResponse" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Associated insurance coverage", + "type": "array" + }, + "intent": { + "binding_description": "Distinguishes whether the task is a proposal, plan or full order.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/task-intent", + "binding_version": "5.0.0", + "description": "Indicates the \"level\" of actionability associated with the Task, i.e. i+R[9]Cs this a proposed task, a planned task, an actionable task, etc.", + "element_property": true, + "element_required": true, + "enum_values": [ + "unknown", + "proposal", + "plan", + "order", + "original-order", + "reflex-order", + "filler-order", + "instance-order", + "option" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "unknown | proposal | plan | order | original-order | reflex-order | filler-order | instance-order | option", + "type": "string" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "lastModified": { + "description": "The date and time of last modification to this task.", + "element_property": true, + "format": "date-time", + "title": "Task Last Modified Date", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "location": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "task", + "description": "Principal physical location where this task is performed.", + "element_property": true, + "enum_reference_types": [ + "Location" + ], + "title": "Where task occurs" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored", + "type": "array" + }, + "note": { + "description": "Free-text information captured about the task as it progresses.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Annotation" + }, + "title": "Comments made about the task", + "type": "array" + }, + "output": { + "description": "Outputs produced by the Task.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/TaskOutput" + }, + "title": "Information produced as part of task", + "type": "array" + }, + "owner": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "owner_task", + "description": "Party responsible for managing task execution.", + "element_property": true, + "enum_reference_types": [ + "Practitioner", + "PractitionerRole", + "Organization", + "CareTeam", + "Patient", + "RelatedPerson" + ], + "title": "Responsible individual" + }, + "partOf": { + "backref": "partOf_task", + "description": "Task that this particular task is part of.", + "element_property": true, + "enum_reference_types": [ + "Task" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Composite task", + "type": "array" + }, + "performer": { + "description": "The entity who performed the requested task.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/TaskPerformer" + }, + "title": "Who or what performed the task", + "type": "array" + }, + "priority": { + "binding_description": "The priority of a task (may affect service level applied to the task).", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/request-priority", + "binding_version": "5.0.0", + "description": "Indicates how quickly the Task should be addressed with respect to other requests.", + "element_property": true, + "enum_values": [ + "routine", + "urgent", + "asap", + "stat" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "routine | urgent | asap | stat", + "type": "string" + }, + "reason": { + "backref": "reason_task", + "description": "A description, code, or reference indicating why this task needs to be performed.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference" + }, + "title": "Why task is needed", + "type": "array" + }, + "relevantHistory": { + "backref": "relevantHistory_task", + "description": "Links to Provenance records for past versions of this Task that identify key state transitions or updates that are likely to be relevant to a user looking at the current version of the task.", + "element_property": true, + "enum_reference_types": [ + "Provenance" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Key events in history of the Task", + "type": "array" + }, + "requestedPerformer": { + "backref": "requestedPerformer_task", + "binding_description": "The type(s) of task performers allowed.", + "binding_strength": "preferred", + "binding_uri": "http://hl7.org/fhir/ValueSet/performer-role", + "binding_version": null, + "description": "The kind of participant or specific participant that should perform the task.", + "element_property": true, + "enum_reference_types": [ + "Practitioner", + "PractitionerRole", + "Organization", + "CareTeam", + "HealthcareService", + "Patient", + "Device", + "RelatedPerson" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference" + }, + "title": "Who should perform Task", + "type": "array" + }, + "requestedPeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "Indicates the start and/or end of the period of time when completion of the task is desired to take place.", + "element_property": true, + "title": "When the task should be performed" + }, + "requester": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "requester_task", + "description": "The creator of the task.", + "element_property": true, + "enum_reference_types": [ + "Device", + "Organization", + "Patient", + "Practitioner", + "PractitionerRole", + "RelatedPerson" + ], + "title": "Who is asking for task to be done" + }, + "resourceType": { + "const": "Task", + "default": "Task", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "restriction": { + "$ref": "http://graph-fhir.io/schema/0.0.2/TaskRestriction", + "description": "If the Task.focus is a request resource and the task is seeking fulfillment (i.e. is asking for the request to be actioned), this element identifies any limitations on what parts of the referenced request should be actioned.", + "element_property": true, + "title": "Constraints on fulfillment tasks" + }, + "status": { + "binding_description": "The current status of the task.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/task-status", + "binding_version": "5.0.0", + "description": "The current status of the task.", + "element_property": true, + "element_required": true, + "enum_values": [ + "draft", + "requested", + "received", + "accepted", + "+" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "draft | requested | received | accepted | +", + "type": "string" + }, + "statusReason": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference", + "backref": "task", + "binding_description": "Codes to identify the reason for current status. These will typically be specific to a particular workflow.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/task-status-reason", + "binding_version": null, + "description": "An explanation as to why this task is held, failed, was refused, etc.", + "element_property": true, + "title": "Reason for current status" + }, + "text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative", + "description": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "element_property": true, + "title": "Text summary of the resource, for human interpretation" + } + }, + "title": "Task", + "type": "object" + }, + "ResearchStudyAssociatedParty": { + "$id": "http://graph-fhir.io/schema/0.0.2/ResearchStudyAssociatedParty", + "additionalProperties": false, + "description": "Sponsors, collaborators, and other parties. [See https://hl7.org/fhir/R5/ResearchStudyAssociatedParty.html]", + "links": [ + { + "href": "{id}", + "rel": "party_Practitioner", + "targetHints": { + "backref": [ + "research_study_associated_party" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/party/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "party_PractitionerRole", + "targetHints": { + "backref": [ + "research_study_associated_party" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/party/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "party_Organization", + "targetHints": { + "backref": [ + "research_study_associated_party" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/party/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_name": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'name'." + }, + "classifier": { + "binding_description": "A characterization or type of the entity.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/research-study-party-organization-type", + "binding_version": null, + "description": "A categorization other than role for the associated party.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "nih | fda | government | nonprofit | academic | industry", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "name": { + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Name of associated party", + "type": "string" + }, + "party": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "research_study_associated_party", + "element_property": true, + "enum_reference_types": [ + "Practitioner", + "PractitionerRole", + "Organization" + ], + "title": "Individual or organization associated with study (use practitionerRole to specify their organisation)" + }, + "period": { + "description": "Identifies the start date and the end date of the associated party in the role.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period" + }, + "title": "When active in the role", + "type": "array" + }, + "resourceType": { + "const": "ResearchStudyAssociatedParty", + "default": "ResearchStudyAssociatedParty", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "role": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "desc.", + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/research-study-party-role", + "binding_version": null, + "description": "Type of association.", + "element_property": true, + "title": "sponsor | lead-sponsor | sponsor-investigator | primary-investigator | collaborator | funding-source | general-contact | recruitment-contact | sub-investigator | study-director | study-chair" + } + }, + "required": [ + "role" + ], + "title": "ResearchStudyAssociatedParty", + "type": "object" + }, + "Range": { + "$id": "http://graph-fhir.io/schema/0.0.2/Range", + "additionalProperties": false, + "description": "Set of values bounded by low and high. A set of ordered Quantities defined by a low and high limit. [See https://hl7.org/fhir/R5/Range.html]", + "links": [], + "properties": { + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "high": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "The high limit. The boundary is inclusive.", + "element_property": true, + "title": "High limit" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "low": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "The low limit. The boundary is inclusive.", + "element_property": true, + "title": "Low limit" + }, + "resourceType": { + "const": "Range", + "default": "Range", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "title": "Range", + "type": "object" + }, + "PatientContact": { + "$id": "http://graph-fhir.io/schema/0.0.2/PatientContact", + "additionalProperties": false, + "description": "A contact party (e.g. guardian, partner, friend) for the patient. [See https://hl7.org/fhir/R5/PatientContact.html]", + "links": [ + { + "href": "{id}", + "rel": "organization", + "targetHints": { + "backref": [ + "patient_contact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/organization/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_gender": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'gender'." + }, + "address": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Address", + "element_property": true, + "title": "Address for the contact person" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "gender": { + "binding_description": "The gender of a person used for administrative purposes.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/administrative-gender", + "binding_version": "5.0.0", + "description": "Administrative Gender - the gender that the contact person is considered to have for administration and record keeping purposes.", + "element_property": true, + "enum_values": [ + "male", + "female", + "other", + "unknown" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "male | female | other | unknown", + "type": "string" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "name": { + "$ref": "http://graph-fhir.io/schema/0.0.2/HumanName", + "element_property": true, + "title": "A name associated with the contact person" + }, + "organization": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "patient_contact", + "description": "Organization on behalf of which the contact is acting or for which the contact is working.", + "element_property": true, + "enum_reference_types": [ + "Organization" + ], + "title": "Organization that is associated with the contact" + }, + "period": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "element_property": true, + "title": "The period during which this contact person or organization is valid to be contacted relating to this patient" + }, + "relationship": { + "binding_description": "The nature of the relationship between a patient and a contact person for that patient.", + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/patient-contactrelationship", + "binding_version": null, + "description": "The nature of the relationship between the patient and the contact person.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "The kind of relationship", + "type": "array" + }, + "resourceType": { + "const": "PatientContact", + "default": "PatientContact", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "telecom": { + "description": "A contact detail for the person, e.g. a telephone number or an email address.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ContactPoint" + }, + "title": "A contact detail for the person", + "type": "array" + } + }, + "title": "PatientContact", + "type": "object" + }, + "DataRequirement": { + "$id": "http://graph-fhir.io/schema/0.0.2/DataRequirement", + "additionalProperties": false, + "description": "Describes a required data item. Describes a required data item for evaluation in terms of the type of data, and optional code or date-based filters of the data. [See https://hl7.org/fhir/R5/DataRequirement.html]", + "links": [ + { + "href": "{id}", + "rel": "subjectReference", + "targetHints": { + "backref": [ + "data_requirement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/subjectReference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_limit": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'limit'." + }, + "_mustSupport": { + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension" + }, + "title": "Extension field for 'mustSupport'.", + "type": "array" + }, + "_profile": { + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension" + }, + "title": "Extension field for 'profile'.", + "type": "array" + }, + "_type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'type'." + }, + "codeFilter": { + "description": "Code filters specify additional constraints on the data, specifying the value set of interest for a particular element of the data. Each code filter defines an additional constraint on the data, i.e. code filters are AND'ed, not OR'ed.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DataRequirementCodeFilter" + }, + "title": "What codes are expected", + "type": "array" + }, + "dateFilter": { + "description": "Date filters specify additional constraints on the data in terms of the applicable date range for specific elements. Each date filter specifies an additional constraint on the data, i.e. date filters are AND'ed, not OR'ed.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DataRequirementDateFilter" + }, + "title": "What dates/date ranges are expected", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "limit": { + "description": "Specifies a maximum number of results that are required (uses the _count search parameter).", + "element_property": true, + "exclusiveMinimum": 0, + "title": "Number of results", + "type": "integer" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "mustSupport": { + "description": "Indicates that specific elements of the type are referenced by the knowledge module and must be supported by the consumer in order to obtain an effective evaluation. This does not mean that a value is required for this element, only that the consuming system must understand the element and be able to provide values for it if they are available. The value of mustSupport SHALL be a FHIRPath resolvable on the type of the DataRequirement. The path SHALL consist only of identifiers, constant indexers, and .resolve() (see the [Simple FHIRPath Profile](fhirpath.html#simple) for full details).", + "element_property": true, + "items": { + "pattern": "[ \\r\\n\\t\\S]+", + "type": "string" + }, + "title": "Indicates specific structure elements that are referenced by the knowledge module", + "type": "array" + }, + "profile": { + "description": "The profile of the required data, specified as the uri of the profile definition.", + "element_property": true, + "enum_reference_types": [ + "StructureDefinition" + ], + "items": { + "pattern": "\\S*", + "type": "string" + }, + "title": "The profile of the required data", + "type": "array" + }, + "resourceType": { + "const": "DataRequirement", + "default": "DataRequirement", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "sort": { + "description": "Specifies the order of the results to be returned.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DataRequirementSort" + }, + "title": "Order of the results", + "type": "array" + }, + "subjectCodeableConcept": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "description": "The intended subjects of the data requirement. If this element is not provided, a Patient subject is assumed.", + "element_property": true, + "one_of_many": "subject", + "one_of_many_required": false, + "title": "E.g. Patient, Practitioner, RelatedPerson, Organization, Location, Device" + }, + "subjectReference": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "data_requirement", + "description": "The intended subjects of the data requirement. If this element is not provided, a Patient subject is assumed.", + "element_property": true, + "enum_reference_types": [ + "Group" + ], + "one_of_many": "subject", + "one_of_many_required": false, + "title": "E.g. Patient, Practitioner, RelatedPerson, Organization, Location, Device" + }, + "type": { + "binding_description": "List of FHIR types (resources, data types).", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/fhir-types", + "binding_version": "5.0.0", + "description": "The type of the required data, specified as the type name of a resource. For profiles, this value is set to the type of the base resource of the profile.", + "element_property": true, + "element_required": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "The type of the required data", + "type": "string" + }, + "valueFilter": { + "description": "Value filters specify additional constraints on the data for elements other than code-valued or date-valued. Each value filter specifies an additional constraint on the data (i.e. valueFilters are AND'ed, not OR'ed).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DataRequirementValueFilter" + }, + "title": "What values are expected", + "type": "array" + } + }, + "title": "DataRequirement", + "type": "object" + }, + "ProcedureFocalDevice": { + "$id": "http://graph-fhir.io/schema/0.0.2/ProcedureFocalDevice", + "additionalProperties": false, + "description": "Manipulated, implanted, or removed device. A device that is implanted, removed or otherwise manipulated (calibration, battery replacement, fitting a prosthesis, attaching a wound-vac, etc.) as a focal portion of the Procedure. [See https://hl7.org/fhir/R5/ProcedureFocalDevice.html]", + "links": [], + "properties": { + "action": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "A kind of change that happened to the device during the procedure.", + "binding_strength": "preferred", + "binding_uri": "http://hl7.org/fhir/ValueSet/device-action", + "binding_version": null, + "description": "The kind of change that happened to the device during the procedure.", + "element_property": true, + "title": "Kind of change to device" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "manipulated": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "procedure_focal_device", + "description": "The device that was manipulated (changed) during the procedure.", + "element_property": true, + "enum_reference_types": [ + "Device" + ], + "title": "Device that was changed" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "ProcedureFocalDevice", + "default": "ProcedureFocalDevice", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "required": [ + "manipulated" + ], + "title": "ProcedureFocalDevice", + "type": "object" + }, + "Condition": { + "$id": "http://graph-fhir.io/schema/0.0.2/Condition", + "additionalProperties": false, + "description": "Detailed information about conditions, problems or diagnoses. A clinical condition, problem, diagnosis, or other event, situation, issue, or clinical concept that has risen to a level of concern. [See https://hl7.org/fhir/R5/Condition.html]", + "links": [ + { + "href": "{id}", + "rel": "subject_Patient", + "targetHints": { + "backref": [ + "condition" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Group", + "targetHints": { + "backref": [ + "condition" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/evidence", + "href": "{id}", + "rel": "evidence_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/evidence/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/evidence", + "href": "{id}", + "rel": "evidence_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/evidence/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/evidence", + "href": "{id}", + "rel": "evidence_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/evidence/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/evidence", + "href": "{id}", + "rel": "evidence_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/evidence/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/evidence", + "href": "{id}", + "rel": "evidence_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/evidence/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/evidence", + "href": "{id}", + "rel": "evidence_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/evidence/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/evidence", + "href": "{id}", + "rel": "evidence_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/evidence/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/evidence", + "href": "{id}", + "rel": "evidence_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/evidence/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/evidence", + "href": "{id}", + "rel": "evidence_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/evidence/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/evidence", + "href": "{id}", + "rel": "evidence_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/evidence/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/evidence", + "href": "{id}", + "rel": "evidence_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/evidence/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/evidence", + "href": "{id}", + "rel": "evidence_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/evidence/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/evidence", + "href": "{id}", + "rel": "evidence_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/evidence/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/evidence", + "href": "{id}", + "rel": "evidence_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/evidence/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/evidence", + "href": "{id}", + "rel": "evidence_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/evidence/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/evidence", + "href": "{id}", + "rel": "evidence_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/evidence/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/evidence", + "href": "{id}", + "rel": "evidence_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/evidence/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/evidence", + "href": "{id}", + "rel": "evidence_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/evidence/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/evidence", + "href": "{id}", + "rel": "evidence_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/evidence/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/evidence", + "href": "{id}", + "rel": "evidence_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/evidence/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/evidence", + "href": "{id}", + "rel": "evidence_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/evidence/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/evidence", + "href": "{id}", + "rel": "evidence_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/evidence/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/evidence", + "href": "{id}", + "rel": "evidence_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/evidence/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Practitioner", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_PractitionerRole", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Patient", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Organization", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ConditionParticipant/participant", + "href": "{id}", + "rel": "participant_actor_Practitioner", + "targetHints": { + "backref": [ + "condition_participant" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/participant/-/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ConditionParticipant/participant", + "href": "{id}", + "rel": "participant_actor_PractitionerRole", + "targetHints": { + "backref": [ + "condition_participant" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/participant/-/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ConditionParticipant/participant", + "href": "{id}", + "rel": "participant_actor_Patient", + "targetHints": { + "backref": [ + "condition_participant" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/participant/-/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ConditionParticipant/participant", + "href": "{id}", + "rel": "participant_actor_Organization", + "targetHints": { + "backref": [ + "condition_participant" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/participant/-/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ConditionStage/stage", + "href": "{id}", + "rel": "stage_assessment_DiagnosticReport", + "targetHints": { + "backref": [ + "assessment_condition_stage" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/stage/-/assessment/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ConditionStage/stage", + "href": "{id}", + "rel": "stage_assessment_Observation", + "targetHints": { + "backref": [ + "assessment_condition_stage" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/stage/-/assessment/-/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_abatementDateTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'abatementDateTime'." + }, + "_abatementString": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'abatementString'." + }, + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "_onsetDateTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'onsetDateTime'." + }, + "_onsetString": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'onsetString'." + }, + "_recordedDate": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'recordedDate'." + }, + "abatementAge": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Age", + "description": "The date or estimated date that the condition resolved or went into remission. This is called \"abatement\" because of the many overloaded connotations associated with \"remission\" or \"resolution\" - Some conditions, such as chronic conditions, are never really resolved, but they can abate.", + "element_property": true, + "one_of_many": "abatement", + "one_of_many_required": false, + "title": "When in resolution/remission" + }, + "abatementDateTime": { + "description": "The date or estimated date that the condition resolved or went into remission. This is called \"abatement\" because of the many overloaded connotations associated with \"remission\" or \"resolution\" - Some conditions, such as chronic conditions, are never really resolved, but they can abate.", + "element_property": true, + "format": "date-time", + "one_of_many": "abatement", + "one_of_many_required": false, + "title": "When in resolution/remission", + "type": "string" + }, + "abatementPeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "The date or estimated date that the condition resolved or went into remission. This is called \"abatement\" because of the many overloaded connotations associated with \"remission\" or \"resolution\" - Some conditions, such as chronic conditions, are never really resolved, but they can abate.", + "element_property": true, + "one_of_many": "abatement", + "one_of_many_required": false, + "title": "When in resolution/remission" + }, + "abatementRange": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Range", + "description": "The date or estimated date that the condition resolved or went into remission. This is called \"abatement\" because of the many overloaded connotations associated with \"remission\" or \"resolution\" - Some conditions, such as chronic conditions, are never really resolved, but they can abate.", + "element_property": true, + "one_of_many": "abatement", + "one_of_many_required": false, + "title": "When in resolution/remission" + }, + "abatementString": { + "description": "The date or estimated date that the condition resolved or went into remission. This is called \"abatement\" because of the many overloaded connotations associated with \"remission\" or \"resolution\" - Some conditions, such as chronic conditions, are never really resolved, but they can abate.", + "element_property": true, + "one_of_many": "abatement", + "one_of_many_required": false, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "When in resolution/remission", + "type": "string" + }, + "bodySite": { + "binding_description": "SNOMED CT Body site concepts", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/body-site", + "binding_version": null, + "description": "The anatomical location where this condition manifests itself.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Anatomical location, if relevant", + "type": "array" + }, + "category": { + "binding_description": "A category assigned to the condition.", + "binding_strength": "preferred", + "binding_uri": "http://hl7.org/fhir/ValueSet/condition-category", + "binding_version": null, + "description": "A category assigned to the condition.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "problem-list-item | encounter-diagnosis", + "type": "array" + }, + "clinicalStatus": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The clinical status of the condition or diagnosis.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/condition-clinical", + "binding_version": "5.0.0", + "description": "The clinical status of the condition.", + "element_property": true, + "title": "active | recurrence | relapse | inactive | remission | resolved | unknown" + }, + "code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Identification of the condition or diagnosis.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/condition-code", + "binding_version": null, + "element_property": true, + "title": "Identification of the condition, problem or diagnosis" + }, + "contained": { + "description": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, nor can they have their own independent transaction scope. This is allowed to be a Parameters resource if and only if it is referenced by a resource that provides context/meaning.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + "title": "Contained, inline Resources", + "type": "array" + }, + "encounter": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "condition", + "description": "The Encounter during which this Condition was created or to which the creation of this record is tightly associated.", + "element_property": true, + "enum_reference_types": [ + "Encounter" + ], + "title": "The Encounter during which this Condition was created" + }, + "evidence": { + "backref": "evidence_condition", + "binding_description": null, + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/clinical-findings", + "binding_version": null, + "description": "Supporting evidence / manifestations that are the basis of the Condition's verification status, such as evidence that confirmed or refuted the condition.", + "element_property": true, + "enum_reference_types": [ + "Resource" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference" + }, + "title": "Supporting evidence for the verification status", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "identifier": { + "description": "Business identifiers assigned to this condition by the performer or other systems which remain constant as the resource is updated and propagates from server to server.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "External Ids for this condition", + "type": "array" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored", + "type": "array" + }, + "note": { + "description": "Additional information about the Condition. This is a general notes/comments entry for description of the Condition, its diagnosis and prognosis.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Annotation" + }, + "title": "Additional information about the Condition", + "type": "array" + }, + "onsetAge": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Age", + "description": "Estimated or actual date or date-time the condition began, in the opinion of the clinician.", + "element_property": true, + "one_of_many": "onset", + "one_of_many_required": false, + "title": "Estimated or actual date, date-time, or age" + }, + "onsetDateTime": { + "description": "Estimated or actual date or date-time the condition began, in the opinion of the clinician.", + "element_property": true, + "format": "date-time", + "one_of_many": "onset", + "one_of_many_required": false, + "title": "Estimated or actual date, date-time, or age", + "type": "string" + }, + "onsetPeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "Estimated or actual date or date-time the condition began, in the opinion of the clinician.", + "element_property": true, + "one_of_many": "onset", + "one_of_many_required": false, + "title": "Estimated or actual date, date-time, or age" + }, + "onsetRange": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Range", + "description": "Estimated or actual date or date-time the condition began, in the opinion of the clinician.", + "element_property": true, + "one_of_many": "onset", + "one_of_many_required": false, + "title": "Estimated or actual date, date-time, or age" + }, + "onsetString": { + "description": "Estimated or actual date or date-time the condition began, in the opinion of the clinician.", + "element_property": true, + "one_of_many": "onset", + "one_of_many_required": false, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Estimated or actual date, date-time, or age", + "type": "string" + }, + "participant": { + "description": "Indicates who or what participated in the activities related to the condition and how they were involved.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ConditionParticipant" + }, + "title": "Who or what participated in the activities related to the condition and how they were involved", + "type": "array" + }, + "recordedDate": { + "description": "The recordedDate represents when this particular Condition record was created in the system, which is often a system-generated date.", + "element_property": true, + "format": "date-time", + "title": "Date condition was first recorded", + "type": "string" + }, + "resourceType": { + "const": "Condition", + "default": "Condition", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "severity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "A subjective assessment of the severity of the condition as evaluated by the clinician.", + "binding_strength": "preferred", + "binding_uri": "http://hl7.org/fhir/ValueSet/condition-severity", + "binding_version": null, + "description": "A subjective assessment of the severity of the condition as evaluated by the clinician.", + "element_property": true, + "title": "Subjective severity of condition" + }, + "stage": { + "description": "A simple summary of the stage such as \"Stage 3\" or \"Early Onset\". The determination of the stage is disease-specific, such as cancer, retinopathy of prematurity, kidney diseases, Alzheimer's, or Parkinson disease.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ConditionStage" + }, + "title": "Stage/grade, usually assessed formally", + "type": "array" + }, + "subject": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "condition", + "description": "Indicates the patient or group who the condition record is associated with.", + "element_property": true, + "enum_reference_types": [ + "Patient", + "Group" + ], + "title": "Who has the condition?" + }, + "text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative", + "description": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "element_property": true, + "title": "Text summary of the resource, for human interpretation" + }, + "verificationStatus": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The verification status to support or decline the clinical status of the condition or diagnosis.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/condition-ver-status", + "binding_version": "5.0.0", + "description": "The verification status to support the clinical status of the condition. The verification status pertains to the condition, itself, not to any specific condition attribute.", + "element_property": true, + "title": "unconfirmed | provisional | differential | confirmed | refuted | entered-in-error" + } + }, + "required": [ + "clinicalStatus", + "subject" + ], + "title": "Condition", + "type": "object" + }, + "AvailabilityAvailableTime": { + "$id": "http://graph-fhir.io/schema/0.0.2/AvailabilityAvailableTime", + "additionalProperties": false, + "description": "Times the {item} is available. [See https://hl7.org/fhir/R5/AvailabilityAvailableTime.html]", + "links": [], + "properties": { + "_allDay": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'allDay'." + }, + "_availableEndTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'availableEndTime'." + }, + "_availableStartTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'availableStartTime'." + }, + "_daysOfWeek": { + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension" + }, + "title": "Extension field for 'daysOfWeek'.", + "type": "array" + }, + "allDay": { + "element_property": true, + "title": "Always available? i.e. 24 hour service", + "type": "boolean" + }, + "availableEndTime": { + "element_property": true, + "format": "time", + "title": "Closing time of day (ignored if allDay = true)", + "type": "string" + }, + "availableStartTime": { + "element_property": true, + "format": "time", + "title": "Opening time of day (ignored if allDay = true)", + "type": "string" + }, + "daysOfWeek": { + "binding_description": "The purpose for which an extended contact detail should be used.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/days-of-week", + "binding_version": "5.0.0", + "element_property": true, + "enum_values": [ + "mon", + "tue", + "wed", + "thu", + "fri", + "sat", + "sun" + ], + "items": { + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "type": "string" + }, + "title": "mon | tue | wed | thu | fri | sat | sun", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "resourceType": { + "const": "AvailabilityAvailableTime", + "default": "AvailabilityAvailableTime", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "title": "AvailabilityAvailableTime", + "type": "object" + }, + "ResearchStudyRecruitment": { + "$id": "http://graph-fhir.io/schema/0.0.2/ResearchStudyRecruitment", + "additionalProperties": false, + "description": "Target or actual group of participants enrolled in study. [See https://hl7.org/fhir/R5/ResearchStudyRecruitment.html]", + "links": [ + { + "href": "{id}", + "rel": "actualGroup", + "targetHints": { + "backref": [ + "actualGroup_research_study_recruitment" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/actualGroup/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "eligibility_Group", + "targetHints": { + "backref": [ + "eligibility_research_study_recruitment" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/eligibility/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_actualNumber": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'actualNumber'." + }, + "_targetNumber": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'targetNumber'." + }, + "actualGroup": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "actualGroup_research_study_recruitment", + "element_property": true, + "enum_reference_types": [ + "Group" + ], + "title": "Group of participants who were enrolled in study" + }, + "actualNumber": { + "element_property": true, + "minimum": 0, + "title": "Actual total number of participants enrolled in study", + "type": "integer" + }, + "eligibility": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "eligibility_research_study_recruitment", + "element_property": true, + "enum_reference_types": [ + "Group", + "EvidenceVariable" + ], + "title": "Inclusion and exclusion criteria" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "ResearchStudyRecruitment", + "default": "ResearchStudyRecruitment", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "targetNumber": { + "element_property": true, + "minimum": 0, + "title": "Estimated total number of participants to be enrolled", + "type": "integer" + } + }, + "title": "ResearchStudyRecruitment", + "type": "object" + }, + "SubstanceDefinitionName": { + "$id": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionName", + "additionalProperties": false, + "description": "Names applicable to this substance. [See https://hl7.org/fhir/R5/SubstanceDefinitionName.html]", + "links": [ + { + "href": "{id}", + "rel": "source", + "targetHints": { + "backref": [ + "source_substance_definition_name" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/source/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From SubstanceDefinitionName/synonym", + "href": "{id}", + "rel": "synonym_source", + "targetHints": { + "backref": [ + "source_substance_definition_name" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/synonym/-/source/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From SubstanceDefinitionName/translation", + "href": "{id}", + "rel": "translation_source", + "targetHints": { + "backref": [ + "source_substance_definition_name" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/translation/-/source/-/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_name": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'name'." + }, + "_preferred": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'preferred'." + }, + "domain": { + "binding_description": "The use context of a substance name for example if there is a different name when used as a drug active ingredient as opposed to a food colour additive.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-name-domain", + "binding_version": null, + "description": "The use context of this name for example if there is a different name a drug active ingredient as opposed to a food colour additive.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "The use context of this name e.g. as an active ingredient or as a food colour additive", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "jurisdiction": { + "binding_description": "Jurisdiction codes", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/jurisdiction", + "binding_version": null, + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "The jurisdiction where this name applies", + "type": "array" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Human language that the name is written in", + "type": "array" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "name": { + "element_property": true, + "element_required": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "The actual name", + "type": "string" + }, + "official": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionNameOfficial" + }, + "title": "Details of the official nature of this name", + "type": "array" + }, + "preferred": { + "element_property": true, + "title": "If this is the preferred name for this substance", + "type": "boolean" + }, + "resourceType": { + "const": "SubstanceDefinitionName", + "default": "SubstanceDefinitionName", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "source": { + "backref": "source_substance_definition_name", + "element_property": true, + "enum_reference_types": [ + "DocumentReference" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Supporting literature", + "type": "array" + }, + "status": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The lifecycle status of an artifact.", + "binding_strength": "preferred", + "binding_uri": "http://hl7.org/fhir/ValueSet/publication-status", + "binding_version": null, + "description": "The status of the name, for example 'current', 'proposed'.", + "element_property": true, + "title": "The status of the name e.g. 'current', 'proposed'" + }, + "synonym": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionName" + }, + "title": "A synonym of this particular name, by which the substance is also known", + "type": "array" + }, + "translation": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionName" + }, + "title": "A translation for this name into another human language", + "type": "array" + }, + "type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The type of a name given to a substance.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-name-type", + "binding_version": null, + "description": "Name type, for example 'systematic', 'scientific, 'brand'.", + "element_property": true, + "title": "Name type e.g. 'systematic', 'scientific, 'brand'" + } + }, + "title": "SubstanceDefinitionName", + "type": "object" + }, + "SpecimenCollection": { + "$id": "http://graph-fhir.io/schema/0.0.2/SpecimenCollection", + "additionalProperties": false, + "description": "Collection details. Details concerning the specimen collection. [See https://hl7.org/fhir/R5/SpecimenCollection.html]", + "links": [ + { + "href": "{id}", + "rel": "collector_Practitioner", + "targetHints": { + "backref": [ + "specimen_collection" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/collector/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "collector_PractitionerRole", + "targetHints": { + "backref": [ + "specimen_collection" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/collector/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "collector_Patient", + "targetHints": { + "backref": [ + "specimen_collection" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/collector/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "procedure", + "targetHints": { + "backref": [ + "specimen_collection" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/procedure/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/bodySite", + "href": "{id}", + "rel": "bodySite_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/bodySite/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/device/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/device/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/device/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/device/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/device/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/device/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/device/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/device/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/device/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/device/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/device/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/device/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/device/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/device/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/device/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/device/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/device/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/device/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/device/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/device/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/device/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/device/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/device/reference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_collectedDateTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'collectedDateTime'." + }, + "bodySite": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference", + "backref": "specimen_collection", + "binding_description": "SNOMED CT Body site concepts", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/body-site", + "binding_version": null, + "description": "Anatomical location from which the specimen was collected (if subject is a patient). This is the target site. This element is not used for environmental specimens.", + "element_property": true, + "enum_reference_types": [ + "BodyStructure" + ], + "title": "Anatomical collection site" + }, + "collectedDateTime": { + "description": "Time when specimen was collected from subject - the physiologically relevant time.", + "element_property": true, + "format": "date-time", + "one_of_many": "collected", + "one_of_many_required": false, + "title": "Collection time", + "type": "string" + }, + "collectedPeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "Time when specimen was collected from subject - the physiologically relevant time.", + "element_property": true, + "one_of_many": "collected", + "one_of_many_required": false, + "title": "Collection time" + }, + "collector": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "specimen_collection", + "description": "Person who collected the specimen.", + "element_property": true, + "enum_reference_types": [ + "Practitioner", + "PractitionerRole", + "Patient", + "RelatedPerson" + ], + "title": "Who collected the specimen" + }, + "device": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference", + "backref": "specimen_collection", + "description": "A coded value specifying the technique that is used to perform the procedure.", + "element_property": true, + "enum_reference_types": [ + "Device" + ], + "title": "Device used to perform collection" + }, + "duration": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Duration", + "description": "The span of time over which the collection of a specimen occurred.", + "element_property": true, + "title": "How long it took to collect specimen" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fastingStatusCodeableConcept": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "description": "Abstinence or reduction from some or all food, drink, or both, for a period of time prior to sample collection.", + "element_property": true, + "one_of_many": "fastingStatus", + "one_of_many_required": false, + "title": "Whether or how long patient abstained from food and/or drink" + }, + "fastingStatusDuration": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Duration", + "description": "Abstinence or reduction from some or all food, drink, or both, for a period of time prior to sample collection.", + "element_property": true, + "one_of_many": "fastingStatus", + "one_of_many_required": false, + "title": "Whether or how long patient abstained from food and/or drink" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "method": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The technique that is used to perform the procedure.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/specimen-collection-method", + "binding_version": null, + "description": "A coded value specifying the technique that is used to perform the procedure.", + "element_property": true, + "title": "Technique used to perform collection" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "procedure": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "specimen_collection", + "description": "The procedure event during which the specimen was collected (e.g. the surgery leading to the collection of a pathology sample).", + "element_property": true, + "enum_reference_types": [ + "Procedure" + ], + "title": "The procedure that collects the specimen" + }, + "quantity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "The quantity of specimen collected; for instance the volume of a blood sample, or the physical measurement of an anatomic pathology sample.", + "element_property": true, + "title": "The quantity of specimen collected" + }, + "resourceType": { + "const": "SpecimenCollection", + "default": "SpecimenCollection", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "title": "SpecimenCollection", + "type": "object" + }, + "GroupMember": { + "$id": "http://graph-fhir.io/schema/0.0.2/GroupMember", + "additionalProperties": false, + "description": "Who or what is in group. Identifies the resource instances that are members of the group. [See https://hl7.org/fhir/R5/GroupMember.html]", + "links": [ + { + "href": "{id}", + "rel": "entity_Group", + "targetHints": { + "backref": [ + "group_member" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/entity/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "entity_Organization", + "targetHints": { + "backref": [ + "group_member" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/entity/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "entity_Patient", + "targetHints": { + "backref": [ + "group_member" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/entity/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "entity_Practitioner", + "targetHints": { + "backref": [ + "group_member" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/entity/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "entity_PractitionerRole", + "targetHints": { + "backref": [ + "group_member" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/entity/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "entity_Specimen", + "targetHints": { + "backref": [ + "group_member" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/entity/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_inactive": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'inactive'." + }, + "entity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "group_member", + "description": "A reference to the entity that is a member of the group. Must be consistent with Group.type. If the entity is another group, then the type must be the same.", + "element_property": true, + "enum_reference_types": [ + "CareTeam", + "Device", + "Group", + "HealthcareService", + "Location", + "Organization", + "Patient", + "Practitioner", + "PractitionerRole", + "RelatedPerson", + "Specimen" + ], + "title": "Reference to the group member" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "inactive": { + "description": "A flag to indicate that the member is no longer in the group, but previously may have been a member.", + "element_property": true, + "title": "If member is no longer in group", + "type": "boolean" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "period": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "The period that the member was in the group, if known.", + "element_property": true, + "title": "Period member belonged to the group" + }, + "resourceType": { + "const": "GroupMember", + "default": "GroupMember", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "required": [ + "entity" + ], + "title": "GroupMember", + "type": "object" + }, + "Attachment": { + "$id": "http://graph-fhir.io/schema/0.0.2/Attachment", + "additionalProperties": false, + "description": "Content in a format defined elsewhere. For referring to data content defined in other formats. [See https://hl7.org/fhir/R5/Attachment.html]", + "links": [], + "properties": { + "_contentType": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'contentType'." + }, + "_creation": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'creation'." + }, + "_data": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'data'." + }, + "_duration": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'duration'." + }, + "_frames": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'frames'." + }, + "_hash": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'hash'." + }, + "_height": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'height'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "_pages": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'pages'." + }, + "_size": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'size'." + }, + "_title": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'title'." + }, + "_url": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'url'." + }, + "_width": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'width'." + }, + "contentType": { + "binding_description": "BCP 13 (RFCs 2045, 2046, 2047, 4288, 4289 and 2049)", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/mimetypes", + "binding_version": "5.0.0", + "description": "Identifies the type of the data in the attachment and allows a method to be chosen to interpret or render the data. Includes mime type parameters such as charset where appropriate.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Mime type of the content, with charset etc.", + "type": "string" + }, + "creation": { + "description": "The date that the attachment was first created.", + "element_property": true, + "format": "date-time", + "title": "Date attachment was first created", + "type": "string" + }, + "data": { + "description": "The actual data of the attachment - a sequence of bytes, base64 encoded.", + "element_property": true, + "format": "binary", + "title": "Data inline, base64ed", + "type": "string" + }, + "duration": { + "description": "The duration of the recording in seconds - for audio and video.", + "element_property": true, + "title": "Length in seconds (audio / video)", + "type": "number" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "frames": { + "description": "The number of frames in a photo. This is used with a multi-page fax, or an imaging acquisition context that takes multiple slices in a single image, or an animated gif. If there is more than one frame, this SHALL have a value in order to alert interface software that a multi-frame capable rendering widget is required.", + "element_property": true, + "exclusiveMinimum": 0, + "title": "Number of frames if > 1 (photo)", + "type": "integer" + }, + "hash": { + "description": "The calculated hash of the data using SHA-1. Represented using base64.", + "element_property": true, + "format": "binary", + "title": "Hash of the data (sha-1, base64ed)", + "type": "string" + }, + "height": { + "element_property": true, + "exclusiveMinimum": 0, + "title": "Height of the image in pixels (photo/video)", + "type": "integer" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "language": { + "binding_description": "IETF language tag for a human language.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The human language of the content. The value can be any valid value according to BCP 47.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Human language of the content (BCP-47)", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "pages": { + "description": "The number of pages when printed.", + "element_property": true, + "exclusiveMinimum": 0, + "title": "Number of printed pages", + "type": "integer" + }, + "resourceType": { + "const": "Attachment", + "default": "Attachment", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "size": { + "description": "The number of bytes of data that make up this attachment (before base64 encoding, if that is done).", + "element_property": true, + "title": "Number of bytes of content (if url provided)", + "type": "integer" + }, + "title": { + "description": "A label or set of text to display in place of the data.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Label to display in place of the data", + "type": "string" + }, + "url": { + "description": "A location where the data can be accessed.", + "element_property": true, + "format": "uri", + "maxLength": 65536, + "minLength": 1, + "title": "Uri where the data can be found", + "type": "string" + }, + "width": { + "element_property": true, + "exclusiveMinimum": 0, + "title": "Width of the image in pixels (photo/video)", + "type": "integer" + } + }, + "title": "Attachment", + "type": "object" + }, + "ResearchStudyProgressStatus": { + "$id": "http://graph-fhir.io/schema/0.0.2/ResearchStudyProgressStatus", + "additionalProperties": false, + "description": "Status of study with time for that status. [See https://hl7.org/fhir/R5/ResearchStudyProgressStatus.html]", + "links": [], + "properties": { + "_actual": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'actual'." + }, + "actual": { + "description": "An indication of whether or not the date is a known date when the state changed or will change. A value of true indicates a known date. A value of false indicates an estimated date.", + "element_property": true, + "title": "Actual if true else anticipated", + "type": "boolean" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "period": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "element_property": true, + "title": "Date range" + }, + "resourceType": { + "const": "ResearchStudyProgressStatus", + "default": "ResearchStudyProgressStatus", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "state": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "defn.", + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/research-study-status", + "binding_version": null, + "element_property": true, + "title": "Label for status or state (e.g. recruitment status)" + } + }, + "required": [ + "state" + ], + "title": "ResearchStudyProgressStatus", + "type": "object" + }, + "MedicationIngredient": { + "$id": "http://graph-fhir.io/schema/0.0.2/MedicationIngredient", + "additionalProperties": false, + "description": "Active or inactive ingredient. Identifies a particular constituent of interest in the product. [See https://hl7.org/fhir/R5/MedicationIngredient.html]", + "links": [ + { + "$comment": "From CodeableReference/item", + "href": "{id}", + "rel": "item_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/item/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/item", + "href": "{id}", + "rel": "item_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/item/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/item", + "href": "{id}", + "rel": "item_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/item/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/item", + "href": "{id}", + "rel": "item_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/item/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/item", + "href": "{id}", + "rel": "item_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/item/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/item", + "href": "{id}", + "rel": "item_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/item/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/item", + "href": "{id}", + "rel": "item_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/item/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/item", + "href": "{id}", + "rel": "item_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/item/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/item", + "href": "{id}", + "rel": "item_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/item/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/item", + "href": "{id}", + "rel": "item_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/item/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/item", + "href": "{id}", + "rel": "item_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/item/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/item", + "href": "{id}", + "rel": "item_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/item/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/item", + "href": "{id}", + "rel": "item_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/item/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/item", + "href": "{id}", + "rel": "item_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/item/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/item", + "href": "{id}", + "rel": "item_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/item/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/item", + "href": "{id}", + "rel": "item_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/item/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/item", + "href": "{id}", + "rel": "item_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/item/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/item", + "href": "{id}", + "rel": "item_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/item/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/item", + "href": "{id}", + "rel": "item_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/item/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/item", + "href": "{id}", + "rel": "item_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/item/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/item", + "href": "{id}", + "rel": "item_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/item/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/item", + "href": "{id}", + "rel": "item_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/item/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/item", + "href": "{id}", + "rel": "item_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/item/reference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_isActive": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'isActive'." + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "isActive": { + "description": "Indication of whether this ingredient affects the therapeutic action of the drug.", + "element_property": true, + "title": "Active ingredient indicator", + "type": "boolean" + }, + "item": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference", + "backref": "medication_ingredient", + "binding_description": null, + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/medication-codes", + "binding_version": null, + "description": "The ingredient (substance or medication) that the ingredient.strength relates to. This is represented as a concept from a code system or described in another resource (Substance or Medication).", + "element_property": true, + "enum_reference_types": [ + "Substance", + "Medication" + ], + "title": "The ingredient (substance or medication) that the ingredient.strength relates to" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "MedicationIngredient", + "default": "MedicationIngredient", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "strengthCodeableConcept": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "description": "Specifies how many (or how much) of the items there are in this Medication. For example, 250 mg per tablet. This is expressed as a ratio where the numerator is 250mg and the denominator is 1 tablet but can also be expressed a quantity when the denominator is assumed to be 1 tablet.", + "element_property": true, + "one_of_many": "strength", + "one_of_many_required": false, + "title": "Quantity of ingredient present" + }, + "strengthQuantity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "Specifies how many (or how much) of the items there are in this Medication. For example, 250 mg per tablet. This is expressed as a ratio where the numerator is 250mg and the denominator is 1 tablet but can also be expressed a quantity when the denominator is assumed to be 1 tablet.", + "element_property": true, + "one_of_many": "strength", + "one_of_many_required": false, + "title": "Quantity of ingredient present" + }, + "strengthRatio": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Ratio", + "description": "Specifies how many (or how much) of the items there are in this Medication. For example, 250 mg per tablet. This is expressed as a ratio where the numerator is 250mg and the denominator is 1 tablet but can also be expressed a quantity when the denominator is assumed to be 1 tablet.", + "element_property": true, + "one_of_many": "strength", + "one_of_many_required": false, + "title": "Quantity of ingredient present" + } + }, + "required": [ + "item" + ], + "title": "MedicationIngredient", + "type": "object" + }, + "SubstanceDefinitionNameOfficial": { + "$id": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionNameOfficial", + "additionalProperties": false, + "description": "Details of the official nature of this name. [See https://hl7.org/fhir/R5/SubstanceDefinitionNameOfficial.html]", + "links": [], + "properties": { + "_date": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'date'." + }, + "authority": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "An authority that officates substance names.", + "binding_strength": "preferred", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-name-authority", + "binding_version": null, + "element_property": true, + "title": "Which authority uses this official name" + }, + "date": { + "description": "Date of the official name change.", + "element_property": true, + "format": "date-time", + "title": "Date of official name change", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "SubstanceDefinitionNameOfficial", + "default": "SubstanceDefinitionNameOfficial", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "status": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The lifecycle status of an artifact.", + "binding_strength": "preferred", + "binding_uri": "http://hl7.org/fhir/ValueSet/publication-status", + "binding_version": null, + "description": "The status of the official name, for example 'draft', 'active', 'retired'.", + "element_property": true, + "title": "The status of the official name, for example 'draft', 'active'" + } + }, + "title": "SubstanceDefinitionNameOfficial", + "type": "object" + }, + "Money": { + "$id": "http://graph-fhir.io/schema/0.0.2/Money", + "additionalProperties": false, + "description": "An amount of economic utility in some recognized currency. [See https://hl7.org/fhir/R5/Money.html]", + "links": [], + "properties": { + "_currency": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'currency'." + }, + "_value": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'value'." + }, + "currency": { + "binding_description": "A code indicating the currency, taken from ISO 4217.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/currencies", + "binding_version": "5.0.0", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "ISO 4217 Currency Code", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "resourceType": { + "const": "Money", + "default": "Money", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "value": { + "element_property": true, + "title": "Numerical value (with implicit precision)", + "type": "number" + } + }, + "title": "Money", + "type": "object" + }, + "MedicationRequestSubstitution": { + "$id": "http://graph-fhir.io/schema/0.0.2/MedicationRequestSubstitution", + "additionalProperties": false, + "description": "Any restrictions on medication substitution. Indicates whether or not substitution can or should be part of the dispense. In some cases, substitution must happen, in other cases substitution must not happen. This block explains the prescriber's intent. If nothing is specified substitution may be done. [See https://hl7.org/fhir/R5/MedicationRequestSubstitution.html]", + "links": [], + "properties": { + "_allowedBoolean": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'allowedBoolean'." + }, + "allowedBoolean": { + "description": "True if the prescriber allows a different drug to be dispensed from what was prescribed.", + "element_property": true, + "one_of_many": "allowed", + "one_of_many_required": true, + "title": "Whether substitution is allowed or not", + "type": "boolean" + }, + "allowedCodeableConcept": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "description": "True if the prescriber allows a different drug to be dispensed from what was prescribed.", + "element_property": true, + "one_of_many": "allowed", + "one_of_many_required": true, + "title": "Whether substitution is allowed or not" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "reason": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "SubstanceAdminSubstitutionReason", + "binding_strength": "example", + "binding_uri": "http://terminology.hl7.org/ValueSet/v3-SubstanceAdminSubstitutionReason", + "binding_version": null, + "description": "Indicates the reason for the substitution, or why substitution must or must not be performed.", + "element_property": true, + "title": "Why should (not) substitution be made" + }, + "resourceType": { + "const": "MedicationRequestSubstitution", + "default": "MedicationRequestSubstitution", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "title": "MedicationRequestSubstitution", + "type": "object" + }, + "FamilyMemberHistoryProcedure": { + "$id": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistoryProcedure", + "additionalProperties": false, + "description": "Procedures that the related person had. The significant Procedures (or procedure) that the family member had. This is a repeating section to allow a system to represent more than one procedure per resource, though there is nothing stopping multiple resources - one per procedure. [See https://hl7.org/fhir/R5/FamilyMemberHistoryProcedure.html]", + "links": [ + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Practitioner", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_PractitionerRole", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Patient", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Organization", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_contributedToDeath": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'contributedToDeath'." + }, + "_performedDateTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'performedDateTime'." + }, + "_performedString": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'performedString'." + }, + "code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "A code to identify a specific procedure.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/procedure-code", + "binding_version": null, + "description": "The actual procedure specified. Could be a coded procedure or a less specific string depending on how much is known about the procedure and the capabilities of the creating system.", + "element_property": true, + "title": "Procedures performed on the related person" + }, + "contributedToDeath": { + "description": "This procedure contributed to the cause of death of the related person. If contributedToDeath is not populated, then it is unknown.", + "element_property": true, + "title": "Whether the procedure contributed to the cause of death", + "type": "boolean" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "note": { + "description": "An area where general notes can be placed about this specific procedure.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Annotation" + }, + "title": "Extra information about the procedure", + "type": "array" + }, + "outcome": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The result of the procedure; e.g. death, permanent disability, temporary disability, etc.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/clinical-findings", + "binding_version": null, + "description": "Indicates what happened following the procedure. If the procedure resulted in death, deceased date is captured on the relation.", + "element_property": true, + "title": "What happened following the procedure" + }, + "performedAge": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Age", + "description": "Estimated or actual date, date-time, period, or age when the procedure was performed. Allows a period to support complex procedures that span more than one date, and also allows for the length of the procedure to be captured.", + "element_property": true, + "one_of_many": "performed", + "one_of_many_required": false, + "title": "When the procedure was performed" + }, + "performedDateTime": { + "description": "Estimated or actual date, date-time, period, or age when the procedure was performed. Allows a period to support complex procedures that span more than one date, and also allows for the length of the procedure to be captured.", + "element_property": true, + "format": "date-time", + "one_of_many": "performed", + "one_of_many_required": false, + "title": "When the procedure was performed", + "type": "string" + }, + "performedPeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "Estimated or actual date, date-time, period, or age when the procedure was performed. Allows a period to support complex procedures that span more than one date, and also allows for the length of the procedure to be captured.", + "element_property": true, + "one_of_many": "performed", + "one_of_many_required": false, + "title": "When the procedure was performed" + }, + "performedRange": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Range", + "description": "Estimated or actual date, date-time, period, or age when the procedure was performed. Allows a period to support complex procedures that span more than one date, and also allows for the length of the procedure to be captured.", + "element_property": true, + "one_of_many": "performed", + "one_of_many_required": false, + "title": "When the procedure was performed" + }, + "performedString": { + "description": "Estimated or actual date, date-time, period, or age when the procedure was performed. Allows a period to support complex procedures that span more than one date, and also allows for the length of the procedure to be captured.", + "element_property": true, + "one_of_many": "performed", + "one_of_many_required": false, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "When the procedure was performed", + "type": "string" + }, + "resourceType": { + "const": "FamilyMemberHistoryProcedure", + "default": "FamilyMemberHistoryProcedure", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "required": [ + "code" + ], + "title": "FamilyMemberHistoryProcedure", + "type": "object" + }, + "TaskRestriction": { + "$id": "http://graph-fhir.io/schema/0.0.2/TaskRestriction", + "additionalProperties": false, + "description": "Constraints on fulfillment tasks. If the Task.focus is a request resource and the task is seeking fulfillment (i.e. is asking for the request to be actioned), this element identifies any limitations on what parts of the referenced request should be actioned. [See https://hl7.org/fhir/R5/TaskRestriction.html]", + "links": [ + { + "href": "{id}", + "rel": "recipient_Patient", + "targetHints": { + "backref": [ + "recipient_task_restriction" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/recipient/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "recipient_Practitioner", + "targetHints": { + "backref": [ + "recipient_task_restriction" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/recipient/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "recipient_PractitionerRole", + "targetHints": { + "backref": [ + "recipient_task_restriction" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/recipient/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "recipient_Group", + "targetHints": { + "backref": [ + "recipient_task_restriction" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/recipient/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "recipient_Organization", + "targetHints": { + "backref": [ + "recipient_task_restriction" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/recipient/-/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_repetitions": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'repetitions'." + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "period": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "The time-period for which fulfillment is sought. This must fall within the overall time period authorized in the referenced request. E.g. ServiceRequest.occurance[x].", + "element_property": true, + "title": "When fulfillment is sought" + }, + "recipient": { + "backref": "recipient_task_restriction", + "description": "For requests that are targeted to more than one potential recipient/target, to identify who is fulfillment is sought for.", + "element_property": true, + "enum_reference_types": [ + "Patient", + "Practitioner", + "PractitionerRole", + "RelatedPerson", + "Group", + "Organization" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "For whom is fulfillment sought?", + "type": "array" + }, + "repetitions": { + "description": "Indicates the number of times the requested action should occur.", + "element_property": true, + "exclusiveMinimum": 0, + "title": "How many times to repeat", + "type": "integer" + }, + "resourceType": { + "const": "TaskRestriction", + "default": "TaskRestriction", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "title": "TaskRestriction", + "type": "object" + }, + "RatioRange": { + "$id": "http://graph-fhir.io/schema/0.0.2/RatioRange", + "additionalProperties": false, + "description": "Range of ratio values. A range of ratios expressed as a low and high numerator and a denominator. [See https://hl7.org/fhir/R5/RatioRange.html]", + "links": [], + "properties": { + "denominator": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "The value of the denominator.", + "element_property": true, + "title": "Denominator value" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "highNumerator": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "The value of the high limit numerator.", + "element_property": true, + "title": "High Numerator limit" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "lowNumerator": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "The value of the low limit numerator.", + "element_property": true, + "title": "Low Numerator limit" + }, + "resourceType": { + "const": "RatioRange", + "default": "RatioRange", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "title": "RatioRange", + "type": "object" + }, + "MedicationStatementAdherence": { + "$id": "http://graph-fhir.io/schema/0.0.2/MedicationStatementAdherence", + "additionalProperties": false, + "description": "Indicates whether the medication is or is not being consumed or administered. [See https://hl7.org/fhir/R5/MedicationStatementAdherence.html]", + "links": [], + "properties": { + "code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": null, + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/medication-statement-adherence", + "binding_version": null, + "description": "Type of the adherence for the medication.", + "element_property": true, + "title": "Type of adherence" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "reason": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": null, + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/reason-medication-status-codes", + "binding_version": null, + "description": "Captures the reason for the current use or adherence of a medication.", + "element_property": true, + "title": "Details of the reason for the current use of the medication" + }, + "resourceType": { + "const": "MedicationStatementAdherence", + "default": "MedicationStatementAdherence", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "required": [ + "code" + ], + "title": "MedicationStatementAdherence", + "type": "object" + }, + "FamilyMemberHistoryCondition": { + "$id": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistoryCondition", + "additionalProperties": false, + "description": "Condition that the related person had. The significant Conditions (or condition) that the family member had. This is a repeating section to allow a system to represent more than one condition per resource, though there is nothing stopping multiple resources - one per condition. [See https://hl7.org/fhir/R5/FamilyMemberHistoryCondition.html]", + "links": [ + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Practitioner", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_PractitionerRole", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Patient", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Organization", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_contributedToDeath": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'contributedToDeath'." + }, + "_onsetString": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'onsetString'." + }, + "code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Identification of the Condition or diagnosis.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/condition-code", + "binding_version": null, + "description": "The actual condition specified. Could be a coded condition (like MI or Diabetes) or a less specific string like 'cancer' depending on how much is known about the condition and the capabilities of the creating system.", + "element_property": true, + "title": "Condition suffered by relation" + }, + "contributedToDeath": { + "description": "This condition contributed to the cause of death of the related person. If contributedToDeath is not populated, then it is unknown.", + "element_property": true, + "title": "Whether the condition contributed to the cause of death", + "type": "boolean" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "note": { + "description": "An area where general notes can be placed about this specific condition.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Annotation" + }, + "title": "Extra information about condition", + "type": "array" + }, + "onsetAge": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Age", + "description": "Either the age of onset, range of approximate age or descriptive string can be recorded. For conditions with multiple occurrences, this describes the first known occurrence.", + "element_property": true, + "one_of_many": "onset", + "one_of_many_required": false, + "title": "When condition first manifested" + }, + "onsetPeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "Either the age of onset, range of approximate age or descriptive string can be recorded. For conditions with multiple occurrences, this describes the first known occurrence.", + "element_property": true, + "one_of_many": "onset", + "one_of_many_required": false, + "title": "When condition first manifested" + }, + "onsetRange": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Range", + "description": "Either the age of onset, range of approximate age or descriptive string can be recorded. For conditions with multiple occurrences, this describes the first known occurrence.", + "element_property": true, + "one_of_many": "onset", + "one_of_many_required": false, + "title": "When condition first manifested" + }, + "onsetString": { + "description": "Either the age of onset, range of approximate age or descriptive string can be recorded. For conditions with multiple occurrences, this describes the first known occurrence.", + "element_property": true, + "one_of_many": "onset", + "one_of_many_required": false, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "When condition first manifested", + "type": "string" + }, + "outcome": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The result of the condition for the patient; e.g. death, permanent disability, temporary disability, etc.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/condition-outcome", + "binding_version": null, + "description": "Indicates what happened following the condition. If the condition resulted in death, deceased date is captured on the relation.", + "element_property": true, + "title": "deceased | permanent disability | etc" + }, + "resourceType": { + "const": "FamilyMemberHistoryCondition", + "default": "FamilyMemberHistoryCondition", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "required": [ + "code" + ], + "title": "FamilyMemberHistoryCondition", + "type": "object" + }, + "ImagingStudySeriesInstance": { + "$id": "http://graph-fhir.io/schema/0.0.2/ImagingStudySeriesInstance", + "additionalProperties": false, + "description": "A single SOP instance from the series. A single SOP instance within the series, e.g. an image, or presentation state. [See https://hl7.org/fhir/R5/ImagingStudySeriesInstance.html]", + "links": [], + "properties": { + "_number": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'number'." + }, + "_title": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'title'." + }, + "_uid": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'uid'." + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "number": { + "description": "The number of instance in the series.", + "element_property": true, + "minimum": 0, + "title": "The number of this instance in the series", + "type": "integer" + }, + "resourceType": { + "const": "ImagingStudySeriesInstance", + "default": "ImagingStudySeriesInstance", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "sopClass": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Coding", + "binding_description": "The sopClass for the instance.", + "binding_strength": "extensible", + "binding_uri": "http://dicom.nema.org/medical/dicom/current/output/chtml/part04/sect_B.5.html#table_B.5-1", + "binding_version": null, + "description": "DICOM instance type.", + "element_property": true, + "title": "DICOM class type" + }, + "title": { + "description": "The description of the instance.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Description of instance", + "type": "string" + }, + "uid": { + "description": "The DICOM SOP Instance UID for this image or other DICOM content.", + "element_property": true, + "element_required": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "DICOM SOP Instance UID", + "type": "string" + } + }, + "required": [ + "sopClass" + ], + "title": "ImagingStudySeriesInstance", + "type": "object" + }, + "Resource": { + "$id": "http://graph-fhir.io/schema/0.0.2/Resource", + "additionalProperties": false, + "description": "Base Resource. This is the base resource type for everything. [See https://hl7.org/fhir/R5/Resource.html]", + "links": [], + "properties": { + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "resourceType": { + "const": "Resource", + "default": "Resource", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "title": "Resource", + "type": "object" + }, + "PractitionerRole": { + "$id": "http://graph-fhir.io/schema/0.0.2/PractitionerRole", + "additionalProperties": false, + "description": "Roles/organizations the practitioner is associated with. A specific set of Roles/Locations/specialties/services that a practitioner may perform at an organization for a period of time. [See https://hl7.org/fhir/R5/PractitionerRole.html]", + "links": [ + { + "href": "{id}", + "rel": "organization", + "targetHints": { + "backref": [ + "practitioner_role" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/organization/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "practitioner", + "targetHints": { + "backref": [ + "practitioner_role" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/practitioner/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ExtendedContactDetail/contact", + "href": "{id}", + "rel": "contact_organization", + "targetHints": { + "backref": [ + "extended_contact_detail" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/contact/-/organization/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_active": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'active'." + }, + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "active": { + "description": " Whether this practitioner role record is in active use. Some systems may use this property to mark non-active practitioners, such as those that are not currently employed.", + "element_property": true, + "title": "Whether this practitioner role record is in active use", + "type": "boolean" + }, + "availability": { + "description": "A collection of times the practitioner is available or performing this role at the location and/or healthcareservice.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Availability" + }, + "title": "Times the Practitioner is available at this location and/or healthcare service (including exceptions)", + "type": "array" + }, + "characteristic": { + "binding_description": "A custom attribute that could be provided at a service (e.g. Wheelchair accessibility).", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/service-mode", + "binding_version": null, + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Collection of characteristics (attributes)", + "type": "array" + }, + "code": { + "binding_description": "The role a person plays representing an organization.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/practitioner-role", + "binding_version": null, + "description": "Roles which this practitioner is authorized to perform for the organization.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Roles which this practitioner may perform", + "type": "array" + }, + "communication": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "A language the practitioner can use in patient communication. The practitioner may know several languages (listed in practitioner.communication), however these are the languages that could be advertised in a directory for a patient to search.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "A language the practitioner (in this role) can use in patient communication", + "type": "array" + }, + "contact": { + "description": "The contact details of communication devices available relevant to the specific PractitionerRole. This can include addresses, phone numbers, fax numbers, mobile numbers, email addresses and web sites.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ExtendedContactDetail" + }, + "title": "Official contact details relating to this PractitionerRole", + "type": "array" + }, + "contained": { + "description": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, nor can they have their own independent transaction scope. This is allowed to be a Parameters resource if and only if it is referenced by a resource that provides context/meaning.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + "title": "Contained, inline Resources", + "type": "array" + }, + "endpoint": { + "backref": "endpoint_practitioner_role", + "description": " Technical endpoints providing access to services operated for the practitioner with this role. Commonly used for locating scheduling services, or identifying where to send referrals electronically.", + "element_property": true, + "enum_reference_types": [ + "Endpoint" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Endpoints for interacting with the practitioner in this role", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "healthcareService": { + "backref": "healthcareService_practitioner_role", + "description": "The list of healthcare services that this worker provides for this role's Organization/Location(s).", + "element_property": true, + "enum_reference_types": [ + "HealthcareService" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Healthcare services provided for this role's Organization/Location(s)", + "type": "array" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "identifier": { + "description": "Business Identifiers that are specific to a role/location.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "Identifiers for a role/location", + "type": "array" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "location": { + "backref": "location_practitioner_role", + "description": "The location(s) at which this practitioner provides care.", + "element_property": true, + "enum_reference_types": [ + "Location" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Location(s) where the practitioner provides care", + "type": "array" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored", + "type": "array" + }, + "organization": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "practitioner_role", + "description": "The organization where the Practitioner performs the roles associated.", + "element_property": true, + "enum_reference_types": [ + "Organization" + ], + "title": "Organization where the roles are available" + }, + "period": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "The period during which the person is authorized to act as a practitioner in these role(s) for the organization.", + "element_property": true, + "title": "The period during which the practitioner is authorized to perform in these role(s)" + }, + "practitioner": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "practitioner_role", + "description": "Practitioner that is able to provide the defined services for the organization.", + "element_property": true, + "enum_reference_types": [ + "Practitioner" + ], + "title": "Practitioner that provides services for the organization" + }, + "resourceType": { + "const": "PractitionerRole", + "default": "PractitionerRole", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "specialty": { + "binding_description": "Specific specialty associated with the agency.", + "binding_strength": "preferred", + "binding_uri": "http://hl7.org/fhir/ValueSet/c80-practice-codes", + "binding_version": null, + "description": "The specialty of a practitioner that describes the functional role they are practicing at a given organization or location.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Specific specialty of the practitioner", + "type": "array" + }, + "text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative", + "description": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "element_property": true, + "title": "Text summary of the resource, for human interpretation" + } + }, + "title": "PractitionerRole", + "type": "object" + }, + "DosageDoseAndRate": { + "$id": "http://graph-fhir.io/schema/0.0.2/DosageDoseAndRate", + "additionalProperties": false, + "description": "Amount of medication administered, to be administered or typical amount to be administered. Depending on the resource,this is the amount of medication administered, to be administered or typical amount to be administered. [See https://hl7.org/fhir/R5/DosageDoseAndRate.html]", + "links": [], + "properties": { + "doseQuantity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "element_property": true, + "one_of_many": "dose", + "one_of_many_required": false, + "title": "Amount of medication per dose" + }, + "doseRange": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Range", + "element_property": true, + "one_of_many": "dose", + "one_of_many_required": false, + "title": "Amount of medication per dose" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "rateQuantity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "element_property": true, + "one_of_many": "rate", + "one_of_many_required": false, + "title": "Amount of medication per unit of time" + }, + "rateRange": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Range", + "element_property": true, + "one_of_many": "rate", + "one_of_many_required": false, + "title": "Amount of medication per unit of time" + }, + "rateRatio": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Ratio", + "element_property": true, + "one_of_many": "rate", + "one_of_many_required": false, + "title": "Amount of medication per unit of time" + }, + "resourceType": { + "const": "DosageDoseAndRate", + "default": "DosageDoseAndRate", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The kind of dose or rate specified.", + "binding_strength": "example", + "binding_uri": "http://terminology.hl7.org/ValueSet/dose-rate-type", + "binding_version": null, + "description": "The kind of dose or rate specified, for example, ordered or calculated.", + "element_property": true, + "title": "The kind of dose or rate specified" + } + }, + "title": "DosageDoseAndRate", + "type": "object" + }, + "ObservationReferenceRange": { + "$id": "http://graph-fhir.io/schema/0.0.2/ObservationReferenceRange", + "additionalProperties": false, + "description": "Provides guide for interpretation. Guidance on how to interpret the value by comparison to a normal or recommended range. Multiple reference ranges are interpreted as an \"OR\". In other words, to represent two distinct target populations, two `referenceRange` elements would be used. [See https://hl7.org/fhir/R5/ObservationReferenceRange.html]", + "links": [], + "properties": { + "_text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'text'." + }, + "age": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Range", + "description": "The age at which this reference range is applicable. This is a neonatal age (e.g. number of weeks at term) if the meaning says so.", + "element_property": true, + "title": "Applicable age range, if relevant" + }, + "appliesTo": { + "binding_description": "Codes identifying the population the reference range applies to.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/referencerange-appliesto", + "binding_version": null, + "description": "Codes to indicate the target population this reference range applies to. For example, a reference range may be based on the normal population or a particular sex or race. Multiple `appliesTo` are interpreted as an \"AND\" of the target populations. For example, to represent a target population of African American females, both a code of female and a code for African American would be used.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Reference range population", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "high": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "The value of the high bound of the reference range. The high bound of the reference range endpoint is inclusive of the value (e.g. reference range is >=5 - <=9). If the high bound is omitted, it is assumed to be meaningless (e.g. reference range is >= 2.3).", + "element_property": true, + "title": "High Range, if relevant" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "low": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "The value of the low bound of the reference range. The low bound of the reference range endpoint is inclusive of the value (e.g. reference range is >=5 - <=9). If the low bound is omitted, it is assumed to be meaningless (e.g. reference range is <=2.3).", + "element_property": true, + "title": "Low Range, if relevant" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "normalValue": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Codes identifying the normal value of the observation.", + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/observation-referencerange-normalvalue", + "binding_version": null, + "description": "The value of the normal value of the reference range.", + "element_property": true, + "title": "Normal value, if relevant" + }, + "resourceType": { + "const": "ObservationReferenceRange", + "default": "ObservationReferenceRange", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "text": { + "description": "Text based reference range in an observation which may be used when a quantitative range is not appropriate for an observation. An example would be a reference value of \"Negative\" or a list or table of \"normals\".", + "element_property": true, + "pattern": "\\s*(\\S|\\s)*", + "title": "Text based reference range in an observation", + "type": "string" + }, + "type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Code for the meaning of a reference range.", + "binding_strength": "preferred", + "binding_uri": "http://hl7.org/fhir/ValueSet/referencerange-meaning", + "binding_version": null, + "description": "Codes to indicate the what part of the targeted reference population it applies to. For example, the normal or therapeutic range.", + "element_property": true, + "title": "Reference range qualifier" + } + }, + "title": "ObservationReferenceRange", + "type": "object" + }, + "ContactDetail": { + "$id": "http://graph-fhir.io/schema/0.0.2/ContactDetail", + "additionalProperties": false, + "description": "Contact information. Specifies contact information for a person or organization. [See https://hl7.org/fhir/R5/ContactDetail.html]", + "links": [], + "properties": { + "_name": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'name'." + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "name": { + "description": "The name of an individual to contact.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Name of an individual to contact", + "type": "string" + }, + "resourceType": { + "const": "ContactDetail", + "default": "ContactDetail", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "telecom": { + "description": "The contact details for the individual (if a name was provided) or the organization.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ContactPoint" + }, + "title": "Contact details for individual or organization", + "type": "array" + } + }, + "title": "ContactDetail", + "type": "object" + }, + "Procedure": { + "$id": "http://graph-fhir.io/schema/0.0.2/Procedure", + "additionalProperties": false, + "description": "An action that is being or was performed on an individual or entity. An action that is or was performed on or for a patient, practitioner, device, organization, or location. For example, this can be a physical intervention on a patient like an operation, or less invasive like long term services, counseling, or hypnotherapy. This can be a quality or safety inspection for a location, organization, or device. This can be an accreditation procedure on a practitioner for licensing. [See https://hl7.org/fhir/R5/Procedure.html]", + "links": [ + { + "href": "{id}", + "rel": "focus_Patient", + "targetHints": { + "backref": [ + "focus_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Group", + "targetHints": { + "backref": [ + "focus_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Practitioner", + "targetHints": { + "backref": [ + "focus_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Organization", + "targetHints": { + "backref": [ + "focus_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_PractitionerRole", + "targetHints": { + "backref": [ + "focus_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "focus_Specimen", + "targetHints": { + "backref": [ + "focus_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/focus/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "partOf_Procedure", + "targetHints": { + "backref": [ + "partOf_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/partOf/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "partOf_Observation", + "targetHints": { + "backref": [ + "partOf_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/partOf/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "partOf_MedicationAdministration", + "targetHints": { + "backref": [ + "partOf_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/partOf/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "recorder_Patient", + "targetHints": { + "backref": [ + "recorder_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/recorder/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "recorder_Practitioner", + "targetHints": { + "backref": [ + "recorder_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/recorder/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "recorder_PractitionerRole", + "targetHints": { + "backref": [ + "recorder_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/recorder/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "report_DiagnosticReport", + "targetHints": { + "backref": [ + "report_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/report/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "report_DocumentReference", + "targetHints": { + "backref": [ + "report_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/report/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reportedReference_Patient", + "targetHints": { + "backref": [ + "reportedReference_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/reportedReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reportedReference_Practitioner", + "targetHints": { + "backref": [ + "reportedReference_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/reportedReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reportedReference_PractitionerRole", + "targetHints": { + "backref": [ + "reportedReference_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/reportedReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "reportedReference_Organization", + "targetHints": { + "backref": [ + "reportedReference_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/reportedReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Patient", + "targetHints": { + "backref": [ + "subject_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Group", + "targetHints": { + "backref": [ + "subject_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Practitioner", + "targetHints": { + "backref": [ + "subject_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Organization", + "targetHints": { + "backref": [ + "subject_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInfo_Organization", + "targetHints": { + "backref": [ + "supportingInfo_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInfo_Group", + "targetHints": { + "backref": [ + "supportingInfo_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInfo_Practitioner", + "targetHints": { + "backref": [ + "supportingInfo_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInfo_PractitionerRole", + "targetHints": { + "backref": [ + "supportingInfo_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInfo_ResearchStudy", + "targetHints": { + "backref": [ + "supportingInfo_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInfo_Patient", + "targetHints": { + "backref": [ + "supportingInfo_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInfo_ResearchSubject", + "targetHints": { + "backref": [ + "supportingInfo_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInfo_Substance", + "targetHints": { + "backref": [ + "supportingInfo_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInfo_SubstanceDefinition", + "targetHints": { + "backref": [ + "supportingInfo_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInfo_Specimen", + "targetHints": { + "backref": [ + "supportingInfo_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInfo_Observation", + "targetHints": { + "backref": [ + "supportingInfo_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInfo_DiagnosticReport", + "targetHints": { + "backref": [ + "supportingInfo_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInfo_Condition", + "targetHints": { + "backref": [ + "supportingInfo_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInfo_Medication", + "targetHints": { + "backref": [ + "supportingInfo_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInfo_MedicationAdministration", + "targetHints": { + "backref": [ + "supportingInfo_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInfo_MedicationStatement", + "targetHints": { + "backref": [ + "supportingInfo_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInfo_MedicationRequest", + "targetHints": { + "backref": [ + "supportingInfo_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInfo_Procedure", + "targetHints": { + "backref": [ + "supportingInfo_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInfo_DocumentReference", + "targetHints": { + "backref": [ + "supportingInfo_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInfo_Task", + "targetHints": { + "backref": [ + "supportingInfo_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInfo_ImagingStudy", + "targetHints": { + "backref": [ + "supportingInfo_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInfo_FamilyMemberHistory", + "targetHints": { + "backref": [ + "supportingInfo_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supportingInfo_BodyStructure", + "targetHints": { + "backref": [ + "supportingInfo_procedure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/supportingInfo/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/complication", + "href": "{id}", + "rel": "complication_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/complication/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/complication", + "href": "{id}", + "rel": "complication_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/complication/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/complication", + "href": "{id}", + "rel": "complication_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/complication/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/complication", + "href": "{id}", + "rel": "complication_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/complication/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/complication", + "href": "{id}", + "rel": "complication_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/complication/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/complication", + "href": "{id}", + "rel": "complication_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/complication/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/complication", + "href": "{id}", + "rel": "complication_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/complication/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/complication", + "href": "{id}", + "rel": "complication_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/complication/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/complication", + "href": "{id}", + "rel": "complication_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/complication/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/complication", + "href": "{id}", + "rel": "complication_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/complication/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/complication", + "href": "{id}", + "rel": "complication_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/complication/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/complication", + "href": "{id}", + "rel": "complication_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/complication/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/complication", + "href": "{id}", + "rel": "complication_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/complication/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/complication", + "href": "{id}", + "rel": "complication_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/complication/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/complication", + "href": "{id}", + "rel": "complication_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/complication/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/complication", + "href": "{id}", + "rel": "complication_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/complication/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/complication", + "href": "{id}", + "rel": "complication_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/complication/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/complication", + "href": "{id}", + "rel": "complication_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/complication/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/complication", + "href": "{id}", + "rel": "complication_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/complication/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/complication", + "href": "{id}", + "rel": "complication_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/complication/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/complication", + "href": "{id}", + "rel": "complication_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/complication/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/complication", + "href": "{id}", + "rel": "complication_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/complication/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/complication", + "href": "{id}", + "rel": "complication_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/complication/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Practitioner", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_PractitionerRole", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Patient", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Organization", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ProcedurePerformer/performer", + "href": "{id}", + "rel": "performer_actor_Practitioner", + "targetHints": { + "backref": [ + "actor_procedure_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/performer/-/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ProcedurePerformer/performer", + "href": "{id}", + "rel": "performer_actor_PractitionerRole", + "targetHints": { + "backref": [ + "actor_procedure_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/performer/-/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ProcedurePerformer/performer", + "href": "{id}", + "rel": "performer_actor_Organization", + "targetHints": { + "backref": [ + "actor_procedure_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/performer/-/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ProcedurePerformer/performer", + "href": "{id}", + "rel": "performer_actor_Patient", + "targetHints": { + "backref": [ + "actor_procedure_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/performer/-/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ProcedurePerformer/performer", + "href": "{id}", + "rel": "performer_onBehalfOf", + "targetHints": { + "backref": [ + "onBehalfOf_procedure_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/performer/-/onBehalfOf/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/used", + "href": "{id}", + "rel": "used_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/used/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/used", + "href": "{id}", + "rel": "used_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/used/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/used", + "href": "{id}", + "rel": "used_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/used/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/used", + "href": "{id}", + "rel": "used_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/used/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/used", + "href": "{id}", + "rel": "used_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/used/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/used", + "href": "{id}", + "rel": "used_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/used/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/used", + "href": "{id}", + "rel": "used_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/used/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/used", + "href": "{id}", + "rel": "used_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/used/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/used", + "href": "{id}", + "rel": "used_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/used/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/used", + "href": "{id}", + "rel": "used_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/used/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/used", + "href": "{id}", + "rel": "used_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/used/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/used", + "href": "{id}", + "rel": "used_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/used/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/used", + "href": "{id}", + "rel": "used_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/used/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/used", + "href": "{id}", + "rel": "used_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/used/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/used", + "href": "{id}", + "rel": "used_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/used/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/used", + "href": "{id}", + "rel": "used_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/used/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/used", + "href": "{id}", + "rel": "used_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/used/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/used", + "href": "{id}", + "rel": "used_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/used/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/used", + "href": "{id}", + "rel": "used_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/used/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/used", + "href": "{id}", + "rel": "used_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/used/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/used", + "href": "{id}", + "rel": "used_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/used/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/used", + "href": "{id}", + "rel": "used_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/used/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/used", + "href": "{id}", + "rel": "used_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/used/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_instantiatesCanonical": { + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension" + }, + "title": "Extension field for 'instantiatesCanonical'.", + "type": "array" + }, + "_instantiatesUri": { + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension" + }, + "title": "Extension field for 'instantiatesUri'.", + "type": "array" + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "_occurrenceDateTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'occurrenceDateTime'." + }, + "_occurrenceString": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'occurrenceString'." + }, + "_recorded": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'recorded'." + }, + "_reportedBoolean": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'reportedBoolean'." + }, + "_status": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'status'." + }, + "basedOn": { + "backref": "basedOn_procedure", + "description": "A reference to a resource that contains details of the request for this procedure.", + "element_property": true, + "enum_reference_types": [ + "CarePlan", + "ServiceRequest" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "A request for this procedure", + "type": "array" + }, + "bodySite": { + "binding_description": "SNOMED CT Body site concepts", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/body-site", + "binding_version": null, + "description": "Detailed and structured anatomical location information. Multiple locations are allowed - e.g. multiple punch biopsies of a lesion.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Target body sites", + "type": "array" + }, + "category": { + "binding_description": "A code that classifies a procedure for searching, sorting and display purposes.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/procedure-category", + "binding_version": null, + "description": "A code that classifies the procedure for searching, sorting and display purposes (e.g. \"Surgical Procedure\").", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Classification of the procedure", + "type": "array" + }, + "code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "A code to identify a specific procedure .", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/procedure-code", + "binding_version": null, + "description": "The specific procedure that is performed. Use text if the exact nature of the procedure cannot be coded (e.g. \"Laparoscopic Appendectomy\").", + "element_property": true, + "title": "Identification of the procedure" + }, + "complication": { + "backref": "complication_procedure", + "binding_description": "Codes describing complications that resulted from a procedure.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/condition-code", + "binding_version": null, + "description": "Any complications that occurred during the procedure, or in the immediate post-performance period. These are generally tracked separately from the notes, which will typically describe the procedure itself rather than any 'post procedure' issues.", + "element_property": true, + "enum_reference_types": [ + "Condition" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference" + }, + "title": "Complication following the procedure", + "type": "array" + }, + "contained": { + "description": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, nor can they have their own independent transaction scope. This is allowed to be a Parameters resource if and only if it is referenced by a resource that provides context/meaning.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + "title": "Contained, inline Resources", + "type": "array" + }, + "encounter": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "procedure", + "description": "The Encounter during which this Procedure was created or performed or to which the creation of this record is tightly associated.", + "element_property": true, + "enum_reference_types": [ + "Encounter" + ], + "title": "The Encounter during which this Procedure was created" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "focalDevice": { + "description": "A device that is implanted, removed or otherwise manipulated (calibration, battery replacement, fitting a prosthesis, attaching a wound-vac, etc.) as a focal portion of the Procedure.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ProcedureFocalDevice" + }, + "title": "Manipulated, implanted, or removed device", + "type": "array" + }, + "focus": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "focus_procedure", + "description": "Who is the target of the procedure when it is not the subject of record only. If focus is not present, then subject is the focus. If focus is present and the subject is one of the targets of the procedure, include subject as a focus as well. If focus is present and the subject is not included in focus, it implies that the procedure was only targeted on the focus. For example, when a caregiver is given education for a patient, the caregiver would be the focus and the procedure record is associated with the subject (e.g. patient). For example, use focus when recording the target of the education, training, or counseling is the parent or relative of a patient.", + "element_property": true, + "enum_reference_types": [ + "Patient", + "Group", + "RelatedPerson", + "Practitioner", + "Organization", + "CareTeam", + "PractitionerRole", + "Specimen" + ], + "title": "Who is the target of the procedure when it is not the subject of record only" + }, + "followUp": { + "binding_description": "Specific follow up required for a procedure e.g. removal of sutures.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/procedure-followup", + "binding_version": null, + "description": "If the procedure required specific follow up - e.g. removal of sutures. The follow up may be represented as a simple note or could potentially be more complex, in which case the CarePlan resource can be used.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Instructions for follow up", + "type": "array" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "identifier": { + "description": "Business identifiers assigned to this procedure by the performer or other systems which remain constant as the resource is updated and is propagated from server to server.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "External Identifiers for this procedure", + "type": "array" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "instantiatesCanonical": { + "description": "The URL pointing to a FHIR-defined protocol, guideline, order set or other definition that is adhered to in whole or in part by this Procedure.", + "element_property": true, + "enum_reference_types": [ + "PlanDefinition", + "ActivityDefinition", + "Measure", + "OperationDefinition", + "Questionnaire" + ], + "items": { + "pattern": "\\S*", + "type": "string" + }, + "title": "Instantiates FHIR protocol or definition", + "type": "array" + }, + "instantiatesUri": { + "description": "The URL pointing to an externally maintained protocol, guideline, order set or other definition that is adhered to in whole or in part by this Procedure.", + "element_property": true, + "items": { + "pattern": "\\S*", + "type": "string" + }, + "title": "Instantiates external protocol or definition", + "type": "array" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "location": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "location_procedure", + "description": "The location where the procedure actually happened. E.g. a newborn at home, a tracheostomy at a restaurant.", + "element_property": true, + "enum_reference_types": [ + "Location" + ], + "title": "Where the procedure happened" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored", + "type": "array" + }, + "note": { + "description": "Any other notes and comments about the procedure.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Annotation" + }, + "title": "Additional information about the procedure", + "type": "array" + }, + "occurrenceAge": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Age", + "description": "Estimated or actual date, date-time, period, or age when the procedure did occur or is occurring. Allows a period to support complex procedures that span more than one date, and also allows for the length of the procedure to be captured.", + "element_property": true, + "one_of_many": "occurrence", + "one_of_many_required": false, + "title": "When the procedure occurred or is occurring" + }, + "occurrenceDateTime": { + "description": "Estimated or actual date, date-time, period, or age when the procedure did occur or is occurring. Allows a period to support complex procedures that span more than one date, and also allows for the length of the procedure to be captured.", + "element_property": true, + "format": "date-time", + "one_of_many": "occurrence", + "one_of_many_required": false, + "title": "When the procedure occurred or is occurring", + "type": "string" + }, + "occurrencePeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "Estimated or actual date, date-time, period, or age when the procedure did occur or is occurring. Allows a period to support complex procedures that span more than one date, and also allows for the length of the procedure to be captured.", + "element_property": true, + "one_of_many": "occurrence", + "one_of_many_required": false, + "title": "When the procedure occurred or is occurring" + }, + "occurrenceRange": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Range", + "description": "Estimated or actual date, date-time, period, or age when the procedure did occur or is occurring. Allows a period to support complex procedures that span more than one date, and also allows for the length of the procedure to be captured.", + "element_property": true, + "one_of_many": "occurrence", + "one_of_many_required": false, + "title": "When the procedure occurred or is occurring" + }, + "occurrenceString": { + "description": "Estimated or actual date, date-time, period, or age when the procedure did occur or is occurring. Allows a period to support complex procedures that span more than one date, and also allows for the length of the procedure to be captured.", + "element_property": true, + "one_of_many": "occurrence", + "one_of_many_required": false, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "When the procedure occurred or is occurring", + "type": "string" + }, + "occurrenceTiming": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Timing", + "description": "Estimated or actual date, date-time, period, or age when the procedure did occur or is occurring. Allows a period to support complex procedures that span more than one date, and also allows for the length of the procedure to be captured.", + "element_property": true, + "one_of_many": "occurrence", + "one_of_many_required": false, + "title": "When the procedure occurred or is occurring" + }, + "outcome": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "An outcome of a procedure - whether it was resolved or otherwise.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/procedure-outcome", + "binding_version": null, + "description": "The outcome of the procedure - did it resolve the reasons for the procedure being performed?", + "element_property": true, + "title": "The result of procedure" + }, + "partOf": { + "backref": "partOf_procedure", + "description": "A larger event of which this particular procedure is a component or step.", + "element_property": true, + "enum_reference_types": [ + "Procedure", + "Observation", + "MedicationAdministration" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Part of referenced event", + "type": "array" + }, + "performer": { + "description": "Indicates who or what performed the procedure and how they were involved.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ProcedurePerformer" + }, + "title": "Who performed the procedure and what they did", + "type": "array" + }, + "reason": { + "backref": "reason_procedure", + "binding_description": "A code that identifies the reason a procedure is required.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/procedure-reason", + "binding_version": null, + "description": "The coded reason or reference why the procedure was performed. This may be a coded entity of some type, be present as text, or be a reference to one of several resources that justify the procedure.", + "element_property": true, + "enum_reference_types": [ + "Condition", + "Observation", + "Procedure", + "DiagnosticReport", + "DocumentReference" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference" + }, + "title": "The justification that the procedure was performed", + "type": "array" + }, + "recorded": { + "description": "The date the occurrence of the procedure was first captured in the record regardless of Procedure.status (potentially after the occurrence of the event).", + "element_property": true, + "format": "date-time", + "title": "When the procedure was first captured in the subject's record", + "type": "string" + }, + "recorder": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "recorder_procedure", + "description": "Individual who recorded the record and takes responsibility for its content.", + "element_property": true, + "enum_reference_types": [ + "Patient", + "RelatedPerson", + "Practitioner", + "PractitionerRole" + ], + "title": "Who recorded the procedure" + }, + "report": { + "backref": "report_procedure", + "description": "This could be a histology result, pathology report, surgical report, etc.", + "element_property": true, + "enum_reference_types": [ + "DiagnosticReport", + "DocumentReference", + "Composition" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Any report resulting from the procedure", + "type": "array" + }, + "reportedBoolean": { + "description": "Indicates if this record was captured as a secondary 'reported' record rather than as an original primary source-of-truth record. It may also indicate the source of the report.", + "element_property": true, + "one_of_many": "reported", + "one_of_many_required": false, + "title": "Reported rather than primary record", + "type": "boolean" + }, + "reportedReference": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "reportedReference_procedure", + "description": "Indicates if this record was captured as a secondary 'reported' record rather than as an original primary source-of-truth record. It may also indicate the source of the report.", + "element_property": true, + "enum_reference_types": [ + "Patient", + "RelatedPerson", + "Practitioner", + "PractitionerRole", + "Organization" + ], + "one_of_many": "reported", + "one_of_many_required": false, + "title": "Reported rather than primary record" + }, + "resourceType": { + "const": "Procedure", + "default": "Procedure", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "status": { + "binding_description": "A code specifying the state of the procedure.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/event-status", + "binding_version": "5.0.0", + "description": "A code specifying the state of the procedure. Generally, this will be the in-progress or completed state.", + "element_property": true, + "element_required": true, + "enum_values": [ + "preparation", + "in-progress", + "not-done", + "on-hold", + "stopped", + "completed", + "entered-in-error", + "unknown" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "preparation | in-progress | not-done | on-hold | stopped | completed | entered-in-error | unknown", + "type": "string" + }, + "statusReason": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "A code that identifies the reason a procedure was not performed.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/procedure-not-performed-reason", + "binding_version": null, + "description": "Captures the reason for the current state of the procedure.", + "element_property": true, + "title": "Reason for current status" + }, + "subject": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "subject_procedure", + "description": "On whom or on what the procedure was performed. This is usually an individual human, but can also be performed on animals, groups of humans or animals, organizations or practitioners (for licensing), locations or devices (for safety inspections or regulatory authorizations). If the actual focus of the procedure is different from the subject, the focus element specifies the actual focus of the procedure.", + "element_property": true, + "enum_reference_types": [ + "Patient", + "Group", + "Device", + "Practitioner", + "Organization", + "Location" + ], + "title": "Individual or entity the procedure was performed on" + }, + "supportingInfo": { + "backref": "supportingInfo_procedure", + "description": "Other resources from the patient record that may be relevant to the procedure. The information from these resources was either used to create the instance or is provided to help with its interpretation. This extension should not be used if more specific inline elements or extensions are available.", + "element_property": true, + "enum_reference_types": [ + "Organization", + "Group", + "Practitioner", + "PractitionerRole", + "ResearchStudy", + "Patient", + "ResearchSubject", + "Substance", + "SubstanceDefinition", + "Specimen", + "Observation", + "DiagnosticReport", + "Condition", + "Medication", + "MedicationAdministration", + "MedicationStatement", + "MedicationRequest", + "Procedure", + "DocumentReference", + "Task", + "ImagingStudy", + "FamilyMemberHistory", + "BodyStructure" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Extra information relevant to the procedure", + "type": "array" + }, + "text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative", + "description": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "element_property": true, + "title": "Text summary of the resource, for human interpretation" + }, + "used": { + "backref": "used_procedure", + "binding_description": "Codes describing items used during a procedure.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/device-type", + "binding_version": null, + "description": "Identifies medications, devices and any other substance used as part of the procedure.", + "element_property": true, + "enum_reference_types": [ + "Device", + "Medication", + "Substance", + "BiologicallyDerivedProduct" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference" + }, + "title": "Items used during procedure", + "type": "array" + } + }, + "required": [ + "subject" + ], + "title": "Procedure", + "type": "object" + }, + "MedicationRequestDispenseRequestInitialFill": { + "$id": "http://graph-fhir.io/schema/0.0.2/MedicationRequestDispenseRequestInitialFill", + "additionalProperties": false, + "description": "First fill details. Indicates the quantity or duration for the first dispense of the medication. [See https://hl7.org/fhir/R5/MedicationRequestDispenseRequestInitialFill.html]", + "links": [], + "properties": { + "duration": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Duration", + "description": "The length of time that the first dispense is expected to last.", + "element_property": true, + "title": "First fill duration" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "quantity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "The amount or quantity to provide as part of the first dispense.", + "element_property": true, + "title": "First fill quantity" + }, + "resourceType": { + "const": "MedicationRequestDispenseRequestInitialFill", + "default": "MedicationRequestDispenseRequestInitialFill", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "title": "MedicationRequestDispenseRequestInitialFill", + "type": "object" + }, + "ResearchStudyLabel": { + "$id": "http://graph-fhir.io/schema/0.0.2/ResearchStudyLabel", + "additionalProperties": false, + "description": "Additional names for the study. [See https://hl7.org/fhir/R5/ResearchStudyLabel.html]", + "links": [], + "properties": { + "_value": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'value'." + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "ResearchStudyLabel", + "default": "ResearchStudyLabel", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "desc.", + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/title-type", + "binding_version": null, + "description": "Kind of name.", + "element_property": true, + "title": "primary | official | scientific | plain-language | subtitle | short-title | acronym | earlier-title | language | auto-translated | human-use | machine-use | duplicate-uid" + }, + "value": { + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "The name", + "type": "string" + } + }, + "title": "ResearchStudyLabel", + "type": "object" + }, + "DocumentReferenceContentProfile": { + "$id": "http://graph-fhir.io/schema/0.0.2/DocumentReferenceContentProfile", + "additionalProperties": false, + "description": "Content profile rules for the document. An identifier of the document constraints, encoding, structure, and template that the document conforms to beyond the base format indicated in the mimeType. [See https://hl7.org/fhir/R5/DocumentReferenceContentProfile.html]", + "links": [], + "properties": { + "_valueCanonical": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueCanonical'." + }, + "_valueUri": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueUri'." + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "DocumentReferenceContentProfile", + "default": "DocumentReferenceContentProfile", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "valueCanonical": { + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "pattern": "\\S*", + "title": "Code|uri|canonical", + "type": "string" + }, + "valueCoding": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Coding", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Code|uri|canonical" + }, + "valueUri": { + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "pattern": "\\S*", + "title": "Code|uri|canonical", + "type": "string" + } + }, + "title": "DocumentReferenceContentProfile", + "type": "object" + }, + "ResearchStudyObjective": { + "$id": "http://graph-fhir.io/schema/0.0.2/ResearchStudyObjective", + "additionalProperties": false, + "description": "A goal for the study. A goal that the study is aiming to achieve in terms of a scientific question to be answered by the analysis of data collected during the study. [See https://hl7.org/fhir/R5/ResearchStudyObjective.html]", + "links": [], + "properties": { + "_description": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'description'." + }, + "_name": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'name'." + }, + "description": { + "description": "Free text description of the objective of the study. This is what the study is trying to achieve rather than how it is going to achieve it (see ResearchStudy.description).", + "element_property": true, + "pattern": "\\s*(\\S|\\s)*", + "title": "Description of the objective", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "name": { + "description": "Unique, human-readable label for this objective of the study.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Label for the objective", + "type": "string" + }, + "resourceType": { + "const": "ResearchStudyObjective", + "default": "ResearchStudyObjective", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Codes for the kind of study objective.", + "binding_strength": "preferred", + "binding_uri": "http://hl7.org/fhir/ValueSet/research-study-objective-type", + "binding_version": null, + "description": "The kind of study objective.", + "element_property": true, + "title": "primary | secondary | exploratory" + } + }, + "title": "ResearchStudyObjective", + "type": "object" + }, + "ProcedurePerformer": { + "$id": "http://graph-fhir.io/schema/0.0.2/ProcedurePerformer", + "additionalProperties": false, + "description": "Who performed the procedure and what they did. Indicates who or what performed the procedure and how they were involved. [See https://hl7.org/fhir/R5/ProcedurePerformer.html]", + "links": [ + { + "href": "{id}", + "rel": "actor_Practitioner", + "targetHints": { + "backref": [ + "actor_procedure_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "actor_PractitionerRole", + "targetHints": { + "backref": [ + "actor_procedure_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "actor_Organization", + "targetHints": { + "backref": [ + "actor_procedure_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "actor_Patient", + "targetHints": { + "backref": [ + "actor_procedure_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/actor/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "onBehalfOf", + "targetHints": { + "backref": [ + "onBehalfOf_procedure_performer" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/onBehalfOf/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "actor": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "actor_procedure_performer", + "description": "Indicates who or what performed the procedure.", + "element_property": true, + "enum_reference_types": [ + "Practitioner", + "PractitionerRole", + "Organization", + "Patient", + "RelatedPerson", + "Device", + "CareTeam", + "HealthcareService" + ], + "title": "Who performed the procedure" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "function": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "A code that identifies the role of a performer of the procedure.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/performer-role", + "binding_version": null, + "description": "Distinguishes the type of involvement of the performer in the procedure. For example, surgeon, anaesthetist, endoscopist.", + "element_property": true, + "title": "Type of performance" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "onBehalfOf": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "onBehalfOf_procedure_performer", + "description": "The Organization the Patient, RelatedPerson, Device, CareTeam, and HealthcareService was acting on behalf of.", + "element_property": true, + "enum_reference_types": [ + "Organization" + ], + "title": "Organization the device or practitioner was acting for" + }, + "period": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "Time period during which the performer performed the procedure.", + "element_property": true, + "title": "When the performer performed the procedure" + }, + "resourceType": { + "const": "ProcedurePerformer", + "default": "ProcedurePerformer", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "required": [ + "actor" + ], + "title": "ProcedurePerformer", + "type": "object" + }, + "ResearchSubjectProgress": { + "$id": "http://graph-fhir.io/schema/0.0.2/ResearchSubjectProgress", + "additionalProperties": false, + "description": "Subject status. The current state (status) of the subject and resons for status change where appropriate. [See https://hl7.org/fhir/R5/ResearchSubjectProgress.html]", + "links": [], + "properties": { + "_endDate": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'endDate'." + }, + "_startDate": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'startDate'." + }, + "endDate": { + "description": "The date when the state ended.", + "element_property": true, + "format": "date-time", + "title": "State change date", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "milestone": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Indicates the progression of a study subject through the study milestones.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/research-subject-milestone", + "binding_version": null, + "description": "The milestones the subject has passed through.", + "element_property": true, + "title": "SignedUp | Screened | Randomized" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "reason": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Indicates why the state of the subject changed.", + "binding_strength": "example", + "binding_uri": "http://terminology.hl7.org/ValueSet/state-change-reason", + "binding_version": null, + "description": "The reason for the state change. If coded it should follow the formal subject state model.", + "element_property": true, + "title": "State change reason" + }, + "resourceType": { + "const": "ResearchSubjectProgress", + "default": "ResearchSubjectProgress", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "startDate": { + "description": "The date when the new status started.", + "element_property": true, + "format": "date-time", + "title": "State change date", + "type": "string" + }, + "subjectState": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Indicates the progression of a study subject through a study.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/research-subject-state", + "binding_version": "5.0.0", + "description": "The current state of the subject.", + "element_property": true, + "title": "candidate | eligible | follow-up | ineligible | not-registered | off-study | on-study | on-study-intervention | on-study-observation | pending-on-study | potential-candidate | screening | withdrawn" + }, + "type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Identifies the kind of state being refered to.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/research-subject-state-type", + "binding_version": null, + "description": "Identifies the aspect of the subject's journey that the state refers to.", + "element_property": true, + "title": "state | milestone" + } + }, + "title": "ResearchSubjectProgress", + "type": "object" + }, + "Organization": { + "$id": "http://graph-fhir.io/schema/0.0.2/Organization", + "additionalProperties": false, + "description": "A grouping of people or organizations with a common purpose. A formally or informally recognized grouping of people or organizations formed for the purpose of achieving some form of collective action. Includes companies, institutions, corporations, departments, community groups, healthcare practice groups, payer/insurer, etc. [See https://hl7.org/fhir/R5/Organization.html]", + "links": [ + { + "href": "{id}", + "rel": "partOf", + "targetHints": { + "backref": [ + "organization" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/partOf/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ExtendedContactDetail/contact", + "href": "{id}", + "rel": "contact_organization", + "targetHints": { + "backref": [ + "extended_contact_detail" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/contact/-/organization/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From OrganizationQualification/qualification", + "href": "{id}", + "rel": "qualification_issuer", + "targetHints": { + "backref": [ + "organization_qualification" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/qualification/-/issuer/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_active": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'active'." + }, + "_alias": { + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension" + }, + "title": "Extension field for 'alias'.", + "type": "array" + }, + "_description": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'description'." + }, + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "_name": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'name'." + }, + "active": { + "element_property": true, + "title": "Whether the organization's record is still in active use", + "type": "boolean" + }, + "alias": { + "element_property": true, + "items": { + "pattern": "[ \\r\\n\\t\\S]+", + "type": "string" + }, + "title": "A list of alternate names that the organization is known as, or was known as in the past", + "type": "array" + }, + "contact": { + "description": "The contact details of communication devices available relevant to the specific Organization. This can include addresses, phone numbers, fax numbers, mobile numbers, email addresses and web sites.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ExtendedContactDetail" + }, + "title": "Official contact details for the Organization", + "type": "array" + }, + "contained": { + "description": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, nor can they have their own independent transaction scope. This is allowed to be a Parameters resource if and only if it is referenced by a resource that provides context/meaning.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + "title": "Contained, inline Resources", + "type": "array" + }, + "description": { + "description": "Description of the organization, which helps provide additional general context on the organization to ensure that the correct organization is selected.", + "element_property": true, + "pattern": "\\s*(\\S|\\s)*", + "title": "Additional details about the Organization that could be displayed as further information to identify the Organization beyond its name", + "type": "string" + }, + "endpoint": { + "backref": "endpoint_organization", + "element_property": true, + "enum_reference_types": [ + "Endpoint" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Technical endpoints providing access to services operated for the organization", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "identifier": { + "description": "Identifier for the organization that is used to identify the organization across multiple disparate systems.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "Identifies this organization across multiple systems", + "type": "array" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored", + "type": "array" + }, + "name": { + "description": "A name associated with the organization.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Name used for the organization", + "type": "string" + }, + "partOf": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "organization", + "element_property": true, + "enum_reference_types": [ + "Organization" + ], + "title": "The organization of which this organization forms a part" + }, + "qualification": { + "description": "The official certifications, accreditations, training, designations and licenses that authorize and/or otherwise endorse the provision of care by the organization. For example, an approval to provide a type of services issued by a certifying body (such as the US Joint Commission) to an organization.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/OrganizationQualification" + }, + "title": "Qualifications, certifications, accreditations, licenses, training, etc. pertaining to the provision of care", + "type": "array" + }, + "resourceType": { + "const": "Organization", + "default": "Organization", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative", + "description": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "element_property": true, + "title": "Text summary of the resource, for human interpretation" + }, + "type": { + "binding_description": "Used to categorize the organization.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/organization-type", + "binding_version": null, + "description": "The kind(s) of organization that this is.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Kind of organization", + "type": "array" + } + }, + "title": "Organization", + "type": "object" + }, + "Distance": { + "$id": "http://graph-fhir.io/schema/0.0.2/Distance", + "additionalProperties": false, + "description": "A length - a value with a unit that is a physical distance. [See https://hl7.org/fhir/R5/Distance.html]", + "links": [], + "properties": { + "_code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'code'." + }, + "_comparator": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'comparator'." + }, + "_system": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'system'." + }, + "_unit": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'unit'." + }, + "_value": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'value'." + }, + "code": { + "description": "A computer processable form of the unit in some unit representation system.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Coded form of the unit", + "type": "string" + }, + "comparator": { + "binding_description": "How the Quantity should be understood and represented.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/quantity-comparator", + "binding_version": "5.0.0", + "description": "How the value should be understood and represented - whether the actual value is greater or less than the stated value due to measurement issues; e.g. if the comparator is \"<\" , then the real value is < stated value.", + "element_property": true, + "enum_values": [ + "<", + "<=", + ">=", + ">", + "ad" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "< | <= | >= | > | ad - how to understand the value", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "resourceType": { + "const": "Distance", + "default": "Distance", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "system": { + "description": "The identification of the system that provides the coded form of the unit.", + "element_property": true, + "pattern": "\\S*", + "title": "System that defines coded unit form", + "type": "string" + }, + "unit": { + "description": "A human-readable form of the unit.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unit representation", + "type": "string" + }, + "value": { + "description": "The value of the measured amount. The value includes an implicit precision in the presentation of the value.", + "element_property": true, + "title": "Numerical value (with implicit precision)", + "type": "number" + } + }, + "title": "Distance", + "type": "object" + }, + "ImagingStudy": { + "$id": "http://graph-fhir.io/schema/0.0.2/ImagingStudy", + "additionalProperties": false, + "description": "A set of images produced in single study (one or more series of references images). Representation of the content produced in a DICOM imaging study. A study comprises a set of series, each of which includes a set of Service-Object Pair Instances (SOP Instances - images or other data) acquired or produced in a common context. A series is of only one modality (e.g. X-ray, CT, MR, ultrasound), but a study may have multiple series of different modalities. [See https://hl7.org/fhir/R5/ImagingStudy.html]", + "links": [ + { + "href": "{id}", + "rel": "basedOn_Task", + "targetHints": { + "backref": [ + "basedOn_imaging_study" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/basedOn/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "partOf", + "targetHints": { + "backref": [ + "partOf_imaging_study" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/partOf/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "referrer_Practitioner", + "targetHints": { + "backref": [ + "imaging_study" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/referrer/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "referrer_PractitionerRole", + "targetHints": { + "backref": [ + "imaging_study" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/referrer/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Patient", + "targetHints": { + "backref": [ + "imaging_study" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Group", + "targetHints": { + "backref": [ + "imaging_study" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Practitioner", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_PractitionerRole", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Patient", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Organization", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/procedure", + "href": "{id}", + "rel": "procedure_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/procedure/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/procedure", + "href": "{id}", + "rel": "procedure_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/procedure/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/procedure", + "href": "{id}", + "rel": "procedure_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/procedure/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/procedure", + "href": "{id}", + "rel": "procedure_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/procedure/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/procedure", + "href": "{id}", + "rel": "procedure_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/procedure/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/procedure", + "href": "{id}", + "rel": "procedure_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/procedure/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/procedure", + "href": "{id}", + "rel": "procedure_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/procedure/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/procedure", + "href": "{id}", + "rel": "procedure_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/procedure/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/procedure", + "href": "{id}", + "rel": "procedure_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/procedure/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/procedure", + "href": "{id}", + "rel": "procedure_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/procedure/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/procedure", + "href": "{id}", + "rel": "procedure_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/procedure/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/procedure", + "href": "{id}", + "rel": "procedure_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/procedure/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/procedure", + "href": "{id}", + "rel": "procedure_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/procedure/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/procedure", + "href": "{id}", + "rel": "procedure_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/procedure/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/procedure", + "href": "{id}", + "rel": "procedure_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/procedure/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/procedure", + "href": "{id}", + "rel": "procedure_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/procedure/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/procedure", + "href": "{id}", + "rel": "procedure_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/procedure/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/procedure", + "href": "{id}", + "rel": "procedure_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/procedure/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/procedure", + "href": "{id}", + "rel": "procedure_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/procedure/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/procedure", + "href": "{id}", + "rel": "procedure_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/procedure/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/procedure", + "href": "{id}", + "rel": "procedure_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/procedure/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/procedure", + "href": "{id}", + "rel": "procedure_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/procedure/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/procedure", + "href": "{id}", + "rel": "procedure_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/procedure/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/reason", + "href": "{id}", + "rel": "reason_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/reason/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ImagingStudySeries/series", + "href": "{id}", + "rel": "series_specimen", + "targetHints": { + "backref": [ + "specimen_imaging_study_series" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/series/-/specimen/-/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_description": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'description'." + }, + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "_numberOfInstances": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'numberOfInstances'." + }, + "_numberOfSeries": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'numberOfSeries'." + }, + "_started": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'started'." + }, + "_status": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'status'." + }, + "basedOn": { + "backref": "basedOn_imaging_study", + "description": "A list of the diagnostic requests that resulted in this imaging study being performed.", + "element_property": true, + "enum_reference_types": [ + "CarePlan", + "ServiceRequest", + "Appointment", + "AppointmentResponse", + "Task" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Request fulfilled", + "type": "array" + }, + "contained": { + "description": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, nor can they have their own independent transaction scope. This is allowed to be a Parameters resource if and only if it is referenced by a resource that provides context/meaning.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + "title": "Contained, inline Resources", + "type": "array" + }, + "description": { + "description": "The Imaging Manager description of the study. Institution-generated description or classification of the Study (component) performed.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Institution-generated description", + "type": "string" + }, + "encounter": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "imaging_study", + "description": "The healthcare event (e.g. a patient and healthcare provider interaction) during which this ImagingStudy is made.", + "element_property": true, + "enum_reference_types": [ + "Encounter" + ], + "title": "Encounter with which this imaging study is associated" + }, + "endpoint": { + "backref": "endpoint_imaging_study", + "description": "The network service providing access (e.g., query, view, or retrieval) for the study. See implementation notes for information about using DICOM endpoints. A study-level endpoint applies to each series in the study, unless overridden by a series-level endpoint with the same Endpoint.connectionType.", + "element_property": true, + "enum_reference_types": [ + "Endpoint" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Study access endpoint", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "identifier": { + "description": "Identifiers for the ImagingStudy such as DICOM Study Instance UID.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "Identifiers for the whole study", + "type": "array" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "location": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "imaging_study", + "description": "The principal physical location where the ImagingStudy was performed.", + "element_property": true, + "enum_reference_types": [ + "Location" + ], + "title": "Where ImagingStudy occurred" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "modality": { + "binding_description": "Type of acquired data in the instance.", + "binding_strength": "extensible", + "binding_uri": "http://dicom.nema.org/medical/dicom/current/output/chtml/part16/sect_CID_33.html", + "binding_version": null, + "description": "A list of all the distinct values of series.modality. This may include both acquisition and non-acquisition modalities.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "All of the distinct values for series' modalities", + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored", + "type": "array" + }, + "note": { + "description": "Per the recommended DICOM mapping, this element is derived from the Study Description attribute (0008,1030). Observations or findings about the imaging study should be recorded in another resource, e.g. Observation, and not in this element.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Annotation" + }, + "title": "User-defined comments", + "type": "array" + }, + "numberOfInstances": { + "description": "Number of SOP Instances in Study. This value given may be larger than the number of instance elements this resource contains due to resource availability, security, or other factors. This element should be present if any instance elements are present.", + "element_property": true, + "minimum": 0, + "title": "Number of Study Related Instances", + "type": "integer" + }, + "numberOfSeries": { + "description": "Number of Series in the Study. This value given may be larger than the number of series elements this Resource contains due to resource availability, security, or other factors. This element should be present if any series elements are present.", + "element_property": true, + "minimum": 0, + "title": "Number of Study Related Series", + "type": "integer" + }, + "partOf": { + "backref": "partOf_imaging_study", + "description": "A larger event of which this particular ImagingStudy is a component or step. For example, an ImagingStudy as part of a procedure.", + "element_property": true, + "enum_reference_types": [ + "Procedure" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Part of referenced event", + "type": "array" + }, + "procedure": { + "backref": "procedure_imaging_study", + "binding_description": "Use of RadLex is preferred", + "binding_strength": "preferred", + "binding_uri": "http://loinc.org/vs/loinc-rsna-radiology-playbook", + "binding_version": null, + "description": "This field corresponds to the DICOM Procedure Code Sequence (0008,1032). This is different from the FHIR Procedure resource that may include the ImagingStudy.", + "element_property": true, + "enum_reference_types": [ + "PlanDefinition", + "ActivityDefinition" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference" + }, + "title": "The performed procedure or code", + "type": "array" + }, + "reason": { + "backref": "reason_imaging_study", + "binding_description": "The reason for the study.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/procedure-reason", + "binding_version": null, + "description": "Description of clinical condition indicating why the ImagingStudy was requested, and/or Indicates another resource whose existence justifies this Study.", + "element_property": true, + "enum_reference_types": [ + "Condition", + "Observation", + "DiagnosticReport", + "DocumentReference" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference" + }, + "title": "Why the study was requested / performed", + "type": "array" + }, + "referrer": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "imaging_study", + "description": "The requesting/referring physician.", + "element_property": true, + "enum_reference_types": [ + "Practitioner", + "PractitionerRole" + ], + "title": "Referring physician" + }, + "resourceType": { + "const": "ImagingStudy", + "default": "ImagingStudy", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "series": { + "description": "Each study has one or more series of images or other content.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudySeries" + }, + "title": "Each study has one or more series of instances", + "type": "array" + }, + "started": { + "description": "Date and time the study started.", + "element_property": true, + "format": "date-time", + "title": "When the study was started", + "type": "string" + }, + "status": { + "binding_description": "The status of the ImagingStudy.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/imagingstudy-status", + "binding_version": "5.0.0", + "description": "The current state of the ImagingStudy resource. This is not the status of any ServiceRequest or Task resources associated with the ImagingStudy.", + "element_property": true, + "element_required": true, + "enum_values": [ + "registered", + "available", + "cancelled", + "entered-in-error", + "unknown" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "registered | available | cancelled | entered-in-error | unknown", + "type": "string" + }, + "subject": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "imaging_study", + "description": "The subject, typically a patient, of the imaging study.", + "element_property": true, + "enum_reference_types": [ + "Patient", + "Device", + "Group" + ], + "title": "Who or what is the subject of the study" + }, + "text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative", + "description": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "element_property": true, + "title": "Text summary of the resource, for human interpretation" + } + }, + "required": [ + "subject" + ], + "title": "ImagingStudy", + "type": "object" + }, + "BodyStructure": { + "$id": "http://graph-fhir.io/schema/0.0.2/BodyStructure", + "additionalProperties": false, + "description": "Specific and identified anatomical structure. Record details about an anatomical structure. This resource may be used when a coded concept does not provide the necessary detail needed for the use case. [See https://hl7.org/fhir/R5/BodyStructure.html]", + "links": [ + { + "href": "{id}", + "rel": "patient", + "targetHints": { + "backref": [ + "body_structure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/patient/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_active": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'active'." + }, + "_description": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'description'." + }, + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "active": { + "description": "Whether this body site is in active use.", + "element_property": true, + "title": "Whether this record is in active use", + "type": "boolean" + }, + "contained": { + "description": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, nor can they have their own independent transaction scope. This is allowed to be a Parameters resource if and only if it is referenced by a resource that provides context/meaning.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + "title": "Contained, inline Resources", + "type": "array" + }, + "description": { + "description": "A summary, characterization or explanation of the body structure.", + "element_property": true, + "pattern": "\\s*(\\S|\\s)*", + "title": "Text description", + "type": "string" + }, + "excludedStructure": { + "description": "The anatomical location(s) or region(s) not occupied or represented by the specimen, lesion, or body structure.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructureIncludedStructure" + }, + "title": "Excluded anatomic locations(s)", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "identifier": { + "description": "Identifier for this instance of the anatomical structure.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "Bodystructure identifier", + "type": "array" + }, + "image": { + "description": "Image or images used to identify a location.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Attachment" + }, + "title": "Attached images", + "type": "array" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "includedStructure": { + "description": "The anatomical location(s) or region(s) of the specimen, lesion, or body structure.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructureIncludedStructure" + }, + "title": "Included anatomic location(s)", + "type": "array" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored", + "type": "array" + }, + "morphology": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Codes describing anatomic morphology.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/bodystructure-code", + "binding_version": null, + "description": "The kind of structure being represented by the body structure at `BodyStructure.location`. This can define both normal and abnormal morphologies.", + "element_property": true, + "title": "Kind of Structure" + }, + "patient": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "body_structure", + "description": "The person to which the body site belongs.", + "element_property": true, + "enum_reference_types": [ + "Patient" + ], + "title": "Who this is about" + }, + "resourceType": { + "const": "BodyStructure", + "default": "BodyStructure", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative", + "description": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "element_property": true, + "title": "Text summary of the resource, for human interpretation" + } + }, + "required": [ + "includedStructure", + "patient" + ], + "title": "BodyStructure", + "type": "object" + }, + "ObservationComponent": { + "$id": "http://graph-fhir.io/schema/0.0.2/ObservationComponent", + "additionalProperties": false, + "description": "Component results. Some observations have multiple component observations. These component observations are expressed as separate code value pairs that share the same attributes. Examples include systolic and diastolic component observations for blood pressure measurement and multiple component observations for genetics observations. [See https://hl7.org/fhir/R5/ObservationComponent.html]", + "links": [], + "properties": { + "_valueBoolean": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueBoolean'." + }, + "_valueDateTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueDateTime'." + }, + "_valueInteger": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueInteger'." + }, + "_valueString": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueString'." + }, + "_valueTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueTime'." + }, + "code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Codes identifying names of simple observations.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/observation-codes", + "binding_version": null, + "description": "Describes what was observed. Sometimes this is called the observation \"code\".", + "element_property": true, + "title": "Type of component observation (code / type)" + }, + "dataAbsentReason": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Codes specifying why the result (`Observation.value[x]`) is missing.", + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/data-absent-reason", + "binding_version": null, + "description": "Provides a reason why the expected value in the element Observation.component.value[x] is missing.", + "element_property": true, + "title": "Why the component result is missing" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "interpretation": { + "binding_description": "Codes identifying interpretations of observations.", + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/observation-interpretation", + "binding_version": null, + "description": "A categorical assessment of an observation value. For example, high, low, normal.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "High, low, normal, etc", + "type": "array" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "referenceRange": { + "description": "Guidance on how to interpret the value by comparison to a normal or recommended range.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ObservationReferenceRange" + }, + "title": "Provides guide for interpretation of component result", + "type": "array" + }, + "resourceType": { + "const": "ObservationComponent", + "default": "ObservationComponent", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "valueAttachment": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Attachment", + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual component result" + }, + "valueBoolean": { + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual component result", + "type": "boolean" + }, + "valueCodeableConcept": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual component result" + }, + "valueDateTime": { + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "format": "date-time", + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual component result", + "type": "string" + }, + "valueInteger": { + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual component result", + "type": "integer" + }, + "valuePeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual component result" + }, + "valueQuantity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual component result" + }, + "valueRange": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Range", + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual component result" + }, + "valueRatio": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Ratio", + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual component result" + }, + "valueReference": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "observation_component", + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "enum_reference_types": [ + "MolecularSequence" + ], + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual component result" + }, + "valueSampledData": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SampledData", + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual component result" + }, + "valueString": { + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Actual component result", + "type": "string" + }, + "valueTime": { + "description": "The information determined as a result of making the observation, if the information has a simple value.", + "element_property": true, + "format": "time", + "one_of_many": "value", + "one_of_many_required": false, + "title": "Actual component result", + "type": "string" + } + }, + "required": [ + "code" + ], + "title": "ObservationComponent", + "type": "object" + }, + "Address": { + "$id": "http://graph-fhir.io/schema/0.0.2/Address", + "additionalProperties": false, + "description": "An address expressed using postal conventions (as opposed to GPS or other location definition formats). An address expressed using postal conventions (as opposed to GPS or other location definition formats). This data type may be used to convey addresses for use in delivering mail as well as for visiting locations which might not be valid for mail delivery. There are a variety of postal address formats defined around the world. The ISO21090-codedString may be used to provide a coded representation of the contents of strings in an Address. [See https://hl7.org/fhir/R5/Address.html]", + "links": [], + "properties": { + "_city": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'city'." + }, + "_country": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'country'." + }, + "_district": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'district'." + }, + "_line": { + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension" + }, + "title": "Extension field for 'line'.", + "type": "array" + }, + "_postalCode": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'postalCode'." + }, + "_state": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'state'." + }, + "_text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'text'." + }, + "_type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'type'." + }, + "_use": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'use'." + }, + "city": { + "description": "The name of the city, town, suburb, village or other community or delivery center.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Name of city, town etc.", + "type": "string" + }, + "country": { + "description": "Country - a nation as commonly understood or generally accepted.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Country (e.g. may be ISO 3166 2 or 3 letter code)", + "type": "string" + }, + "district": { + "description": "The name of the administrative area (county).", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "District name (aka county)", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "line": { + "description": "This component contains the house number, apartment number, street name, street direction, P.O. Box number, delivery hints, and similar address information.", + "element_property": true, + "items": { + "pattern": "[ \\r\\n\\t\\S]+", + "type": "string" + }, + "title": "Street name, number, direction & P.O. Box etc.", + "type": "array" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "period": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "element_property": true, + "title": "Time period when address was/is in use" + }, + "postalCode": { + "description": "A postal code designating a region defined by the postal service.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Postal code for area", + "type": "string" + }, + "resourceType": { + "const": "Address", + "default": "Address", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "state": { + "description": "Sub-unit of a country with limited sovereignty in a federally organized country. A code may be used if codes are in common use (e.g. US 2 letter state codes).", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Sub-unit of country (abbreviations ok)", + "type": "string" + }, + "text": { + "description": "Specifies the entire address as it should be displayed e.g. on a postal label. This may be provided instead of or as well as the specific parts.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Text representation of the address", + "type": "string" + }, + "type": { + "binding_description": "The type of an address (physical / postal).", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/address-type", + "binding_version": "5.0.0", + "description": "Distinguishes between physical addresses (those you can visit) and mailing addresses (e.g. PO Boxes and care-of addresses). Most addresses are both.", + "element_property": true, + "enum_values": [ + "postal", + "physical", + "both" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "postal | physical | both", + "type": "string" + }, + "use": { + "binding_description": "The use of an address (home / work / etc.).", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/address-use", + "binding_version": "5.0.0", + "description": "The purpose of this address.", + "element_property": true, + "enum_values": [ + "home", + "work", + "temp", + "old", + "billing" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "home | work | temp | old | billing - purpose of this address", + "type": "string" + } + }, + "title": "Address", + "type": "object" + }, + "SubstanceDefinitionStructureRepresentation": { + "$id": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionStructureRepresentation", + "additionalProperties": false, + "description": "A depiction of the structure of the substance. [See https://hl7.org/fhir/R5/SubstanceDefinitionStructureRepresentation.html]", + "links": [ + { + "href": "{id}", + "rel": "document", + "targetHints": { + "backref": [ + "substance_definition_structure_representation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/document/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_representation": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'representation'." + }, + "document": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "substance_definition_structure_representation", + "description": "An attached file with the structural representation e.g. a molecular structure graphic of the substance, a JCAMP or AnIML file.", + "element_property": true, + "enum_reference_types": [ + "DocumentReference" + ], + "title": "An attachment with the structural representation e.g. a structure graphic or AnIML file" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "format": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "A format of a substance representation.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-representation-format", + "binding_version": null, + "description": "The format of the representation e.g. InChI, SMILES, MOLFILE, CDX, SDF, PDB, mmCIF. The logical content type rather than the physical file format of a document.", + "element_property": true, + "title": "The format of the representation e.g. InChI, SMILES, MOLFILE (note: not the physical file format)" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "representation": { + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "The structural representation as a text string in a standard format", + "type": "string" + }, + "resourceType": { + "const": "SubstanceDefinitionStructureRepresentation", + "default": "SubstanceDefinitionStructureRepresentation", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "A format of a substance representation.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-representation-type", + "binding_version": null, + "element_property": true, + "title": "The kind of structural representation (e.g. full, partial)" + } + }, + "title": "SubstanceDefinitionStructureRepresentation", + "type": "object" + }, + "Expression": { + "$id": "http://graph-fhir.io/schema/0.0.2/Expression", + "additionalProperties": false, + "description": "An expression that can be used to generate a value. A expression that is evaluated in a specified context and returns a value. The context of use of the expression must specify the context in which the expression is evaluated, and how the result of the expression is used. [See https://hl7.org/fhir/R5/Expression.html]", + "links": [], + "properties": { + "_description": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'description'." + }, + "_expression": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'expression'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "_name": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'name'." + }, + "_reference": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'reference'." + }, + "description": { + "description": "A brief, natural language description of the condition that effectively communicates the intended semantics.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Natural language description of the condition", + "type": "string" + }, + "expression": { + "description": "An expression in the specified language that returns a value.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Expression in specified language", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "language": { + "binding_description": "The media type of the expression language.", + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/expression-language", + "binding_version": null, + "description": "The media type of the language for the expression.", + "element_property": true, + "enum_values": [ + "text/cql", + "text/fhirpath", + "application/x-fhir-query", + "etc." + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "text/cql | text/fhirpath | application/x-fhir-query | etc.", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "name": { + "description": "A short name assigned to the expression to allow for multiple reuse of the expression in the context where it is defined.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Short name assigned to expression for reuse", + "type": "string" + }, + "reference": { + "description": "A URI that defines where the expression is found.", + "element_property": true, + "pattern": "\\S*", + "title": "Where the expression is found", + "type": "string" + }, + "resourceType": { + "const": "Expression", + "default": "Expression", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "title": "Expression", + "type": "object" + }, + "SubstanceIngredient": { + "$id": "http://graph-fhir.io/schema/0.0.2/SubstanceIngredient", + "additionalProperties": false, + "description": "Composition information about the substance. A substance can be composed of other substances. [See https://hl7.org/fhir/R5/SubstanceIngredient.html]", + "links": [ + { + "href": "{id}", + "rel": "substanceReference", + "targetHints": { + "backref": [ + "substance_ingredient" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/substanceReference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "quantity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Ratio", + "description": "The amount of the ingredient in the substance - a concentration ratio.", + "element_property": true, + "title": "Optional amount (concentration)" + }, + "resourceType": { + "const": "SubstanceIngredient", + "default": "SubstanceIngredient", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "substanceCodeableConcept": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "description": "Another substance that is a component of this substance.", + "element_property": true, + "one_of_many": "substance", + "one_of_many_required": true, + "title": "A component of the substance" + }, + "substanceReference": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "substance_ingredient", + "description": "Another substance that is a component of this substance.", + "element_property": true, + "enum_reference_types": [ + "Substance" + ], + "one_of_many": "substance", + "one_of_many_required": true, + "title": "A component of the substance" + } + }, + "title": "SubstanceIngredient", + "type": "object" + }, + "Reference": { + "$id": "http://graph-fhir.io/schema/0.0.2/Reference", + "additionalProperties": false, + "description": "A reference from one resource to another. [See https://hl7.org/fhir/R5/Reference.html]", + "links": [], + "properties": { + "_display": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'display'." + }, + "_reference": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'reference'." + }, + "_type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'type'." + }, + "display": { + "description": "Plain text narrative that identifies the resource in addition to the resource reference.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Text alternative for the resource", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "identifier": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier", + "description": "An identifier for the target resource. This is used when there is no way to reference the other resource directly, either because the entity it represents is not available through a FHIR server, or because there is no way for the author of the resource to convert a known identifier to an actual location. There is no requirement that a Reference.identifier point to something that is actually exposed as a FHIR instance, but it SHALL point to a business concept that would be expected to be exposed as a FHIR instance, and that instance would need to be of a FHIR resource type allowed by the reference.", + "element_property": true, + "title": "Logical reference, when literal reference is not known" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "reference": { + "description": "A reference to a location at which the other resource is found. The reference may be a relative reference, in which case it is relative to the service base URL, or an absolute URL that resolves to the location where the resource is found. The reference may be version specific or not. If the reference is not to a FHIR RESTful server, then it should be assumed to be version specific. Internal fragment references (start with '#') refer to contained resources.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Literal reference, Relative, internal or absolute URL", + "type": "string" + }, + "resourceType": { + "const": "Reference", + "default": "Reference", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "type": { + "binding_description": "Aa resource (or, for logical models, the URI of the logical model).", + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/resource-types", + "binding_version": null, + "description": "The expected type of the target of the reference. If both Reference.type and Reference.reference are populated and Reference.reference is a FHIR URL, both SHALL be consistent. The type is the Canonical URL of Resource Definition that is the type this reference refers to. References are URLs that are relative to http://hl7.org/fhir/StructureDefinition/ e.g. \"Patient\" is a reference to http://hl7.org/fhir/StructureDefinition/Patient. Absolute URLs are only allowed for logical models (and can only be used in references in logical models, not resources).", + "element_property": true, + "pattern": "\\S*", + "title": "Type the reference refers to (e.g. \"Patient\") - must be a resource in resources", + "type": "string" + } + }, + "title": "Reference", + "type": "object" + }, + "SubstanceDefinitionMoiety": { + "$id": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionMoiety", + "additionalProperties": false, + "description": "Moiety, for structural modifications. [See https://hl7.org/fhir/R5/SubstanceDefinitionMoiety.html]", + "links": [], + "properties": { + "_amountString": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'amountString'." + }, + "_molecularFormula": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'molecularFormula'." + }, + "_name": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'name'." + }, + "amountQuantity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "element_property": true, + "one_of_many": "amount", + "one_of_many_required": false, + "title": "Quantitative value for this moiety" + }, + "amountString": { + "element_property": true, + "one_of_many": "amount", + "one_of_many_required": false, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Quantitative value for this moiety", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "identifier": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier", + "element_property": true, + "title": "Identifier by which this moiety substance is known" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "measurementType": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The relationship between two substance types.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-amount-type", + "binding_version": null, + "description": "The measurement type of the quantitative value. In capturing the actual relative amounts of substances or molecular fragments it may be necessary to indicate whether the amount refers to, for example, a mole ratio or weight ratio.", + "element_property": true, + "title": "The measurement type of the quantitative value" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "molecularFormula": { + "description": "Molecular formula for this moiety of this substance, typically using the Hill system.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Molecular formula for this moiety (e.g. with the Hill system)", + "type": "string" + }, + "name": { + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Textual name for this moiety substance", + "type": "string" + }, + "opticalActivity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The optical rotation type of a substance.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-optical-activity", + "binding_version": null, + "element_property": true, + "title": "Optical activity type" + }, + "resourceType": { + "const": "SubstanceDefinitionMoiety", + "default": "SubstanceDefinitionMoiety", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "role": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "element_property": true, + "title": "Role that the moiety is playing" + }, + "stereochemistry": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The optical rotation type of a substance.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-stereochemistry", + "binding_version": null, + "element_property": true, + "title": "Stereochemistry type" + } + }, + "title": "SubstanceDefinitionMoiety", + "type": "object" + }, + "Availability": { + "$id": "http://graph-fhir.io/schema/0.0.2/Availability", + "additionalProperties": false, + "description": "Availability data for an {item}. [See https://hl7.org/fhir/R5/Availability.html]", + "links": [], + "properties": { + "availableTime": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/AvailabilityAvailableTime" + }, + "title": "Times the {item} is available", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "notAvailableTime": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/AvailabilityNotAvailableTime" + }, + "title": "Not available during this time due to provided reason", + "type": "array" + }, + "resourceType": { + "const": "Availability", + "default": "Availability", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "title": "Availability", + "type": "object" + }, + "Count": { + "$id": "http://graph-fhir.io/schema/0.0.2/Count", + "additionalProperties": false, + "description": "A measured or measurable amount. A measured amount (or an amount that can potentially be measured). Note that measured amounts include amounts that are not precisely quantified, including amounts involving arbitrary units and floating currencies. [See https://hl7.org/fhir/R5/Count.html]", + "links": [], + "properties": { + "_code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'code'." + }, + "_comparator": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'comparator'." + }, + "_system": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'system'." + }, + "_unit": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'unit'." + }, + "_value": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'value'." + }, + "code": { + "description": "A computer processable form of the unit in some unit representation system.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Coded form of the unit", + "type": "string" + }, + "comparator": { + "binding_description": "How the Quantity should be understood and represented.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/quantity-comparator", + "binding_version": "5.0.0", + "description": "How the value should be understood and represented - whether the actual value is greater or less than the stated value due to measurement issues; e.g. if the comparator is \"<\" , then the real value is < stated value.", + "element_property": true, + "enum_values": [ + "<", + "<=", + ">=", + ">", + "ad" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "< | <= | >= | > | ad - how to understand the value", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "resourceType": { + "const": "Count", + "default": "Count", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "system": { + "description": "The identification of the system that provides the coded form of the unit.", + "element_property": true, + "pattern": "\\S*", + "title": "System that defines coded unit form", + "type": "string" + }, + "unit": { + "description": "A human-readable form of the unit.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unit representation", + "type": "string" + }, + "value": { + "description": "The value of the measured amount. The value includes an implicit precision in the presentation of the value.", + "element_property": true, + "title": "Numerical value (with implicit precision)", + "type": "number" + } + }, + "title": "Count", + "type": "object" + }, + "Quantity": { + "$id": "http://graph-fhir.io/schema/0.0.2/Quantity", + "additionalProperties": false, + "description": "A measured or measurable amount. A measured amount (or an amount that can potentially be measured). Note that measured amounts include amounts that are not precisely quantified, including amounts involving arbitrary units and floating currencies. [See https://hl7.org/fhir/R5/Quantity.html]", + "links": [], + "properties": { + "_code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'code'." + }, + "_comparator": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'comparator'." + }, + "_system": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'system'." + }, + "_unit": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'unit'." + }, + "_value": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'value'." + }, + "code": { + "description": "A computer processable form of the unit in some unit representation system.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Coded form of the unit", + "type": "string" + }, + "comparator": { + "binding_description": "How the Quantity should be understood and represented.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/quantity-comparator", + "binding_version": "5.0.0", + "description": "How the value should be understood and represented - whether the actual value is greater or less than the stated value due to measurement issues; e.g. if the comparator is \"<\" , then the real value is < stated value.", + "element_property": true, + "enum_values": [ + "<", + "<=", + ">=", + ">", + "ad" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "< | <= | >= | > | ad - how to understand the value", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "resourceType": { + "const": "Quantity", + "default": "Quantity", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "system": { + "description": "The identification of the system that provides the coded form of the unit.", + "element_property": true, + "pattern": "\\S*", + "title": "System that defines coded unit form", + "type": "string" + }, + "unit": { + "description": "A human-readable form of the unit.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unit representation", + "type": "string" + }, + "value": { + "description": "The value of the measured amount. The value includes an implicit precision in the presentation of the value.", + "element_property": true, + "title": "Numerical value (with implicit precision)", + "type": "number" + } + }, + "title": "Quantity", + "type": "object" + }, + "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark": { + "$id": "http://graph-fhir.io/schema/0.0.2/BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + "additionalProperties": false, + "description": "Landmark relative location. The distance in centimeters a certain observation is made from a body landmark. [See https://hl7.org/fhir/R5/BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark.html]", + "links": [ + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/device", + "href": "{id}", + "rel": "device_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/device/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "device": { + "backref": "device_body_structure_included_structure_body_landmark_orientation_distance_from_landmark", + "binding_description": "Codes to identify medical devices.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/device-type", + "binding_version": null, + "description": "An instrument, tool, analyzer, etc. used in the measurement.", + "element_property": true, + "enum_reference_types": [ + "Device" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference" + }, + "title": "Measurement device", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + "default": "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "value": { + "description": "The measured distance (e.g., in cm) from a body landmark.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity" + }, + "title": "Measured distance from body landmark", + "type": "array" + } + }, + "title": "BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark", + "type": "object" + }, + "DocumentReferenceAttester": { + "$id": "http://graph-fhir.io/schema/0.0.2/DocumentReferenceAttester", + "additionalProperties": false, + "description": "Attests to accuracy of the document. A participant who has authenticated the accuracy of the document. [See https://hl7.org/fhir/R5/DocumentReferenceAttester.html]", + "links": [ + { + "href": "{id}", + "rel": "party_Patient", + "targetHints": { + "backref": [ + "document_reference_attester" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/party/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "party_Practitioner", + "targetHints": { + "backref": [ + "document_reference_attester" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/party/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "party_PractitionerRole", + "targetHints": { + "backref": [ + "document_reference_attester" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/party/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "party_Organization", + "targetHints": { + "backref": [ + "document_reference_attester" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/party/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_time": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'time'." + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "mode": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The way in which a person authenticated a document.", + "binding_strength": "preferred", + "binding_uri": "http://hl7.org/fhir/ValueSet/composition-attestation-mode", + "binding_version": null, + "description": "The type of attestation the authenticator offers.", + "element_property": true, + "title": "personal | professional | legal | official" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "party": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "document_reference_attester", + "description": "Who attested the document in the specified way.", + "element_property": true, + "enum_reference_types": [ + "Patient", + "RelatedPerson", + "Practitioner", + "PractitionerRole", + "Organization" + ], + "title": "Who attested the document" + }, + "resourceType": { + "const": "DocumentReferenceAttester", + "default": "DocumentReferenceAttester", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "time": { + "description": "When the document was attested by the party.", + "element_property": true, + "format": "date-time", + "title": "When the document was attested", + "type": "string" + } + }, + "required": [ + "mode" + ], + "title": "DocumentReferenceAttester", + "type": "object" + }, + "DocumentReferenceRelatesTo": { + "$id": "http://graph-fhir.io/schema/0.0.2/DocumentReferenceRelatesTo", + "additionalProperties": false, + "description": "Relationships to other documents. Relationships that this document has with other document references that already exist. [See https://hl7.org/fhir/R5/DocumentReferenceRelatesTo.html]", + "links": [ + { + "href": "{id}", + "rel": "target", + "targetHints": { + "backref": [ + "document_reference_relates_to" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/target/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The type of relationship between the documents.", + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/document-relationship-type", + "binding_version": null, + "description": "The type of relationship that this document has with anther document.", + "element_property": true, + "title": "The relationship type with another document" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "DocumentReferenceRelatesTo", + "default": "DocumentReferenceRelatesTo", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "target": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "document_reference_relates_to", + "description": "The target document of this relationship.", + "element_property": true, + "enum_reference_types": [ + "DocumentReference" + ], + "title": "Target of the relationship" + } + }, + "required": [ + "code", + "target" + ], + "title": "DocumentReferenceRelatesTo", + "type": "object" + }, + "Narrative": { + "$id": "http://graph-fhir.io/schema/0.0.2/Narrative", + "additionalProperties": false, + "description": "Human-readable summary of the resource (essential clinical and business information). A human-readable summary of the resource conveying the essential clinical and business information for the resource. [See https://hl7.org/fhir/R5/Narrative.html]", + "links": [], + "properties": { + "_div": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'div'." + }, + "_status": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'status'." + }, + "div": { + "description": "The actual narrative content, a stripped down version of XHTML.", + "element_property": true, + "element_required": true, + "title": "Limited xhtml content", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "resourceType": { + "const": "Narrative", + "default": "Narrative", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "status": { + "binding_description": "The status of a resource narrative.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/narrative-status", + "binding_version": "5.0.0", + "description": "The status of the narrative - whether it's entirely generated (from just the defined data or the extensions too), or whether a human authored it and it may contain additional data.", + "element_property": true, + "element_required": true, + "enum_values": [ + "generated", + "extensions", + "additional", + "empty" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "generated | extensions | additional | empty", + "type": "string" + } + }, + "title": "Narrative", + "type": "object" + }, + "SpecimenFeature": { + "$id": "http://graph-fhir.io/schema/0.0.2/SpecimenFeature", + "additionalProperties": false, + "description": "The physical feature of a specimen. A physical feature or landmark on a specimen, highlighted for context by the collector of the specimen (e.g. surgeon), that identifies the type of feature as well as its meaning (e.g. the red ink indicating the resection margin of the right lobe of the excised prostate tissue or wire loop at radiologically suspected tumor location). [See https://hl7.org/fhir/R5/SpecimenFeature.html]", + "links": [], + "properties": { + "_description": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'description'." + }, + "description": { + "description": "Description of the feature of the specimen.", + "element_property": true, + "element_required": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Information about the feature", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "SpecimenFeature", + "default": "SpecimenFeature", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "SNOMED CT Body site concepts", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/body-site", + "binding_version": null, + "description": "The landmark or feature being highlighted.", + "element_property": true, + "title": "Highlighted feature" + } + }, + "required": [ + "type" + ], + "title": "SpecimenFeature", + "type": "object" + }, + "DocumentReferenceContent": { + "$id": "http://graph-fhir.io/schema/0.0.2/DocumentReferenceContent", + "additionalProperties": false, + "description": "Document referenced. The document and format referenced. If there are multiple content element repetitions, these must all represent the same document in different format, or attachment metadata. [See https://hl7.org/fhir/R5/DocumentReferenceContent.html]", + "links": [], + "properties": { + "attachment": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Attachment", + "description": "The document or URL of the document along with critical metadata to prove content has integrity.", + "element_property": true, + "title": "Where to access the document" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "profile": { + "description": "An identifier of the document constraints, encoding, structure, and template that the document conforms to beyond the base format indicated in the mimeType.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReferenceContentProfile" + }, + "title": "Content profile rules for the document", + "type": "array" + }, + "resourceType": { + "const": "DocumentReferenceContent", + "default": "DocumentReferenceContent", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "required": [ + "attachment" + ], + "title": "DocumentReferenceContent", + "type": "object" + }, + "ResearchStudy": { + "$id": "http://graph-fhir.io/schema/0.0.2/ResearchStudy", + "additionalProperties": false, + "description": "Investigation to increase healthcare-related patient-independent knowledge. A scientific study of nature that sometimes includes processes involved in health and disease. For example, clinical trials are research studies that involve people. These studies may be related to new ways to screen, prevent, diagnose, and treat disease. They may also study certain outcomes and certain groups of people by looking at data collected in the past or future. [See https://hl7.org/fhir/R5/ResearchStudy.html]", + "links": [ + { + "href": "{id}", + "rel": "rootDir_Directory", + "targetHints": { + "backref": [], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Directory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Directory" + }, + "templatePointers": { + "id": "/rootDir/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "partOf", + "targetHints": { + "backref": [ + "partOf_research_study" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/partOf/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "result_DiagnosticReport", + "targetHints": { + "backref": [ + "result_research_study" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/result/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "site_ResearchStudy", + "targetHints": { + "backref": [ + "site_research_study" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/site/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "site_Organization", + "targetHints": { + "backref": [ + "site_research_study" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/site/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ResearchStudyAssociatedParty/associatedParty", + "href": "{id}", + "rel": "associatedParty_party_Practitioner", + "targetHints": { + "backref": [ + "research_study_associated_party" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/associatedParty/-/party/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ResearchStudyAssociatedParty/associatedParty", + "href": "{id}", + "rel": "associatedParty_party_PractitionerRole", + "targetHints": { + "backref": [ + "research_study_associated_party" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/associatedParty/-/party/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ResearchStudyAssociatedParty/associatedParty", + "href": "{id}", + "rel": "associatedParty_party_Organization", + "targetHints": { + "backref": [ + "research_study_associated_party" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/associatedParty/-/party/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ResearchStudyComparisonGroup/comparisonGroup", + "href": "{id}", + "rel": "comparisonGroup_observedGroup", + "targetHints": { + "backref": [ + "research_study_comparison_group" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/comparisonGroup/-/observedGroup/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/focus", + "href": "{id}", + "rel": "focus_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/focus/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/focus", + "href": "{id}", + "rel": "focus_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/focus/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/focus", + "href": "{id}", + "rel": "focus_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/focus/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/focus", + "href": "{id}", + "rel": "focus_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/focus/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/focus", + "href": "{id}", + "rel": "focus_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/focus/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/focus", + "href": "{id}", + "rel": "focus_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/focus/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/focus", + "href": "{id}", + "rel": "focus_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/focus/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/focus", + "href": "{id}", + "rel": "focus_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/focus/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/focus", + "href": "{id}", + "rel": "focus_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/focus/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/focus", + "href": "{id}", + "rel": "focus_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/focus/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/focus", + "href": "{id}", + "rel": "focus_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/focus/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/focus", + "href": "{id}", + "rel": "focus_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/focus/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/focus", + "href": "{id}", + "rel": "focus_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/focus/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/focus", + "href": "{id}", + "rel": "focus_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/focus/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/focus", + "href": "{id}", + "rel": "focus_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/focus/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/focus", + "href": "{id}", + "rel": "focus_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/focus/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/focus", + "href": "{id}", + "rel": "focus_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/focus/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/focus", + "href": "{id}", + "rel": "focus_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/focus/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/focus", + "href": "{id}", + "rel": "focus_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/focus/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/focus", + "href": "{id}", + "rel": "focus_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/focus/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/focus", + "href": "{id}", + "rel": "focus_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/focus/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/focus", + "href": "{id}", + "rel": "focus_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/focus/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/focus", + "href": "{id}", + "rel": "focus_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/focus/-/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Practitioner", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_PractitionerRole", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Patient", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Organization", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ResearchStudyRecruitment/recruitment", + "href": "{id}", + "rel": "recruitment_actualGroup", + "targetHints": { + "backref": [ + "actualGroup_research_study_recruitment" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/recruitment/actualGroup/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ResearchStudyRecruitment/recruitment", + "href": "{id}", + "rel": "recruitment_eligibility_Group", + "targetHints": { + "backref": [ + "eligibility_research_study_recruitment" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/recruitment/eligibility/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/relatedArtifact", + "href": "{id}", + "rel": "relatedArtifact_resourceReference_Organization", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/relatedArtifact/-/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/relatedArtifact", + "href": "{id}", + "rel": "relatedArtifact_resourceReference_Group", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/relatedArtifact/-/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/relatedArtifact", + "href": "{id}", + "rel": "relatedArtifact_resourceReference_Practitioner", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/relatedArtifact/-/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/relatedArtifact", + "href": "{id}", + "rel": "relatedArtifact_resourceReference_PractitionerRole", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/relatedArtifact/-/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/relatedArtifact", + "href": "{id}", + "rel": "relatedArtifact_resourceReference_ResearchStudy", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/relatedArtifact/-/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/relatedArtifact", + "href": "{id}", + "rel": "relatedArtifact_resourceReference_Patient", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/relatedArtifact/-/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/relatedArtifact", + "href": "{id}", + "rel": "relatedArtifact_resourceReference_ResearchSubject", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/relatedArtifact/-/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/relatedArtifact", + "href": "{id}", + "rel": "relatedArtifact_resourceReference_Substance", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/relatedArtifact/-/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/relatedArtifact", + "href": "{id}", + "rel": "relatedArtifact_resourceReference_SubstanceDefinition", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/relatedArtifact/-/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/relatedArtifact", + "href": "{id}", + "rel": "relatedArtifact_resourceReference_Specimen", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/relatedArtifact/-/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/relatedArtifact", + "href": "{id}", + "rel": "relatedArtifact_resourceReference_Observation", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/relatedArtifact/-/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/relatedArtifact", + "href": "{id}", + "rel": "relatedArtifact_resourceReference_DiagnosticReport", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/relatedArtifact/-/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/relatedArtifact", + "href": "{id}", + "rel": "relatedArtifact_resourceReference_Condition", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/relatedArtifact/-/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/relatedArtifact", + "href": "{id}", + "rel": "relatedArtifact_resourceReference_Medication", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/relatedArtifact/-/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/relatedArtifact", + "href": "{id}", + "rel": "relatedArtifact_resourceReference_MedicationAdministration", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/relatedArtifact/-/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/relatedArtifact", + "href": "{id}", + "rel": "relatedArtifact_resourceReference_MedicationStatement", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/relatedArtifact/-/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/relatedArtifact", + "href": "{id}", + "rel": "relatedArtifact_resourceReference_MedicationRequest", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/relatedArtifact/-/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/relatedArtifact", + "href": "{id}", + "rel": "relatedArtifact_resourceReference_Procedure", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/relatedArtifact/-/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/relatedArtifact", + "href": "{id}", + "rel": "relatedArtifact_resourceReference_DocumentReference", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/relatedArtifact/-/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/relatedArtifact", + "href": "{id}", + "rel": "relatedArtifact_resourceReference_Task", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/relatedArtifact/-/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/relatedArtifact", + "href": "{id}", + "rel": "relatedArtifact_resourceReference_ImagingStudy", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/relatedArtifact/-/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/relatedArtifact", + "href": "{id}", + "rel": "relatedArtifact_resourceReference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/relatedArtifact/-/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/relatedArtifact", + "href": "{id}", + "rel": "relatedArtifact_resourceReference_BodyStructure", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/relatedArtifact/-/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_date": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'date'." + }, + "_description": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'description'." + }, + "_descriptionSummary": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'descriptionSummary'." + }, + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "_name": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'name'." + }, + "_status": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'status'." + }, + "_title": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'title'." + }, + "_url": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'url'." + }, + "_version": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'version'." + }, + "associatedParty": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudyAssociatedParty" + }, + "title": "Sponsors, collaborators, and other parties", + "type": "array" + }, + "classifier": { + "binding_description": "desc.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/research-study-classifiers", + "binding_version": null, + "description": "Additional grouping mechanism or categorization of a research study. Example: FDA regulated device, FDA regulated drug, MPG Paragraph 23b (a German legal requirement), IRB-exempt, etc. Implementation Note: do not use the classifier element to support existing semantics that are already supported thru explicit elements in the resource.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Classification for the study", + "type": "array" + }, + "comparisonGroup": { + "description": "Describes an expected event or sequence of events for one of the subjects of a study. E.g. for a living subject: exposure to drug A, wash-out, exposure to drug B, wash-out, follow-up. E.g. for a stability study: {store sample from lot A at 25 degrees for 1 month}, {store sample from lot A at 40 degrees for 1 month}.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudyComparisonGroup" + }, + "title": "Defined path through the study for a subject", + "type": "array" + }, + "condition": { + "binding_description": "Identification of the condition or diagnosis.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/condition-code", + "binding_version": null, + "description": "The condition that is the focus of the study. For example, In a study to examine risk factors for Lupus, might have as an inclusion criterion \"healthy volunteer\", but the target condition code would be a Lupus SNOMED code.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Condition being studied", + "type": "array" + }, + "contained": { + "description": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, nor can they have their own independent transaction scope. This is allowed to be a Parameters resource if and only if it is referenced by a resource that provides context/meaning.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + "title": "Contained, inline Resources", + "type": "array" + }, + "date": { + "description": "The date (and optionally time) when the ResearchStudy Resource was last significantly changed. The date must change when the business version changes and it must change if the status code changes. In addition, it should change when the substantive content of the ResearchStudy Resource changes.", + "element_property": true, + "format": "date-time", + "title": "Date the resource last changed", + "type": "string" + }, + "description": { + "description": "A detailed and human-readable narrative of the study. E.g., study abstract.", + "element_property": true, + "pattern": "\\s*(\\S|\\s)*", + "title": "Detailed narrative of the study", + "type": "string" + }, + "descriptionSummary": { + "description": "A brief text for explaining the study.", + "element_property": true, + "pattern": "\\s*(\\S|\\s)*", + "title": "Brief text explaining the study", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "focus": { + "backref": "focus_research_study", + "binding_description": "Common codes of research study focus", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/research-study-focus-type", + "binding_version": null, + "description": "The medication(s), food(s), therapy(ies), device(s) or other concerns or interventions that the study is seeking to gain more information about.", + "element_property": true, + "enum_reference_types": [ + "Medication", + "MedicinalProductDefinition", + "SubstanceDefinition", + "EvidenceVariable" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference" + }, + "title": "Drugs, devices, etc. under study", + "type": "array" + }, + "rootDir": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "rootdir_research_study", + "enum_reference_types": [ + "Directory" + ], + "type": "object" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "identifier": { + "description": "Identifiers assigned to this research study by the sponsor or other systems.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "Business Identifier for study", + "type": "array" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "keyword": { + "description": "Key terms to aid in searching for or filtering the study.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Used to search for the study", + "type": "array" + }, + "label": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudyLabel" + }, + "title": "Additional names for the study", + "type": "array" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored", + "type": "array" + }, + "name": { + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Name for this study (computer friendly)", + "type": "string" + }, + "note": { + "description": "Comments made about the study by the performer, subject or other participants.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Annotation" + }, + "title": "Comments made about the study", + "type": "array" + }, + "objective": { + "description": "A goal that the study is aiming to achieve in terms of a scientific question to be answered by the analysis of data collected during the study.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudyObjective" + }, + "title": "A goal for the study", + "type": "array" + }, + "outcomeMeasure": { + "description": "An \"outcome measure\", \"endpoint\", \"effect measure\" or \"measure of effect\" is a specific measurement or observation used to quantify the effect of experimental variables on the participants in a study, or for observational studies, to describe patterns of diseases or traits or associations with exposures, risk factors or treatment.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudyOutcomeMeasure" + }, + "title": "A variable measured during the study", + "type": "array" + }, + "partOf": { + "backref": "partOf_research_study", + "description": "A larger research study of which this particular study is a component or step.", + "element_property": true, + "enum_reference_types": [ + "ResearchStudy" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Part of larger study", + "type": "array" + }, + "period": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "Identifies the start date and the expected (or actual, depending on status) end date for the study.", + "element_property": true, + "title": "When the study began and ended" + }, + "phase": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Codes for the stage in the progression of a therapy from initial experimental use in humans in clinical trials to post-market evaluation.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/research-study-phase", + "binding_version": null, + "description": "The stage in the progression of a therapy from initial experimental use in humans in clinical trials to post-market evaluation.", + "element_property": true, + "title": "n-a | early-phase-1 | phase-1 | phase-1-phase-2 | phase-2 | phase-2-phase-3 | phase-3 | phase-4" + }, + "primaryPurposeType": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Codes for the main intent of the study.", + "binding_strength": "preferred", + "binding_uri": "http://hl7.org/fhir/ValueSet/research-study-prim-purp-type", + "binding_version": null, + "description": "The type of study based upon the intent of the study activities. A classification of the intent of the study.", + "element_property": true, + "title": "treatment | prevention | diagnostic | supportive-care | screening | health-services-research | basic-science | device-feasibility" + }, + "progressStatus": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudyProgressStatus" + }, + "title": "Status of study with time for that status", + "type": "array" + }, + "protocol": { + "backref": "protocol_research_study", + "description": "The set of steps expected to be performed as part of the execution of the study.", + "element_property": true, + "enum_reference_types": [ + "PlanDefinition" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Steps followed in executing study", + "type": "array" + }, + "recruitment": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudyRecruitment", + "element_property": true, + "title": "Target or actual group of participants enrolled in study" + }, + "region": { + "binding_description": "Countries and regions within which this artifact is targeted for use.", + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/jurisdiction", + "binding_version": null, + "description": "A country, state or other area where the study is taking place rather than its precise geographic location or address.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Geographic area for the study", + "type": "array" + }, + "relatedArtifact": { + "description": "Citations, references, URLs and other related documents. When using relatedArtifact to share URLs, the relatedArtifact.type will often be set to one of \"documentation\" or \"supported-with\" and the URL value will often be in relatedArtifact.document.url but another possible location is relatedArtifact.resource when it is a canonical URL.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/RelatedArtifact" + }, + "title": "References, URLs, and attachments", + "type": "array" + }, + "resourceType": { + "const": "ResearchStudy", + "default": "ResearchStudy", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "result": { + "backref": "result_research_study", + "description": "Link to one or more sets of results generated by the study. Could also link to a research registry holding the results such as ClinicalTrials.gov.", + "element_property": true, + "enum_reference_types": [ + "EvidenceReport", + "Citation", + "DiagnosticReport" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Link to results generated during the study", + "type": "array" + }, + "site": { + "backref": "site_research_study", + "description": "A facility in which study activities are conducted.", + "element_property": true, + "enum_reference_types": [ + "Location", + "ResearchStudy", + "Organization" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Facility where study activities are conducted", + "type": "array" + }, + "status": { + "binding_description": "Codes that convey the current publication status of the research study resource.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/publication-status", + "binding_version": "5.0.0", + "description": "The publication state of the resource (not of the study).", + "element_property": true, + "element_required": true, + "enum_values": [ + "draft", + "active", + "retired", + "unknown" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "draft | active | retired | unknown", + "type": "string" + }, + "studyDesign": { + "binding_description": "This is a set of terms for study design characteristics.", + "binding_strength": "preferred", + "binding_uri": "http://hl7.org/fhir/ValueSet/study-design", + "binding_version": null, + "description": "Codes categorizing the type of study such as investigational vs. observational, type of blinding, type of randomization, safety vs. efficacy, etc.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Classifications of the study design characteristics", + "type": "array" + }, + "text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative", + "description": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "element_property": true, + "title": "Text summary of the resource, for human interpretation" + }, + "title": { + "description": "The human readable name of the research study.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Human readable name of the study", + "type": "string" + }, + "url": { + "description": "Canonical identifier for this study resource, represented as a globally unique URI.", + "element_property": true, + "pattern": "\\S*", + "title": "Canonical identifier for this study resource", + "type": "string" + }, + "version": { + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "The business version for the study record", + "type": "string" + }, + "whyStopped": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Codes for why the study ended prematurely.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/research-study-reason-stopped", + "binding_version": null, + "description": "A description and/or code explaining the premature termination of the study.", + "element_property": true, + "title": "accrual-goal-met | closed-due-to-toxicity | closed-due-to-lack-of-study-progress | temporarily-closed-per-study-design" + } + }, + "title": "ResearchStudy", + "type": "object" + }, + "DataRequirementDateFilter": { + "$id": "http://graph-fhir.io/schema/0.0.2/DataRequirementDateFilter", + "additionalProperties": false, + "description": "What dates/date ranges are expected. Date filters specify additional constraints on the data in terms of the applicable date range for specific elements. Each date filter specifies an additional constraint on the data, i.e. date filters are AND'ed, not OR'ed. [See https://hl7.org/fhir/R5/DataRequirementDateFilter.html]", + "links": [], + "properties": { + "_path": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'path'." + }, + "_searchParam": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'searchParam'." + }, + "_valueDateTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueDateTime'." + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "path": { + "description": "The date-valued attribute of the filter. The specified path SHALL be a FHIRPath resolvable on the specified type of the DataRequirement, and SHALL consist only of identifiers, constant indexers, and .resolve(). The path is allowed to contain qualifiers (.) to traverse sub-elements, as well as indexers ([x]) to traverse multiple-cardinality sub-elements (see the [Simple FHIRPath Profile](fhirpath.html#simple) for full details). Note that the index must be an integer constant. The path must resolve to an element of type date, dateTime, Period, Schedule, or Timing.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "A date-valued attribute to filter on", + "type": "string" + }, + "resourceType": { + "const": "DataRequirementDateFilter", + "default": "DataRequirementDateFilter", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "searchParam": { + "description": "A date parameter that refers to a search parameter defined on the specified type of the DataRequirement, and which searches on elements of type date, dateTime, Period, Schedule, or Timing.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "A date valued parameter to search on", + "type": "string" + }, + "valueDateTime": { + "description": "The value of the filter. If period is specified, the filter will return only those data items that fall within the bounds determined by the Period, inclusive of the period boundaries. If dateTime is specified, the filter will return only those data items that are equal to the specified dateTime. If a Duration is specified, the filter will return only those data items that fall within Duration before now.", + "element_property": true, + "format": "date-time", + "one_of_many": "value", + "one_of_many_required": false, + "title": "The value of the filter, as a Period, DateTime, or Duration value", + "type": "string" + }, + "valueDuration": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Duration", + "description": "The value of the filter. If period is specified, the filter will return only those data items that fall within the bounds determined by the Period, inclusive of the period boundaries. If dateTime is specified, the filter will return only those data items that are equal to the specified dateTime. If a Duration is specified, the filter will return only those data items that fall within Duration before now.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "The value of the filter, as a Period, DateTime, or Duration value" + }, + "valuePeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "The value of the filter. If period is specified, the filter will return only those data items that fall within the bounds determined by the Period, inclusive of the period boundaries. If dateTime is specified, the filter will return only those data items that are equal to the specified dateTime. If a Duration is specified, the filter will return only those data items that fall within Duration before now.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "The value of the filter, as a Period, DateTime, or Duration value" + } + }, + "title": "DataRequirementDateFilter", + "type": "object" + }, + "Signature": { + "$id": "http://graph-fhir.io/schema/0.0.2/Signature", + "additionalProperties": false, + "description": "A Signature - XML DigSig, JWS, Graphical image of signature, etc.. A signature along with supporting context. The signature may be a digital signature that is cryptographic in nature, or some other signature acceptable to the domain. This other signature may be as simple as a graphical image representing a hand-written signature, or a signature ceremony Different signature approaches have different utilities. [See https://hl7.org/fhir/R5/Signature.html]", + "links": [ + { + "href": "{id}", + "rel": "onBehalfOf_Practitioner", + "targetHints": { + "backref": [ + "onBehalfOf_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/onBehalfOf/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "onBehalfOf_PractitionerRole", + "targetHints": { + "backref": [ + "onBehalfOf_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/onBehalfOf/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "onBehalfOf_Patient", + "targetHints": { + "backref": [ + "onBehalfOf_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/onBehalfOf/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "onBehalfOf_Organization", + "targetHints": { + "backref": [ + "onBehalfOf_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/onBehalfOf/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "who_Practitioner", + "targetHints": { + "backref": [ + "who_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/who/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "who_PractitionerRole", + "targetHints": { + "backref": [ + "who_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/who/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "who_Patient", + "targetHints": { + "backref": [ + "who_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/who/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "who_Organization", + "targetHints": { + "backref": [ + "who_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/who/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_data": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'data'." + }, + "_sigFormat": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'sigFormat'." + }, + "_targetFormat": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'targetFormat'." + }, + "_when": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'when'." + }, + "data": { + "description": "The base64 encoding of the Signature content. When signature is not recorded electronically this element would be empty.", + "element_property": true, + "format": "binary", + "title": "The actual signature content (XML DigSig. JWS, picture, etc.)", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "onBehalfOf": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "onBehalfOf_signature", + "description": "A reference to an application-usable description of the identity that is represented by the signature.", + "element_property": true, + "enum_reference_types": [ + "Practitioner", + "PractitionerRole", + "RelatedPerson", + "Patient", + "Device", + "Organization" + ], + "title": "The party represented" + }, + "resourceType": { + "const": "Signature", + "default": "Signature", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "sigFormat": { + "binding_description": "BCP 13 (RFCs 2045, 2046, 2047, 4288, 4289 and 2049)", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/mimetypes", + "binding_version": "5.0.0", + "description": "A mime type that indicates the technical format of the signature. Important mime types are application/signature+xml for X ML DigSig, application/jose for JWS, and image/* for a graphical image of a signature, etc.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "The technical format of the signature", + "type": "string" + }, + "targetFormat": { + "binding_description": "BCP 13 (RFCs 2045, 2046, 2047, 4288, 4289 and 2049)", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/mimetypes", + "binding_version": "5.0.0", + "description": "A mime type that indicates the technical format of the target resources signed by the signature.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "The technical format of the signed resources", + "type": "string" + }, + "type": { + "binding_description": "An indication of the reason that an entity signed the object.", + "binding_strength": "preferred", + "binding_uri": "http://hl7.org/fhir/ValueSet/signature-type", + "binding_version": null, + "description": "An indication of the reason that the entity signed this document. This may be explicitly included as part of the signature information and can be used when determining accountability for various actions concerning the document.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Coding" + }, + "title": "Indication of the reason the entity signed the object(s)", + "type": "array" + }, + "when": { + "description": "When the digital signature was signed.", + "element_property": true, + "format": "date-time", + "title": "When the signature was created", + "type": "string" + }, + "who": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "who_signature", + "description": "A reference to an application-usable description of the identity that signed (e.g. the signature used their private key).", + "element_property": true, + "enum_reference_types": [ + "Practitioner", + "PractitionerRole", + "RelatedPerson", + "Patient", + "Device", + "Organization" + ], + "title": "Who signed" + } + }, + "title": "Signature", + "type": "object" + }, + "Dosage": { + "$id": "http://graph-fhir.io/schema/0.0.2/Dosage", + "additionalProperties": false, + "description": "How the medication is/was taken or should be taken. Indicates how the medication is/was taken or should be taken by the patient. [See https://hl7.org/fhir/R5/Dosage.html]", + "links": [], + "properties": { + "_asNeeded": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'asNeeded'." + }, + "_patientInstruction": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'patientInstruction'." + }, + "_sequence": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'sequence'." + }, + "_text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'text'." + }, + "additionalInstruction": { + "binding_description": "A coded concept identifying additional instructions such as \"take with water\" or \"avoid operating heavy machinery\".", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/additional-instruction-codes", + "binding_version": null, + "description": "Supplemental instructions to the patient on how to take the medication (e.g. \"with meals\" or\"take half to one hour before food\") or warnings for the patient about the medication (e.g. \"may cause drowsiness\" or \"avoid exposure of skin to direct sunlight or sunlamps\").", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Supplemental instruction or warnings to the patient - e.g. \"with meals\", \"may cause drowsiness\"", + "type": "array" + }, + "asNeeded": { + "description": "Indicates whether the Medication is only taken when needed within a specific dosing schedule (Boolean option).", + "element_property": true, + "title": "Take \"as needed\"", + "type": "boolean" + }, + "asNeededFor": { + "binding_description": "A coded concept identifying the precondition that should be met or evaluated prior to consuming or administering a medication dose. For example \"pain\", \"30 minutes prior to sexual intercourse\", \"on flare-up\" etc.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/medication-as-needed-reason", + "binding_version": null, + "description": "Indicates whether the Medication is only taken based on a precondition for taking the Medication (CodeableConcept).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Take \"as needed\" (for x)", + "type": "array" + }, + "doseAndRate": { + "description": "Depending on the resource,this is the amount of medication administered, to be administered or typical amount to be administered.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DosageDoseAndRate" + }, + "title": "Amount of medication administered, to be administered or typical amount to be administered", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "maxDosePerAdministration": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "element_property": true, + "title": "Upper limit on medication per administration" + }, + "maxDosePerLifetime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "element_property": true, + "title": "Upper limit on medication per lifetime of the patient" + }, + "maxDosePerPeriod": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Ratio" + }, + "title": "Upper limit on medication per unit of time", + "type": "array" + }, + "method": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "A coded concept describing the technique by which the medicine is administered.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/administration-method-codes", + "binding_version": null, + "element_property": true, + "title": "Technique for administering medication" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "patientInstruction": { + "description": "Instructions in terms that are understood by the patient or consumer.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Patient or consumer oriented instructions", + "type": "string" + }, + "resourceType": { + "const": "Dosage", + "default": "Dosage", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "route": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "A coded concept describing the route or physiological path of administration of a therapeutic agent into or onto the body of a subject.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/route-codes", + "binding_version": null, + "element_property": true, + "title": "How drug should enter body" + }, + "sequence": { + "description": "Indicates the order in which the dosage instructions should be applied or interpreted.", + "element_property": true, + "title": "The order of the dosage instructions", + "type": "integer" + }, + "site": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "A coded concept describing the site location the medicine enters into or onto the body.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/approach-site-codes", + "binding_version": null, + "element_property": true, + "title": "Body site to administer to" + }, + "text": { + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Free text dosage instructions e.g. SIG", + "type": "string" + }, + "timing": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Timing", + "element_property": true, + "title": "When medication should be administered" + } + }, + "title": "Dosage", + "type": "object" + }, + "PatientCommunication": { + "$id": "http://graph-fhir.io/schema/0.0.2/PatientCommunication", + "additionalProperties": false, + "description": "A language which may be used to communicate with the patient about his or her health. [See https://hl7.org/fhir/R5/PatientCommunication.html]", + "links": [], + "properties": { + "_preferred": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'preferred'." + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The ISO-639-1 alpha 2 code in lower case for the language, optionally followed by a hyphen and the ISO-3166-1 alpha 2 code for the region in upper case; e.g. \"en\" for English, or \"en-US\" for American English versus \"en-AU\" for Australian English.", + "element_property": true, + "title": "The language which can be used to communicate with the patient about his or her health" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "preferred": { + "description": "Indicates whether or not the patient prefers this language (over other languages he masters up a certain level).", + "element_property": true, + "title": "Language preference indicator", + "type": "boolean" + }, + "resourceType": { + "const": "PatientCommunication", + "default": "PatientCommunication", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "required": [ + "language" + ], + "title": "PatientCommunication", + "type": "object" + }, + "Specimen": { + "$id": "http://graph-fhir.io/schema/0.0.2/Specimen", + "additionalProperties": false, + "description": "Sample for analysis. A sample to be used for analysis. [See https://hl7.org/fhir/R5/Specimen.html]", + "links": [ + { + "href": "{id}", + "rel": "parent", + "targetHints": { + "backref": [ + "parent_specimen" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/parent/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Patient", + "targetHints": { + "backref": [ + "specimen" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Group", + "targetHints": { + "backref": [ + "specimen" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Substance", + "targetHints": { + "backref": [ + "specimen" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From SpecimenCollection/collection", + "href": "{id}", + "rel": "collection_collector_Practitioner", + "targetHints": { + "backref": [ + "specimen_collection" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/collection/collector/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From SpecimenCollection/collection", + "href": "{id}", + "rel": "collection_collector_PractitionerRole", + "targetHints": { + "backref": [ + "specimen_collection" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/collection/collector/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From SpecimenCollection/collection", + "href": "{id}", + "rel": "collection_collector_Patient", + "targetHints": { + "backref": [ + "specimen_collection" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/collection/collector/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From SpecimenCollection/collection", + "href": "{id}", + "rel": "collection_procedure", + "targetHints": { + "backref": [ + "specimen_collection" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/collection/procedure/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Practitioner", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_PractitionerRole", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Patient", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Organization", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From SpecimenProcessing/processing", + "href": "{id}", + "rel": "processing_additive", + "targetHints": { + "backref": [ + "additive_specimen_processing" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/processing/-/additive/-/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_combined": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'combined'." + }, + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "_receivedTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'receivedTime'." + }, + "_status": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'status'." + }, + "accessionIdentifier": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier", + "description": "The identifier assigned by the lab when accessioning specimen(s). This is not necessarily the same as the specimen identifier, depending on local lab procedures.", + "element_property": true, + "title": "Identifier assigned by the lab" + }, + "collection": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SpecimenCollection", + "description": "Details concerning the specimen collection.", + "element_property": true, + "title": "Collection details" + }, + "combined": { + "binding_description": "Codes for the combined status of a specimen.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/specimen-combined", + "binding_version": "5.0.0", + "description": "This element signifies if the specimen is part of a group or pooled.", + "element_property": true, + "enum_values": [ + "grouped", + "pooled" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "grouped | pooled", + "type": "string" + }, + "condition": { + "binding_description": "Codes describing the state of the specimen.", + "binding_strength": "extensible", + "binding_uri": "http://terminology.hl7.org/ValueSet/v2-0493", + "binding_version": null, + "description": "A mode or state of being that describes the nature of the specimen.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "State of the specimen", + "type": "array" + }, + "contained": { + "description": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, nor can they have their own independent transaction scope. This is allowed to be a Parameters resource if and only if it is referenced by a resource that provides context/meaning.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + "title": "Contained, inline Resources", + "type": "array" + }, + "container": { + "description": "The container holding the specimen. The recursive nature of containers; i.e. blood in tube in tray in rack is not addressed here.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SpecimenContainer" + }, + "title": "Direct container of specimen (tube/slide, etc.)", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "feature": { + "description": "A physical feature or landmark on a specimen, highlighted for context by the collector of the specimen (e.g. surgeon), that identifies the type of feature as well as its meaning (e.g. the red ink indicating the resection margin of the right lobe of the excised prostate tissue or wire loop at radiologically suspected tumor location).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SpecimenFeature" + }, + "title": "The physical feature of a specimen", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "identifier": { + "description": "Id for specimen.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "External Identifier", + "type": "array" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored", + "type": "array" + }, + "note": { + "description": "To communicate any details or issues about the specimen or during the specimen collection. (for example: broken vial, sent with patient, frozen).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Annotation" + }, + "title": "Comments", + "type": "array" + }, + "parent": { + "backref": "parent_specimen", + "description": "Reference to the parent (source) specimen which is used when the specimen was either derived from or a component of another specimen.", + "element_property": true, + "enum_reference_types": [ + "Specimen" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Specimen from which this specimen originated", + "type": "array" + }, + "processing": { + "description": "Details concerning processing and processing steps for the specimen.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SpecimenProcessing" + }, + "title": "Processing and processing step details", + "type": "array" + }, + "receivedTime": { + "description": "Time when specimen is received by the testing laboratory for processing or testing.", + "element_property": true, + "format": "date-time", + "title": "The time when specimen is received by the testing laboratory", + "type": "string" + }, + "request": { + "backref": "request_specimen", + "description": "Details concerning a service request that required a specimen to be collected.", + "element_property": true, + "enum_reference_types": [ + "ServiceRequest" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Why the specimen was collected", + "type": "array" + }, + "resourceType": { + "const": "Specimen", + "default": "Specimen", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "role": { + "binding_description": "Codes describing specimen role.", + "binding_strength": "preferred", + "binding_uri": "http://hl7.org/fhir/ValueSet/specimen-role", + "binding_version": null, + "description": "The role or reason for the specimen in the testing workflow.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "The role the specimen serves", + "type": "array" + }, + "status": { + "binding_description": "Codes providing the status/availability of a specimen.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/specimen-status", + "binding_version": "5.0.0", + "description": "The availability of the specimen.", + "element_property": true, + "enum_values": [ + "available", + "unavailable", + "unsatisfactory", + "entered-in-error" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "available | unavailable | unsatisfactory | entered-in-error", + "type": "string" + }, + "subject": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "specimen", + "element_property": true, + "enum_reference_types": [ + "Patient", + "Group", + "Device", + "BiologicallyDerivedProduct", + "Substance", + "Location" + ], + "title": "Where the specimen came from. This may be from patient(s), from a location (e.g., the source of an environmental sample), or a sampling of a substance, a biologically-derived product, or a device" + }, + "text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative", + "description": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "element_property": true, + "title": "Text summary of the resource, for human interpretation" + }, + "type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The type of the specimen.", + "binding_strength": "example", + "binding_uri": "http://terminology.hl7.org/ValueSet/v2-0487", + "binding_version": null, + "description": "The kind of material that forms the specimen.", + "element_property": true, + "title": "Kind of material that forms the specimen" + } + }, + "title": "Specimen", + "type": "object" + }, + "MedicationAdministrationDosage": { + "$id": "http://graph-fhir.io/schema/0.0.2/MedicationAdministrationDosage", + "additionalProperties": false, + "description": "Details of how medication was taken. Describes the medication dosage information details e.g. dose, rate, site, route, etc. [See https://hl7.org/fhir/R5/MedicationAdministrationDosage.html]", + "links": [], + "properties": { + "_text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'text'." + }, + "dose": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "The amount of the medication given at one administration event. Use this value when the administration is essentially an instantaneous event such as a swallowing a tablet or giving an injection.", + "element_property": true, + "title": "Amount of medication per dose" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "method": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "A coded concept describing the technique by which the medicine is administered.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/administration-method-codes", + "binding_version": null, + "description": "A coded value indicating the method by which the medication is intended to be or was introduced into or on the body. This attribute will most often NOT be populated. It is most commonly used for injections. For example, Slow Push, Deep IV.", + "element_property": true, + "title": "How drug was administered" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "rateQuantity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "Identifies the speed with which the medication was or will be introduced into the patient. Typically, the rate for an infusion e.g. 100 ml per 1 hour or 100 ml/hr. May also be expressed as a rate per unit of time, e.g. 500 ml per 2 hours. Other examples: 200 mcg/min or 200 mcg/1 minute; 1 liter/8 hours.", + "element_property": true, + "one_of_many": "rate", + "one_of_many_required": false, + "title": "Dose quantity per unit of time" + }, + "rateRatio": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Ratio", + "description": "Identifies the speed with which the medication was or will be introduced into the patient. Typically, the rate for an infusion e.g. 100 ml per 1 hour or 100 ml/hr. May also be expressed as a rate per unit of time, e.g. 500 ml per 2 hours. Other examples: 200 mcg/min or 200 mcg/1 minute; 1 liter/8 hours.", + "element_property": true, + "one_of_many": "rate", + "one_of_many_required": false, + "title": "Dose quantity per unit of time" + }, + "resourceType": { + "const": "MedicationAdministrationDosage", + "default": "MedicationAdministrationDosage", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "route": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "A coded concept describing the route or physiological path of administration of a therapeutic agent into or onto the body of a subject.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/route-codes", + "binding_version": null, + "description": "A code specifying the route or physiological path of administration of a therapeutic agent into or onto the patient. For example, topical, intravenous, etc.", + "element_property": true, + "title": "Path of substance into body" + }, + "site": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "A coded concept describing the site location the medicine enters into or onto the body.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/approach-site-codes", + "binding_version": null, + "description": "A coded specification of the anatomic site where the medication first entered the body. For example, \"left arm\".", + "element_property": true, + "title": "Body site administered to" + }, + "text": { + "description": "Free text dosage can be used for cases where the dosage administered is too complex to code. When coded dosage is present, the free text dosage may still be present for display to humans. The dosage instructions should reflect the dosage of the medication that was administered.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Free text dosage instructions e.g. SIG", + "type": "string" + } + }, + "title": "MedicationAdministrationDosage", + "type": "object" + }, + "SpecimenContainer": { + "$id": "http://graph-fhir.io/schema/0.0.2/SpecimenContainer", + "additionalProperties": false, + "description": "Direct container of specimen (tube/slide, etc.). The container holding the specimen. The recursive nature of containers; i.e. blood in tube in tray in rack is not addressed here. [See https://hl7.org/fhir/R5/SpecimenContainer.html]", + "links": [], + "properties": { + "device": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "specimen_container", + "description": "The device resource for the the container holding the specimen. If the container is in a holder then the referenced device will point to a parent device.", + "element_property": true, + "enum_reference_types": [ + "Device" + ], + "title": "Device resource for the container" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "location": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "specimen_container", + "description": "The location of the container holding the specimen.", + "element_property": true, + "enum_reference_types": [ + "Location" + ], + "title": "Where the container is" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "SpecimenContainer", + "default": "SpecimenContainer", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "specimenQuantity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "The quantity of specimen in the container; may be volume, dimensions, or other appropriate measurements, depending on the specimen type.", + "element_property": true, + "title": "Quantity of specimen within container" + } + }, + "required": [ + "device" + ], + "title": "SpecimenContainer", + "type": "object" + }, + "Extension": { + "$id": "http://graph-fhir.io/schema/0.0.2/Extension", + "additionalProperties": false, + "description": "Optional Extensions Element. Optional Extension Element - found in all resources. [See https://hl7.org/fhir/R5/Extension.html]", + "links": [ + { + "href": "{id}", + "rel": "valueReference_Organization", + "targetHints": { + "backref": [ + "extension" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Group", + "targetHints": { + "backref": [ + "extension" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Practitioner", + "targetHints": { + "backref": [ + "extension" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_PractitionerRole", + "targetHints": { + "backref": [ + "extension" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_ResearchStudy", + "targetHints": { + "backref": [ + "extension" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Patient", + "targetHints": { + "backref": [ + "extension" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_ResearchSubject", + "targetHints": { + "backref": [ + "extension" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Substance", + "targetHints": { + "backref": [ + "extension" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_SubstanceDefinition", + "targetHints": { + "backref": [ + "extension" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Specimen", + "targetHints": { + "backref": [ + "extension" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Observation", + "targetHints": { + "backref": [ + "extension" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_DiagnosticReport", + "targetHints": { + "backref": [ + "extension" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Condition", + "targetHints": { + "backref": [ + "extension" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Medication", + "targetHints": { + "backref": [ + "extension" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_MedicationAdministration", + "targetHints": { + "backref": [ + "extension" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_MedicationStatement", + "targetHints": { + "backref": [ + "extension" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_MedicationRequest", + "targetHints": { + "backref": [ + "extension" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Procedure", + "targetHints": { + "backref": [ + "extension" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_DocumentReference", + "targetHints": { + "backref": [ + "extension" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Task", + "targetHints": { + "backref": [ + "extension" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_ImagingStudy", + "targetHints": { + "backref": [ + "extension" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "extension" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_BodyStructure", + "targetHints": { + "backref": [ + "extension" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/valueAnnotation", + "href": "{id}", + "rel": "valueAnnotation_authorReference_Practitioner", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/valueAnnotation/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/valueAnnotation", + "href": "{id}", + "rel": "valueAnnotation_authorReference_PractitionerRole", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/valueAnnotation/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/valueAnnotation", + "href": "{id}", + "rel": "valueAnnotation_authorReference_Patient", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/valueAnnotation/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/valueAnnotation", + "href": "{id}", + "rel": "valueAnnotation_authorReference_Organization", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueAnnotation/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From DataRequirement/valueDataRequirement", + "href": "{id}", + "rel": "valueDataRequirement_subjectReference", + "targetHints": { + "backref": [ + "data_requirement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/valueDataRequirement/subjectReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ExtendedContactDetail/valueExtendedContactDetail", + "href": "{id}", + "rel": "valueExtendedContactDetail_organization", + "targetHints": { + "backref": [ + "extended_contact_detail" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueExtendedContactDetail/organization/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Organization", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Group", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Practitioner", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_PractitionerRole", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_ResearchStudy", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Patient", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_ResearchSubject", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Substance", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_SubstanceDefinition", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Specimen", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Observation", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_DiagnosticReport", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Condition", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Medication", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_MedicationAdministration", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_MedicationStatement", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_MedicationRequest", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Procedure", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_DocumentReference", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Task", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_ImagingStudy", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_BodyStructure", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_onBehalfOf_Practitioner", + "targetHints": { + "backref": [ + "onBehalfOf_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/valueSignature/onBehalfOf/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_onBehalfOf_PractitionerRole", + "targetHints": { + "backref": [ + "onBehalfOf_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/valueSignature/onBehalfOf/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_onBehalfOf_Patient", + "targetHints": { + "backref": [ + "onBehalfOf_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/valueSignature/onBehalfOf/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_onBehalfOf_Organization", + "targetHints": { + "backref": [ + "onBehalfOf_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueSignature/onBehalfOf/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_who_Practitioner", + "targetHints": { + "backref": [ + "who_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/valueSignature/who/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_who_PractitionerRole", + "targetHints": { + "backref": [ + "who_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/valueSignature/who/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_who_Patient", + "targetHints": { + "backref": [ + "who_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/valueSignature/who/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_who_Organization", + "targetHints": { + "backref": [ + "who_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueSignature/who/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From UsageContext/valueUsageContext", + "href": "{id}", + "rel": "valueUsageContext_valueReference_ResearchStudy", + "targetHints": { + "backref": [ + "usage_context" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/valueUsageContext/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From UsageContext/valueUsageContext", + "href": "{id}", + "rel": "valueUsageContext_valueReference_Group", + "targetHints": { + "backref": [ + "usage_context" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/valueUsageContext/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From UsageContext/valueUsageContext", + "href": "{id}", + "rel": "valueUsageContext_valueReference_Organization", + "targetHints": { + "backref": [ + "usage_context" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueUsageContext/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "resourceType": { + "const": "Extension", + "default": "Extension", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "url": { + "description": "Source of the definition for the extension code - a logical name or a URL.", + "element_property": true, + "element_required": true, + "pattern": "\\S*", + "title": "identifies the meaning of the extension", + "type": "string" + }, + "valueAddress": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Address", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueAge": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Age", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueAnnotation": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Annotation", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueAttachment": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Attachment", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueAvailability": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Availability", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueBase64Binary": { + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "format": "binary", + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension", + "type": "string" + }, + "valueBoolean": { + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension", + "type": "boolean" + }, + "valueCanonical": { + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "pattern": "\\S*", + "title": "Value of extension", + "type": "string" + }, + "valueCode": { + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Value of extension", + "type": "string" + }, + "valueCodeableConcept": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueCodeableReference": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference", + "backref": "extension", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueCoding": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Coding", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueContactDetail": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ContactDetail", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueContactPoint": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ContactPoint", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueCount": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Count", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueDataRequirement": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DataRequirement", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueDate": { + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "format": "date", + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension", + "type": "string" + }, + "valueDateTime": { + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "format": "date-time", + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension", + "type": "string" + }, + "valueDecimal": { + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension", + "type": "number" + }, + "valueDistance": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Distance", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueDosage": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Dosage", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueDuration": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Duration", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueExpression": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Expression", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueExtendedContactDetail": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ExtendedContactDetail", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueHumanName": { + "$ref": "http://graph-fhir.io/schema/0.0.2/HumanName", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueId": { + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "one_of_many": "value", + "one_of_many_required": false, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Value of extension", + "type": "string" + }, + "valueIdentifier": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueInstant": { + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "format": "date-time", + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension", + "type": "string" + }, + "valueInteger": { + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension", + "type": "integer" + }, + "valueInteger64": { + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension", + "type": "integer" + }, + "valueMarkdown": { + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "pattern": "\\s*(\\S|\\s)*", + "title": "Value of extension", + "type": "string" + }, + "valueMeta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueMoney": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Money", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueOid": { + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "pattern": "^urn:oid:[0-2](\\.(0|[1-9][0-9]*))+$", + "title": "Value of extension", + "type": "string" + }, + "valueParameterDefinition": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ParameterDefinition", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valuePeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valuePositiveInt": { + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "exclusiveMinimum": 0, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension", + "type": "integer" + }, + "valueQuantity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueRange": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Range", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueRatio": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Ratio", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueRatioRange": { + "$ref": "http://graph-fhir.io/schema/0.0.2/RatioRange", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueReference": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "extension", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "enum_reference_types": [ + "Organization", + "Group", + "Practitioner", + "PractitionerRole", + "ResearchStudy", + "Patient", + "ResearchSubject", + "Substance", + "SubstanceDefinition", + "Specimen", + "Observation", + "DiagnosticReport", + "Condition", + "Medication", + "MedicationAdministration", + "MedicationStatement", + "MedicationRequest", + "Procedure", + "DocumentReference", + "Task", + "ImagingStudy", + "FamilyMemberHistory", + "BodyStructure" + ], + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueRelatedArtifact": { + "$ref": "http://graph-fhir.io/schema/0.0.2/RelatedArtifact", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueSampledData": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SampledData", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueSignature": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Signature", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueString": { + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Value of extension", + "type": "string" + }, + "valueTime": { + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "format": "time", + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension", + "type": "string" + }, + "valueTiming": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Timing", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueTriggerDefinition": { + "$ref": "http://graph-fhir.io/schema/0.0.2/TriggerDefinition", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueUnsignedInt": { + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "minimum": 0, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension", + "type": "integer" + }, + "valueUri": { + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "pattern": "\\S*", + "title": "Value of extension", + "type": "string" + }, + "valueUrl": { + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "format": "uri", + "maxLength": 65536, + "minLength": 1, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension", + "type": "string" + }, + "valueUsageContext": { + "$ref": "http://graph-fhir.io/schema/0.0.2/UsageContext", + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension" + }, + "valueUuid": { + "description": "Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).", + "element_property": true, + "format": "uuid", + "one_of_many": "value", + "one_of_many_required": false, + "title": "Value of extension", + "type": "string" + } + }, + "title": "Extension", + "type": "object" + }, + "HumanName": { + "$id": "http://graph-fhir.io/schema/0.0.2/HumanName", + "additionalProperties": false, + "description": "Name of a human or other living entity - parts and usage. A name, normally of a human, that can be used for other living entities (e.g. animals but not organizations) that have been assigned names by a human and may need the use of name parts or the need for usage information. [See https://hl7.org/fhir/R5/HumanName.html]", + "links": [], + "properties": { + "_family": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'family'." + }, + "_given": { + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension" + }, + "title": "Extension field for 'given'.", + "type": "array" + }, + "_prefix": { + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension" + }, + "title": "Extension field for 'prefix'.", + "type": "array" + }, + "_suffix": { + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension" + }, + "title": "Extension field for 'suffix'.", + "type": "array" + }, + "_text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'text'." + }, + "_use": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'use'." + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "family": { + "description": "The part of a name that links to the genealogy. In some cultures (e.g. Eritrea) the family name of a son is the first name of his father.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Family name (often called 'Surname')", + "type": "string" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "given": { + "description": "Given name.", + "element_property": true, + "items": { + "pattern": "[ \\r\\n\\t\\S]+", + "type": "string" + }, + "title": "Given names (not always 'first'). Includes middle names", + "type": "array" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "period": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "Indicates the period of time when this name was valid for the named person.", + "element_property": true, + "title": "Time period when name was/is in use" + }, + "prefix": { + "description": "Part of the name that is acquired as a title due to academic, legal, employment or nobility status, etc. and that appears at the start of the name.", + "element_property": true, + "items": { + "pattern": "[ \\r\\n\\t\\S]+", + "type": "string" + }, + "title": "Parts that come before the name", + "type": "array" + }, + "resourceType": { + "const": "HumanName", + "default": "HumanName", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "suffix": { + "description": "Part of the name that is acquired as a title due to academic, legal, employment or nobility status, etc. and that appears at the end of the name.", + "element_property": true, + "items": { + "pattern": "[ \\r\\n\\t\\S]+", + "type": "string" + }, + "title": "Parts that come after the name", + "type": "array" + }, + "text": { + "description": "Specifies the entire name as it should be displayed e.g. on an application UI. This may be provided instead of or as well as the specific parts.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Text representation of the full name", + "type": "string" + }, + "use": { + "binding_description": "The use of a human name.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/name-use", + "binding_version": "5.0.0", + "description": "Identifies the purpose for this name.", + "element_property": true, + "enum_values": [ + "usual", + "official", + "temp", + "nickname", + "anonymous", + "old", + "maiden" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "usual | official | temp | nickname | anonymous | old | maiden", + "type": "string" + } + }, + "title": "HumanName", + "type": "object" + }, + "SubstanceDefinitionCharacterization": { + "$id": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionCharacterization", + "additionalProperties": false, + "description": "General specifications for this substance. [See https://hl7.org/fhir/R5/SubstanceDefinitionCharacterization.html]", + "links": [], + "properties": { + "_description": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'description'." + }, + "description": { + "element_property": true, + "pattern": "\\s*(\\S|\\s)*", + "title": "The description or justification in support of the interpretation of the data file", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "file": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Attachment" + }, + "title": "The data produced by the analytical instrument or a pictorial representation of that data. Examples: a JCAMP, JDX, or ADX file, or a chromatogram or spectrum analysis", + "type": "array" + }, + "form": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": null, + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-form", + "binding_version": null, + "element_property": true, + "title": "Describes the nature of the chemical entity and explains, for instance, whether this is a base or a salt form" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "SubstanceDefinitionCharacterization", + "default": "SubstanceDefinitionCharacterization", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "technique": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The method used to elucidate the characterization of the drug substance.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-structure-technique", + "binding_version": null, + "description": "The method used to elucidate the characterization of the drug substance. Example: HPLC.", + "element_property": true, + "title": "The method used to find the characterization e.g. HPLC" + } + }, + "title": "SubstanceDefinitionCharacterization", + "type": "object" + }, + "TriggerDefinition": { + "$id": "http://graph-fhir.io/schema/0.0.2/TriggerDefinition", + "additionalProperties": false, + "description": "Defines an expected trigger for a module. A description of a triggering event. Triggering events can be named events, data events, or periodic, as determined by the type element. [See https://hl7.org/fhir/R5/TriggerDefinition.html]", + "links": [ + { + "$comment": "From DataRequirement/data", + "href": "{id}", + "rel": "data_subjectReference", + "targetHints": { + "backref": [ + "data_requirement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/data/-/subjectReference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_name": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'name'." + }, + "_subscriptionTopic": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'subscriptionTopic'." + }, + "_timingDate": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'timingDate'." + }, + "_timingDateTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'timingDateTime'." + }, + "_type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'type'." + }, + "code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "description": "A code that identifies the event.", + "element_property": true, + "title": "Coded definition of the event" + }, + "condition": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Expression", + "description": "A boolean-valued expression that is evaluated in the context of the container of the trigger definition and returns whether or not the trigger fires.", + "element_property": true, + "title": "Whether the event triggers (boolean expression)" + }, + "data": { + "description": "The triggering data of the event (if this is a data trigger). If more than one data is requirement is specified, then all the data requirements must be true.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DataRequirement" + }, + "title": "Triggering data of the event (multiple = 'and')", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "name": { + "description": "A formal name for the event. This may be an absolute URI that identifies the event formally (e.g. from a trigger registry), or a simple relative URI that identifies the event in a local context.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Name or URI that identifies the event", + "type": "string" + }, + "resourceType": { + "const": "TriggerDefinition", + "default": "TriggerDefinition", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "subscriptionTopic": { + "description": "A reference to a SubscriptionTopic resource that defines the event. If this element is provided, no other information about the trigger definition may be supplied.", + "element_property": true, + "enum_reference_types": [ + "SubscriptionTopic" + ], + "pattern": "\\S*", + "title": "What event", + "type": "string" + }, + "timingDate": { + "description": "The timing of the event (if this is a periodic trigger).", + "element_property": true, + "format": "date", + "one_of_many": "timing", + "one_of_many_required": false, + "title": "Timing of the event", + "type": "string" + }, + "timingDateTime": { + "description": "The timing of the event (if this is a periodic trigger).", + "element_property": true, + "format": "date-time", + "one_of_many": "timing", + "one_of_many_required": false, + "title": "Timing of the event", + "type": "string" + }, + "timingReference": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "trigger_definition", + "description": "The timing of the event (if this is a periodic trigger).", + "element_property": true, + "enum_reference_types": [ + "Schedule" + ], + "one_of_many": "timing", + "one_of_many_required": false, + "title": "Timing of the event" + }, + "timingTiming": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Timing", + "description": "The timing of the event (if this is a periodic trigger).", + "element_property": true, + "one_of_many": "timing", + "one_of_many_required": false, + "title": "Timing of the event" + }, + "type": { + "binding_description": "The type of trigger.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/trigger-type", + "binding_version": "5.0.0", + "description": "The type of triggering event.", + "element_property": true, + "element_required": true, + "enum_values": [ + "named-event", + "periodic", + "data-changed", + "data-added", + "data-modified", + "data-removed", + "data-accessed", + "data-access-ended" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "named-event | periodic | data-changed | data-added | data-modified | data-removed | data-accessed | data-access-ended", + "type": "string" + } + }, + "title": "TriggerDefinition", + "type": "object" + }, + "Meta": { + "$id": "http://graph-fhir.io/schema/0.0.2/Meta", + "additionalProperties": false, + "description": "Metadata about a resource. The metadata about a resource. This is content in the resource that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource. [See https://hl7.org/fhir/R5/Meta.html]", + "links": [], + "properties": { + "_lastUpdated": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'lastUpdated'." + }, + "_profile": { + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension" + }, + "title": "Extension field for 'profile'.", + "type": "array" + }, + "_source": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'source'." + }, + "_versionId": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'versionId'." + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "lastUpdated": { + "description": "When the resource last changed - e.g. when the version changed.", + "element_property": true, + "format": "date-time", + "title": "When the resource version last changed", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "profile": { + "description": "A list of profiles (references to [StructureDefinition](structuredefinition.html#) resources) that this resource claims to conform to. The URL is a reference to [StructureDefinition.url](structuredefinition-definitions.html#StructureDefinition.url).", + "element_property": true, + "enum_reference_types": [ + "StructureDefinition" + ], + "items": { + "pattern": "\\S*", + "type": "string" + }, + "title": "Profiles this resource claims to conform to", + "type": "array" + }, + "resourceType": { + "const": "Meta", + "default": "Meta", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "security": { + "binding_description": "Security Labels from the Healthcare Privacy and Security Classification System.", + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/security-labels", + "binding_version": null, + "description": "Security labels applied to this resource. These tags connect specific resources to the overall security policy and infrastructure.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Coding" + }, + "title": "Security Labels applied to this resource", + "type": "array" + }, + "source": { + "description": "A uri that identifies the source system of the resource. This provides a minimal amount of [Provenance](provenance.html#) information that can be used to track or differentiate the source of information in the resource. The source may identify another FHIR server, document, message, database, etc.", + "element_property": true, + "pattern": "\\S*", + "title": "Identifies where the resource comes from", + "type": "string" + }, + "tag": { + "binding_description": "Codes that represent various types of tags, commonly workflow-related; e.g. \"Needs review by Dr. Jones\".", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/common-tags", + "binding_version": null, + "description": "Tags applied to this resource. Tags are intended to be used to identify and relate resources to process and workflow, and applications are not required to consider the tags when interpreting the meaning of a resource.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Coding" + }, + "title": "Tags applied to this resource", + "type": "array" + }, + "versionId": { + "description": "The version specific identifier, as it appears in the version portion of the URL. This value changes when the resource is created, updated, or deleted.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Version specific identifier", + "type": "string" + } + }, + "title": "Meta", + "type": "object" + }, + "ResearchStudyOutcomeMeasure": { + "$id": "http://graph-fhir.io/schema/0.0.2/ResearchStudyOutcomeMeasure", + "additionalProperties": false, + "description": "A variable measured during the study. An \"outcome measure\", \"endpoint\", \"effect measure\" or \"measure of effect\" is a specific measurement or observation used to quantify the effect of experimental variables on the participants in a study, or for observational studies, to describe patterns of diseases or traits or associations with exposures, risk factors or treatment. [See https://hl7.org/fhir/R5/ResearchStudyOutcomeMeasure.html]", + "links": [], + "properties": { + "_description": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'description'." + }, + "_name": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'name'." + }, + "description": { + "element_property": true, + "pattern": "\\s*(\\S|\\s)*", + "title": "Description of the outcome", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "name": { + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Label for the outcome", + "type": "string" + }, + "reference": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "research_study_outcome_measure", + "element_property": true, + "enum_reference_types": [ + "EvidenceVariable" + ], + "title": "Structured outcome definition" + }, + "resourceType": { + "const": "ResearchStudyOutcomeMeasure", + "default": "ResearchStudyOutcomeMeasure", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "type": { + "binding_description": "defn.", + "binding_strength": "preferred", + "binding_uri": "http://hl7.org/fhir/ValueSet/research-study-objective-type", + "binding_version": null, + "description": "The parameter or characteristic being assessed as one of the values by which the study is assessed.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "primary | secondary | exploratory", + "type": "array" + } + }, + "title": "ResearchStudyOutcomeMeasure", + "type": "object" + }, + "DiagnosticReportMedia": { + "$id": "http://graph-fhir.io/schema/0.0.2/DiagnosticReportMedia", + "additionalProperties": false, + "description": "Key images or data associated with this report. A list of key images or data associated with this report. The images or data are generally created during the diagnostic process, and may be directly of the patient, or of treated specimens (i.e. slides of interest). [See https://hl7.org/fhir/R5/DiagnosticReportMedia.html]", + "links": [ + { + "href": "{id}", + "rel": "link", + "targetHints": { + "backref": [ + "diagnostic_report_media" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/link/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_comment": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'comment'." + }, + "comment": { + "description": "A comment about the image or data. Typically, this is used to provide an explanation for why the image or data is included, or to draw the viewer's attention to important features.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Comment about the image or data (e.g. explanation)", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "link": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "diagnostic_report_media", + "element_property": true, + "enum_reference_types": [ + "DocumentReference" + ], + "title": "Reference to the image or data source" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "DiagnosticReportMedia", + "default": "DiagnosticReportMedia", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "required": [ + "link" + ], + "title": "DiagnosticReportMedia", + "type": "object" + }, + "Identifier": { + "$id": "http://graph-fhir.io/schema/0.0.2/Identifier", + "additionalProperties": false, + "description": "An identifier intended for computation. An identifier - identifies some entity uniquely and unambiguously. Typically this is used for business identifiers. [See https://hl7.org/fhir/R5/Identifier.html]", + "links": [ + { + "href": "{id}", + "rel": "assigner", + "targetHints": { + "backref": [ + "identifier" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/assigner/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_system": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'system'." + }, + "_use": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'use'." + }, + "_value": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'value'." + }, + "assigner": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "identifier", + "description": "Organization that issued/manages the identifier.", + "element_property": true, + "enum_reference_types": [ + "Organization" + ], + "title": "Organization that issued id (may be just text)" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "period": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "Time period during which identifier is/was valid for use.", + "element_property": true, + "title": "Time period when id is/was valid for use" + }, + "resourceType": { + "const": "Identifier", + "default": "Identifier", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "system": { + "description": "Establishes the namespace for the value - that is, an absolute URL that describes a set values that are unique.", + "element_property": true, + "pattern": "\\S*", + "title": "The namespace for the identifier value", + "type": "string" + }, + "type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "A coded type for an identifier that can be used to determine which identifier to use for a specific purpose.", + "binding_strength": "extensible", + "binding_uri": "http://hl7.org/fhir/ValueSet/identifier-type", + "binding_version": null, + "description": "A coded type for the identifier that can be used to determine which identifier to use for a specific purpose.", + "element_property": true, + "title": "Description of identifier" + }, + "use": { + "binding_description": "Identifies the purpose for this identifier, if known .", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/identifier-use", + "binding_version": "5.0.0", + "description": "The purpose of this identifier.", + "element_property": true, + "enum_values": [ + "usual", + "official", + "temp", + "secondary", + "old" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "usual | official | temp | secondary | old (If known)", + "type": "string" + }, + "value": { + "description": "The portion of the identifier typically relevant to the user and which is unique within the context of the system.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "The value that is unique", + "type": "string" + } + }, + "title": "Identifier", + "type": "object" + }, + "MedicationAdministrationPerformer": { + "$id": "http://graph-fhir.io/schema/0.0.2/MedicationAdministrationPerformer", + "additionalProperties": false, + "description": "Who or what performed the medication administration and what type of performance they did. The performer of the medication treatment. For devices this is the device that performed the administration of the medication. An IV Pump would be an example of a device that is performing the administration. Both the IV Pump and the practitioner that set the rate or bolus on the pump can be listed as performers. [See https://hl7.org/fhir/R5/MedicationAdministrationPerformer.html]", + "links": [ + { + "$comment": "From CodeableReference/actor", + "href": "{id}", + "rel": "actor_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/actor/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/actor", + "href": "{id}", + "rel": "actor_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/actor/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/actor", + "href": "{id}", + "rel": "actor_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/actor/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/actor", + "href": "{id}", + "rel": "actor_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/actor/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/actor", + "href": "{id}", + "rel": "actor_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/actor/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/actor", + "href": "{id}", + "rel": "actor_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/actor/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/actor", + "href": "{id}", + "rel": "actor_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/actor/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/actor", + "href": "{id}", + "rel": "actor_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/actor/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/actor", + "href": "{id}", + "rel": "actor_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/actor/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/actor", + "href": "{id}", + "rel": "actor_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/actor/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/actor", + "href": "{id}", + "rel": "actor_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/actor/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/actor", + "href": "{id}", + "rel": "actor_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/actor/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/actor", + "href": "{id}", + "rel": "actor_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/actor/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/actor", + "href": "{id}", + "rel": "actor_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/actor/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/actor", + "href": "{id}", + "rel": "actor_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/actor/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/actor", + "href": "{id}", + "rel": "actor_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/actor/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/actor", + "href": "{id}", + "rel": "actor_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/actor/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/actor", + "href": "{id}", + "rel": "actor_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/actor/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/actor", + "href": "{id}", + "rel": "actor_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/actor/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/actor", + "href": "{id}", + "rel": "actor_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/actor/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/actor", + "href": "{id}", + "rel": "actor_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/actor/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/actor", + "href": "{id}", + "rel": "actor_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/actor/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/actor", + "href": "{id}", + "rel": "actor_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/actor/reference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "actor": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference", + "backref": "medication_administration_performer", + "description": "Indicates who or what performed the medication administration.", + "element_property": true, + "enum_reference_types": [ + "Practitioner", + "PractitionerRole", + "Patient", + "RelatedPerson", + "Device" + ], + "title": "Who or what performed the medication administration" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "function": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "A code describing the role an individual played in administering the medication.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/med-admin-perform-function", + "binding_version": null, + "description": "Distinguishes the type of involvement of the performer in the medication administration.", + "element_property": true, + "title": "Type of performance" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "MedicationAdministrationPerformer", + "default": "MedicationAdministrationPerformer", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "required": [ + "actor" + ], + "title": "MedicationAdministrationPerformer", + "type": "object" + }, + "BodyStructureIncludedStructure": { + "$id": "http://graph-fhir.io/schema/0.0.2/BodyStructureIncludedStructure", + "additionalProperties": false, + "description": "Included anatomic location(s). The anatomical location(s) or region(s) of the specimen, lesion, or body structure. [See https://hl7.org/fhir/R5/BodyStructureIncludedStructure.html]", + "links": [], + "properties": { + "bodyLandmarkOrientation": { + "description": "Body locations in relation to a specific body landmark (tatoo, scar, other body structure).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructureIncludedStructureBodyLandmarkOrientation" + }, + "title": "Landmark relative location", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "laterality": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Concepts modifying the anatomic location.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/bodystructure-relative-location", + "binding_version": null, + "element_property": true, + "title": "Code that represents the included structure laterality" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "qualifier": { + "binding_description": "Concepts modifying the anatomic location.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/bodystructure-relative-location", + "binding_version": null, + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "Code that represents the included structure qualifier", + "type": "array" + }, + "resourceType": { + "const": "BodyStructureIncludedStructure", + "default": "BodyStructureIncludedStructure", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "spatialReference": { + "backref": "spatialReference_body_structure_included_structure", + "description": "XY or XYZ-coordinate orientation for structure.", + "element_property": true, + "enum_reference_types": [ + "ImagingSelection" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Cartesian reference for structure", + "type": "array" + }, + "structure": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "SNOMED CT Body site concepts", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/body-site", + "binding_version": null, + "element_property": true, + "title": "Code that represents the included structure" + } + }, + "required": [ + "structure" + ], + "title": "BodyStructureIncludedStructure", + "type": "object" + }, + "Group": { + "$id": "http://graph-fhir.io/schema/0.0.2/Group", + "additionalProperties": false, + "description": "Group of multiple entities. Represents a defined collection of entities that may be discussed or acted upon collectively but which are not expected to act collectively, and are not formally or legally recognized; i.e. a collection of entities that isn't an Organization. [See https://hl7.org/fhir/R5/Group.html]", + "links": [ + { + "href": "{id}", + "rel": "managingEntity_Organization", + "targetHints": { + "backref": [ + "group" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/managingEntity/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "managingEntity_Practitioner", + "targetHints": { + "backref": [ + "group" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/managingEntity/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "managingEntity_PractitionerRole", + "targetHints": { + "backref": [ + "group" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/managingEntity/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupCharacteristic/characteristic", + "href": "{id}", + "rel": "characteristic_valueReference_Organization", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/characteristic/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupCharacteristic/characteristic", + "href": "{id}", + "rel": "characteristic_valueReference_Group", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/characteristic/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupCharacteristic/characteristic", + "href": "{id}", + "rel": "characteristic_valueReference_Practitioner", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/characteristic/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupCharacteristic/characteristic", + "href": "{id}", + "rel": "characteristic_valueReference_PractitionerRole", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/characteristic/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupCharacteristic/characteristic", + "href": "{id}", + "rel": "characteristic_valueReference_ResearchStudy", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/characteristic/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupCharacteristic/characteristic", + "href": "{id}", + "rel": "characteristic_valueReference_Patient", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/characteristic/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupCharacteristic/characteristic", + "href": "{id}", + "rel": "characteristic_valueReference_ResearchSubject", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/characteristic/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupCharacteristic/characteristic", + "href": "{id}", + "rel": "characteristic_valueReference_Substance", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/characteristic/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupCharacteristic/characteristic", + "href": "{id}", + "rel": "characteristic_valueReference_SubstanceDefinition", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/characteristic/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupCharacteristic/characteristic", + "href": "{id}", + "rel": "characteristic_valueReference_Specimen", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/characteristic/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupCharacteristic/characteristic", + "href": "{id}", + "rel": "characteristic_valueReference_Observation", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/characteristic/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupCharacteristic/characteristic", + "href": "{id}", + "rel": "characteristic_valueReference_DiagnosticReport", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/characteristic/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupCharacteristic/characteristic", + "href": "{id}", + "rel": "characteristic_valueReference_Condition", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/characteristic/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupCharacteristic/characteristic", + "href": "{id}", + "rel": "characteristic_valueReference_Medication", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/characteristic/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupCharacteristic/characteristic", + "href": "{id}", + "rel": "characteristic_valueReference_MedicationAdministration", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/characteristic/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupCharacteristic/characteristic", + "href": "{id}", + "rel": "characteristic_valueReference_MedicationStatement", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/characteristic/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupCharacteristic/characteristic", + "href": "{id}", + "rel": "characteristic_valueReference_MedicationRequest", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/characteristic/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupCharacteristic/characteristic", + "href": "{id}", + "rel": "characteristic_valueReference_Procedure", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/characteristic/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupCharacteristic/characteristic", + "href": "{id}", + "rel": "characteristic_valueReference_DocumentReference", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/characteristic/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupCharacteristic/characteristic", + "href": "{id}", + "rel": "characteristic_valueReference_Task", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/characteristic/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupCharacteristic/characteristic", + "href": "{id}", + "rel": "characteristic_valueReference_ImagingStudy", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/characteristic/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupCharacteristic/characteristic", + "href": "{id}", + "rel": "characteristic_valueReference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/characteristic/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupCharacteristic/characteristic", + "href": "{id}", + "rel": "characteristic_valueReference_BodyStructure", + "targetHints": { + "backref": [ + "group_characteristic" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/characteristic/-/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupMember/member", + "href": "{id}", + "rel": "member_entity_Group", + "targetHints": { + "backref": [ + "group_member" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/member/-/entity/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupMember/member", + "href": "{id}", + "rel": "member_entity_Organization", + "targetHints": { + "backref": [ + "group_member" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/member/-/entity/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupMember/member", + "href": "{id}", + "rel": "member_entity_Patient", + "targetHints": { + "backref": [ + "group_member" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/member/-/entity/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupMember/member", + "href": "{id}", + "rel": "member_entity_Practitioner", + "targetHints": { + "backref": [ + "group_member" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/member/-/entity/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupMember/member", + "href": "{id}", + "rel": "member_entity_PractitionerRole", + "targetHints": { + "backref": [ + "group_member" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/member/-/entity/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From GroupMember/member", + "href": "{id}", + "rel": "member_entity_Specimen", + "targetHints": { + "backref": [ + "group_member" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/member/-/entity/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_active": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'active'." + }, + "_description": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'description'." + }, + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "_membership": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'membership'." + }, + "_name": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'name'." + }, + "_quantity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'quantity'." + }, + "_type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'type'." + }, + "active": { + "description": "Indicates whether the record for the group is available for use or is merely being retained for historical purposes.", + "element_property": true, + "title": "Whether this group's record is in active use", + "type": "boolean" + }, + "characteristic": { + "description": "Identifies traits whose presence r absence is shared by members of the group.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/GroupCharacteristic" + }, + "title": "Include / Exclude group members by Trait", + "type": "array" + }, + "code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "description": "Provides a specific type of resource the group includes; e.g. \"cow\", \"syringe\", etc.", + "element_property": true, + "title": "Kind of Group members" + }, + "contained": { + "description": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, nor can they have their own independent transaction scope. This is allowed to be a Parameters resource if and only if it is referenced by a resource that provides context/meaning.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + "title": "Contained, inline Resources", + "type": "array" + }, + "description": { + "description": "Explanation of what the group represents and how it is intended to be used.", + "element_property": true, + "pattern": "\\s*(\\S|\\s)*", + "title": "Natural language description of the group", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "identifier": { + "description": "Business identifiers assigned to this participant by one of the applications involved. These identifiers remain constant as the resource is updated and propagates from server to server.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "Business Identifier for this Group", + "type": "array" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "managingEntity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "group", + "description": "Entity responsible for defining and maintaining Group characteristics and/or registered members.", + "element_property": true, + "enum_reference_types": [ + "Organization", + "RelatedPerson", + "Practitioner", + "PractitionerRole" + ], + "title": "Entity that is the custodian of the Group's definition" + }, + "member": { + "description": "Identifies the resource instances that are members of the group.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/GroupMember" + }, + "title": "Who or what is in group", + "type": "array" + }, + "membership": { + "binding_description": "The basis for membership in a group", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/group-membership-basis", + "binding_version": "5.0.0", + "description": "Basis for membership in the Group: * 'definitional': The Group.characteristics specified are both necessary and sufficient to determine membership. All entities that meet the criteria are considered to be members of the group, whether referenced by the group or not. If members are present, they are individuals that happen to be known as meeting the Group.characteristics. The list cannot be presumed to be complete. * 'enumerated': The Group.characteristics are necessary but not sufficient to determine membership. Membership is determined by being listed as one of the Group.member.", + "element_property": true, + "element_required": true, + "enum_values": [ + "definitional", + "enumerated" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "definitional | enumerated", + "type": "string" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored", + "type": "array" + }, + "name": { + "description": "A label assigned to the group for human identification and communication.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Label for Group", + "type": "string" + }, + "quantity": { + "description": "A count of the number of resource instances that are part of the group.", + "element_property": true, + "minimum": 0, + "title": "Number of members", + "type": "integer" + }, + "resourceType": { + "const": "Group", + "default": "Group", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative", + "description": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "element_property": true, + "title": "Text summary of the resource, for human interpretation" + }, + "type": { + "binding_description": "Types of resources that are part of group.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/group-type", + "binding_version": "5.0.0", + "description": "Identifies the broad classification of the kind of resources the group includes.", + "element_property": true, + "element_required": true, + "enum_values": [ + "person", + "animal", + "practitioner", + "device", + "careteam", + "healthcareservice", + "location", + "organization", + "relatedperson", + "specimen" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "person | animal | practitioner | device | careteam | healthcareservice | location | organization | relatedperson | specimen", + "type": "string" + } + }, + "title": "Group", + "type": "object" + }, + "TaskInput": { + "$id": "http://graph-fhir.io/schema/0.0.2/TaskInput", + "additionalProperties": false, + "description": "Information used to perform task. Additional information that may be needed in the execution of the task. [See https://hl7.org/fhir/R5/TaskInput.html]", + "links": [ + { + "href": "{id}", + "rel": "valueReference_Organization", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Group", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Practitioner", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_PractitionerRole", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_ResearchStudy", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Patient", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_ResearchSubject", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Substance", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_SubstanceDefinition", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Specimen", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Observation", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_DiagnosticReport", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Condition", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Medication", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_MedicationAdministration", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_MedicationStatement", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_MedicationRequest", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Procedure", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_DocumentReference", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_Task", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_ImagingStudy", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "valueReference_BodyStructure", + "targetHints": { + "backref": [ + "task_input" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/valueAnnotation", + "href": "{id}", + "rel": "valueAnnotation_authorReference_Practitioner", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/valueAnnotation/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/valueAnnotation", + "href": "{id}", + "rel": "valueAnnotation_authorReference_PractitionerRole", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/valueAnnotation/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/valueAnnotation", + "href": "{id}", + "rel": "valueAnnotation_authorReference_Patient", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/valueAnnotation/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/valueAnnotation", + "href": "{id}", + "rel": "valueAnnotation_authorReference_Organization", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueAnnotation/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Organization", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Group", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Practitioner", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_PractitionerRole", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_ResearchStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Patient", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_ResearchSubject", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Substance", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_SubstanceDefinition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Specimen", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Observation", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_DiagnosticReport", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Condition", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Medication", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_MedicationAdministration", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_MedicationStatement", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_MedicationRequest", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Procedure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_DocumentReference", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_Task", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_ImagingStudy", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From CodeableReference/valueCodeableReference", + "href": "{id}", + "rel": "valueCodeableReference_reference_BodyStructure", + "targetHints": { + "backref": [ + "codeable_reference" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/valueCodeableReference/reference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From DataRequirement/valueDataRequirement", + "href": "{id}", + "rel": "valueDataRequirement_subjectReference", + "targetHints": { + "backref": [ + "data_requirement" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/valueDataRequirement/subjectReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From ExtendedContactDetail/valueExtendedContactDetail", + "href": "{id}", + "rel": "valueExtendedContactDetail_organization", + "targetHints": { + "backref": [ + "extended_contact_detail" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueExtendedContactDetail/organization/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Organization", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Group", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Practitioner", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_PractitionerRole", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_ResearchStudy", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Patient", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_ResearchSubject", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchSubject/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Substance", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_SubstanceDefinition", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Specimen", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Observation", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_DiagnosticReport", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Condition", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Condition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Medication", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_MedicationAdministration", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationAdministration/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_MedicationStatement", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationStatement/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_MedicationRequest", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "MedicationRequest/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Procedure", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Procedure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_DocumentReference", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_Task", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Task/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_ImagingStudy", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ImagingStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_FamilyMemberHistory", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "FamilyMemberHistory/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From RelatedArtifact/valueRelatedArtifact", + "href": "{id}", + "rel": "valueRelatedArtifact_resourceReference_BodyStructure", + "targetHints": { + "backref": [ + "related_artifact" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "BodyStructure/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + "templatePointers": { + "id": "/valueRelatedArtifact/resourceReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_onBehalfOf_Practitioner", + "targetHints": { + "backref": [ + "onBehalfOf_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/valueSignature/onBehalfOf/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_onBehalfOf_PractitionerRole", + "targetHints": { + "backref": [ + "onBehalfOf_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/valueSignature/onBehalfOf/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_onBehalfOf_Patient", + "targetHints": { + "backref": [ + "onBehalfOf_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/valueSignature/onBehalfOf/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_onBehalfOf_Organization", + "targetHints": { + "backref": [ + "onBehalfOf_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueSignature/onBehalfOf/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_who_Practitioner", + "targetHints": { + "backref": [ + "who_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/valueSignature/who/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_who_PractitionerRole", + "targetHints": { + "backref": [ + "who_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/valueSignature/who/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_who_Patient", + "targetHints": { + "backref": [ + "who_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/valueSignature/who/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Signature/valueSignature", + "href": "{id}", + "rel": "valueSignature_who_Organization", + "targetHints": { + "backref": [ + "who_signature" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueSignature/who/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From UsageContext/valueUsageContext", + "href": "{id}", + "rel": "valueUsageContext_valueReference_ResearchStudy", + "targetHints": { + "backref": [ + "usage_context" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/valueUsageContext/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From UsageContext/valueUsageContext", + "href": "{id}", + "rel": "valueUsageContext_valueReference_Group", + "targetHints": { + "backref": [ + "usage_context" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/valueUsageContext/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From UsageContext/valueUsageContext", + "href": "{id}", + "rel": "valueUsageContext_valueReference_Organization", + "targetHints": { + "backref": [ + "usage_context" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/valueUsageContext/valueReference/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_valueBase64Binary": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueBase64Binary'." + }, + "_valueBoolean": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueBoolean'." + }, + "_valueCanonical": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueCanonical'." + }, + "_valueCode": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueCode'." + }, + "_valueDate": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueDate'." + }, + "_valueDateTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueDateTime'." + }, + "_valueDecimal": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueDecimal'." + }, + "_valueId": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueId'." + }, + "_valueInstant": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueInstant'." + }, + "_valueInteger": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueInteger'." + }, + "_valueInteger64": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueInteger64'." + }, + "_valueMarkdown": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueMarkdown'." + }, + "_valueOid": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueOid'." + }, + "_valuePositiveInt": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valuePositiveInt'." + }, + "_valueString": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueString'." + }, + "_valueTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueTime'." + }, + "_valueUnsignedInt": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueUnsignedInt'." + }, + "_valueUri": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueUri'." + }, + "_valueUrl": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueUrl'." + }, + "_valueUuid": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'valueUuid'." + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "TaskInput", + "default": "TaskInput", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "description": "A code or description indicating how the input is intended to be used as part of the task execution.", + "element_property": true, + "title": "Label for the input" + }, + "valueAddress": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Address", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueAge": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Age", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueAnnotation": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Annotation", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueAttachment": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Attachment", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueAvailability": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Availability", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueBase64Binary": { + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "format": "binary", + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task", + "type": "string" + }, + "valueBoolean": { + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task", + "type": "boolean" + }, + "valueCanonical": { + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "pattern": "\\S*", + "title": "Content to use in performing the task", + "type": "string" + }, + "valueCode": { + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Content to use in performing the task", + "type": "string" + }, + "valueCodeableConcept": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueCodeableReference": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference", + "backref": "task_input", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueCoding": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Coding", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueContactDetail": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ContactDetail", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueContactPoint": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ContactPoint", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueCount": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Count", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueDataRequirement": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DataRequirement", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueDate": { + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "format": "date", + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task", + "type": "string" + }, + "valueDateTime": { + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "format": "date-time", + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task", + "type": "string" + }, + "valueDecimal": { + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task", + "type": "number" + }, + "valueDistance": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Distance", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueDosage": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Dosage", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueDuration": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Duration", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueExpression": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Expression", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueExtendedContactDetail": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ExtendedContactDetail", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueHumanName": { + "$ref": "http://graph-fhir.io/schema/0.0.2/HumanName", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueId": { + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "one_of_many": "value", + "one_of_many_required": true, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Content to use in performing the task", + "type": "string" + }, + "valueIdentifier": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueInstant": { + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "format": "date-time", + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task", + "type": "string" + }, + "valueInteger": { + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task", + "type": "integer" + }, + "valueInteger64": { + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task", + "type": "integer" + }, + "valueMarkdown": { + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "pattern": "\\s*(\\S|\\s)*", + "title": "Content to use in performing the task", + "type": "string" + }, + "valueMeta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueMoney": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Money", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueOid": { + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "pattern": "^urn:oid:[0-2](\\.(0|[1-9][0-9]*))+$", + "title": "Content to use in performing the task", + "type": "string" + }, + "valueParameterDefinition": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ParameterDefinition", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valuePeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valuePositiveInt": { + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "exclusiveMinimum": 0, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task", + "type": "integer" + }, + "valueQuantity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueRange": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Range", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueRatio": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Ratio", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueRatioRange": { + "$ref": "http://graph-fhir.io/schema/0.0.2/RatioRange", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueReference": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "task_input", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "enum_reference_types": [ + "Organization", + "Group", + "Practitioner", + "PractitionerRole", + "ResearchStudy", + "Patient", + "ResearchSubject", + "Substance", + "SubstanceDefinition", + "Specimen", + "Observation", + "DiagnosticReport", + "Condition", + "Medication", + "MedicationAdministration", + "MedicationStatement", + "MedicationRequest", + "Procedure", + "DocumentReference", + "Task", + "ImagingStudy", + "FamilyMemberHistory", + "BodyStructure" + ], + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueRelatedArtifact": { + "$ref": "http://graph-fhir.io/schema/0.0.2/RelatedArtifact", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueSampledData": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SampledData", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueSignature": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Signature", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueString": { + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Content to use in performing the task", + "type": "string" + }, + "valueTime": { + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "format": "time", + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task", + "type": "string" + }, + "valueTiming": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Timing", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueTriggerDefinition": { + "$ref": "http://graph-fhir.io/schema/0.0.2/TriggerDefinition", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueUnsignedInt": { + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "minimum": 0, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task", + "type": "integer" + }, + "valueUri": { + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "pattern": "\\S*", + "title": "Content to use in performing the task", + "type": "string" + }, + "valueUrl": { + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "format": "uri", + "maxLength": 65536, + "minLength": 1, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task", + "type": "string" + }, + "valueUsageContext": { + "$ref": "http://graph-fhir.io/schema/0.0.2/UsageContext", + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task" + }, + "valueUuid": { + "description": "The value of the input parameter as a basic type.", + "element_property": true, + "format": "uuid", + "one_of_many": "value", + "one_of_many_required": true, + "title": "Content to use in performing the task", + "type": "string" + } + }, + "required": [ + "type" + ], + "title": "TaskInput", + "type": "object" + }, + "Medication": { + "$id": "http://graph-fhir.io/schema/0.0.2/Medication", + "additionalProperties": false, + "description": "Definition of a Medication. This resource is primarily used for the identification and definition of a medication, including ingredients, for the purposes of prescribing, dispensing, and administering a medication as well as for making statements about medication use. [See https://hl7.org/fhir/R5/Medication.html]", + "links": [ + { + "href": "{id}", + "rel": "marketingAuthorizationHolder", + "targetHints": { + "backref": [ + "medication" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/marketingAuthorizationHolder/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "_status": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'status'." + }, + "batch": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationBatch", + "description": "Information that only applies to packages (not products).", + "element_property": true, + "title": "Details about packaged medications" + }, + "code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "A coded concept that defines the type of a medication.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/medication-codes", + "binding_version": null, + "description": "A code (or set of codes) that specify this medication, or a textual description if no code is available. Usage note: This could be a standard medication code such as a code from RxNorm, SNOMED CT, IDMP etc. It could also be a national or local formulary code, optionally with translations to other code systems.", + "element_property": true, + "title": "Codes that identify this medication" + }, + "contained": { + "description": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, nor can they have their own independent transaction scope. This is allowed to be a Parameters resource if and only if it is referenced by a resource that provides context/meaning.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + "title": "Contained, inline Resources", + "type": "array" + }, + "definition": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "medication", + "description": "A reference to a knowledge resource that provides more information about this medication.", + "element_property": true, + "enum_reference_types": [ + "MedicationKnowledge" + ], + "title": "Knowledge about this medication" + }, + "doseForm": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "A coded concept defining the form of a medication.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/medication-form-codes", + "binding_version": null, + "description": "Describes the form of the item. Powder; tablets; capsule.", + "element_property": true, + "title": "powder | tablets | capsule +" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "identifier": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "Business identifier for this medication", + "type": "array" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "ingredient": { + "description": "Identifies a particular constituent of interest in the product.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationIngredient" + }, + "title": "Active or inactive ingredient", + "type": "array" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "marketingAuthorizationHolder": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "medication", + "description": "The company or other legal entity that has authorization, from the appropriate drug regulatory authority, to market a medicine in one or more jurisdictions. Typically abbreviated MAH.Note: The MAH may manufacture the product and may also contract the manufacturing of the product to one or more companies (organizations).", + "element_property": true, + "enum_reference_types": [ + "Organization" + ], + "title": "Organization that has authorization to market medication" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored", + "type": "array" + }, + "resourceType": { + "const": "Medication", + "default": "Medication", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "status": { + "binding_description": "A coded concept defining if the medication is in active use.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/medication-status", + "binding_version": "5.0.0", + "description": "A code to indicate if the medication is in active use.", + "element_property": true, + "enum_values": [ + "active", + "inactive", + "entered-in-error" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "active | inactive | entered-in-error", + "type": "string" + }, + "text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative", + "description": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "element_property": true, + "title": "Text summary of the resource, for human interpretation" + }, + "totalVolume": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "When the specified product code does not infer a package size, this is the specific amount of drug in the product. For example, when specifying a product that has the same strength (For example, Insulin glargine 100 unit per mL solution for injection), this attribute provides additional clarification of the package amount (For example, 3 mL, 10mL, etc.).", + "element_property": true, + "title": "When the specified product code does not infer a package size, this is the specific amount of drug in the product" + } + }, + "title": "Medication", + "type": "object" + }, + "MedicationBatch": { + "$id": "http://graph-fhir.io/schema/0.0.2/MedicationBatch", + "additionalProperties": false, + "description": "Details about packaged medications. Information that only applies to packages (not products). [See https://hl7.org/fhir/R5/MedicationBatch.html]", + "links": [], + "properties": { + "_expirationDate": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'expirationDate'." + }, + "_lotNumber": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'lotNumber'." + }, + "expirationDate": { + "description": "When this specific batch of product will expire.", + "element_property": true, + "format": "date-time", + "title": "When batch will expire", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "lotNumber": { + "description": "The assigned lot number of a batch of the specified product.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Identifier assigned to batch", + "type": "string" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "MedicationBatch", + "default": "MedicationBatch", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "title": "MedicationBatch", + "type": "object" + }, + "ResearchSubject": { + "$id": "http://graph-fhir.io/schema/0.0.2/ResearchSubject", + "additionalProperties": false, + "description": "Participant or object which is the recipient of investigative activities in a study. A ResearchSubject is a participant or object which is the recipient of investigative activities in a research study. [See https://hl7.org/fhir/R5/ResearchSubject.html]", + "links": [ + { + "href": "{id}", + "rel": "study", + "targetHints": { + "backref": [ + "research_subject" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "ResearchStudy/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + "templatePointers": { + "id": "/study/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Patient", + "targetHints": { + "backref": [ + "research_subject" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Group", + "targetHints": { + "backref": [ + "research_subject" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Group/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Specimen", + "targetHints": { + "backref": [ + "research_subject" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Specimen/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Medication", + "targetHints": { + "backref": [ + "research_subject" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Medication/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "subject_Substance", + "targetHints": { + "backref": [ + "research_subject" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/subject/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_actualComparisonGroup": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'actualComparisonGroup'." + }, + "_assignedComparisonGroup": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'assignedComparisonGroup'." + }, + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "_status": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'status'." + }, + "actualComparisonGroup": { + "description": "The name of the arm in the study the subject actually followed as part of this study.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "What path was followed", + "type": "string" + }, + "assignedComparisonGroup": { + "description": "The name of the arm in the study the subject is expected to follow as part of this study.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "What path should be followed", + "type": "string" + }, + "consent": { + "backref": "consent_research_subject", + "description": "A record of the patient's informed agreement to participate in the study.", + "element_property": true, + "enum_reference_types": [ + "Consent" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Agreement to participate in study", + "type": "array" + }, + "contained": { + "description": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, nor can they have their own independent transaction scope. This is allowed to be a Parameters resource if and only if it is referenced by a resource that provides context/meaning.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + "title": "Contained, inline Resources", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "identifier": { + "description": "Identifiers assigned to this research subject for a study.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "Business Identifier for research subject in a study", + "type": "array" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored", + "type": "array" + }, + "period": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "The dates the subject began and ended their participation in the study.", + "element_property": true, + "title": "Start and end of participation" + }, + "progress": { + "description": "The current state (status) of the subject and resons for status change where appropriate.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubjectProgress" + }, + "title": "Subject status", + "type": "array" + }, + "resourceType": { + "const": "ResearchSubject", + "default": "ResearchSubject", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "status": { + "binding_description": "Codes that convey the current publication status of the research study resource.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/publication-status", + "binding_version": "5.0.0", + "description": "The publication state of the resource (not of the subject).", + "element_property": true, + "element_required": true, + "enum_values": [ + "draft", + "active", + "retired", + "unknown" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "draft | active | retired | unknown", + "type": "string" + }, + "study": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "research_subject", + "description": "Reference to the study the subject is participating in.", + "element_property": true, + "enum_reference_types": [ + "ResearchStudy" + ], + "title": "Study subject is part of" + }, + "subject": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "research_subject", + "description": "The record of the person, animal or other entity involved in the study.", + "element_property": true, + "enum_reference_types": [ + "Patient", + "Group", + "Specimen", + "Device", + "Medication", + "Substance", + "BiologicallyDerivedProduct" + ], + "title": "Who or what is part of study" + }, + "text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative", + "description": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "element_property": true, + "title": "Text summary of the resource, for human interpretation" + } + }, + "required": [ + "study", + "subject" + ], + "title": "ResearchSubject", + "type": "object" + }, + "CodeableConcept": { + "$id": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "additionalProperties": false, + "description": "Concept - reference to a terminology or just text. A concept that may be defined by a formal reference to a terminology or ontology or may be provided by text. [See https://hl7.org/fhir/R5/CodeableConcept.html]", + "links": [], + "properties": { + "_text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'text'." + }, + "coding": { + "description": "A reference to a code defined by a terminology system.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Coding" + }, + "title": "Code defined by a terminology system", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "resourceType": { + "const": "CodeableConcept", + "default": "CodeableConcept", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "text": { + "description": "A human language representation of the concept as seen/selected/uttered by the user who entered the data and/or which represents the intended meaning of the user.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Plain text representation of the concept", + "type": "string" + } + }, + "title": "CodeableConcept", + "type": "object" + }, + "ContactPoint": { + "$id": "http://graph-fhir.io/schema/0.0.2/ContactPoint", + "additionalProperties": false, + "description": "Details of a Technology mediated contact point (phone, fax, email, etc.). Details for all kinds of technology mediated contact points for a person or organization, including telephone, email, etc. [See https://hl7.org/fhir/R5/ContactPoint.html]", + "links": [], + "properties": { + "_rank": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'rank'." + }, + "_system": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'system'." + }, + "_use": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'use'." + }, + "_value": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'value'." + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "period": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "element_property": true, + "title": "Time period when the contact point was/is in use" + }, + "rank": { + "description": "Specifies a preferred order in which to use a set of contacts. ContactPoints with lower rank values are more preferred than those with higher rank values.", + "element_property": true, + "exclusiveMinimum": 0, + "title": "Specify preferred order of use (1 = highest)", + "type": "integer" + }, + "resourceType": { + "const": "ContactPoint", + "default": "ContactPoint", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "system": { + "binding_description": "Telecommunications form for contact point.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/contact-point-system", + "binding_version": "5.0.0", + "description": "Telecommunications form for contact point - what communications system is required to make use of the contact.", + "element_property": true, + "enum_values": [ + "phone", + "fax", + "email", + "pager", + "url", + "sms", + "other" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "phone | fax | email | pager | url | sms | other", + "type": "string" + }, + "use": { + "binding_description": "Use of contact point.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/contact-point-use", + "binding_version": "5.0.0", + "description": "Identifies the purpose for the contact point.", + "element_property": true, + "enum_values": [ + "home", + "work", + "temp", + "old", + "mobile" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "home | work | temp | old | mobile - purpose of this contact point", + "type": "string" + }, + "value": { + "description": "The actual contact point details, in a form that is meaningful to the designated communication system (i.e. phone number or email address).", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "The actual contact point details", + "type": "string" + } + }, + "title": "ContactPoint", + "type": "object" + }, + "Age": { + "$id": "http://graph-fhir.io/schema/0.0.2/Age", + "additionalProperties": false, + "description": "A duration of time during which an organism (or a process) has existed. [See https://hl7.org/fhir/R5/Age.html]", + "links": [], + "properties": { + "_code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'code'." + }, + "_comparator": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'comparator'." + }, + "_system": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'system'." + }, + "_unit": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'unit'." + }, + "_value": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'value'." + }, + "code": { + "description": "A computer processable form of the unit in some unit representation system.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Coded form of the unit", + "type": "string" + }, + "comparator": { + "binding_description": "How the Quantity should be understood and represented.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/quantity-comparator", + "binding_version": "5.0.0", + "description": "How the value should be understood and represented - whether the actual value is greater or less than the stated value due to measurement issues; e.g. if the comparator is \"<\" , then the real value is < stated value.", + "element_property": true, + "enum_values": [ + "<", + "<=", + ">=", + ">", + "ad" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "< | <= | >= | > | ad - how to understand the value", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "resourceType": { + "const": "Age", + "default": "Age", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "system": { + "description": "The identification of the system that provides the coded form of the unit.", + "element_property": true, + "pattern": "\\S*", + "title": "System that defines coded unit form", + "type": "string" + }, + "unit": { + "description": "A human-readable form of the unit.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unit representation", + "type": "string" + }, + "value": { + "description": "The value of the measured amount. The value includes an implicit precision in the presentation of the value.", + "element_property": true, + "title": "Numerical value (with implicit precision)", + "type": "number" + } + }, + "title": "Age", + "type": "object" + }, + "SubstanceDefinition": { + "$id": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition", + "additionalProperties": false, + "description": "The detailed description of a substance, typically at a level beyond what is used for prescribing. [See https://hl7.org/fhir/R5/SubstanceDefinition.html]", + "links": [ + { + "href": "{id}", + "rel": "manufacturer", + "targetHints": { + "backref": [ + "manufacturer_substance_definition" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/manufacturer/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "supplier", + "targetHints": { + "backref": [ + "supplier_substance_definition" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/supplier/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From SubstanceDefinitionCode/code", + "href": "{id}", + "rel": "code_source", + "targetHints": { + "backref": [ + "source_substance_definition_code" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/code/-/source/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From SubstanceDefinitionName/name", + "href": "{id}", + "rel": "name_source", + "targetHints": { + "backref": [ + "source_substance_definition_name" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/name/-/source/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Practitioner", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Practitioner/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_PractitionerRole", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "PractitionerRole/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Patient", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Patient/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From Annotation/note", + "href": "{id}", + "rel": "note_authorReference_Organization", + "targetHints": { + "backref": [ + "annotation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "Organization/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + "templatePointers": { + "id": "/note/-/authorReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From SubstanceDefinitionRelationship/relationship", + "href": "{id}", + "rel": "relationship_source", + "targetHints": { + "backref": [ + "source_substance_definition_relationship" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/relationship/-/source/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From SubstanceDefinitionRelationship/relationship", + "href": "{id}", + "rel": "relationship_substanceDefinitionReference", + "targetHints": { + "backref": [ + "substance_definition_relationship" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "SubstanceDefinition/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + "templatePointers": { + "id": "/relationship/-/substanceDefinitionReference/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From SubstanceDefinitionStructure/structure", + "href": "{id}", + "rel": "structure_sourceDocument", + "targetHints": { + "backref": [ + "sourceDocument_substance_definition_structure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/structure/sourceDocument/-/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_description": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'description'." + }, + "_implicitRules": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'implicitRules'." + }, + "_language": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'language'." + }, + "_version": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'version'." + }, + "characterization": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionCharacterization" + }, + "title": "General specifications for this substance", + "type": "array" + }, + "classification": { + "description": "A high level categorization, e.g. polymer or nucleic acid, or food, chemical, biological, or a lower level such as the general types of polymer (linear or branch chain) or type of impurity (process related or contaminant).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "A categorization, high level e.g. polymer or nucleic acid, or food, chemical, biological, or lower e.g. polymer linear or branch chain, or type of impurity", + "type": "array" + }, + "code": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionCode" + }, + "title": "Codes associated with the substance", + "type": "array" + }, + "contained": { + "description": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, nor can they have their own independent transaction scope. This is allowed to be a Parameters resource if and only if it is referenced by a resource that provides context/meaning.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + "title": "Contained, inline Resources", + "type": "array" + }, + "description": { + "element_property": true, + "pattern": "\\s*(\\S|\\s)*", + "title": "Textual description of the substance", + "type": "string" + }, + "domain": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Applicable domain for this product (e.g. human, veterinary).", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/medicinal-product-domain", + "binding_version": null, + "element_property": true, + "title": "If the substance applies to human or veterinary use" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "grade": { + "binding_description": "The quality standard, established benchmark, to which a substance complies", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-grade", + "binding_version": null, + "description": "The quality standard, established benchmark, to which substance complies (e.g. USP/NF, Ph. Eur, JP, BP, Company Standard).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "The quality standard, established benchmark, to which substance complies (e.g. USP/NF, BP)", + "type": "array" + }, + "id": { + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "element_property": true, + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9\\-.]+$", + "title": "Logical id of this artifact", + "type": "string" + }, + "identifier": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + "title": "Identifier by which this substance is known", + "type": "array" + }, + "implicitRules": { + "description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "element_property": true, + "pattern": "\\S*", + "title": "A set of rules under which this content was created", + "type": "string" + }, + "informationSource": { + "backref": "informationSource_substance_definition", + "element_property": true, + "enum_reference_types": [ + "Citation" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Supporting literature", + "type": "array" + }, + "language": { + "binding_description": "IETF language tag for a human language", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/all-languages", + "binding_version": "5.0.0", + "description": "The base language in which the resource is written.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Language of the resource content", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "manufacturer": { + "backref": "manufacturer_substance_definition", + "description": "The entity that creates, makes, produces or fabricates the substance. This is a set of potential manufacturers but is not necessarily comprehensive.", + "element_property": true, + "enum_reference_types": [ + "Organization" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "The entity that creates, makes, produces or fabricates the substance", + "type": "array" + }, + "meta": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta", + "description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "element_property": true, + "title": "Metadata about the resource" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored", + "type": "array" + }, + "moiety": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionMoiety" + }, + "title": "Moiety, for structural modifications", + "type": "array" + }, + "molecularWeight": { + "description": "The average mass of a molecule of a compound compared to 1/12 the mass of carbon 12 and calculated as the sum of the atomic weights of the constituent atoms.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionMolecularWeight" + }, + "title": "The average mass of a molecule of a compound", + "type": "array" + }, + "name": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionName" + }, + "title": "Names applicable to this substance", + "type": "array" + }, + "note": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Annotation" + }, + "title": "Textual comment about the substance's catalogue or registry record", + "type": "array" + }, + "nucleicAcid": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "substance_definition", + "element_property": true, + "enum_reference_types": [ + "SubstanceNucleicAcid" + ], + "title": "Data items specific to nucleic acids" + }, + "polymer": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "substance_definition", + "element_property": true, + "enum_reference_types": [ + "SubstancePolymer" + ], + "title": "Data items specific to polymers" + }, + "property": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionProperty" + }, + "title": "General specifications for this substance", + "type": "array" + }, + "protein": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "substance_definition", + "element_property": true, + "enum_reference_types": [ + "SubstanceProtein" + ], + "title": "Data items specific to proteins" + }, + "referenceInformation": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference", + "backref": "substance_definition", + "element_property": true, + "enum_reference_types": [ + "SubstanceReferenceInformation" + ], + "title": "General information detailing this substance" + }, + "relationship": { + "description": "A link between this substance and another, with details of the relationship.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionRelationship" + }, + "title": "A link between this substance and another", + "type": "array" + }, + "resourceType": { + "const": "SubstanceDefinition", + "default": "SubstanceDefinition", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "sourceMaterial": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionSourceMaterial", + "description": "Material or taxonomic/anatomical source for the substance.", + "element_property": true, + "title": "Material or taxonomic/anatomical source" + }, + "status": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The lifecycle status of an artifact.", + "binding_strength": "preferred", + "binding_uri": "http://hl7.org/fhir/ValueSet/publication-status", + "binding_version": null, + "element_property": true, + "title": "Status of substance within the catalogue e.g. active, retired" + }, + "structure": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionStructure", + "element_property": true, + "title": "Structural information" + }, + "supplier": { + "backref": "supplier_substance_definition", + "description": "An entity that is the source for the substance. It may be different from the manufacturer. Supplier is synonymous to a distributor.", + "element_property": true, + "enum_reference_types": [ + "Organization" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "An entity that is the source for the substance. It may be different from the manufacturer", + "type": "array" + }, + "text": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative", + "description": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "element_property": true, + "title": "Text summary of the resource, for human interpretation" + }, + "version": { + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "A business level version identifier of the substance", + "type": "string" + } + }, + "title": "SubstanceDefinition", + "type": "object" + }, + "ConditionStage": { + "$id": "http://graph-fhir.io/schema/0.0.2/ConditionStage", + "additionalProperties": false, + "description": "Stage/grade, usually assessed formally. A simple summary of the stage such as \"Stage 3\" or \"Early Onset\". The determination of the stage is disease-specific, such as cancer, retinopathy of prematurity, kidney diseases, Alzheimer's, or Parkinson disease. [See https://hl7.org/fhir/R5/ConditionStage.html]", + "links": [ + { + "href": "{id}", + "rel": "assessment_DiagnosticReport", + "targetHints": { + "backref": [ + "assessment_condition_stage" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DiagnosticReport/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + "templatePointers": { + "id": "/assessment/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "href": "{id}", + "rel": "assessment_Observation", + "targetHints": { + "backref": [ + "assessment_condition_stage" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Observation/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + "templatePointers": { + "id": "/assessment/-/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "assessment": { + "backref": "assessment_condition_stage", + "description": "Reference to a formal record of the evidence on which the staging assessment is based.", + "element_property": true, + "enum_reference_types": [ + "ClinicalImpression", + "DiagnosticReport", + "Observation" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Formal record of assessment", + "type": "array" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "ConditionStage", + "default": "ConditionStage", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "summary": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Codes describing condition stages (e.g. Cancer stages).", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/condition-stage", + "binding_version": null, + "description": "A simple summary of the stage such as \"Stage 3\" or \"Early Onset\". The determination of the stage is disease-specific, such as cancer, retinopathy of prematurity, kidney diseases, Alzheimer's, or Parkinson disease.", + "element_property": true, + "title": "Simple summary (disease specific)" + }, + "type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Codes describing the kind of condition staging (e.g. clinical or pathological).", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/condition-stage-type", + "binding_version": null, + "description": "The kind of staging, such as pathological or clinical staging.", + "element_property": true, + "title": "Kind of staging" + } + }, + "title": "ConditionStage", + "type": "object" + }, + "Duration": { + "$id": "http://graph-fhir.io/schema/0.0.2/Duration", + "additionalProperties": false, + "description": "A length of time. [See https://hl7.org/fhir/R5/Duration.html]", + "links": [], + "properties": { + "_code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'code'." + }, + "_comparator": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'comparator'." + }, + "_system": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'system'." + }, + "_unit": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'unit'." + }, + "_value": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'value'." + }, + "code": { + "description": "A computer processable form of the unit in some unit representation system.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Coded form of the unit", + "type": "string" + }, + "comparator": { + "binding_description": "How the Quantity should be understood and represented.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/quantity-comparator", + "binding_version": "5.0.0", + "description": "How the value should be understood and represented - whether the actual value is greater or less than the stated value due to measurement issues; e.g. if the comparator is \"<\" , then the real value is < stated value.", + "element_property": true, + "enum_values": [ + "<", + "<=", + ">=", + ">", + "ad" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "< | <= | >= | > | ad - how to understand the value", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "resourceType": { + "const": "Duration", + "default": "Duration", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "system": { + "description": "The identification of the system that provides the coded form of the unit.", + "element_property": true, + "pattern": "\\S*", + "title": "System that defines coded unit form", + "type": "string" + }, + "unit": { + "description": "A human-readable form of the unit.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unit representation", + "type": "string" + }, + "value": { + "description": "The value of the measured amount. The value includes an implicit precision in the presentation of the value.", + "element_property": true, + "title": "Numerical value (with implicit precision)", + "type": "number" + } + }, + "title": "Duration", + "type": "object" + }, + "SpecimenProcessing": { + "$id": "http://graph-fhir.io/schema/0.0.2/SpecimenProcessing", + "additionalProperties": false, + "description": "Processing and processing step details. Details concerning processing and processing steps for the specimen. [See https://hl7.org/fhir/R5/SpecimenProcessing.html]", + "links": [ + { + "href": "{id}", + "rel": "additive", + "targetHints": { + "backref": [ + "additive_specimen_processing" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "Substance/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + "templatePointers": { + "id": "/additive/-/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_description": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'description'." + }, + "_timeDateTime": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'timeDateTime'." + }, + "additive": { + "backref": "additive_specimen_processing", + "element_property": true, + "enum_reference_types": [ + "Substance" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Material used in the processing step", + "type": "array" + }, + "description": { + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Textual description of procedure", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "method": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "Type indicating the technique used to process the specimen.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/specimen-processing-method", + "binding_version": null, + "description": "A coded value specifying the method used to process the specimen.", + "element_property": true, + "title": "Indicates the treatment step applied to the specimen" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "resourceType": { + "const": "SpecimenProcessing", + "default": "SpecimenProcessing", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "timeDateTime": { + "description": "A record of the time or period when the specimen processing occurred. For example the time of sample fixation or the period of time the sample was in formalin.", + "element_property": true, + "format": "date-time", + "one_of_many": "time", + "one_of_many_required": false, + "title": "Date and time of specimen processing", + "type": "string" + }, + "timePeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "A record of the time or period when the specimen processing occurred. For example the time of sample fixation or the period of time the sample was in formalin.", + "element_property": true, + "one_of_many": "time", + "one_of_many_required": false, + "title": "Date and time of specimen processing" + } + }, + "title": "SpecimenProcessing", + "type": "object" + }, + "SubstanceDefinitionStructure": { + "$id": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionStructure", + "additionalProperties": false, + "description": "Structural information. [See https://hl7.org/fhir/R5/SubstanceDefinitionStructure.html]", + "links": [ + { + "href": "{id}", + "rel": "sourceDocument", + "targetHints": { + "backref": [ + "sourceDocument_substance_definition_structure" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_many" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/sourceDocument/-/reference" + }, + "templateRequired": [ + "id" + ] + }, + { + "$comment": "From SubstanceDefinitionStructureRepresentation/representation", + "href": "{id}", + "rel": "representation_document", + "targetHints": { + "backref": [ + "substance_definition_structure_representation" + ], + "direction": [ + "outbound" + ], + "multiplicity": [ + "has_one" + ], + "regex_match": [ + "DocumentReference/*" + ] + }, + "targetSchema": { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + "templatePointers": { + "id": "/representation/-/document/reference" + }, + "templateRequired": [ + "id" + ] + } + ], + "properties": { + "_molecularFormula": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'molecularFormula'." + }, + "_molecularFormulaByMoiety": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'molecularFormulaByMoiety'." + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "modifierExtension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions. Modifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Extensions that cannot be ignored even if unrecognized", + "type": "array" + }, + "molecularFormula": { + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "An expression which states the number and type of atoms present in a molecule of a substance", + "type": "string" + }, + "molecularFormulaByMoiety": { + "description": "Specified per moiety according to the Hill system, i.e. first C, then H, then alphabetical, each moiety separated by a dot.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Specified per moiety according to the Hill system", + "type": "string" + }, + "molecularWeight": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionMolecularWeight", + "description": "The molecular weight or weight range (for proteins, polymers or nucleic acids).", + "element_property": true, + "title": "The molecular weight or weight range" + }, + "opticalActivity": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The optical rotation type of a substance.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-optical-activity", + "binding_version": null, + "element_property": true, + "title": "Optical activity type" + }, + "representation": { + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionStructureRepresentation" + }, + "title": "A depiction of the structure of the substance", + "type": "array" + }, + "resourceType": { + "const": "SubstanceDefinitionStructure", + "default": "SubstanceDefinitionStructure", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "sourceDocument": { + "backref": "sourceDocument_substance_definition_structure", + "description": "The source of information about the structure.", + "element_property": true, + "enum_reference_types": [ + "DocumentReference" + ], + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + "title": "Source of information for the structure", + "type": "array" + }, + "stereochemistry": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept", + "binding_description": "The optical rotation type of a substance.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-stereochemistry", + "binding_version": null, + "element_property": true, + "title": "Stereochemistry type" + }, + "technique": { + "binding_description": "The method used to elucidate the structure of the drug substance.", + "binding_strength": "example", + "binding_uri": "http://hl7.org/fhir/ValueSet/substance-structure-technique", + "binding_version": null, + "description": "The method used to elucidate the structure of the drug substance. Examples: X-ray, NMR, Peptide mapping, Ligand binding assay.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + "title": "The method used to find the structure e.g. X-ray, NMR", + "type": "array" + } + }, + "title": "SubstanceDefinitionStructure", + "type": "object" + }, + "Ratio": { + "$id": "http://graph-fhir.io/schema/0.0.2/Ratio", + "additionalProperties": false, + "description": "A ratio of two Quantity values - a numerator and a denominator. A relationship of two Quantity values - expressed as a numerator and a denominator. [See https://hl7.org/fhir/R5/Ratio.html]", + "links": [], + "properties": { + "denominator": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "The value of the denominator.", + "element_property": true, + "title": "Denominator value" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "numerator": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity", + "description": "The value of the numerator.", + "element_property": true, + "title": "Numerator value" + }, + "resourceType": { + "const": "Ratio", + "default": "Ratio", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + } + }, + "title": "Ratio", + "type": "object" + }, + "ParameterDefinition": { + "$id": "http://graph-fhir.io/schema/0.0.2/ParameterDefinition", + "additionalProperties": false, + "description": "Definition of a parameter to a module. The parameters to the module. This collection specifies both the input and output parameters. Input parameters are provided by the caller as part of the $evaluate operation. Output parameters are included in the GuidanceResponse. [See https://hl7.org/fhir/R5/ParameterDefinition.html]", + "links": [], + "properties": { + "_documentation": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'documentation'." + }, + "_max": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'max'." + }, + "_min": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'min'." + }, + "_name": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'name'." + }, + "_profile": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'profile'." + }, + "_type": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'type'." + }, + "_use": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'use'." + }, + "documentation": { + "description": "A brief discussion of what the parameter is for and how it is used by the module.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "A brief description of the parameter", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "max": { + "description": "The maximum number of times this element is permitted to appear in the request or response.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Maximum cardinality (a number of *)", + "type": "string" + }, + "min": { + "description": "The minimum number of times this parameter SHALL appear in the request or response.", + "element_property": true, + "title": "Minimum cardinality", + "type": "integer" + }, + "name": { + "description": "The name of the parameter used to allow access to the value of the parameter in evaluation contexts.", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Name used to access the parameter value", + "type": "string" + }, + "profile": { + "description": "If specified, this indicates a profile that the input data must conform to, or that the output data will conform to.", + "element_property": true, + "enum_reference_types": [ + "StructureDefinition" + ], + "pattern": "\\S*", + "title": "What profile the value is expected to be", + "type": "string" + }, + "resourceType": { + "const": "ParameterDefinition", + "default": "ParameterDefinition", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "type": { + "binding_description": "List of FHIR types (resources, data types).", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/fhir-types", + "binding_version": "5.0.0", + "description": "The type of the parameter.", + "element_property": true, + "element_required": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "What type of value", + "type": "string" + }, + "use": { + "binding_description": "Whether the parameter is input or output.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/operation-parameter-use", + "binding_version": "5.0.0", + "description": "Whether the parameter is input or output for the module.", + "element_property": true, + "element_required": true, + "enum_values": [ + "in", + "out" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "in | out", + "type": "string" + } + }, + "title": "ParameterDefinition", + "type": "object" + }, + "Coding": { + "$id": "http://graph-fhir.io/schema/0.0.2/Coding", + "additionalProperties": false, + "description": "A reference to a code defined by a terminology system. [See https://hl7.org/fhir/R5/Coding.html]", + "links": [], + "properties": { + "_code": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'code'." + }, + "_display": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'display'." + }, + "_system": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'system'." + }, + "_userSelected": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'userSelected'." + }, + "_version": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'version'." + }, + "code": { + "description": "A symbol in syntax defined by the system. The symbol may be a predefined code or an expression in a syntax defined by the coding system (e.g. post-coordination).", + "element_property": true, + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "Symbol in syntax defined by the system", + "type": "string" + }, + "display": { + "description": "A representation of the meaning of the code in the system, following the rules of the system.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Representation defined by the system", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "resourceType": { + "const": "Coding", + "default": "Coding", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "system": { + "description": "The identification of the code system that defines the meaning of the symbol in the code.", + "element_property": true, + "pattern": "\\S*", + "title": "Identity of the terminology system", + "type": "string" + }, + "userSelected": { + "description": "Indicates that this coding was chosen by a user directly - e.g. off a pick list of available items (codes or displays).", + "element_property": true, + "title": "If this coding was chosen directly by the user", + "type": "boolean" + }, + "version": { + "description": "The version of the code system which was used when choosing this code. Note that a well-maintained code system does not need the version reported, because the meaning of codes is consistent across versions. However this cannot consistently be assured, and when the meaning is not guaranteed to be consistent, the version SHOULD be exchanged.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Version of the system - if relevant", + "type": "string" + } + }, + "title": "Coding", + "type": "object" + }, + "TimingRepeat": { + "$id": "http://graph-fhir.io/schema/0.0.2/TimingRepeat", + "additionalProperties": false, + "description": "When the event is to occur. A set of rules that describe when the event is scheduled. [See https://hl7.org/fhir/R5/TimingRepeat.html]", + "links": [], + "properties": { + "_count": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'count'." + }, + "_countMax": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'countMax'." + }, + "_dayOfWeek": { + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension" + }, + "title": "Extension field for 'dayOfWeek'.", + "type": "array" + }, + "_duration": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'duration'." + }, + "_durationMax": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'durationMax'." + }, + "_durationUnit": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'durationUnit'." + }, + "_frequency": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'frequency'." + }, + "_frequencyMax": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'frequencyMax'." + }, + "_offset": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'offset'." + }, + "_period": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'period'." + }, + "_periodMax": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'periodMax'." + }, + "_periodUnit": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension", + "title": "Extension field for 'periodUnit'." + }, + "_timeOfDay": { + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension" + }, + "title": "Extension field for 'timeOfDay'.", + "type": "array" + }, + "_when": { + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension" + }, + "title": "Extension field for 'when'.", + "type": "array" + }, + "boundsDuration": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Duration", + "description": "Either a duration for the length of the timing schedule, a range of possible length, or outer bounds for start and/or end limits of the timing schedule.", + "element_property": true, + "one_of_many": "bounds", + "one_of_many_required": false, + "title": "Length/Range of lengths, or (Start and/or end) limits" + }, + "boundsPeriod": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period", + "description": "Either a duration for the length of the timing schedule, a range of possible length, or outer bounds for start and/or end limits of the timing schedule.", + "element_property": true, + "one_of_many": "bounds", + "one_of_many_required": false, + "title": "Length/Range of lengths, or (Start and/or end) limits" + }, + "boundsRange": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Range", + "description": "Either a duration for the length of the timing schedule, a range of possible length, or outer bounds for start and/or end limits of the timing schedule.", + "element_property": true, + "one_of_many": "bounds", + "one_of_many_required": false, + "title": "Length/Range of lengths, or (Start and/or end) limits" + }, + "count": { + "description": "A total count of the desired number of repetitions across the duration of the entire timing specification. If countMax is present, this element indicates the lower bound of the allowed range of count values.", + "element_property": true, + "exclusiveMinimum": 0, + "title": "Number of times to repeat", + "type": "integer" + }, + "countMax": { + "description": "If present, indicates that the count is a range - so to perform the action between [count] and [countMax] times.", + "element_property": true, + "exclusiveMinimum": 0, + "title": "Maximum number of times to repeat", + "type": "integer" + }, + "dayOfWeek": { + "binding_description": null, + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/days-of-week", + "binding_version": "5.0.0", + "description": "If one or more days of week is provided, then the action happens only on the specified day(s).", + "element_property": true, + "enum_values": [ + "mon", + "tue", + "wed", + "thu", + "fri", + "sat", + "sun" + ], + "items": { + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "type": "string" + }, + "title": "mon | tue | wed | thu | fri | sat | sun", + "type": "array" + }, + "duration": { + "description": "How long this thing happens for when it happens. If durationMax is present, this element indicates the lower bound of the allowed range of the duration.", + "element_property": true, + "title": "How long when it happens", + "type": "number" + }, + "durationMax": { + "description": "If present, indicates that the duration is a range - so to perform the action between [duration] and [durationMax] time length.", + "element_property": true, + "title": "How long when it happens (Max)", + "type": "number" + }, + "durationUnit": { + "binding_description": "A unit of time (units from UCUM).", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/units-of-time", + "binding_version": "5.0.0", + "description": "The units of time for the duration, in UCUM units Normal practice is to use the 'mo' code as a calendar month when calculating the next occurrence.", + "element_property": true, + "enum_values": [ + "s", + "min", + "h", + "d", + "wk", + "mo", + "a" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "s | min | h | d | wk | mo | a - unit of time (UCUM)", + "type": "string" + }, + "extension": { + "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "element_property": true, + "items": { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + "title": "Additional content defined by implementations", + "type": "array" + }, + "fhir_comments": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "element_property": false, + "title": "Fhir Comments" + }, + "frequency": { + "description": "The number of times to repeat the action within the specified period. If frequencyMax is present, this element indicates the lower bound of the allowed range of the frequency.", + "element_property": true, + "exclusiveMinimum": 0, + "title": "Indicates the number of repetitions that should occur within a period. I.e. Event occurs frequency times per period", + "type": "integer" + }, + "frequencyMax": { + "description": "If present, indicates that the frequency is a range - so to repeat between [frequency] and [frequencyMax] times within the period or period range.", + "element_property": true, + "exclusiveMinimum": 0, + "title": "Event occurs up to frequencyMax times per period", + "type": "integer" + }, + "id": { + "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "element_property": true, + "pattern": "[ \\r\\n\\t\\S]+", + "title": "Unique id for inter-element referencing", + "type": "string" + }, + "links": { + "items": { + "$ref": "https://json-schema.org/draft/2020-12/links" + }, + "type": "array" + }, + "offset": { + "description": "The number of minutes from the event. If the event code does not indicate whether the minutes is before or after the event, then the offset is assumed to be after the event.", + "element_property": true, + "minimum": 0, + "title": "Minutes from event (before or after)", + "type": "integer" + }, + "period": { + "description": "Indicates the duration of time over which repetitions are to occur; e.g. to express \"3 times per day\", 3 would be the frequency and \"1 day\" would be the period. If periodMax is present, this element indicates the lower bound of the allowed range of the period length.", + "element_property": true, + "title": "The duration to which the frequency applies. I.e. Event occurs frequency times per period", + "type": "number" + }, + "periodMax": { + "description": "If present, indicates that the period is a range from [period] to [periodMax], allowing expressing concepts such as \"do this once every 3-5 days.", + "element_property": true, + "title": "Upper limit of period (3-4 hours)", + "type": "number" + }, + "periodUnit": { + "binding_description": "A unit of time (units from UCUM).", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/units-of-time", + "binding_version": "5.0.0", + "description": "The units of time for the period in UCUM units Normal practice is to use the 'mo' code as a calendar month when calculating the next occurrence.", + "element_property": true, + "enum_values": [ + "s", + "min", + "h", + "d", + "wk", + "mo", + "a" + ], + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "title": "s | min | h | d | wk | mo | a - unit of time (UCUM)", + "type": "string" + }, + "resourceType": { + "const": "TimingRepeat", + "default": "TimingRepeat", + "description": "One of the resource types defined as part of FHIR", + "title": "Resource Type", + "type": "string" + }, + "timeOfDay": { + "description": "Specified time of day for action to take place.", + "element_property": true, + "items": { + "format": "time", + "type": "string" + }, + "title": "Time of day for action", + "type": "array" + }, + "when": { + "binding_description": "Real-world event relating to the schedule.", + "binding_strength": "required", + "binding_uri": "http://hl7.org/fhir/ValueSet/event-timing", + "binding_version": "5.0.0", + "description": "An approximate time period during the day, potentially linked to an event of daily living that indicates when the action should occur.", + "element_property": true, + "items": { + "pattern": "^[^\\s]+(\\s[^\\s]+)*$", + "type": "string" + }, + "title": "Code for time period of occurrence", + "type": "array" + } + }, + "title": "TimingRepeat", + "type": "object" + } + }, + "anyOf": [ + { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministration" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReference" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudySeriesPerformer" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/TaskPerformer" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Timing" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/SampledData" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudyComparisonGroup" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistory" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/RelatedArtifact" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Observation" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ObservationTriggeredBy" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionCode" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/DataRequirementCodeFilter" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistoryParticipant" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/PatientLink" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/TaskOutput" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Patient" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Practitioner" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionProperty" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Annotation" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Substance" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/UsageContext" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableReference" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReportSupportingInfo" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequest" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerCommunication" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/GroupCharacteristic" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequestDispenseRequest" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Period" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerQualification" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/AvailabilityNotAvailableTime" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionMolecularWeight" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructureIncludedStructureBodyLandmarkOrientation" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ConditionParticipant" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionSourceMaterial" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/FHIRPrimitiveExtension" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ExtendedContactDetail" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/DataRequirementValueFilter" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/DataRequirementSort" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudySeries" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionRelationship" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatement" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReport" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/OrganizationQualification" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Task" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudyAssociatedParty" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Range" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/PatientContact" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/DataRequirement" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ProcedureFocalDevice" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Condition" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/AvailabilityAvailableTime" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudyRecruitment" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionName" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/SpecimenCollection" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/GroupMember" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Attachment" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudyProgressStatus" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationIngredient" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionNameOfficial" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Money" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequestSubstitution" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistoryProcedure" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/TaskRestriction" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/RatioRange" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationStatementAdherence" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/FamilyMemberHistoryCondition" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudySeriesInstance" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Resource" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/PractitionerRole" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/DosageDoseAndRate" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ObservationReferenceRange" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ContactDetail" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Procedure" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationRequestDispenseRequestInitialFill" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudyLabel" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReferenceContentProfile" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudyObjective" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ProcedurePerformer" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubjectProgress" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Organization" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Distance" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ImagingStudy" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructure" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ObservationComponent" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Address" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionStructureRepresentation" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Expression" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceIngredient" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Reference" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionMoiety" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Availability" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Count" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Quantity" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructureIncludedStructureBodyLandmarkOrientationDistanceFromLandmark" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReferenceAttester" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReferenceRelatesTo" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Narrative" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/SpecimenFeature" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/DocumentReferenceContent" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudy" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/DataRequirementDateFilter" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Signature" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Dosage" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/PatientCommunication" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Specimen" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministrationDosage" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/SpecimenContainer" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Extension" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/HumanName" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionCharacterization" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/TriggerDefinition" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Meta" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchStudyOutcomeMeasure" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/DiagnosticReportMedia" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Identifier" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationAdministrationPerformer" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/BodyStructureIncludedStructure" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Group" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/TaskInput" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Medication" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/MedicationBatch" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ResearchSubject" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/CodeableConcept" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ContactPoint" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Age" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinition" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ConditionStage" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Duration" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/SpecimenProcessing" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/SubstanceDefinitionStructure" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Ratio" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/ParameterDefinition" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/Coding" + }, + { + "$ref": "http://graph-fhir.io/schema/0.0.2/TimingRepeat" + } + ] +} \ No newline at end of file From 3d867be89682439231868fa2e8e3611803a44bb7 Mon Sep 17 00:00:00 2001 From: matthewpeterkort Date: Mon, 13 Jul 2026 11:04:58 -0700 Subject: [PATCH 09/15] build: use published FHIR schema modules --- Dockerfile | 6 ------ go.mod | 11 +++-------- go.sum | 24 ++++-------------------- internal/ingest/row_builder.go | 22 ++++++++-------------- 4 files changed, 15 insertions(+), 48 deletions(-) diff --git a/Dockerfile b/Dockerfile index b7fd35f..c0c0242 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,14 +7,8 @@ ENV CGO_ENABLED=0 WORKDIR /src COPY go.mod go.sum ./ -# Local development may replace these modules with sibling checkouts. The -# server image uses the published module graph; ingest's generic path is kept -# on the published APIs so this image is reproducible from this repository -# alone. RUN --mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/root/.cache/go-build \ - go mod edit -dropreplace=github.com/bmeg/jsonschema/v6 \ - -dropreplace=github.com/bmeg/jsonschemagraph && \ go mod download COPY cmd ./cmd diff --git a/go.mod b/go.mod index ea320b2..655aa93 100644 --- a/go.mod +++ b/go.mod @@ -6,8 +6,9 @@ require ( github.com/99designs/gqlgen v0.17.66 github.com/ClickHouse/clickhouse-go/v2 v2.47.0 github.com/arangodb/go-driver/v2 v2.3.1 - github.com/bmeg/jsonschema/v6 v6.0.4 - github.com/bmeg/jsonschemagraph v0.0.4-0.20250828230703-257ca9afd85a + github.com/bmeg/grip v0.0.0-20250915204302-93cb1e8117c8 + github.com/bmeg/jsonschema/v6 v6.0.5 + github.com/bmeg/jsonschemagraph v0.0.4 github.com/bytedance/sonic v1.15.2 github.com/gofiber/fiber/v3 v3.3.0 github.com/google/uuid v1.6.0 @@ -19,7 +20,6 @@ require ( github.com/agnivade/levenshtein v1.2.0 // indirect github.com/andybalholm/brotli v1.2.1 // indirect github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e // indirect - github.com/bmeg/grip v0.0.0-20250915204302-93cb1e8117c8 // indirect github.com/bytedance/gopkg v0.1.3 // indirect github.com/bytedance/sonic/loader v0.5.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -64,7 +64,6 @@ require ( golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect golang.org/x/crypto v0.53.0 // indirect golang.org/x/net v0.56.0 // indirect - golang.org/x/sync v0.21.0 // indirect golang.org/x/sys v0.46.0 // indirect golang.org/x/term v0.44.0 // indirect golang.org/x/text v0.38.0 // indirect @@ -72,7 +71,3 @@ require ( google.golang.org/grpc v1.71.0 // indirect google.golang.org/protobuf v1.36.7 // indirect ) - -replace github.com/bmeg/jsonschemagraph => /Users/peterkor/Desktop/BMEG/jsonschemagraph - -replace github.com/bmeg/jsonschema/v6 => /Users/peterkor/Desktop/BMEG/jsonschema diff --git a/go.sum b/go.sum index 9a4123e..43f5e20 100644 --- a/go.sum +++ b/go.sum @@ -25,12 +25,10 @@ github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdK github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/bmeg/grip v0.0.0-20250915204302-93cb1e8117c8 h1:UhgcpVbQuvqg8KJ0ioB4i/KaQw1Zel34oHKjSENPEIA= github.com/bmeg/grip v0.0.0-20250915204302-93cb1e8117c8/go.mod h1:mIN98ALRqqjqRHqopIuZ9iDJ97w4gAzXqdKE6Enuu7Y= -github.com/bmeg/jsonschema/v6 v6.0.4 h1:AXFAz7G05VZkKretSSU+uacMKF8+C16ONG6pzFzzA7E= -github.com/bmeg/jsonschema/v6 v6.0.4/go.mod h1:gTh32doM+BEZyi/TDPJEp8k3qXTckXY4ohptV2xExQY= -github.com/bmeg/jsonschemagraph v0.0.3 h1:n5c1p7VJKt3I4UVBmROLyHZ4NWDHR8unxBFwODHprAg= -github.com/bmeg/jsonschemagraph v0.0.3/go.mod h1:R3JJHOyGpYDGp9vaXSTPc55A+dt9+c8TUrwbiFujAAA= -github.com/bmeg/jsonschemagraph v0.0.4-0.20250828230703-257ca9afd85a h1:O0JcMLcazrwVzf8iC/RogUen4CG5UVErrBU76UkxhYQ= -github.com/bmeg/jsonschemagraph v0.0.4-0.20250828230703-257ca9afd85a/go.mod h1:rlek2WcKAhnynqE7NJi8U+RDbUkRFr8Kqpb2SDmcW94= +github.com/bmeg/jsonschema/v6 v6.0.5 h1:GnyWf8badsqBE0KytRwiuev240HtH89aj04+CzOd6SQ= +github.com/bmeg/jsonschema/v6 v6.0.5/go.mod h1:g21s8u35PcH2eGtPBjavAPmXWTwBLd40lHNyq72+ihs= +github.com/bmeg/jsonschemagraph v0.0.4 h1:/uL7TkE1bae4yR9jaJdk38wySu1ScVAg7x6gRKsz58g= +github.com/bmeg/jsonschemagraph v0.0.4/go.mod h1:PS6Pay0bC/7fGUbqNocpUCWhVJY5xivlXwzX6vbY7JM= github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M= github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM= github.com/bytedance/sonic v1.15.2 h1:90H+rcF/FwLXwfB1cudOLq/je83n683Utf4Cbp0xHCo= @@ -45,8 +43,6 @@ github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= -github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -155,8 +151,6 @@ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99 github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/segmentio/asm v1.2.1 h1:DTNbBqs57ioxAD4PrArqftgypG4/qNpXoJx8TVXxPR0= github.com/segmentio/asm v1.2.1/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= @@ -190,8 +184,6 @@ github.com/tinylib/msgp v1.6.4 h1:mOwYbyYDLPj35mkA2BjjYejgJk9BuHxDdvRnb6v2ZcQ= github.com/tinylib/msgp v1.6.4/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= -github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.71.0 h1:tepR7H+Guh9VUqxxcPggYi8R3lGUu2Rsdh+z7/FCY3k= @@ -200,8 +192,6 @@ github.com/vektah/gqlparser/v2 v2.5.22 h1:yaaeJ0fu+nv1vUMW0Hl+aS1eiv1vMfapBNjpff github.com/vektah/gqlparser/v2 v2.5.22/go.mod h1:xMl+ta8a5M1Yo1A1Iwt/k7gSpscwSnHZdw7tfhEGfTM= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= -github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -238,8 +228,6 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4= -golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -256,8 +244,6 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= -golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -284,8 +270,6 @@ golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8= -golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/ingest/row_builder.go b/internal/ingest/row_builder.go index 15936c9..43fae67 100644 --- a/internal/ingest/row_builder.go +++ b/internal/ingest/row_builder.go @@ -2,10 +2,8 @@ package ingest import ( "encoding/json" - "maps" "time" - "github.com/bmeg/grip/gripql" "github.com/bmeg/jsonschema/v6" "github.com/bmeg/jsonschemagraph/graph" "github.com/bytedance/sonic" @@ -112,7 +110,7 @@ func (b *GenericRowBuilder) Build(resourceType string, line []byte, stageSeconds stageSeconds["decode"] += time.Since(decodeStart).Seconds() validateStart := time.Now() - if err := b.class.Validate(payload); err != nil { + if err := b.class.ValidateFast(payload); err != nil { stageSeconds["validate"] += time.Since(validateStart).Seconds() return rowBuildResult{}, rowErrorValidation, err } @@ -126,22 +124,18 @@ func (b *GenericRowBuilder) Build(resourceType string, line []byte, stageSeconds } edgeStart := time.Now() - // Generate is the public jsonschemagraph API. The repository's historical - // BuildEdgesWithID helper is not part of the published module, so select the - // edge elements from Generate while preserving the same edge conversion and - // authorization propagation below. - elements, err := b.schema.Generate(resourceType, payload, maps.Clone(b.extraArgs)) + objectIDStart := time.Now() + objectID, err := graphObjectID(payload, b.class) + stageSeconds["object_id"] += time.Since(objectIDStart).Seconds() + if err != nil { + return rowBuildResult{}, rowErrorGeneration, err + } + gripEdges, err := b.schema.BuildEdgesWithID(resourceType, objectID, payload, b.extraArgs, true) stageSeconds["edge_generation"] += time.Since(edgeStart).Seconds() if err != nil { return rowBuildResult{}, rowErrorGeneration, err } - gripEdges := make([]*gripql.Edge, 0, len(elements)) - for _, element := range elements { - if element != nil && element.Edge != nil { - gripEdges = append(gripEdges, element.Edge) - } - } convertedEdges := make([]json.RawMessage, 0, len(gripEdges)) authResourcePath, _ := b.extraArgs["auth_resource_path"].(string) for _, generatedEdge := range gripEdges { From cbaece8dd0044164d5516f66751ea3025e3f256c Mon Sep 17 00:00:00 2001 From: matthewpeterkort Date: Mon, 13 Jul 2026 11:08:45 -0700 Subject: [PATCH 10/15] build: make repository root the server command --- README.md | 6 ++ cmd/arango-fhir-server/main.go | 178 +------------------------------- internal/server/server.go | 182 +++++++++++++++++++++++++++++++++ main.go | 7 ++ 4 files changed, 197 insertions(+), 176 deletions(-) create mode 100644 internal/server/server.go create mode 100644 main.go diff --git a/README.md b/README.md index 3596be8..494becb 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,12 @@ make generate-graphql make build ``` +The repository root is also the server command, so a plain build works: + +```bash +go build . +``` + Load the bundled sample dataset: ```bash diff --git a/cmd/arango-fhir-server/main.go b/cmd/arango-fhir-server/main.go index 9e5d63b..4b96f6d 100644 --- a/cmd/arango-fhir-server/main.go +++ b/cmd/arango-fhir-server/main.go @@ -1,181 +1,7 @@ package main -import ( - "context" - "flag" - "fmt" - "log/slog" - "os" - "os/signal" - "syscall" - - "github.com/calypr/loom/graphqlapi" - dataframeapi "github.com/calypr/loom/graphqlapi/dataframe" - "github.com/calypr/loom/internal/authscope" - "github.com/calypr/loom/internal/catalog" - "github.com/calypr/loom/internal/dataframe" - "github.com/calypr/loom/internal/dataframe/materialization" - materializationarango "github.com/calypr/loom/internal/dataframe/materialization/arango" - "github.com/calypr/loom/internal/dataset" - datasetarango "github.com/calypr/loom/internal/dataset/arango" - api "github.com/calypr/loom/internal/httpapi" - "github.com/calypr/loom/internal/ingest" - arangostore "github.com/calypr/loom/internal/store/arango" - clickhousestore "github.com/calypr/loom/internal/store/clickhouse" -) +import "github.com/calypr/loom/internal/server" func main() { - var ( - listen = flag.String("listen", ":8080", "HTTP listen address") - noAuth = flag.Bool("no-auth", false, "disable scoped authorization for local development") - backend = flag.String("backend", "arango", "storage backend") - url = flag.String("url", "http://127.0.0.1:8529", "ArangoDB URL") - database = flag.String("database", "fhir_proto", "ArangoDB database") - schema = flag.String("schema", "schemas/graph-fhir.json", "FHIR graph schema path for imports") - // Dataset generations opt the server into resolving a project's READY - // active manifest before dataframe discovery or execution. This mode - // disables the legacy one-file import route because that route cannot - // safely construct a complete immutable snapshot. - datasetGenerations = flag.Bool("dataset-generations", false, "resolve active immutable dataset generations for dataframe reads and disable legacy single-resource imports") - clickhouseURL = flag.String("clickhouse-url", "clickhouse://127.0.0.1:9000", "ClickHouse native URL for published dataframe reads") - clickhouseDatabase = flag.String("clickhouse-database", "loom", "ClickHouse database for published dataframe reads") - ) - flag.Parse() - - if *backend != "arango" { - exitf("unsupported backend %q: only arango is wired in this server", *backend) - } - - logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{})) - connOpts := arangostore.ConnectionOptions{ - URL: *url, - Database: *database, - } - - // Keep this as an interface, not a typed *datasetarango.Store nil. Passing a - // typed nil into dataframeapi.Config makes the interface non-nil and - // incorrectly activates immutable-generation lookup for legacy META loads. - var activeManifestResolver dataset.ActiveManifestResolver - if *datasetGenerations { - lifecycleClient, err := arangostore.Open(context.Background(), connOpts.URL, connOpts.Database) - if err != nil { - exitf("open dataset lifecycle store: %v", err) - } - defer lifecycleClient.Close(context.Background()) - if err := lifecycleClient.Bootstrap(context.Background(), datasetarango.BootstrapSpec()); err != nil { - exitf("bootstrap dataset lifecycle store: %v", err) - } - activeManifestResolver, err = datasetarango.New(lifecycleClient) - if err != nil { - exitf("create dataset lifecycle store: %v", err) - } - } - - discoveryCache := catalog.NewCache() - discoverFields := discoveryCache.DiscoverFields(catalog.DiscoverPopulatedFields) - discoverReferences := discoveryCache.DiscoverReferences(catalog.DiscoverPopulatedReferences) - - var scopeResolver *authscope.ScopeResolver - var authorizer authscope.Authorizer - if *noAuth { - authorizer = authscope.AllowAllAuthorizer{} - } else { - scopeResolver = authscope.NewScopeResolver(authscope.ScopeResolverConfig{ - ConnectionOptions: connOpts, - }) - authorizer = authscope.ScopeAuthorizer{Resolver: scopeResolver} - } - - dataframes := dataframe.NewService(dataframe.ServiceConfig{ - ConnectionOptions: connOpts, - DiscoverReferences: discoverReferences, - DiscoverFields: discoverFields, - ScopeResolver: scopeResolver, - ActiveManifestResolver: activeManifestResolver, - }) - registryClient, err := arangostore.Open(context.Background(), connOpts.URL, connOpts.Database) - if err != nil { - exitf("open dataframe registry store: %v", err) - } - defer registryClient.Close(context.Background()) - if err := registryClient.Bootstrap(context.Background(), materializationarango.BootstrapSpec()); err != nil { - exitf("bootstrap dataframe registry store: %v", err) - } - registry, err := materializationarango.New(registryClient) - if err != nil { - exitf("create dataframe registry: %v", err) - } - clickhouse, err := clickhousestore.New(clickhousestore.Options{URL: *clickhouseURL, Database: *clickhouseDatabase}) - if err != nil { - exitf("create ClickHouse client: %v", err) - } - defer clickhouse.Close() - materializer := &materialization.Service{Dataframes: dataframes, ClickHouse: clickhouse, Registry: registry} - materializationReader := &materialization.Reader{ClickHouse: clickhouse, Registry: registry, MaxPage: 1000} - resolver := graphqlapi.NewResolver(dataframeapi.Config{ - ConnectionOptions: connOpts, - DiscoverReferences: discoverReferences, - DiscoverFields: discoverFields, - Dataframes: dataframes, - ScopeResolver: scopeResolver, - ActiveManifestResolver: activeManifestResolver, - Materializations: materializer, - MaterializationReader: materializationReader, - }) - - importService, err := api.NewService(api.ServiceConfig{ - Runner: api.IngestRunner{BaseOptions: ingest.LoadOptions{ - ConnectionOptions: connOpts, - Schema: *schema, - }}, - Logger: logger, - OnSuccess: func(project string) { - discoveryCache.InvalidateProject(project) - if scopeResolver != nil { - scopeResolver.InvalidateProject(project) - } - }, - }) - if err != nil { - exitf("create import service: %v", err) - } - - server, err := api.NewHTTPServer(api.HTTPConfig{ - Service: importService, - Authorizer: authorizer, - GraphQLHandler: graphqlapi.NewHandler(resolver), - GraphQLPlaygroundHandler: graphqlapi.NewPlaygroundHandler("/graphql"), - ApolloSandboxHandler: graphqlapi.NewApolloSandboxHandler("/graphql"), - DisableSingleResourceImports: *datasetGenerations, - Logger: logger, - }) - if err != nil { - exitf("create HTTP server: %v", err) - } - - errCh := make(chan error, 1) - go func() { - logger.Info("starting HTTP server", "listen", *listen, "database", *database, "no_auth", *noAuth, "dataset_generations", *datasetGenerations) - errCh <- server.App().Listen(*listen) - }() - - stop := make(chan os.Signal, 1) - signal.Notify(stop, os.Interrupt, syscall.SIGTERM) - - select { - case err := <-errCh: - if err != nil { - exitf("server stopped: %v", err) - } - case sig := <-stop: - logger.Info("shutting down HTTP server", "signal", sig.String()) - if err := server.App().ShutdownWithContext(context.Background()); err != nil { - exitf("shutdown failed: %v", err) - } - } -} - -func exitf(format string, args ...any) { - _, _ = fmt.Fprintf(os.Stderr, format+"\n", args...) - os.Exit(1) + server.Run() } diff --git a/internal/server/server.go b/internal/server/server.go new file mode 100644 index 0000000..77df3e6 --- /dev/null +++ b/internal/server/server.go @@ -0,0 +1,182 @@ +package server + +import ( + "context" + "flag" + "fmt" + "log/slog" + "os" + "os/signal" + "syscall" + + "github.com/calypr/loom/graphqlapi" + dataframeapi "github.com/calypr/loom/graphqlapi/dataframe" + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/dataframe" + "github.com/calypr/loom/internal/dataframe/materialization" + materializationarango "github.com/calypr/loom/internal/dataframe/materialization/arango" + "github.com/calypr/loom/internal/dataset" + datasetarango "github.com/calypr/loom/internal/dataset/arango" + api "github.com/calypr/loom/internal/httpapi" + "github.com/calypr/loom/internal/ingest" + arangostore "github.com/calypr/loom/internal/store/arango" + clickhousestore "github.com/calypr/loom/internal/store/clickhouse" +) + +// Run starts the Loom HTTP server using the process command-line flags. +func Run() { + var ( + listen = flag.String("listen", ":8080", "HTTP listen address") + noAuth = flag.Bool("no-auth", false, "disable scoped authorization for local development") + backend = flag.String("backend", "arango", "storage backend") + url = flag.String("url", "http://127.0.0.1:8529", "ArangoDB URL") + database = flag.String("database", "fhir_proto", "ArangoDB database") + schema = flag.String("schema", "schemas/graph-fhir.json", "FHIR graph schema path for imports") + // Dataset generations opt the server into resolving a project's READY + // active manifest before dataframe discovery or execution. This mode + // disables the legacy one-file import route because that route cannot + // safely construct a complete immutable snapshot. + datasetGenerations = flag.Bool("dataset-generations", false, "resolve active immutable dataset generations for dataframe reads and disable legacy single-resource imports") + clickhouseURL = flag.String("clickhouse-url", "clickhouse://127.0.0.1:9000", "ClickHouse native URL for published dataframe reads") + clickhouseDatabase = flag.String("clickhouse-database", "loom", "ClickHouse database for published dataframe reads") + ) + flag.Parse() + + if *backend != "arango" { + exitf("unsupported backend %q: only arango is wired in this server", *backend) + } + + logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{})) + connOpts := arangostore.ConnectionOptions{ + URL: *url, + Database: *database, + } + + // Keep this as an interface, not a typed *datasetarango.Store nil. Passing a + // typed nil into dataframeapi.Config makes the interface non-nil and + // incorrectly activates immutable-generation lookup for legacy META loads. + var activeManifestResolver dataset.ActiveManifestResolver + if *datasetGenerations { + lifecycleClient, err := arangostore.Open(context.Background(), connOpts.URL, connOpts.Database) + if err != nil { + exitf("open dataset lifecycle store: %v", err) + } + defer lifecycleClient.Close(context.Background()) + if err := lifecycleClient.Bootstrap(context.Background(), datasetarango.BootstrapSpec()); err != nil { + exitf("bootstrap dataset lifecycle store: %v", err) + } + activeManifestResolver, err = datasetarango.New(lifecycleClient) + if err != nil { + exitf("create dataset lifecycle store: %v", err) + } + } + + discoveryCache := catalog.NewCache() + discoverFields := discoveryCache.DiscoverFields(catalog.DiscoverPopulatedFields) + discoverReferences := discoveryCache.DiscoverReferences(catalog.DiscoverPopulatedReferences) + + var scopeResolver *authscope.ScopeResolver + var authorizer authscope.Authorizer + if *noAuth { + authorizer = authscope.AllowAllAuthorizer{} + } else { + scopeResolver = authscope.NewScopeResolver(authscope.ScopeResolverConfig{ + ConnectionOptions: connOpts, + }) + authorizer = authscope.ScopeAuthorizer{Resolver: scopeResolver} + } + + dataframes := dataframe.NewService(dataframe.ServiceConfig{ + ConnectionOptions: connOpts, + DiscoverReferences: discoverReferences, + DiscoverFields: discoverFields, + ScopeResolver: scopeResolver, + ActiveManifestResolver: activeManifestResolver, + }) + registryClient, err := arangostore.Open(context.Background(), connOpts.URL, connOpts.Database) + if err != nil { + exitf("open dataframe registry store: %v", err) + } + defer registryClient.Close(context.Background()) + if err := registryClient.Bootstrap(context.Background(), materializationarango.BootstrapSpec()); err != nil { + exitf("bootstrap dataframe registry store: %v", err) + } + registry, err := materializationarango.New(registryClient) + if err != nil { + exitf("create dataframe registry: %v", err) + } + clickhouse, err := clickhousestore.New(clickhousestore.Options{URL: *clickhouseURL, Database: *clickhouseDatabase}) + if err != nil { + exitf("create ClickHouse client: %v", err) + } + defer clickhouse.Close() + materializer := &materialization.Service{Dataframes: dataframes, ClickHouse: clickhouse, Registry: registry} + materializationReader := &materialization.Reader{ClickHouse: clickhouse, Registry: registry, MaxPage: 1000} + resolver := graphqlapi.NewResolver(dataframeapi.Config{ + ConnectionOptions: connOpts, + DiscoverReferences: discoverReferences, + DiscoverFields: discoverFields, + Dataframes: dataframes, + ScopeResolver: scopeResolver, + ActiveManifestResolver: activeManifestResolver, + Materializations: materializer, + MaterializationReader: materializationReader, + }) + + importService, err := api.NewService(api.ServiceConfig{ + Runner: api.IngestRunner{BaseOptions: ingest.LoadOptions{ + ConnectionOptions: connOpts, + Schema: *schema, + }}, + Logger: logger, + OnSuccess: func(project string) { + discoveryCache.InvalidateProject(project) + if scopeResolver != nil { + scopeResolver.InvalidateProject(project) + } + }, + }) + if err != nil { + exitf("create import service: %v", err) + } + + server, err := api.NewHTTPServer(api.HTTPConfig{ + Service: importService, + Authorizer: authorizer, + GraphQLHandler: graphqlapi.NewHandler(resolver), + GraphQLPlaygroundHandler: graphqlapi.NewPlaygroundHandler("/graphql"), + ApolloSandboxHandler: graphqlapi.NewApolloSandboxHandler("/graphql"), + DisableSingleResourceImports: *datasetGenerations, + Logger: logger, + }) + if err != nil { + exitf("create HTTP server: %v", err) + } + + errCh := make(chan error, 1) + go func() { + logger.Info("starting HTTP server", "listen", *listen, "database", *database, "no_auth", *noAuth, "dataset_generations", *datasetGenerations) + errCh <- server.App().Listen(*listen) + }() + + stop := make(chan os.Signal, 1) + signal.Notify(stop, os.Interrupt, syscall.SIGTERM) + + select { + case err := <-errCh: + if err != nil { + exitf("server stopped: %v", err) + } + case sig := <-stop: + logger.Info("shutting down HTTP server", "signal", sig.String()) + if err := server.App().ShutdownWithContext(context.Background()); err != nil { + exitf("shutdown failed: %v", err) + } + } +} + +func exitf(format string, args ...any) { + _, _ = fmt.Fprintf(os.Stderr, format+"\n", args...) + os.Exit(1) +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..4b96f6d --- /dev/null +++ b/main.go @@ -0,0 +1,7 @@ +package main + +import "github.com/calypr/loom/internal/server" + +func main() { + server.Run() +} From da75f0aaeb87db4dbed7f05384870b0f78227fb6 Mon Sep 17 00:00:00 2001 From: matthewpeterkort Date: Mon, 13 Jul 2026 11:49:07 -0700 Subject: [PATCH 11/15] remove local data based ci go tests --- .github/workflows/build.yaml | 145 +++++++++--- internal/ingest/bench_test.go | 2 +- internal/ingest/generation_identity_test.go | 64 +----- internal/ingest/integration_test.go | 12 +- internal/ingest/parity_test.go | 230 -------------------- internal/ingest/row_builder_auth_test.go | 56 ----- 6 files changed, 117 insertions(+), 392 deletions(-) delete mode 100644 internal/ingest/parity_test.go delete mode 100644 internal/ingest/row_builder_auth_test.go diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index ebf9256..09a8724 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,9 +1,10 @@ -name: Build and publish arango-fhir-server image +name: Build and publish Loom image on: push: branches: - main + - development tags: - 'v*' workflow_dispatch: @@ -11,41 +12,113 @@ on: permissions: contents: read +concurrency: + group: loom-image-${{ github.ref }} + cancel-in-progress: true + +env: + IMAGE: quay.io/ohsu-comp-bio/arango-fhir-proto + jobs: - build: + build-and-push: + name: Build ${{ matrix.arch }} image + runs-on: ${{ matrix.arch == 'amd64' && 'ubuntu-latest' || 'ubuntu-24.04-arm' }} + strategy: + fail-fast: false + matrix: + arch: [amd64, arm64] + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.IMAGE }} + tags: | + type=ref,event=branch + type=sha,format=short + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=raw,value=latest,enable=${{ github.ref_type == 'tag' && !contains(github.ref_name, '-rc.') }} + + - name: Log in to Quay.io + uses: docker/login-action@v3 + with: + registry: quay.io + username: ${{ secrets.QUAY_USERNAME }} + password: ${{ secrets.QUAY_ROBOT_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and push by digest + id: build + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + platforms: linux/${{ matrix.arch }} + labels: ${{ steps.meta.outputs.labels }} + outputs: type=image,name=${{ env.IMAGE }},push-by-digest=true,name-canonical=true,push=true + cache-from: type=gha,scope=loom-${{ matrix.arch }} + cache-to: type=gha,mode=max,scope=loom-${{ matrix.arch }} + + - name: Export image digest + run: | + set -euo pipefail + mkdir -p /tmp/loom-digests + printf '%s\n' "${{ steps.build.outputs.digest }}" > "/tmp/loom-digests/${{ matrix.arch }}.txt" + + - name: Upload image digest + uses: actions/upload-artifact@v4 + with: + name: loom-digest-${{ matrix.arch }} + path: /tmp/loom-digests/* + if-no-files-found: error + retention-days: 1 + + merge: + name: Publish multi-architecture manifest runs-on: ubuntu-latest + needs: build-and-push steps: - - name: Check out code - uses: actions/checkout@v4 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to Quay.io - uses: docker/login-action@v3 - with: - registry: quay.io - username: ${{ secrets.QUAY_USERNAME }} - password: ${{ secrets.QUAY_ROBOT_TOKEN }} - - - name: Extract Docker metadata - id: meta - uses: docker/metadata-action@v5 - with: - images: quay.io/ohsu-comp-bio/arango-fhir-proto - tags: | - type=ref,event=branch - type=ref,event=tag - type=sha - type=raw,value=latest,enable={{is_default_branch}} - - - name: Build and push image - uses: docker/build-push-action@v6 - with: - context: . - file: ./Dockerfile - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max + - name: Download image digests + uses: actions/download-artifact@v4 + with: + path: /tmp/loom-digests + pattern: loom-digest-* + merge-multiple: true + + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.IMAGE }} + tags: | + type=ref,event=branch + type=sha,format=short + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=raw,value=latest,enable=${{ github.ref_type == 'tag' && !contains(github.ref_name, '-rc.') }} + + - name: Log in to Quay.io + uses: docker/login-action@v3 + with: + registry: quay.io + username: ${{ secrets.QUAY_USERNAME }} + password: ${{ secrets.QUAY_ROBOT_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Create and push manifest list + env: + DOCKER_METADATA_OUTPUT_TAGS: ${{ steps.meta.outputs.tags }} + run: | + set -euo pipefail + mapfile -t digests < <(cat /tmp/loom-digests/*.txt) + docker buildx imagetools create \ + $(printf '%s\n' "$DOCKER_METADATA_OUTPUT_TAGS" | xargs -n 1 printf -- '-t %s ') \ + $(printf '%s@%s ' "$IMAGE" "${digests[@]}") diff --git a/internal/ingest/bench_test.go b/internal/ingest/bench_test.go index d4fe1d3..44d7fe7 100644 --- a/internal/ingest/bench_test.go +++ b/internal/ingest/bench_test.go @@ -17,7 +17,7 @@ import ( ) func BenchmarkValidateAndExtract(b *testing.B) { - schemaPath := benchRepoPath(b, "..", "iceberg", "schemas", "graph", "graph-fhir.json") + schemaPath := benchRepoPath(b, "schemas", "graph-fhir.json") schema, err := graph.Load(schemaPath) if err != nil { b.Fatalf("failed to load schema: %v", err) diff --git a/internal/ingest/generation_identity_test.go b/internal/ingest/generation_identity_test.go index 5145d13..03484f9 100644 --- a/internal/ingest/generation_identity_test.go +++ b/internal/ingest/generation_identity_test.go @@ -2,15 +2,12 @@ package ingest import ( "encoding/json" - "os" "path/filepath" "reflect" "runtime" "sort" "strings" "testing" - - "github.com/bmeg/jsonschemagraph/graph" ) func TestNamespaceRowBuildResultKeepsLogicalFHIRIdentityAndQualifiesGraphIdentity(t *testing.T) { @@ -141,46 +138,6 @@ func TestGenerationRowBuilderTurnsIdentityFailureIntoGenerationError(t *testing. } } -func TestGeneratedAndGenericBuildersShareGenerationQualifiedIdentityForMETA(t *testing.T) { - line := metaFixtureLine(t, "Specimen.ndjson") - schema, err := graph.Load(filepath.Join(repoRoot(t), "schemas", "graph-fhir.json")) - if err != nil { - t.Fatalf("graph.Load: %v", err) - } - class := schema.GetClass("Specimen") - if class == nil { - t.Fatal("Specimen class is absent from checked-in graph schema") - } - - generated, err := newGenerationRowBuilder(NewGeneratedRowBuilder("meta-baseline", ""), "meta-baseline", "generation-a") - if err != nil { - t.Fatal(err) - } - generic, err := newGenerationRowBuilder(NewGenericRowBuilder("meta-baseline", class, schema, nil), "meta-baseline", "generation-a") - if err != nil { - t.Fatal(err) - } - - generatedResult, generatedKind, err := generated.Build("Specimen", line, map[string]float64{}) - if err != nil { - t.Fatalf("generated Build() kind %q: %v", generatedKind, err) - } - genericResult, genericKind, err := generic.Build("Specimen", line, map[string]float64{}) - if err != nil { - t.Fatalf("generic Build() kind %q: %v", genericKind, err) - } - - if got, want := documentString(t, decodeIdentityDocument(t, generatedResult.vertex), "_key"), documentString(t, decodeIdentityDocument(t, genericResult.vertex), "_key"); got != want { - t.Fatalf("generation-qualified vertex keys differ\ngenerated: %q\ngeneric: %q", got, want) - } - if got, want := documentString(t, decodeIdentityDocument(t, generatedResult.vertex), logicalKeyField), documentString(t, decodeIdentityDocument(t, genericResult.vertex), logicalKeyField); got != want { - t.Fatalf("logical vertex keys differ\ngenerated: %q\ngeneric: %q", got, want) - } - if got, want := edgeIdentityTuples(t, generatedResult.edges), edgeIdentityTuples(t, genericResult.edges); !reflect.DeepEqual(got, want) { - t.Fatalf("generation-qualified edge identities differ\ngenerated: %#v\ngeneric: %#v", got, want) - } -} - type rowBuilderFunc func(string, []byte, map[string]float64) (rowBuildResult, rowErrorType, error) func (f rowBuilderFunc) Build(resourceType string, line []byte, stageSeconds map[string]float64) (rowBuildResult, rowErrorType, error) { @@ -231,22 +188,6 @@ func edgeIdentityTuples(t *testing.T, edges []json.RawMessage) []string { return tuples } -func metaFixtureLine(t *testing.T, filename string) []byte { - t.Helper() - data, err := os.ReadFile(filepath.Join(repoRoot(t), "META", filename)) - if err != nil { - t.Fatalf("read META fixture %s: %v", filename, err) - } - for _, line := range strings.Split(string(data), "\n") { - line = strings.TrimSpace(line) - if line != "" { - return []byte(line) - } - } - t.Fatalf("META fixture %s has no NDJSON row", filename) - return nil -} - func repoRoot(t *testing.T) string { t.Helper() _, source, _, ok := runtime.Caller(0) @@ -255,3 +196,8 @@ func repoRoot(t *testing.T) string { } return filepath.Clean(filepath.Join(filepath.Dir(source), "..", "..")) } + +func repoPath(t *testing.T, elems ...string) string { + t.Helper() + return filepath.Join(append([]string{repoRoot(t)}, elems...)...) +} diff --git a/internal/ingest/integration_test.go b/internal/ingest/integration_test.go index 18e0992..da4c42d 100644 --- a/internal/ingest/integration_test.go +++ b/internal/ingest/integration_test.go @@ -5,7 +5,6 @@ import ( "context" "os" "path/filepath" - "runtime" "strings" "testing" "time" @@ -31,7 +30,7 @@ func TestLoadAndQueryFixture(t *testing.T) { } expectedVertices := 0 expectedEdges := 0 - schema, err := graph.Load(repoPath(t, "..", "iceberg", "schemas", "graph", "graph-fhir.json")) + schema, err := graph.Load(repoPath(t, "schemas", "graph-fhir.json")) if err != nil { t.Fatalf("load graph schema: %v", err) } @@ -66,7 +65,7 @@ func TestLoadAndQueryFixture(t *testing.T) { URL: "http://127.0.0.1:8529", Database: database, }, - Schema: repoPath(t, "..", "iceberg", "schemas", "graph", "graph-fhir.json"), + Schema: repoPath(t, "schemas", "graph-fhir.json"), MetaDir: fixtureDir, Project: "ARANGO_PROTO_TEST", BatchSize: 100, @@ -132,10 +131,3 @@ func copyFirstLineFixture(t *testing.T, src, dst string) map[string]any { } return payload } - -func repoPath(t *testing.T, elems ...string) string { - t.Helper() - _, file, _, _ := runtime.Caller(0) - base := filepath.Clean(filepath.Join(filepath.Dir(file), "..", "..")) - return filepath.Join(append([]string{base}, elems...)...) -} diff --git a/internal/ingest/parity_test.go b/internal/ingest/parity_test.go deleted file mode 100644 index 058719d..0000000 --- a/internal/ingest/parity_test.go +++ /dev/null @@ -1,230 +0,0 @@ -package ingest - -import ( - "bufio" - "bytes" - "encoding/json" - "os" - "path/filepath" - "reflect" - "strings" - "testing" - - fhir "github.com/calypr/loom/fhirstructs" - - "github.com/bmeg/jsonschemagraph/graph" - "github.com/bytedance/sonic" - jsgarango "github.com/calypr/loom/internal/graphstore" -) - -type EdgeDocument = jsgarango.EdgeDocument - -func TestGenericAndGeneratedParity(t *testing.T) { - schemaPath := repoPath(t, "..", "iceberg", "schemas", "graph", "graph-fhir.json") - schema, err := graph.Load(schemaPath) - if err != nil { - t.Fatalf("failed to load schema: %v", err) - } - - hotResources := []string{ - "Condition", - "DocumentReference", - "MedicationAdministration", - "Observation", - "Group", - "Specimen", - "Patient", - } - - metaDir := repoPath(t, "META") - - for _, resourceType := range hotResources { - t.Run(resourceType, func(t *testing.T) { - path := filepath.Join(metaDir, resourceType+".ndjson") - file, err := os.Open(path) - if err != nil { - t.Fatalf("failed to open ndjson for %s: %v", resourceType, err) - } - defer file.Close() - - scanner := bufio.NewScanner(file) - scanner.Buffer(make([]byte, 1024*1024), 10*1024*1024) - - class := schema.GetClass(resourceType) - if class == nil { - t.Fatalf("failed to get class schema for %s", resourceType) - } - - lineCount := 0 - for scanner.Scan() { - lineCount++ - if lineCount > 200 { // Check first 200 rows of each hot resource - break - } - - line := strings.TrimSpace(scanner.Text()) - if line == "" { - continue - } - - raw := []byte(line) - - // 1. Generic Engine Validation & ID & Edge Build - var genericPayload map[string]any - genericDecodeErr := sonic.ConfigFastest.Unmarshal(raw, &genericPayload) - - var genericValid bool - var genericObjectID string - var genericEdges []any - - if genericDecodeErr == nil { - if err := class.ValidateFast(genericPayload); err == nil { - genericValid = true - genericObjectID, err = graphObjectID(genericPayload, class) - if err != nil { - t.Errorf("row %d: generic graphObjectID error: %v", lineCount, err) - continue - } - gripEdges, err := schema.BuildEdgesWithID(resourceType, genericObjectID, genericPayload, nil, true) - if err != nil { - t.Errorf("row %d: generic BuildEdgesWithID error: %v", lineCount, err) - continue - } - // Convert to Arango edge documents - for _, ge := range gripEdges { - edgeDoc, err := EdgeFromGrip("PARITY_TEST", resourceType, ge) - if err != nil { - t.Errorf("row %d: generic EdgeFromGrip error: %v", lineCount, err) - continue - } - genericEdges = append(genericEdges, edgeDoc) - } - } - } - - // 2. Generated Engine Validation & ID & Edge Build - stageTiming := make(map[string]float64) - genVertex, genEdges, genErr := loadRowGenerated(resourceType, raw, "PARITY_TEST", stageTiming) - genValid := genErr == nil - - // 3. Assert Parity - if genericValid != genValid { - t.Fatalf("row %d: acceptance mismatch. generic_valid=%t, generated_valid=%t. genErr: %v", - lineCount, genericValid, genValid, genErr) - } - - if !genericValid { - // Both rejected, which is correct parity - continue - } - - // Verify Object ID - if genericObjectID != genVertex.ID { - t.Fatalf("row %d: Object ID mismatch. generic=%q, generated=%q", - lineCount, genericObjectID, genVertex.ID) - } - - // Verify edges content (order might differ, so we compare as sets) - genericEdgeMap := make(map[string]EdgeDocument) - for _, e := range genericEdges { - doc := e.(EdgeDocument) - genericEdgeMap[doc.Key] = doc - } - - genEdgeMap := make(map[string]EdgeDocument) - for _, rawBytes := range genEdges { - var doc fhir.EdgeDocument - if err := sonic.Unmarshal(rawBytes, &doc); err != nil { - t.Fatalf("row %d: failed to unmarshal generated edge: %v", lineCount, err) - } - genDoc := EdgeDocument{ - Key: doc.Key, - From: doc.From, - To: doc.To, - Label: doc.Label, - Project: doc.Project, - FromType: doc.FromType, - ToType: doc.ToType, - } - genEdgeMap[genDoc.Key] = genDoc - } - - if len(genericEdgeMap) != len(genEdgeMap) { - t.Fatalf("row %d: Edge count mismatch (after dedup). generic=%d edges, generated=%d edges", - lineCount, len(genericEdgeMap), len(genEdgeMap)) - } - - for key, genDoc := range genEdgeMap { - matching, found := genericEdgeMap[key] - if !found { - t.Fatalf("row %d: generated edge key %q not found in generic edges", lineCount, key) - } - - if !reflect.DeepEqual(matching, genDoc) { - t.Fatalf("row %d: edge mismatch for key %q.\nGeneric: %+v\nGenerated: %+v", - lineCount, key, matching, genDoc) - } - } - } - - if err := scanner.Err(); err != nil { - t.Fatalf("scanner error: %v", err) - } - }) - } -} - -// EdgeFromGrip helper wrapper to avoid dependency issues in parity tests -func EdgeFromGrip(project, sourceType string, edge any) (EdgeDocument, error) { - data, err := json.Marshal(edge) - if err != nil { - return EdgeDocument{}, err - } - var doc struct { - ID string `json:"id"` - From string `json:"from"` - To string `json:"to"` - Label string `json:"label"` - } - if err := json.Unmarshal(data, &doc); err != nil { - return EdgeDocument{}, err - } - - targetType, targetID := "", doc.To - if strings.Contains(doc.To, "/") { - parts := strings.Split(doc.To, "/") - targetType, targetID = parts[0], parts[1] - } else { - parts := strings.Split(doc.Label, "_") - targetType = parts[len(parts)-1] - } - - sanitize := func(value string) string { - value = strings.TrimSpace(value) - if value == "" { - return "_" - } - var sb bytes.Buffer - for _, r := range value { - if (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || - r == '_' || r == '-' || r == ':' || r == '.' || r == '@' || r == '(' || r == ')' || - r == '+' || r == ',' || r == '=' || r == ';' || r == '$' || r == '!' || r == '*' || - r == '\'' || r == '%' { - sb.WriteRune(r) - } else { - sb.WriteRune('_') - } - } - return sb.String() - } - - return EdgeDocument{ - Key: sanitize(doc.ID), - From: sanitize(sourceType) + "/" + sanitize(doc.From), - To: sanitize(targetType) + "/" + sanitize(targetID), - Label: doc.Label, - Project: project, - FromType: sourceType, - ToType: targetType, - }, nil -} diff --git a/internal/ingest/row_builder_auth_test.go b/internal/ingest/row_builder_auth_test.go deleted file mode 100644 index 0bd445b..0000000 --- a/internal/ingest/row_builder_auth_test.go +++ /dev/null @@ -1,56 +0,0 @@ -package ingest - -import ( - "bufio" - "encoding/json" - "os" - "testing" - - "github.com/bmeg/jsonschemagraph/graph" -) - -func TestGenericRowBuilderPropagatesAuthScopeToEdges(t *testing.T) { - schema, err := graph.Load(repoPath(t, "schemas", "graph-fhir.json")) - if err != nil { - t.Fatal(err) - } - class := schema.GetClass("Specimen") - if class == nil { - t.Fatal("Specimen class is missing from checked-in graph schema") - } - line := firstFixtureLine(t, repoPath(t, "META", "Specimen.ndjson")) - builder := NewGenericRowBuilder("P1", class, schema, graphExtraArgs("/programs/p1")) - result, kind, err := builder.Build("Specimen", line, map[string]float64{}) - if err != nil || kind != "" { - t.Fatalf("generic Build() kind=%q error=%v", kind, err) - } - if len(result.edges) == 0 { - t.Fatal("fixture Specimen produced no graph edges") - } - for _, raw := range result.edges { - var edge map[string]any - if err := json.Unmarshal(raw, &edge); err != nil { - t.Fatal(err) - } - if got := edge["auth_resource_path"]; got != "/programs/p1" { - t.Fatalf("generic edge scope = %#v, want /programs/p1; edge=%s", got, raw) - } - } -} - -func firstFixtureLine(t *testing.T, path string) []byte { - t.Helper() - file, err := os.Open(path) - if err != nil { - t.Fatal(err) - } - defer file.Close() - scanner := bufio.NewScanner(file) - if !scanner.Scan() { - t.Fatalf("fixture %s is empty", path) - } - if err := scanner.Err(); err != nil { - t.Fatal(err) - } - return append([]byte(nil), scanner.Bytes()...) -} From deba6c7514621a5f7bddebaf02e8ecf1c398b00f Mon Sep 17 00:00:00 2001 From: matthewpeterkort Date: Mon, 13 Jul 2026 13:16:39 -0700 Subject: [PATCH 12/15] reorg graphqlapi package --- .github/workflows/build.yaml | 5 + .github/workflows/tests.yaml | 4 +- README.md | 5 +- cmd/dataframe-profile/main.go | 4 +- experimental/README.md | 16 +- experimental/docker-compose.yml | 9 + go.mod | 1 + go.sum | 14 ++ graphqlapi/dataframe/service.go | 238 ------------------ graphqlapi/http_integration_test.go | 187 +++++++------- .../output.go} | 8 +- graphqlapi/materialization/service.go | 162 ++++++++++++ graphqlapi/output_mapping.go | 10 +- .../{dataframe => query}/active_generation.go | 2 +- .../active_generation_test.go | 2 +- .../{dataframe => query}/auth_scope_test.go | 2 +- graphqlapi/{dataframe => query}/datasets.go | 2 +- .../{dataframe => query}/datasets_test.go | 2 +- graphqlapi/query/doc.go | 4 + graphqlapi/{dataframe => query}/fieldrefs.go | 2 +- .../{dataframe => query}/fieldrefs_test.go | 2 +- graphqlapi/{dataframe => query}/helpers.go | 2 +- .../{dataframe => query}/input_mapping.go | 2 +- .../input_mapping_test.go | 2 +- .../{dataframe => query}/input_resolution.go | 2 +- .../{dataframe => query}/introspection.go | 2 +- .../introspection_test.go | 2 +- graphqlapi/query/service.go | 110 ++++++++ graphqlapi/{dataframe => query}/templates.go | 2 +- .../{dataframe => query}/templates_test.go | 2 +- graphqlapi/{dataframe => query}/types.go | 2 +- graphqlapi/{dataframe => query}/validation.go | 2 +- .../{dataframe => query}/validation_test.go | 2 +- graphqlapi/resolver.go | 22 +- graphqlapi/schema.resolvers.go | 19 +- internal/server/server.go | 24 +- 36 files changed, 491 insertions(+), 387 deletions(-) delete mode 100644 graphqlapi/dataframe/service.go rename graphqlapi/{materialization_output.go => materialization/output.go} (82%) create mode 100644 graphqlapi/materialization/service.go rename graphqlapi/{dataframe => query}/active_generation.go (97%) rename graphqlapi/{dataframe => query}/active_generation_test.go (99%) rename graphqlapi/{dataframe => query}/auth_scope_test.go (99%) rename graphqlapi/{dataframe => query}/datasets.go (99%) rename graphqlapi/{dataframe => query}/datasets_test.go (99%) create mode 100644 graphqlapi/query/doc.go rename graphqlapi/{dataframe => query}/fieldrefs.go (99%) rename graphqlapi/{dataframe => query}/fieldrefs_test.go (98%) rename graphqlapi/{dataframe => query}/helpers.go (94%) rename graphqlapi/{dataframe => query}/input_mapping.go (99%) rename graphqlapi/{dataframe => query}/input_mapping_test.go (99%) rename graphqlapi/{dataframe => query}/input_resolution.go (99%) rename graphqlapi/{dataframe => query}/introspection.go (99%) rename graphqlapi/{dataframe => query}/introspection_test.go (99%) create mode 100644 graphqlapi/query/service.go rename graphqlapi/{dataframe => query}/templates.go (99%) rename graphqlapi/{dataframe => query}/templates_test.go (99%) rename graphqlapi/{dataframe => query}/types.go (98%) rename graphqlapi/{dataframe => query}/validation.go (99%) rename graphqlapi/{dataframe => query}/validation_test.go (99%) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 09a8724..fc0386c 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -20,8 +20,13 @@ env: IMAGE: quay.io/ohsu-comp-bio/arango-fhir-proto jobs: + tests: + name: Verify Loom before publishing + uses: ./.github/workflows/tests.yaml + build-and-push: name: Build ${{ matrix.arch }} image + needs: tests runs-on: ${{ matrix.arch == 'amd64' && 'ubuntu-latest' || 'ubuntu-24.04-arm' }} strategy: fail-fast: false diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 16282cb..a395bc9 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -1,6 +1,8 @@ name: Go Tests -on: [ pull_request ] +on: + pull_request: + workflow_call: jobs: test: diff --git a/README.md b/README.md index 494becb..65f904f 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,8 @@ directory contains the local Arango compose setup. - [`internal/dataset`](internal/dataset): dataset generation, schema, and scope lifecycle contract - [`internal/dataset/arango`](internal/dataset/arango): Arango-backed immutable manifest and active-generation pointer store - [`graphqlapi`](graphqlapi): GraphQL schema, request mapping, introspection service, and gqlgen output -- [`graphqlapi/dataframe`](graphqlapi/dataframe): GraphQL dataframe input translation and builder introspection +- [`graphqlapi/query`](graphqlapi/query): GraphQL dataframe input translation, discovery, and builder introspection +- [`graphqlapi/materialization`](graphqlapi/materialization): GraphQL authorization and reads for published ClickHouse dataframes - [`internal/dataframe`](internal/dataframe): dataframe validation, lowering, and AQL compilation - [`fhirstructs`](fhirstructs): generated FHIR structs, validators, and graph-edge extraction - [`fhirschema`](fhirschema): generated compiler schema metadata and selector/traversal resolution @@ -233,4 +234,4 @@ What is current and real: - GraphQL introspection for populated traversals/fields/pivots - GraphQL dataframe execution on Arango - generated schema metadata in `fhirschema` -- derived field aliases in `graphqlapi/dataframe` and explicit lowering rules in `internal/dataframe` +- derived field aliases in `graphqlapi/query` and explicit lowering rules in `internal/dataframe` diff --git a/cmd/dataframe-profile/main.go b/cmd/dataframe-profile/main.go index 19153ab..c7bd6c6 100644 --- a/cmd/dataframe-profile/main.go +++ b/cmd/dataframe-profile/main.go @@ -15,8 +15,8 @@ import ( "time" compilerfixture "github.com/calypr/loom/conformance/compiler" - dataframeapi "github.com/calypr/loom/graphqlapi/dataframe" "github.com/calypr/loom/graphqlapi/model" + queryapi "github.com/calypr/loom/graphqlapi/query" "github.com/calypr/loom/internal/dataframe" arangostore "github.com/calypr/loom/internal/store/arango" ) @@ -95,7 +95,7 @@ func main() { if payload.Input.Project == "" || payload.Input.RootResourceType == "" { fatalf("GraphQL variables %q do not contain a complete input", *variables) } - builder = dataframeapi.BuilderFromInput(payload.Input) + builder = queryapi.BuilderFromInput(payload.Input) label = filepath.Base(*variables) } else { fixtures, err := compilerfixture.LoadDir(*fixtureDir) diff --git a/experimental/README.md b/experimental/README.md index b221c7f..8975df6 100644 --- a/experimental/README.md +++ b/experimental/README.md @@ -1,7 +1,7 @@ # Local Arango development -This directory contains the checked-in ArangoDB compose setup used by the -quickstart. Start it from the repository root: +This directory contains the checked-in ArangoDB and ClickHouse compose setup +used by the quickstart. Start it from the repository root: ```bash rtk docker compose -f experimental/docker-compose.yml up -d @@ -10,3 +10,15 @@ rtk docker compose -f experimental/docker-compose.yml up -d The runtime implementation lives under [`internal/store/arango/`](../internal/store/arango/) and [`internal/ingest/`](../internal/ingest/). This is not a home for a second query engine or manually maintained AQL recipes. + +ClickHouse is available at native `clickhouse://127.0.0.1:9000` (and HTTP +`http://127.0.0.1:8123`) for published dataframe materializations. The operator +command uses the native driver by default: + +```bash +./bin/arango-fhir-proto materialize-dataframe \ + --request dataframe.json \ + --name case-explorer \ + --clickhouse-url clickhouse://127.0.0.1:9000 \ + --clickhouse-database loom +``` diff --git a/experimental/docker-compose.yml b/experimental/docker-compose.yml index e74edfb..e59d937 100644 --- a/experimental/docker-compose.yml +++ b/experimental/docker-compose.yml @@ -8,3 +8,12 @@ services: - "8529:8529" volumes: - ./data:/var/lib/arangodb3 + + clickhouse: + image: clickhouse/clickhouse-server:25.3 + container_name: loom-clickhouse + ports: + - "8123:8123" + - "9000:9000" + volumes: + - ./clickhouse-data:/var/lib/clickhouse diff --git a/go.mod b/go.mod index 655aa93..61e667e 100644 --- a/go.mod +++ b/go.mod @@ -64,6 +64,7 @@ require ( golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect golang.org/x/crypto v0.53.0 // indirect golang.org/x/net v0.56.0 // indirect + golang.org/x/sync v0.21.0 // indirect golang.org/x/sys v0.46.0 // indirect golang.org/x/term v0.44.0 // indirect golang.org/x/text v0.38.0 // indirect diff --git a/go.sum b/go.sum index 43f5e20..ee0905a 100644 --- a/go.sum +++ b/go.sum @@ -43,6 +43,8 @@ github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= +github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -151,6 +153,8 @@ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99 github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/segmentio/asm v1.2.1 h1:DTNbBqs57ioxAD4PrArqftgypG4/qNpXoJx8TVXxPR0= github.com/segmentio/asm v1.2.1/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= @@ -184,6 +188,8 @@ github.com/tinylib/msgp v1.6.4 h1:mOwYbyYDLPj35mkA2BjjYejgJk9BuHxDdvRnb6v2ZcQ= github.com/tinylib/msgp v1.6.4/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= +github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.71.0 h1:tepR7H+Guh9VUqxxcPggYi8R3lGUu2Rsdh+z7/FCY3k= @@ -192,6 +198,8 @@ github.com/vektah/gqlparser/v2 v2.5.22 h1:yaaeJ0fu+nv1vUMW0Hl+aS1eiv1vMfapBNjpff github.com/vektah/gqlparser/v2 v2.5.22/go.mod h1:xMl+ta8a5M1Yo1A1Iwt/k7gSpscwSnHZdw7tfhEGfTM= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -228,6 +236,8 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4= +golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -244,6 +254,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= +golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -270,6 +282,8 @@ golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8= +golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/graphqlapi/dataframe/service.go b/graphqlapi/dataframe/service.go deleted file mode 100644 index 5f5ba44..0000000 --- a/graphqlapi/dataframe/service.go +++ /dev/null @@ -1,238 +0,0 @@ -package dataframeapi - -import ( - "context" - "fmt" - "time" - - "github.com/calypr/loom/graphqlapi/model" - "github.com/calypr/loom/internal/authscope" - "github.com/calypr/loom/internal/catalog" - "github.com/calypr/loom/internal/dataframe" - "github.com/calypr/loom/internal/dataframe/materialization" - "github.com/calypr/loom/internal/dataset" - arangostore "github.com/calypr/loom/internal/store/arango" -) - -type Service struct { - connOpts arangostore.ConnectionOptions - discoverReferences func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) - discoverFields func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) - dataframes *dataframe.Service - scopeResolver *authscope.ScopeResolver - activeManifestResolver dataset.ActiveManifestResolver - discoverDatasets func(context.Context, catalog.DatasetSummaryOptions) ([]catalog.DatasetSummary, error) - datasetProjectAllowlist []string - materializations *materialization.Service - materializationReader *materialization.Reader -} - -type Config struct { - ConnectionOptions arangostore.ConnectionOptions - DiscoverReferences func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) - DiscoverFields func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) - Dataframes *dataframe.Service - ScopeResolver *authscope.ScopeResolver - // ActiveManifestResolver is optional. When present, builder catalog - // discovery and recipe preparation resolve one READY active generation - // before inspecting any fields or relationship routes. - ActiveManifestResolver dataset.ActiveManifestResolver - // DatasetProjectAllowlist is the explicit project source used when a - // principal does not carry a project list. An empty value never triggers an - // unrestricted catalog scan. - DatasetProjectAllowlist []string - DiscoverDatasets func(context.Context, catalog.DatasetSummaryOptions) ([]catalog.DatasetSummary, error) - Materializations *materialization.Service - MaterializationReader *materialization.Reader -} - -func NewService(cfg Config) *Service { - service := &Service{ - connOpts: cfg.ConnectionOptions, - scopeResolver: cfg.ScopeResolver, - activeManifestResolver: cfg.ActiveManifestResolver, - datasetProjectAllowlist: cloneStrings(cfg.DatasetProjectAllowlist), - materializations: cfg.Materializations, - materializationReader: cfg.MaterializationReader, - } - if cfg.DiscoverDatasets != nil { - service.discoverDatasets = cfg.DiscoverDatasets - } else { - service.discoverDatasets = catalog.DiscoverDatasetSummaries - } - if cfg.DiscoverReferences != nil { - service.discoverReferences = cfg.DiscoverReferences - } else { - service.discoverReferences = catalog.DiscoverPopulatedReferences - } - if cfg.DiscoverFields != nil { - service.discoverFields = cfg.DiscoverFields - } else { - service.discoverFields = catalog.DiscoverPopulatedFields - } - if cfg.Dataframes != nil { - service.dataframes = cfg.Dataframes - } else { - service.dataframes = dataframe.NewService(dataframe.ServiceConfig{ - ConnectionOptions: cfg.ConnectionOptions, - DiscoverReferences: service.discoverReferences, - DiscoverFields: service.discoverFields, - ScopeResolver: cfg.ScopeResolver, - ActiveManifestResolver: cfg.ActiveManifestResolver, - }) - } - return service -} - -func (s *Service) Run(ctx context.Context, input model.FhirDataframeInput, limit *int) (*dataframe.Result, error) { - started := time.Now() - normalizedInput, scope, generation, err := s.prepareRunInput(ctx, input) - if err != nil { - return nil, err - } - rowLimit := 0 - if limit != nil { - rowLimit = *limit - } else if normalizedInput.Limit != nil { - rowLimit = *normalizedInput.Limit - } - builder := BuilderFromInput(normalizedInput) - builder.DatasetGeneration = generation - // Preserve the scope mode that resolved the catalog references above. This - // matters when no catalog paths survive a restricted caller's intersection: - // an empty list alone would otherwise be legacy-unrestricted downstream. - builder.AuthScopeMode = scope.Mode - result, err := s.dataframes.Run(ctx, dataframe.RunRequest{ - Builder: builder, - Limit: rowLimit, - }) - if err != nil { - return nil, err - } - result.Diagnostics.InputResolution = time.Since(started) - result.Diagnostics.Total - if result.Diagnostics.InputResolution < 0 { - result.Diagnostics.InputResolution = 0 - } - result.Diagnostics.Total = time.Since(started) - return result, nil -} - -func (s *Service) GetMaterialization(ctx context.Context, id string) (*materialization.Materialization, error) { - if s.materializationReader == nil { - return nil, fmt.Errorf("dataframe materialization reads are not configured") - } - value, err := s.materializationReader.Registry.Get(ctx, id) - if err != nil { - return nil, err - } - if err := s.authorizeMaterialization(ctx, value); err != nil { - return nil, err - } - return &value, nil -} - -func (s *Service) ReadMaterialization(ctx context.Context, input model.DataframeRowsInput) (materialization.Page, error) { - if s.materializationReader == nil { - return materialization.Page{}, fmt.Errorf("dataframe materialization reads are not configured") - } - materialized, err := s.materializationReader.Registry.Get(ctx, input.MaterializationID) - if err != nil { - return materialization.Page{}, err - } - if err := s.authorizeMaterialization(ctx, materialized); err != nil { - return materialization.Page{}, err - } - filters := make([]materialization.Filter, 0, len(input.Filters)) - for _, filter := range input.Filters { - if filter == nil { - continue - } - filters = append(filters, materialization.Filter{Column: filter.Column, Op: filter.Op, Value: filter.Value}) - } - var sortInput *materialization.Sort - if input.Sort != nil { - sortInput = &materialization.Sort{Column: input.Sort.Column, Desc: input.Sort.Desc != nil && *input.Sort.Desc} - } - first := 0 - if input.First != nil { - first = *input.First - } - return s.materializationReader.Page(ctx, materialization.PageRequest{MaterializationID: input.MaterializationID, Columns: input.Columns, Filters: filters, Sort: sortInput, First: first, After: derefString(input.After)}) -} - -func (s *Service) AggregateMaterialization(ctx context.Context, id string, groupBy []string, filters []*model.DataframeFilterInput, operation, column string) (materialization.AggregateResult, error) { - if s.materializationReader == nil { - return materialization.AggregateResult{}, fmt.Errorf("dataframe materialization reads are not configured") - } - value, err := s.materializationReader.Registry.Get(ctx, id) - if err != nil { - return materialization.AggregateResult{}, err - } - if err := s.authorizeMaterialization(ctx, value); err != nil { - return materialization.AggregateResult{}, err - } - converted := make([]materialization.Filter, 0, len(filters)) - for _, filter := range filters { - if filter == nil { - continue - } - converted = append(converted, materialization.Filter{Column: filter.Column, Op: filter.Op, Value: filter.Value}) - } - return s.materializationReader.Aggregate(ctx, materialization.AggregateRequest{MaterializationID: id, GroupBy: groupBy, Filters: converted, Operation: operation, Column: column}) -} - -func (s *Service) authorizeMaterialization(ctx context.Context, value materialization.Materialization) error { - principal, _ := authscope.PrincipalFromContext(ctx) - if principal != nil && len(principal.Projects) > 0 { - allowed := false - for _, project := range principal.Projects { - if project == value.Project { - allowed = true - break - } - } - if !allowed { - return fmt.Errorf("principal is not authorized for project %q", value.Project) - } - } - if value.AuthScopeMode == authscope.ReadScopeUnrestricted { - if s.scopeResolver != nil { - scope, err := s.scopeResolver.ResolveReadScopeForGeneration(ctx, principal, value.Project, value.DatasetGeneration, nil) - if err != nil { - return err - } - if !scope.Unrestricted() { - return fmt.Errorf("materialization %q requires unrestricted authorization", value.ID) - } - } else if principal != nil && len(principal.AuthResourcePaths) > 0 { - return fmt.Errorf("materialization %q requires unrestricted authorization", value.ID) - } - return nil - } - if s.scopeResolver != nil { - scope, err := s.scopeResolver.ResolveReadScopeForGeneration(ctx, principal, value.Project, value.DatasetGeneration, value.AuthResourcePaths) - if err != nil { - return err - } - if len(scope.AuthResourcePaths) != len(value.AuthResourcePaths) { - return fmt.Errorf("materialization %q is outside caller scope", value.ID) - } - return nil - } - if principal == nil { - return fmt.Errorf("materialization %q requires an authorized principal", value.ID) - } - for _, requested := range value.AuthResourcePaths { - found := false - for _, allowed := range principal.AuthResourcePaths { - if requested == allowed { - found = true - break - } - } - if !found { - return fmt.Errorf("materialization %q is outside caller scope", value.ID) - } - } - return nil -} diff --git a/graphqlapi/http_integration_test.go b/graphqlapi/http_integration_test.go index f88e709..44d3d65 100644 --- a/graphqlapi/http_integration_test.go +++ b/graphqlapi/http_integration_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/calypr/loom/graphqlapi" + queryapi "github.com/calypr/loom/graphqlapi/query" "github.com/calypr/loom/internal/authscope" "github.com/calypr/loom/internal/catalog" "github.com/calypr/loom/internal/dataframe" @@ -19,42 +20,44 @@ import ( func TestGraphQLIntrospectionEndpoint(t *testing.T) { graphResolver := graphqlapi.NewResolver(graphqlapi.ResolverConfig{ - ConnectionOptions: arangostore.ConnectionOptions{}, - DiscoverReferences: func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { - return []catalog.PopulatedReference{ - {FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 10}, - }, nil - }, - DiscoverFields: func(ctx context.Context, opts catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { - if opts.PivotOnly { + DataframeQuery: queryapi.Config{ + ConnectionOptions: arangostore.ConnectionOptions{}, + DiscoverReferences: func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + return []catalog.PopulatedReference{ + {FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 10}, + }, nil + }, + DiscoverFields: func(ctx context.Context, opts catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + if opts.PivotOnly { + return []catalog.PopulatedField{ + { + ResourceType: "Patient", + Path: "valueCodeableConcept", + Kind: "codeable_concept", + DocCount: 3, + SampleCount: 1, + PivotCandidate: true, + PivotKind: "codeable_concept_display_value", + PivotColumns: []string{"Stage IVA"}, + DistinctValues: []string{"M0"}, + DistinctTruncated: false, + }, + }, nil + } return []catalog.PopulatedField{ { ResourceType: "Patient", - Path: "valueCodeableConcept", - Kind: "codeable_concept", - DocCount: 3, + Path: "identifier[].value", + Kind: "scalar", + DocCount: 5, SampleCount: 1, - PivotCandidate: true, - PivotKind: "codeable_concept_display_value", - PivotColumns: []string{"Stage IVA"}, - DistinctValues: []string{"M0"}, + DistinctValues: []string{"TCGA-01"}, DistinctTruncated: false, + PivotCandidate: false, + PivotColumns: []string{}, }, }, nil - } - return []catalog.PopulatedField{ - { - ResourceType: "Patient", - Path: "identifier[].value", - Kind: "scalar", - DocCount: 5, - SampleCount: 1, - DistinctValues: []string{"TCGA-01"}, - DistinctTruncated: false, - PivotCandidate: false, - PivotColumns: []string{}, - }, - }, nil + }, }, }) svc, err := api.NewService(api.ServiceConfig{ @@ -221,36 +224,38 @@ func TestGraphQLRunDataframeMutation(t *testing.T) { }, }) graphResolver := graphqlapi.NewResolver(graphqlapi.ResolverConfig{ - ConnectionOptions: arangostore.ConnectionOptions{}, - DiscoverFields: func(ctx context.Context, opts catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { - switch opts.ResourceType { - case "Patient": - return []catalog.PopulatedField{ - {ResourceType: "Patient", Path: "gender", Kind: "scalar"}, - {ResourceType: "Patient", Path: "id", Kind: "scalar"}, - }, nil - case "Condition": - return []catalog.PopulatedField{ - {ResourceType: "Condition", Path: "id", Kind: "scalar"}, - }, nil - case "Specimen": - return []catalog.PopulatedField{ - {ResourceType: "Specimen", Path: "type[].coding[].display", Kind: "scalar"}, - }, nil - default: - return []catalog.PopulatedField{}, nil - } + DataframeQuery: queryapi.Config{ + ConnectionOptions: arangostore.ConnectionOptions{}, + DiscoverFields: func(ctx context.Context, opts catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + switch opts.ResourceType { + case "Patient": + return []catalog.PopulatedField{ + {ResourceType: "Patient", Path: "gender", Kind: "scalar"}, + {ResourceType: "Patient", Path: "id", Kind: "scalar"}, + }, nil + case "Condition": + return []catalog.PopulatedField{ + {ResourceType: "Condition", Path: "id", Kind: "scalar"}, + }, nil + case "Specimen": + return []catalog.PopulatedField{ + {ResourceType: "Specimen", Path: "type[].coding[].display", Kind: "scalar"}, + }, nil + default: + return []catalog.PopulatedField{}, nil + } + }, + DiscoverReferences: func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + if opts.NodeType == "Patient" { + return []catalog.PopulatedReference{ + {FromType: "Patient", Label: "subject_Patient", ToType: "Condition", EdgeCount: 1}, + {FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 1}, + }, nil + } + return []catalog.PopulatedReference{}, nil + }, + Dataframes: dfService, }, - DiscoverReferences: func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { - if opts.NodeType == "Patient" { - return []catalog.PopulatedReference{ - {FromType: "Patient", Label: "subject_Patient", ToType: "Condition", EdgeCount: 1}, - {FromType: "Patient", Label: "subject_Patient", ToType: "Specimen", EdgeCount: 1}, - }, nil - } - return []catalog.PopulatedReference{}, nil - }, - Dataframes: dfService, }) svc, err := api.NewService(api.ServiceConfig{ Runner: fakeRunner{}, @@ -355,39 +360,41 @@ func TestGraphQLRunDataframeTraversalBuilder(t *testing.T) { }, }) graphResolver := graphqlapi.NewResolver(graphqlapi.ResolverConfig{ - ConnectionOptions: arangostore.ConnectionOptions{}, - DiscoverFields: func(ctx context.Context, opts catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { - switch opts.ResourceType { - case "Patient": - return []catalog.PopulatedField{{ResourceType: "Patient", Path: "gender", Kind: "scalar"}}, nil - case "Specimen": - return []catalog.PopulatedField{{ResourceType: "Specimen", Path: "type[].coding[].display", Kind: "scalar"}}, nil - case "Condition": - return []catalog.PopulatedField{{ResourceType: "Condition", Path: "id", Kind: "scalar"}}, nil - default: - return []catalog.PopulatedField{}, nil - } - }, - DiscoverReferences: func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { - if opts.NodeType == "Patient" { - return []catalog.PopulatedReference{ - { - FromType: "Patient", - Label: "subject_Patient", - ToType: "Specimen", - EdgeCount: 2, - }, - { - FromType: "Patient", - Label: "subject_Patient", - ToType: "Condition", - EdgeCount: 1, - }, - }, nil - } - return []catalog.PopulatedReference{}, nil + DataframeQuery: queryapi.Config{ + ConnectionOptions: arangostore.ConnectionOptions{}, + DiscoverFields: func(ctx context.Context, opts catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) { + switch opts.ResourceType { + case "Patient": + return []catalog.PopulatedField{{ResourceType: "Patient", Path: "gender", Kind: "scalar"}}, nil + case "Specimen": + return []catalog.PopulatedField{{ResourceType: "Specimen", Path: "type[].coding[].display", Kind: "scalar"}}, nil + case "Condition": + return []catalog.PopulatedField{{ResourceType: "Condition", Path: "id", Kind: "scalar"}}, nil + default: + return []catalog.PopulatedField{}, nil + } + }, + DiscoverReferences: func(ctx context.Context, opts catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) { + if opts.NodeType == "Patient" { + return []catalog.PopulatedReference{ + { + FromType: "Patient", + Label: "subject_Patient", + ToType: "Specimen", + EdgeCount: 2, + }, + { + FromType: "Patient", + Label: "subject_Patient", + ToType: "Condition", + EdgeCount: 1, + }, + }, nil + } + return []catalog.PopulatedReference{}, nil + }, + Dataframes: dfService, }, - Dataframes: dfService, }) svc, err := api.NewService(api.ServiceConfig{ Runner: fakeRunner{}, diff --git a/graphqlapi/materialization_output.go b/graphqlapi/materialization/output.go similarity index 82% rename from graphqlapi/materialization_output.go rename to graphqlapi/materialization/output.go index 5625cfc..8bdc3ba 100644 --- a/graphqlapi/materialization_output.go +++ b/graphqlapi/materialization/output.go @@ -1,4 +1,4 @@ -package graphqlapi +package materializationapi import ( "encoding/json" @@ -7,7 +7,7 @@ import ( "github.com/calypr/loom/internal/dataframe/materialization" ) -func materializationModel(value materialization.Materialization) *model.DataframeMaterialization { +func Model(value materialization.Materialization) *model.DataframeMaterialization { columns := make([]*model.DataframeColumn, 0, len(value.Columns)) for _, column := range value.Columns { columns = append(columns, &model.DataframeColumn{Name: column.Name, ClickhouseType: column.ClickHouse}) @@ -25,13 +25,13 @@ func materializationModel(value materialization.Materialization) *model.Datafram ID: value.ID, Name: value.Name, Project: value.Project, DatasetGeneration: value.DatasetGeneration, State: model.DataframeMaterializationState(value.State), Columns: columns, - RowCount: int(value.RowCount), + RowCount: int(value.RowCount), CreatedAt: value.CreatedAt.UTC().Format("2006-01-02T15:04:05.999Z07:00"), ReadyAt: readyAt, Error: failure, } } -func aggregateRows(value []map[string]any) json.RawMessage { +func AggregateRows(value []map[string]any) json.RawMessage { data, _ := json.Marshal(value) return data } diff --git a/graphqlapi/materialization/service.go b/graphqlapi/materialization/service.go new file mode 100644 index 0000000..b41603a --- /dev/null +++ b/graphqlapi/materialization/service.go @@ -0,0 +1,162 @@ +// Package materializationapi adapts published dataframe materializations to +// GraphQL. It owns read authorization and ClickHouse-backed row/aggregate +// access; dataframe compilation remains in internal/dataframe. +package materializationapi + +import ( + "context" + "fmt" + + "github.com/calypr/loom/graphqlapi/model" + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/dataframe/materialization" +) + +type Service struct { + reader *materialization.Reader + scopeResolver *authscope.ScopeResolver +} + +type Config struct { + Reader *materialization.Reader + ScopeResolver *authscope.ScopeResolver +} + +func NewService(cfg Config) *Service { + return &Service{reader: cfg.Reader, scopeResolver: cfg.ScopeResolver} +} + +func (s *Service) Get(ctx context.Context, id string) (*materialization.Materialization, error) { + if s.reader == nil { + return nil, fmt.Errorf("dataframe materialization reads are not configured") + } + value, err := s.reader.Registry.Get(ctx, id) + if err != nil { + return nil, err + } + if err := s.authorize(ctx, value); err != nil { + return nil, err + } + return &value, nil +} + +func (s *Service) Rows(ctx context.Context, input model.DataframeRowsInput) (materialization.Page, error) { + if s.reader == nil { + return materialization.Page{}, fmt.Errorf("dataframe materialization reads are not configured") + } + value, err := s.reader.Registry.Get(ctx, input.MaterializationID) + if err != nil { + return materialization.Page{}, err + } + if err := s.authorize(ctx, value); err != nil { + return materialization.Page{}, err + } + filters := make([]materialization.Filter, 0, len(input.Filters)) + for _, filter := range input.Filters { + if filter != nil { + filters = append(filters, materialization.Filter{Column: filter.Column, Op: filter.Op, Value: filter.Value}) + } + } + var sortInput *materialization.Sort + if input.Sort != nil { + sortInput = &materialization.Sort{Column: input.Sort.Column, Desc: input.Sort.Desc != nil && *input.Sort.Desc} + } + first := 0 + if input.First != nil { + first = *input.First + } + after := "" + if input.After != nil { + after = *input.After + } + return s.reader.Page(ctx, materialization.PageRequest{ + MaterializationID: input.MaterializationID, + Columns: input.Columns, + Filters: filters, + Sort: sortInput, + First: first, + After: after, + }) +} + +func (s *Service) Aggregate(ctx context.Context, id string, groupBy []string, filters []*model.DataframeFilterInput, operation, column string) (materialization.AggregateResult, error) { + if s.reader == nil { + return materialization.AggregateResult{}, fmt.Errorf("dataframe materialization reads are not configured") + } + value, err := s.reader.Registry.Get(ctx, id) + if err != nil { + return materialization.AggregateResult{}, err + } + if err := s.authorize(ctx, value); err != nil { + return materialization.AggregateResult{}, err + } + converted := make([]materialization.Filter, 0, len(filters)) + for _, filter := range filters { + if filter != nil { + converted = append(converted, materialization.Filter{Column: filter.Column, Op: filter.Op, Value: filter.Value}) + } + } + return s.reader.Aggregate(ctx, materialization.AggregateRequest{ + MaterializationID: id, + GroupBy: groupBy, + Filters: converted, + Operation: operation, + Column: column, + }) +} + +func (s *Service) authorize(ctx context.Context, value materialization.Materialization) error { + principal, _ := authscope.PrincipalFromContext(ctx) + if principal != nil && len(principal.Projects) > 0 { + allowed := false + for _, project := range principal.Projects { + if project == value.Project { + allowed = true + break + } + } + if !allowed { + return fmt.Errorf("principal is not authorized for project %q", value.Project) + } + } + if value.AuthScopeMode == authscope.ReadScopeUnrestricted { + if s.scopeResolver != nil { + scope, err := s.scopeResolver.ResolveReadScopeForGeneration(ctx, principal, value.Project, value.DatasetGeneration, nil) + if err != nil { + return err + } + if !scope.Unrestricted() { + return fmt.Errorf("materialization %q requires unrestricted authorization", value.ID) + } + } else if principal != nil && len(principal.AuthResourcePaths) > 0 { + return fmt.Errorf("materialization %q requires unrestricted authorization", value.ID) + } + return nil + } + if s.scopeResolver != nil { + scope, err := s.scopeResolver.ResolveReadScopeForGeneration(ctx, principal, value.Project, value.DatasetGeneration, value.AuthResourcePaths) + if err != nil { + return err + } + if len(scope.AuthResourcePaths) != len(value.AuthResourcePaths) { + return fmt.Errorf("materialization %q is outside caller scope", value.ID) + } + return nil + } + if principal == nil { + return fmt.Errorf("materialization %q requires an authorized principal", value.ID) + } + for _, requested := range value.AuthResourcePaths { + found := false + for _, allowed := range principal.AuthResourcePaths { + if requested == allowed { + found = true + break + } + } + if !found { + return fmt.Errorf("materialization %q is outside caller scope", value.ID) + } + } + return nil +} diff --git a/graphqlapi/output_mapping.go b/graphqlapi/output_mapping.go index e4391e2..bf1b2a2 100644 --- a/graphqlapi/output_mapping.go +++ b/graphqlapi/output_mapping.go @@ -4,8 +4,8 @@ import ( "encoding/json" "strings" - dataframeapi "github.com/calypr/loom/graphqlapi/dataframe" "github.com/calypr/loom/graphqlapi/model" + queryapi "github.com/calypr/loom/graphqlapi/query" "github.com/calypr/loom/internal/catalog" ) @@ -25,7 +25,7 @@ func traversalHints(in []catalog.PopulatedReference) []*model.DataframeTraversal return out } -func fieldHints(in []dataframeapi.FieldHint) []*model.DataframeFieldHint { +func fieldHints(in []queryapi.FieldHint) []*model.DataframeFieldHint { if len(in) == 0 { return []*model.DataframeFieldHint{} } @@ -78,7 +78,7 @@ func fieldHints(in []dataframeapi.FieldHint) []*model.DataframeFieldHint { return out } -func resourceHints(in dataframeapi.ResourceHints) *model.DataframeResourceHints { +func resourceHints(in queryapi.ResourceHints) *model.DataframeResourceHints { return &model.DataframeResourceHints{ ResourceType: in.ResourceType, Fields: fieldHints(in.Fields), @@ -87,7 +87,7 @@ func resourceHints(in dataframeapi.ResourceHints) *model.DataframeResourceHints } } -func relatedResourceHints(in []dataframeapi.RelatedResourceHints) []*model.DataframeRelatedResourceHints { +func relatedResourceHints(in []queryapi.RelatedResourceHints) []*model.DataframeRelatedResourceHints { if len(in) == 0 { return []*model.DataframeRelatedResourceHints{} } @@ -106,7 +106,7 @@ func selectorModelFromExpression(expression string) *model.DataframeFieldSelecto if strings.TrimSpace(expression) == "" { return nil } - parts := dataframeapi.DecomposeSelector(expression) + parts := queryapi.DecomposeSelector(expression) var predicate *model.DataframeFieldPredicate if parts.Where != nil { diff --git a/graphqlapi/dataframe/active_generation.go b/graphqlapi/query/active_generation.go similarity index 97% rename from graphqlapi/dataframe/active_generation.go rename to graphqlapi/query/active_generation.go index b4c89a1..8b79770 100644 --- a/graphqlapi/dataframe/active_generation.go +++ b/graphqlapi/query/active_generation.go @@ -1,4 +1,4 @@ -package dataframeapi +package queryapi import ( "context" diff --git a/graphqlapi/dataframe/active_generation_test.go b/graphqlapi/query/active_generation_test.go similarity index 99% rename from graphqlapi/dataframe/active_generation_test.go rename to graphqlapi/query/active_generation_test.go index 86f4a63..c9bd53d 100644 --- a/graphqlapi/dataframe/active_generation_test.go +++ b/graphqlapi/query/active_generation_test.go @@ -1,4 +1,4 @@ -package dataframeapi +package queryapi import ( "context" diff --git a/graphqlapi/dataframe/auth_scope_test.go b/graphqlapi/query/auth_scope_test.go similarity index 99% rename from graphqlapi/dataframe/auth_scope_test.go rename to graphqlapi/query/auth_scope_test.go index 218b401..441cf4c 100644 --- a/graphqlapi/dataframe/auth_scope_test.go +++ b/graphqlapi/query/auth_scope_test.go @@ -1,4 +1,4 @@ -package dataframeapi +package queryapi import ( "context" diff --git a/graphqlapi/dataframe/datasets.go b/graphqlapi/query/datasets.go similarity index 99% rename from graphqlapi/dataframe/datasets.go rename to graphqlapi/query/datasets.go index fdb55f3..427d1cd 100644 --- a/graphqlapi/dataframe/datasets.go +++ b/graphqlapi/query/datasets.go @@ -1,4 +1,4 @@ -package dataframeapi +package queryapi import ( "context" diff --git a/graphqlapi/dataframe/datasets_test.go b/graphqlapi/query/datasets_test.go similarity index 99% rename from graphqlapi/dataframe/datasets_test.go rename to graphqlapi/query/datasets_test.go index bc31c07..db542d7 100644 --- a/graphqlapi/dataframe/datasets_test.go +++ b/graphqlapi/query/datasets_test.go @@ -1,4 +1,4 @@ -package dataframeapi +package queryapi import ( "context" diff --git a/graphqlapi/query/doc.go b/graphqlapi/query/doc.go new file mode 100644 index 0000000..6eb9bc3 --- /dev/null +++ b/graphqlapi/query/doc.go @@ -0,0 +1,4 @@ +// Package queryapi adapts GraphQL dataframe requests to Loom's dataframe +// runtime. It owns input mapping, catalog discovery, validation, templates, +// and direct Arango-backed dataframe execution. +package queryapi diff --git a/graphqlapi/dataframe/fieldrefs.go b/graphqlapi/query/fieldrefs.go similarity index 99% rename from graphqlapi/dataframe/fieldrefs.go rename to graphqlapi/query/fieldrefs.go index fad3c75..0ee44ef 100644 --- a/graphqlapi/dataframe/fieldrefs.go +++ b/graphqlapi/query/fieldrefs.go @@ -1,4 +1,4 @@ -package dataframeapi +package queryapi import ( "fmt" diff --git a/graphqlapi/dataframe/fieldrefs_test.go b/graphqlapi/query/fieldrefs_test.go similarity index 98% rename from graphqlapi/dataframe/fieldrefs_test.go rename to graphqlapi/query/fieldrefs_test.go index 710e75d..adf7948 100644 --- a/graphqlapi/dataframe/fieldrefs_test.go +++ b/graphqlapi/query/fieldrefs_test.go @@ -1,4 +1,4 @@ -package dataframeapi +package queryapi import ( "strings" diff --git a/graphqlapi/dataframe/helpers.go b/graphqlapi/query/helpers.go similarity index 94% rename from graphqlapi/dataframe/helpers.go rename to graphqlapi/query/helpers.go index 414ab2c..4c49d76 100644 --- a/graphqlapi/dataframe/helpers.go +++ b/graphqlapi/query/helpers.go @@ -1,4 +1,4 @@ -package dataframeapi +package queryapi import "github.com/calypr/loom/internal/catalog" diff --git a/graphqlapi/dataframe/input_mapping.go b/graphqlapi/query/input_mapping.go similarity index 99% rename from graphqlapi/dataframe/input_mapping.go rename to graphqlapi/query/input_mapping.go index 8131dd8..959640f 100644 --- a/graphqlapi/dataframe/input_mapping.go +++ b/graphqlapi/query/input_mapping.go @@ -1,4 +1,4 @@ -package dataframeapi +package queryapi import ( "strings" diff --git a/graphqlapi/dataframe/input_mapping_test.go b/graphqlapi/query/input_mapping_test.go similarity index 99% rename from graphqlapi/dataframe/input_mapping_test.go rename to graphqlapi/query/input_mapping_test.go index 510294c..6141bb0 100644 --- a/graphqlapi/dataframe/input_mapping_test.go +++ b/graphqlapi/query/input_mapping_test.go @@ -1,4 +1,4 @@ -package dataframeapi +package queryapi import ( "testing" diff --git a/graphqlapi/dataframe/input_resolution.go b/graphqlapi/query/input_resolution.go similarity index 99% rename from graphqlapi/dataframe/input_resolution.go rename to graphqlapi/query/input_resolution.go index ec31711..966d6c7 100644 --- a/graphqlapi/dataframe/input_resolution.go +++ b/graphqlapi/query/input_resolution.go @@ -1,4 +1,4 @@ -package dataframeapi +package queryapi import ( "context" diff --git a/graphqlapi/dataframe/introspection.go b/graphqlapi/query/introspection.go similarity index 99% rename from graphqlapi/dataframe/introspection.go rename to graphqlapi/query/introspection.go index 452bcbf..2f6ed76 100644 --- a/graphqlapi/dataframe/introspection.go +++ b/graphqlapi/query/introspection.go @@ -1,4 +1,4 @@ -package dataframeapi +package queryapi import ( "context" diff --git a/graphqlapi/dataframe/introspection_test.go b/graphqlapi/query/introspection_test.go similarity index 99% rename from graphqlapi/dataframe/introspection_test.go rename to graphqlapi/query/introspection_test.go index a38f1b4..5382814 100644 --- a/graphqlapi/dataframe/introspection_test.go +++ b/graphqlapi/query/introspection_test.go @@ -1,4 +1,4 @@ -package dataframeapi +package queryapi import ( "context" diff --git a/graphqlapi/query/service.go b/graphqlapi/query/service.go new file mode 100644 index 0000000..603021f --- /dev/null +++ b/graphqlapi/query/service.go @@ -0,0 +1,110 @@ +package queryapi + +import ( + "context" + "time" + + "github.com/calypr/loom/graphqlapi/model" + "github.com/calypr/loom/internal/authscope" + "github.com/calypr/loom/internal/catalog" + "github.com/calypr/loom/internal/dataframe" + "github.com/calypr/loom/internal/dataset" + arangostore "github.com/calypr/loom/internal/store/arango" +) + +type Service struct { + connOpts arangostore.ConnectionOptions + discoverReferences func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) + discoverFields func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) + dataframes *dataframe.Service + scopeResolver *authscope.ScopeResolver + activeManifestResolver dataset.ActiveManifestResolver + discoverDatasets func(context.Context, catalog.DatasetSummaryOptions) ([]catalog.DatasetSummary, error) + datasetProjectAllowlist []string +} + +type Config struct { + ConnectionOptions arangostore.ConnectionOptions + DiscoverReferences func(context.Context, catalog.PopulatedReferenceOptions) ([]catalog.PopulatedReference, error) + DiscoverFields func(context.Context, catalog.PopulatedFieldOptions) ([]catalog.PopulatedField, error) + Dataframes *dataframe.Service + ScopeResolver *authscope.ScopeResolver + // ActiveManifestResolver is optional. When present, builder catalog + // discovery and recipe preparation resolve one READY active generation + // before inspecting any fields or relationship routes. + ActiveManifestResolver dataset.ActiveManifestResolver + // DatasetProjectAllowlist is the explicit project source used when a + // principal does not carry a project list. An empty value never triggers an + // unrestricted catalog scan. + DatasetProjectAllowlist []string + DiscoverDatasets func(context.Context, catalog.DatasetSummaryOptions) ([]catalog.DatasetSummary, error) +} + +func NewService(cfg Config) *Service { + service := &Service{ + connOpts: cfg.ConnectionOptions, + scopeResolver: cfg.ScopeResolver, + activeManifestResolver: cfg.ActiveManifestResolver, + datasetProjectAllowlist: cloneStrings(cfg.DatasetProjectAllowlist), + } + if cfg.DiscoverDatasets != nil { + service.discoverDatasets = cfg.DiscoverDatasets + } else { + service.discoverDatasets = catalog.DiscoverDatasetSummaries + } + if cfg.DiscoverReferences != nil { + service.discoverReferences = cfg.DiscoverReferences + } else { + service.discoverReferences = catalog.DiscoverPopulatedReferences + } + if cfg.DiscoverFields != nil { + service.discoverFields = cfg.DiscoverFields + } else { + service.discoverFields = catalog.DiscoverPopulatedFields + } + if cfg.Dataframes != nil { + service.dataframes = cfg.Dataframes + } else { + service.dataframes = dataframe.NewService(dataframe.ServiceConfig{ + ConnectionOptions: cfg.ConnectionOptions, + DiscoverReferences: service.discoverReferences, + DiscoverFields: service.discoverFields, + ScopeResolver: cfg.ScopeResolver, + ActiveManifestResolver: cfg.ActiveManifestResolver, + }) + } + return service +} + +func (s *Service) Run(ctx context.Context, input model.FhirDataframeInput, limit *int) (*dataframe.Result, error) { + started := time.Now() + normalizedInput, scope, generation, err := s.prepareRunInput(ctx, input) + if err != nil { + return nil, err + } + rowLimit := 0 + if limit != nil { + rowLimit = *limit + } else if normalizedInput.Limit != nil { + rowLimit = *normalizedInput.Limit + } + builder := BuilderFromInput(normalizedInput) + builder.DatasetGeneration = generation + // Preserve the scope mode that resolved the catalog references above. This + // matters when no catalog paths survive a restricted caller's intersection: + // an empty list alone would otherwise be legacy-unrestricted downstream. + builder.AuthScopeMode = scope.Mode + result, err := s.dataframes.Run(ctx, dataframe.RunRequest{ + Builder: builder, + Limit: rowLimit, + }) + if err != nil { + return nil, err + } + result.Diagnostics.InputResolution = time.Since(started) - result.Diagnostics.Total + if result.Diagnostics.InputResolution < 0 { + result.Diagnostics.InputResolution = 0 + } + result.Diagnostics.Total = time.Since(started) + return result, nil +} diff --git a/graphqlapi/dataframe/templates.go b/graphqlapi/query/templates.go similarity index 99% rename from graphqlapi/dataframe/templates.go rename to graphqlapi/query/templates.go index 012220b..8327d0d 100644 --- a/graphqlapi/dataframe/templates.go +++ b/graphqlapi/query/templates.go @@ -1,4 +1,4 @@ -package dataframeapi +package queryapi import ( "context" diff --git a/graphqlapi/dataframe/templates_test.go b/graphqlapi/query/templates_test.go similarity index 99% rename from graphqlapi/dataframe/templates_test.go rename to graphqlapi/query/templates_test.go index 98bff83..33fdfdd 100644 --- a/graphqlapi/dataframe/templates_test.go +++ b/graphqlapi/query/templates_test.go @@ -1,4 +1,4 @@ -package dataframeapi +package queryapi import ( "context" diff --git a/graphqlapi/dataframe/types.go b/graphqlapi/query/types.go similarity index 98% rename from graphqlapi/dataframe/types.go rename to graphqlapi/query/types.go index 47372b2..f032527 100644 --- a/graphqlapi/dataframe/types.go +++ b/graphqlapi/query/types.go @@ -1,4 +1,4 @@ -package dataframeapi +package queryapi import "github.com/calypr/loom/internal/catalog" diff --git a/graphqlapi/dataframe/validation.go b/graphqlapi/query/validation.go similarity index 99% rename from graphqlapi/dataframe/validation.go rename to graphqlapi/query/validation.go index b06c65c..683a982 100644 --- a/graphqlapi/dataframe/validation.go +++ b/graphqlapi/query/validation.go @@ -1,4 +1,4 @@ -package dataframeapi +package queryapi import ( "context" diff --git a/graphqlapi/dataframe/validation_test.go b/graphqlapi/query/validation_test.go similarity index 99% rename from graphqlapi/dataframe/validation_test.go rename to graphqlapi/query/validation_test.go index f4be208..8c0a53a 100644 --- a/graphqlapi/dataframe/validation_test.go +++ b/graphqlapi/query/validation_test.go @@ -1,4 +1,4 @@ -package dataframeapi +package queryapi import ( "context" diff --git a/graphqlapi/resolver.go b/graphqlapi/resolver.go index 8e20d94..cb534ea 100644 --- a/graphqlapi/resolver.go +++ b/graphqlapi/resolver.go @@ -1,13 +1,27 @@ package graphqlapi -import dataframeapi "github.com/calypr/loom/graphqlapi/dataframe" +import ( + materializationapi "github.com/calypr/loom/graphqlapi/materialization" + queryapi "github.com/calypr/loom/graphqlapi/query" + "github.com/calypr/loom/internal/dataframe/materialization" +) type Resolver struct { - service *dataframeapi.Service + query *queryapi.Service + materializations *materializationapi.Service } -type ResolverConfig = dataframeapi.Config +type ResolverConfig struct { + DataframeQuery queryapi.Config + MaterializationReader *materialization.Reader +} func NewResolver(cfg ResolverConfig) *Resolver { - return &Resolver{service: dataframeapi.NewService(cfg)} + return &Resolver{ + query: queryapi.NewService(cfg.DataframeQuery), + materializations: materializationapi.NewService(materializationapi.Config{ + Reader: cfg.MaterializationReader, + ScopeResolver: cfg.DataframeQuery.ScopeResolver, + }), + } } diff --git a/graphqlapi/schema.resolvers.go b/graphqlapi/schema.resolvers.go index 1bc48b0..516b12d 100644 --- a/graphqlapi/schema.resolvers.go +++ b/graphqlapi/schema.resolvers.go @@ -8,13 +8,14 @@ import ( "context" "encoding/json" - dataframeapi "github.com/calypr/loom/graphqlapi/dataframe" + materializationapi "github.com/calypr/loom/graphqlapi/materialization" "github.com/calypr/loom/graphqlapi/model" + queryapi "github.com/calypr/loom/graphqlapi/query" ) // RunFhirDataframe is the resolver for the runFhirDataframe field. func (r *mutationResolver) RunFhirDataframe(ctx context.Context, input model.FhirDataframeInput, limit *int) (*model.FhirDataframeResult, error) { - result, err := r.service.Run(ctx, input, limit) + result, err := r.query.Run(ctx, input, limit) if err != nil { return nil, err } @@ -32,7 +33,7 @@ func (r *queryResolver) DataframeBuilderIntrospection(ctx context.Context, input if input.IncludePivotOnlyFields != nil { includePivotOnlyFields = *input.IncludePivotOnlyFields } - resp, err := r.service.Introspect(ctx, dataframeapi.IntrospectionRequest{ + resp, err := r.query.Introspect(ctx, queryapi.IntrospectionRequest{ Project: input.Project, RootResourceType: input.RootResourceType, AuthResourcePaths: input.AuthResourcePaths, @@ -55,16 +56,16 @@ func (r *queryResolver) DataframeBuilderIntrospection(ctx context.Context, input // DataframeMaterialization is the resolver for the dataframeMaterialization field. func (r *queryResolver) DataframeMaterialization(ctx context.Context, id string) (*model.DataframeMaterialization, error) { - value, err := r.service.GetMaterialization(ctx, id) + value, err := r.materializations.Get(ctx, id) if err != nil { return nil, err } - return materializationModel(*value), nil + return materializationapi.Model(*value), nil } // DataframeRows is the resolver for the dataframeRows field. func (r *queryResolver) DataframeRows(ctx context.Context, input model.DataframeRowsInput) (*model.DataframeRowConnection, error) { - page, err := r.service.ReadMaterialization(ctx, input) + page, err := r.materializations.Rows(ctx, input) if err != nil { return nil, err } @@ -77,7 +78,7 @@ func (r *queryResolver) DataframeRows(ctx context.Context, input model.Dataframe cursor = &page.NextCursor } return &model.DataframeRowConnection{ - Materialization: materializationModel(page.Materialization), + Materialization: materializationapi.Model(page.Materialization), Columns: append([]string(nil), page.Columns...), Rows: rows, PageInfo: &model.DataframePageInfo{HasNextPage: page.HasNext, EndCursor: cursor}, }, nil @@ -90,11 +91,11 @@ func (r *queryResolver) DataframeAggregate(ctx context.Context, input model.Data if input.Column != nil { column = *input.Column } - result, err := r.service.AggregateMaterialization(ctx, input.MaterializationID, groupBy, input.Filters, input.Operation, column) + result, err := r.materializations.Aggregate(ctx, input.MaterializationID, groupBy, input.Filters, input.Operation, column) if err != nil { return nil, err } - return &model.DataframeAggregateResult{Materialization: materializationModel(result.Materialization), Columns: result.Columns, Rows: aggregateRows(result.Rows)}, nil + return &model.DataframeAggregateResult{Materialization: materializationapi.Model(result.Materialization), Columns: result.Columns, Rows: materializationapi.AggregateRows(result.Rows)}, nil } // Mutation returns MutationResolver implementation. diff --git a/internal/server/server.go b/internal/server/server.go index 77df3e6..55ba75e 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -10,7 +10,7 @@ import ( "syscall" "github.com/calypr/loom/graphqlapi" - dataframeapi "github.com/calypr/loom/graphqlapi/dataframe" + queryapi "github.com/calypr/loom/graphqlapi/query" "github.com/calypr/loom/internal/authscope" "github.com/calypr/loom/internal/catalog" "github.com/calypr/loom/internal/dataframe" @@ -54,7 +54,7 @@ func Run() { } // Keep this as an interface, not a typed *datasetarango.Store nil. Passing a - // typed nil into dataframeapi.Config makes the interface non-nil and + // typed nil into queryapi.Config makes the interface non-nil and // incorrectly activates immutable-generation lookup for legacy META loads. var activeManifestResolver dataset.ActiveManifestResolver if *datasetGenerations { @@ -111,17 +111,17 @@ func Run() { exitf("create ClickHouse client: %v", err) } defer clickhouse.Close() - materializer := &materialization.Service{Dataframes: dataframes, ClickHouse: clickhouse, Registry: registry} materializationReader := &materialization.Reader{ClickHouse: clickhouse, Registry: registry, MaxPage: 1000} - resolver := graphqlapi.NewResolver(dataframeapi.Config{ - ConnectionOptions: connOpts, - DiscoverReferences: discoverReferences, - DiscoverFields: discoverFields, - Dataframes: dataframes, - ScopeResolver: scopeResolver, - ActiveManifestResolver: activeManifestResolver, - Materializations: materializer, - MaterializationReader: materializationReader, + resolver := graphqlapi.NewResolver(graphqlapi.ResolverConfig{ + DataframeQuery: queryapi.Config{ + ConnectionOptions: connOpts, + DiscoverReferences: discoverReferences, + DiscoverFields: discoverFields, + Dataframes: dataframes, + ScopeResolver: scopeResolver, + ActiveManifestResolver: activeManifestResolver, + }, + MaterializationReader: materializationReader, }) importService, err := api.NewService(api.ServiceConfig{ From 53333b535ae54ca1741855dd032d10b33277de28 Mon Sep 17 00:00:00 2001 From: matthewpeterkort Date: Mon, 13 Jul 2026 13:25:57 -0700 Subject: [PATCH 13/15] update quay push target --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index fc0386c..3eed106 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -17,7 +17,7 @@ concurrency: cancel-in-progress: true env: - IMAGE: quay.io/ohsu-comp-bio/arango-fhir-proto + IMAGE: quay.io/ohsu-comp-bio/loom jobs: tests: From a6e26a02100e4c07ceab742c8fd9a5235848b6a9 Mon Sep 17 00:00:00 2001 From: matthewpeterkort Date: Mon, 13 Jul 2026 13:37:00 -0700 Subject: [PATCH 14/15] add push on PRs --- .github/workflows/build.yaml | 6 ++++++ .github/workflows/tests.yaml | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 3eed106..5bd8e67 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,6 +1,8 @@ name: Build and publish Loom image on: + pull_request: + types: [opened, synchronize, reopened] push: branches: - main @@ -27,6 +29,8 @@ jobs: build-and-push: name: Build ${{ matrix.arch }} image needs: tests + # Never expose Quay credentials to code from a forked pull request. + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository runs-on: ${{ matrix.arch == 'amd64' && 'ubuntu-latest' || 'ubuntu-24.04-arm' }} strategy: fail-fast: false @@ -43,6 +47,7 @@ jobs: images: ${{ env.IMAGE }} tags: | type=ref,event=branch + type=ref,event=pr type=sha,format=short type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} @@ -103,6 +108,7 @@ jobs: images: ${{ env.IMAGE }} tags: | type=ref,event=branch + type=ref,event=pr type=sha,format=short type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index a395bc9..4ebdf8b 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -1,7 +1,6 @@ name: Go Tests on: - pull_request: workflow_call: jobs: From 51fcdb241ee22447d5fcd918e531ae0075a7bcc9 Mon Sep 17 00:00:00 2001 From: matthewpeterkort Date: Mon, 13 Jul 2026 13:49:34 -0700 Subject: [PATCH 15/15] fix manifest merge --- .github/workflows/build.yaml | 32 ++++++++++++++++++++++++-------- .github/workflows/tests.yaml | 1 + 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 5bd8e67..3b8067d 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,4 +1,4 @@ -name: Build and publish Loom image +name: Loom CI on: pull_request: @@ -23,11 +23,11 @@ env: jobs: tests: - name: Verify Loom before publishing + name: Tests uses: ./.github/workflows/tests.yaml build-and-push: - name: Build ${{ matrix.arch }} image + name: Build and push ${{ matrix.arch }} image needs: tests # Never expose Quay credentials to code from a forked pull request. if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository @@ -90,7 +90,7 @@ jobs: retention-days: 1 merge: - name: Publish multi-architecture manifest + name: Push multi-architecture manifest runs-on: ubuntu-latest needs: build-and-push steps: @@ -129,7 +129,23 @@ jobs: DOCKER_METADATA_OUTPUT_TAGS: ${{ steps.meta.outputs.tags }} run: | set -euo pipefail - mapfile -t digests < <(cat /tmp/loom-digests/*.txt) - docker buildx imagetools create \ - $(printf '%s\n' "$DOCKER_METADATA_OUTPUT_TAGS" | xargs -n 1 printf -- '-t %s ') \ - $(printf '%s@%s ' "$IMAGE" "${digests[@]}") + tag_args=() + while IFS= read -r tag; do + if [ -n "$tag" ]; then + tag_args+=("-t" "$tag") + fi + done <<< "$DOCKER_METADATA_OUTPUT_TAGS" + + sources=() + for digest_file in /tmp/loom-digests/*.txt; do + digest=$(tr -d '\r\n' < "$digest_file") + if [ -n "$digest" ]; then + sources+=("${IMAGE}@${digest}") + fi + done + + if [ "${#sources[@]}" -eq 0 ]; then + echo "No image digests were exported" >&2 + exit 1 + fi + docker buildx imagetools create "${tag_args[@]}" "${sources[@]}" diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 4ebdf8b..f2cd9e6 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -5,6 +5,7 @@ on: jobs: test: + name: Go tests runs-on: ubuntu-latest steps: